mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-30 01:38:43 +08:00 
			
		
		
		
	mp:前端 message 增加 voice 语音的播放
This commit is contained in:
		| @@ -43,6 +43,7 @@ | |||||||
|     "@babel/parser": "7.18.4", |     "@babel/parser": "7.18.4", | ||||||
|     "@riophae/vue-treeselect": "0.4.0", |     "@riophae/vue-treeselect": "0.4.0", | ||||||
|     "axios": "0.27.2", |     "axios": "0.27.2", | ||||||
|  |     "benz-amr-recorder": "^1.1.5", | ||||||
|     "bpmn-js-token-simulation": "0.10.0", |     "bpmn-js-token-simulation": "0.10.0", | ||||||
|     "clipboard": "2.0.8", |     "clipboard": "2.0.8", | ||||||
|     "core-js": "^3.26.0", |     "core-js": "^3.26.0", | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| <!-- | <!-- | ||||||
|   - Copyright (C) 2018-2019 |   - Copyright (C) 2018-2019 | ||||||
|   - All rights reserved, Designed By www.joolun.com |   - All rights reserved, Designed By www.joolun.com | ||||||
|   芋艿: |   芋道源码: | ||||||
|   ① bug 修复: |   ① bug 修复: | ||||||
|     1)joolun 的做法:使用 mediaId 从微信公众号,下载对应的 mp4 素材,从而播放内容; |     1)joolun 的做法:使用 mediaId 从微信公众号,下载对应的 mp4 素材,从而播放内容; | ||||||
|       存在的问题:mediaId 有效期是 3 天,超过时间后无法播放 |       存在的问题:mediaId 有效期是 3 天,超过时间后无法播放 | ||||||
|   | |||||||
| @@ -0,0 +1,97 @@ | |||||||
|  | <!-- | ||||||
|  |   - Copyright (C) 2018-2019 | ||||||
|  |   - All rights reserved, Designed By www.joolun.com | ||||||
|  |    芋道源码: | ||||||
|  |   ① bug 修复: | ||||||
|  |     1)joolun 的做法:使用 mediaId 从微信公众号,下载对应的 mp4 素材,从而播放内容; | ||||||
|  |       存在的问题:mediaId 有效期是 3 天,超过时间后无法播放 | ||||||
|  |     2)重构后的做法:后端接收到微信公众号的视频消息后,将视频消息的 media_id 的文件内容保存到文件服务器中,这样前端可以直接使用 URL 播放。 | ||||||
|  |   ② 代码优化:将 props 中的 objData 调成为 data 中对应的属性,并补充相关注释 | ||||||
|  | --> | ||||||
|  | <template> | ||||||
|  |   <div class="wx-voice-div" @click="playVoice"> | ||||||
|  |     <i :class="playing !== true ? 'el-icon-video-play': 'el-icon-video-pause'"> | ||||||
|  |       <span class="amr-duration" v-if="duration">{{ duration }}</span> | ||||||
|  |     </i> | ||||||
|  |     <div v-if="content"> | ||||||
|  |       <el-tag type="success" size="mini">语音识别</el-tag> | ||||||
|  |       {{ content }} | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | // 因为微信语音是 amr 格式,所以需要用到 amr 解码器:https://www.npmjs.com/package/benz-amr-recorder | ||||||
|  | const BenzAMRRecorder = require('benz-amr-recorder') | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |   name: "wxVoicePlayer", | ||||||
|  |   props: { | ||||||
|  |     url: { // 语音地址,例如说:https://www.iocoder.cn/xxx.amr | ||||||
|  |       type: String, | ||||||
|  |       required: true | ||||||
|  |     }, | ||||||
|  |     content: { // 语音文本 | ||||||
|  |       type: String, | ||||||
|  |       required: false | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       amr: undefined, // BenzAMRRecorder 对象 | ||||||
|  |       playing: false, // 是否在播放中 | ||||||
|  |       duration: undefined, // 播放时长 | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   methods:{ | ||||||
|  |     playVoice() { | ||||||
|  |       debugger | ||||||
|  |       // 情况一:未初始化,则创建 BenzAMRRecorder | ||||||
|  |       if (this.amr === undefined){ | ||||||
|  |         this.amrInit(); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (this.amr.isPlaying()) { | ||||||
|  |         this.amrStop(); | ||||||
|  |       } else { | ||||||
|  |         this.amrPlay(); | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     amrInit() { | ||||||
|  |       const amr = new BenzAMRRecorder(); | ||||||
|  |       this.amr = amr; | ||||||
|  |       // 设置播放 | ||||||
|  |       const that = this | ||||||
|  |       amr.initWithUrl(this.url).then(function() { | ||||||
|  |         that.amrPlay() | ||||||
|  |         that.duration = amr.getDuration(); | ||||||
|  |       }) | ||||||
|  |       // 监听暂停 | ||||||
|  |       amr.onEnded(function() { | ||||||
|  |         that.playing = false; | ||||||
|  |       }) | ||||||
|  |     }, | ||||||
|  |     amrPlay() { | ||||||
|  |       this.playing = true; | ||||||
|  |       this.amr.play() | ||||||
|  |     }, | ||||||
|  |     amrStop() { | ||||||
|  |       this.playing = false; | ||||||
|  |       this.amr.stop() | ||||||
|  |     }, | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style lang="scss" scoped> | ||||||
|  |   .wx-voice-div { | ||||||
|  |     padding: 5px; | ||||||
|  |     background-color: #eaeaea; | ||||||
|  |     border-radius: 10px; | ||||||
|  |   } | ||||||
|  |   .amr-duration { | ||||||
|  |     font-size: 11px; | ||||||
|  |     margin-left: 5px; | ||||||
|  |   } | ||||||
|  | </style> | ||||||
| @@ -70,7 +70,9 @@ | |||||||
|           </div> |           </div> | ||||||
|           <!-- 【消息】区域 --> |           <!-- 【消息】区域 --> | ||||||
|           <div v-else-if="scope.row.type === 'text'">{{ scope.row.content }}</div> |           <div v-else-if="scope.row.type === 'text'">{{ scope.row.content }}</div> | ||||||
|           <!-- TODO 语音 --> |           <div v-else-if="scope.row.type === 'voice'"> | ||||||
|  |             <wx-voice-player :url="scope.row.mediaUrl" :content="scope.row.recognition" /> | ||||||
|  |           </div> | ||||||
|           <div v-else-if="scope.row.type === 'image'"> |           <div v-else-if="scope.row.type === 'image'"> | ||||||
|             <a target="_blank" :href="scope.row.mediaUrl"> |             <a target="_blank" :href="scope.row.mediaUrl"> | ||||||
|               <img :src="scope.row.mediaUrl" style="width: 100px"> |               <img :src="scope.row.mediaUrl" style="width: 100px"> | ||||||
| @@ -154,12 +156,14 @@ import { | |||||||
| } from "@/api/mp/message"; | } from "@/api/mp/message"; | ||||||
| import Editor from '@/components/Editor/index.vue'; | import Editor from '@/components/Editor/index.vue'; | ||||||
| import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue'; | import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue'; | ||||||
|  | import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue'; | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: "WxFansMsg", |   name: "WxFansMsg", | ||||||
|   components: { |   components: { | ||||||
|     Editor, |     Editor, | ||||||
|     WxVideoPlayer, |     WxVideoPlayer, | ||||||
|  |     WxVoicePlayer | ||||||
|   }, |   }, | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|   | |||||||
| @@ -2327,6 +2327,18 @@ | |||||||
|   dependencies: |   dependencies: | ||||||
|     "tweetnacl" "^0.14.3" |     "tweetnacl" "^0.14.3" | ||||||
|  |  | ||||||
|  | "benz-amr-recorder@^1.1.5": | ||||||
|  |   "integrity" "sha512-NepctcNTsZHK8NxBb5uKO5p8S+xkbm+vD6GLSkCYdJeEsriexvgumLHpDkanX4QJBcLRMVtg16buWMs+gUPB3g==" | ||||||
|  |   "resolved" "https://registry.npmmirror.com/benz-amr-recorder/-/benz-amr-recorder-1.1.5.tgz" | ||||||
|  |   "version" "1.1.5" | ||||||
|  |   dependencies: | ||||||
|  |     "benz-recorderjs" "^1.0.5" | ||||||
|  |  | ||||||
|  | "benz-recorderjs@^1.0.5": | ||||||
|  |   "integrity" "sha512-EwedOQo9KLti7HxDi/eZY51PSRbAXnOdEZmLvJ6ro3QQSoF9Y3AXBt57MIllGvVz5vtFYMeikG+GD7qTm3+p9w==" | ||||||
|  |   "resolved" "https://registry.npmmirror.com/benz-recorderjs/-/benz-recorderjs-1.0.5.tgz" | ||||||
|  |   "version" "1.0.5" | ||||||
|  |  | ||||||
| "bfj@^6.1.1": | "bfj@^6.1.1": | ||||||
|   "integrity" "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==" |   "integrity" "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==" | ||||||
|   "resolved" "https://registry.npmmirror.com/bfj/-/bfj-6.1.2.tgz" |   "resolved" "https://registry.npmmirror.com/bfj/-/bfj-6.1.2.tgz" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV