Commit 94178998e541d4c829294a1b2dfab5f68e5e2c18
1 parent
8a5db8c1
mp:前端 message 增加 voice 语音的播放
Showing
5 changed files
with
116 additions
and
2 deletions
yudao-ui-admin/package.json
yudao-ui-admin/src/views/mp/components/wx-video-play/main.vue
yudao-ui-admin/src/views/mp/components/wx-voice-play/main.vue
0 → 100644
| 1 | +<!-- | |
| 2 | + - Copyright (C) 2018-2019 | |
| 3 | + - All rights reserved, Designed By www.joolun.com | |
| 4 | + 芋道源码: | |
| 5 | + ① bug 修复: | |
| 6 | + 1)joolun 的做法:使用 mediaId 从微信公众号,下载对应的 mp4 素材,从而播放内容; | |
| 7 | + 存在的问题:mediaId 有效期是 3 天,超过时间后无法播放 | |
| 8 | + 2)重构后的做法:后端接收到微信公众号的视频消息后,将视频消息的 media_id 的文件内容保存到文件服务器中,这样前端可以直接使用 URL 播放。 | |
| 9 | + ② 代码优化:将 props 中的 objData 调成为 data 中对应的属性,并补充相关注释 | |
| 10 | +--> | |
| 11 | +<template> | |
| 12 | + <div class="wx-voice-div" @click="playVoice"> | |
| 13 | + <i :class="playing !== true ? 'el-icon-video-play': 'el-icon-video-pause'"> | |
| 14 | + <span class="amr-duration" v-if="duration">{{ duration }}</span> | |
| 15 | + </i> | |
| 16 | + <div v-if="content"> | |
| 17 | + <el-tag type="success" size="mini">语音识别</el-tag> | |
| 18 | + {{ content }} | |
| 19 | + </div> | |
| 20 | + </div> | |
| 21 | +</template> | |
| 22 | + | |
| 23 | +<script> | |
| 24 | +// 因为微信语音是 amr 格式,所以需要用到 amr 解码器:https://www.npmjs.com/package/benz-amr-recorder | |
| 25 | +const BenzAMRRecorder = require('benz-amr-recorder') | |
| 26 | + | |
| 27 | +export default { | |
| 28 | + name: "wxVoicePlayer", | |
| 29 | + props: { | |
| 30 | + url: { // 语音地址,例如说:https://www.iocoder.cn/xxx.amr | |
| 31 | + type: String, | |
| 32 | + required: true | |
| 33 | + }, | |
| 34 | + content: { // 语音文本 | |
| 35 | + type: String, | |
| 36 | + required: false | |
| 37 | + } | |
| 38 | + }, | |
| 39 | + data() { | |
| 40 | + return { | |
| 41 | + amr: undefined, // BenzAMRRecorder 对象 | |
| 42 | + playing: false, // 是否在播放中 | |
| 43 | + duration: undefined, // 播放时长 | |
| 44 | + } | |
| 45 | + }, | |
| 46 | + methods:{ | |
| 47 | + playVoice() { | |
| 48 | + debugger | |
| 49 | + // 情况一:未初始化,则创建 BenzAMRRecorder | |
| 50 | + if (this.amr === undefined){ | |
| 51 | + this.amrInit(); | |
| 52 | + return; | |
| 53 | + } | |
| 54 | + | |
| 55 | + if (this.amr.isPlaying()) { | |
| 56 | + this.amrStop(); | |
| 57 | + } else { | |
| 58 | + this.amrPlay(); | |
| 59 | + } | |
| 60 | + }, | |
| 61 | + amrInit() { | |
| 62 | + const amr = new BenzAMRRecorder(); | |
| 63 | + this.amr = amr; | |
| 64 | + // 设置播放 | |
| 65 | + const that = this | |
| 66 | + amr.initWithUrl(this.url).then(function() { | |
| 67 | + that.amrPlay() | |
| 68 | + that.duration = amr.getDuration(); | |
| 69 | + }) | |
| 70 | + // 监听暂停 | |
| 71 | + amr.onEnded(function() { | |
| 72 | + that.playing = false; | |
| 73 | + }) | |
| 74 | + }, | |
| 75 | + amrPlay() { | |
| 76 | + this.playing = true; | |
| 77 | + this.amr.play() | |
| 78 | + }, | |
| 79 | + amrStop() { | |
| 80 | + this.playing = false; | |
| 81 | + this.amr.stop() | |
| 82 | + }, | |
| 83 | + } | |
| 84 | +}; | |
| 85 | +</script> | |
| 86 | + | |
| 87 | +<style lang="scss" scoped> | |
| 88 | + .wx-voice-div { | |
| 89 | + padding: 5px; | |
| 90 | + background-color: #eaeaea; | |
| 91 | + border-radius: 10px; | |
| 92 | + } | |
| 93 | + .amr-duration { | |
| 94 | + font-size: 11px; | |
| 95 | + margin-left: 5px; | |
| 96 | + } | |
| 97 | +</style> | ... | ... |
yudao-ui-admin/src/views/mp/message/index.vue
| ... | ... | @@ -70,7 +70,9 @@ |
| 70 | 70 | </div> |
| 71 | 71 | <!-- 【消息】区域 --> |
| 72 | 72 | <div v-else-if="scope.row.type === 'text'">{{ scope.row.content }}</div> |
| 73 | - <!-- TODO 语音 --> | |
| 73 | + <div v-else-if="scope.row.type === 'voice'"> | |
| 74 | + <wx-voice-player :url="scope.row.mediaUrl" :content="scope.row.recognition" /> | |
| 75 | + </div> | |
| 74 | 76 | <div v-else-if="scope.row.type === 'image'"> |
| 75 | 77 | <a target="_blank" :href="scope.row.mediaUrl"> |
| 76 | 78 | <img :src="scope.row.mediaUrl" style="width: 100px"> |
| ... | ... | @@ -154,12 +156,14 @@ import { |
| 154 | 156 | } from "@/api/mp/message"; |
| 155 | 157 | import Editor from '@/components/Editor/index.vue'; |
| 156 | 158 | import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue'; |
| 159 | +import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue'; | |
| 157 | 160 | |
| 158 | 161 | export default { |
| 159 | 162 | name: "WxFansMsg", |
| 160 | 163 | components: { |
| 161 | 164 | Editor, |
| 162 | 165 | WxVideoPlayer, |
| 166 | + WxVoicePlayer | |
| 163 | 167 | }, |
| 164 | 168 | data() { |
| 165 | 169 | return { | ... | ... |
yudao-ui-admin/yarn.lock
| ... | ... | @@ -2327,6 +2327,18 @@ |
| 2327 | 2327 | dependencies: |
| 2328 | 2328 | "tweetnacl" "^0.14.3" |
| 2329 | 2329 | |
| 2330 | +"benz-amr-recorder@^1.1.5": | |
| 2331 | + "integrity" "sha512-NepctcNTsZHK8NxBb5uKO5p8S+xkbm+vD6GLSkCYdJeEsriexvgumLHpDkanX4QJBcLRMVtg16buWMs+gUPB3g==" | |
| 2332 | + "resolved" "https://registry.npmmirror.com/benz-amr-recorder/-/benz-amr-recorder-1.1.5.tgz" | |
| 2333 | + "version" "1.1.5" | |
| 2334 | + dependencies: | |
| 2335 | + "benz-recorderjs" "^1.0.5" | |
| 2336 | + | |
| 2337 | +"benz-recorderjs@^1.0.5": | |
| 2338 | + "integrity" "sha512-EwedOQo9KLti7HxDi/eZY51PSRbAXnOdEZmLvJ6ro3QQSoF9Y3AXBt57MIllGvVz5vtFYMeikG+GD7qTm3+p9w==" | |
| 2339 | + "resolved" "https://registry.npmmirror.com/benz-recorderjs/-/benz-recorderjs-1.0.5.tgz" | |
| 2340 | + "version" "1.0.5" | |
| 2341 | + | |
| 2330 | 2342 | "bfj@^6.1.1": |
| 2331 | 2343 | "integrity" "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==" |
| 2332 | 2344 | "resolved" "https://registry.npmmirror.com/bfj/-/bfj-6.1.2.tgz" | ... | ... |