vue 3.0 百行以内的代码实现一个简单的微信语音文件播放器

1,164 阅读2分钟

背景

很多企业都会有会话存档的需求,我们需要存储企业员工与客户的会话信息,并且可以展示、查询。其中常规的内容就包括:图片、文字、文件、语音、表情包…… 等等。

经过用户授权以后,他的会话数据我们可以通过企微的api获取到,我们获得的语音文件,是amr格式的音频文件。

故事就这么开始了

本来这个播放器,我是打算直接使用h5的<audio></audio>标签的, 但是看了一下文档发现,audio标签只支持wavmpg格式的音频。

所以就走到了命运的岔路口:

左边: 厚着脸皮求后端拿到amr文件的语音以后,转成支持播放的格式返回给我

右边: 在前端整一个amr音频播放器

机智如我,当然先选择了左边。

但是后端老哥就打开搜索引擎简单的看了两个搜索结果,就无情的拒绝了我:“这个后端不太好弄啊,我们的环境不支持。前端看看能不能整吧。”

可恶,看起来是两个岔路口,没想到左边竟然走两步就是一堵墙!

没办法啦,我只能走右边,看看能不能自己写。

正文

翻了十几个搜索结果,分析了一下可行性和难易程度之后,选择了使用benz-amr-recorder 插件,github地址.

  1. 下载依赖:

npm install benz-amr-recorder

  1. 创建一个播放组件:

AmrPlay.vue

  <template>
    <div class="amr-player">
      <span @click="palyUrl">[语音消息]{{ playerInfo.text }}</span>
    </div>
  </template>

  <script>
  import BenzAMRRecorder from 'benz-amr-recorder'
  import { reactive } from '@vue/reactivity'
  import { ElMessage } from 'element-plus'

  export default {
    name: 'AudioBlock',
    props: {
      amrUrl: { // 我们的amr语音文件的文件流url
        type: String,
        default: '',
      },
    },
    setup(props) {
      // 生命周期内创建一个amr对象
      const amr = new BenzAMRRecorder()

      // 我们的播放信息,用来控制播放器的文案以及判断播放器器的状态
      const playerInfo = reactive({
        text: '点击播放',
        status: 'init',
      })

      // 核心播放方法
      const palyUrl = () => {
        if (!BenzAMRRecorder.isPlaySupported()) {
          ElMessage.warning('您的浏览器不支持播放该语音文件!')
          return false
        }

        if (playerInfo.status === 'init') {
          // 初始化状态时,通过initWithUrl方法进行初始化文件并播放,切换播放状态并且更改文案
          amr.initWithUrl(props.amrUrl).then(() => {
            amr.play()
            playerInfo.text = '播放中...'
            playerInfo.status = 'playing'
          })
          // 设置播放结束后的状态信息
          amr.onEnded(function () {
            playerInfo.text = '重新播放'
            playerInfo.status = 'finishing'
          })
        } else if (playerInfo.status === 'playing') {
          // 正在播放中的时候点击,则设置为pausing状态
          amr.pause()
          playerInfo.text = '继续播放'
          playerInfo.status = 'pausing'
        } else if (playerInfo.status === 'pausing' || playerInfo.status === 'finishing') {
          // 当状态为暂停或者已完成播放时,点击继续播放或者重新开始播放
          amr.playOrResume()
          playerInfo.text = '播放中...'
          playerInfo.status = 'playing'
        }
      }
      return {
        palyUrl,
        playerInfo,
      }
    },
  }
  </script>

就这么简单!

故事的最后

其实在benz-amr-recorder的使用文档里,作者也很清楚的说明了:由于使用了 amr.js 做编码和解码,因此 js 文件(压缩后,未 gzip)接近 500 KB,使用前请考虑。 所以整个项目编译后,体积确实是很大哈……, 我的项目中通过rollup打包到生产后,整个查看会话存档的组件,达到了172kb!以下是编译文件中, benz-amr-recorder 部分的代码:

!!!本来想复制下来的,但是实在是太长了。还是算了。总之你们知道这个文件很大就是了…… 但是一百多k,对于web端来说也不是不能接受。并且整个项目是异步chunk分割之后,按需加载的。所以并不影响用户体验。

所以,本次任务还是圆满完成啦~