基于Vue的网页版录音并播放

最近项目中需要实现一个效果,需要在网页上录制音频,并上传给后台,后续还需要做语音识别处理。

下面的表格罗列了我的前端项目中所使用的框架以及插件(本项目基于Vue):

插件名称资源地址
ElementUIhttps://element.eleme.cn/#/zh-CN/
网页录音js插件(兼容主流浏览器,使用了感觉还可以的。IE?不存在的,一想到flash,恶心到吐了)https://github.com/streamproc/MediaStreamRecorder
网页播放器audio样式重写(国人写的插件nice,我尝试过使用有关外国友人的东西,我就呵呵了)https://github.com/trsoliu/vue-audio

下面是我实现的效果:

 下面重点介绍在实现的过程中需要注意的几个关键点:

1.vue中如何引入第三方的js库?

因为我们这里使用的录音库是第三方的js库,而本项目是基于vue的,在传统的web项目里,我们可以直接使用<script/>标签添加进去就行了,但是在这里这样的做法无疑是行不通的。我们需要对插件的源码作出调整,打开MediaStreamRecorder.js:

聪明的你发现了,我把这个插件放到了一个新建的文件夹下,专门用来存储第三方的js插件。下一步为了能够在我们的页面上使用这个插件,需要对源码作出调整:

小小的说明:因为这里我们录音主要使用了这个方法,所以只要修改MedaStreamRecorder就行了。下面需要export提供给外部文件使用。把源代码拉倒最底下:

编辑并保存。

2.页面上点击录音实现录音的功能按钮部分,是本人自己封装的小组件MRecorder,具体代码组织见下图:

下面的代码是我主要封装的内容:
 

<template>
  <div class="wrapper">
    <el-row>
      <el-col>
        <svg-icon :icon-class="(recording==true)?'ly_s1':'ly_s0'" :class="['mrecorder', {anirecorder: recording } ]" @click="handleClick"/>
      </el-col>
    </el-row>
    <el-row>
      <el-col>
        <span class="tip">{{ tiptext }}</span>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import { MediaStreamRecorder } from '@/external/MediaStreamRecorder.js'
export default {
  name: 'MRecorder',
  props: {
    timelimit: {
      default: 60, // 默认为1min
      type: Number
    },
    pushurl: {
      default: '', // 上传到服务器的路径
      type: String
    }
  },
  data() {
    return {
      mcounter: 0, // 累积时间
      recording: false, // 标记是否在录音
      intervaltimerid: '', // 间隔时间定时器编号
      tiptext: '点击录音', // 提示文字
      mediaRecorder: null, // 录音笔
      mediaConstraints: {
        audio: true
      }
    }
  },
  methods: {
    // 处理点击
    handleClick() {
      var that = this
      this.recording = !this.recording
      // 如果开始录音
      if (this.recording === true) {
        this.mcounter = 0
        this.tiptext = '录音中 ' + this.mcounter + 's'
        this.captureRecord()
        this.intervaltimerid = setInterval(() => {
          // 开始累积
          that.mcounter = that.mcounter + 1
          this.tiptext = '录音中 ' + that.mcounter + 's'
        }, 1000)
      } else { // 如果结束录音
        this.tiptext = '点击录音'
        this.mediaRecorder.stop()
        this.mediaRecorder.stream.stop()
      }
    },
    // 错误处理方法
    onMediaError(e) {
      console.log('阿偶~您的浏览器貌似不支持录音哦...', e)
      clearInterval(this.intervaltimerid)
      this.tiptext = '点击录音'
      this.recording = false
      this.$message.error('您的浏览器暂不支持录音功能')
    },
    // 成功
    onMediaSuccess(stream) {
      this.mediaRecorder = new MediaStreamRecorder(stream)
      // 获取音频流
      this.mediaRecorder.stream = stream
      this.mediaRecorder.mimeType = 'audio/wav'
      var _that = this
      this.mediaRecorder.ondataavailable = function(blob) {
        clearInterval(_that.intervaltimerid)
        const url = URL.createObjectURL(blob)
        _that.$emit('handleStop', {
          url: url,
          mblob: blob
        })
      }
      // 定义间隔
      this.mediaRecorder.start(this.timelimit * 1000)
    },
    // 开始记录方法
    captureRecord() {
      navigator.mediaDevices
        .getUserMedia(this.mediaConstraints)
        .then(this.onMediaSuccess)
        .catch(this.onMediaError)
    }
  }
}
</script>
<style scoped>
.wrapper {
    text-align: center;
}

.mrecorder {
    width:40px;
    height:40px;
    font-size:40px;
}

.anirecorder {
    position: relative;
    animation: mymove 5s infinite;
    -webkit-animation: mymove 5s infinite;
    animation-direction:alternate;
    animation-timing-function: ease-in-out;
    /*safari & chrome*/
    -webkit-animation-direction: alternate;
    -webkit-transition-timing-function: ease-in-out;
}

 @keyframes mymove
{
    0%{
    transform: scale(1);  /*开始为原始大小*/
    }
    25%{
        transform: scale(1.1); /*放大1.1倍*/
    }
    50%{
        transform: scale(0.9);
    }
    75%{
        transform: scale(1.1);
    }

}

@-webkit-keyframes mymove /*Safari and Chrome*/
{
    0%{
    transform: scale(1);  /*开始为原始大小*/
    }
    25%{
        transform: scale(1.1); /*放大1.1倍*/
    }
    50%{
        transform: scale(0.9);
    }
    75%{
        transform: scale(1.1);
    }
}

</style>

其实里面的功能并不复杂,应该很容能够看懂了。

最后再需要的页面上这样使用:

import MRecorder from '@/components/MRecorder'
 <!-- 录音笔 -->
 <MRecorder @handleStop="handelEndRecord" />
// 处理结束事件  
handelEndRecord(param) {
     console.log(param)
     this.msource = param.url
}

3.播放器的使用,因为传统的播放器ui会比较简陋,无法达到用户的体验效果。我试了好几个关于vue播放音频的,结果效果都不是很理想。这时候我都打算自己手写一个了,可是功夫不负有心人,一番费尽周折中找到了一个插件vue-audio。哎呀,就是我想要的效果啊!查看github上主页的介绍其实也很简单了(有空深入看一下人家怎么实现的,其实这个插件主要是对传统的<audio>的样式进行了一番改造,主要的知识点主要涉及audio控件相关事件的使用了,后续项目忙完后可以继续深入研究一下)

安装插件:

$ npm install vue-audio-native --save

在main.js中引入这个插件 

import vueAudioNative from 'vue-audio-native'
Vue.use(vueAudioNative)

页面中的用法:

 <vue-audio-native
     :url="msource"
     :show-current-time="true"
     :show-controls="false"
     :show-download="true"
     :autoplay="false"
     :wait-buffer="true"/>

附上介绍页面上的属性的配置:

好了以上就是主要内容了,赶紧尝试一波吧。

  • 11
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值