Commit 94178998e541d4c829294a1b2dfab5f68e5e2c18

Authored by YunaiV
1 parent 8a5db8c1

mp:前端 message 增加 voice 语音的播放

yudao-ui-admin/package.json
... ... @@ -43,6 +43,7 @@
43 43 "@babel/parser": "7.18.4",
44 44 "@riophae/vue-treeselect": "0.4.0",
45 45 "axios": "0.27.2",
  46 + "benz-amr-recorder": "^1.1.5",
46 47 "bpmn-js-token-simulation": "0.10.0",
47 48 "clipboard": "2.0.8",
48 49 "core-js": "^3.26.0",
... ...
yudao-ui-admin/src/views/mp/components/wx-video-play/main.vue
1 1 <!--
2 2 - Copyright (C) 2018-2019
3 3 - All rights reserved, Designed By www.joolun.com
4   - 芋艿:
  4 + 芋道源码:
5 5 ① bug 修复:
6 6 1)joolun 的做法:使用 mediaId 从微信公众号,下载对应的 mp4 素材,从而播放内容;
7 7 存在的问题:mediaId 有效期是 3 天,超过时间后无法播放
... ...
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"
... ...