VUE pc端+移动端上传录音并上传(recorder-core)

首先安装 npm install recorder-core

以下录音组件完整代码可复用

<template>
  <div>
    <div>
      <img
        v-if="!isSound"
        src="@/assets/images/mobile/mobileDoWork/answer_question_voice_icon.png"
        alt=""
        @click="recStart"
      />
      <div
        v-else
        class="flexCenter"
        style="padding-top: 1px;color:#707070;cursor: pointer;"
        @click="recStop"
      >
        <img
          style="width:24px;height:24px;margin:0 5px 0 0;"
          src="@/assets/images/mobile/mobileDoWork/answer_question_voice_pause_icon.png"
          alt=""
        />
        暂停录音
      </div>
      <span v-if="!isSound">语音</span>
      <!--<button @click="recPlay">本地试听</button> -->
    </div>
    <div>
      <div
        v-show="isSound"
        style="padding-top: 6px"
      >
        <!-- 波形绘制区域 -->
        <div style="
            border: 1px solid #ccc;
            display: inline-block;
            vertical-align: bottom;
            border-radius: 80px;
            padding: 0 10px;
          ">
          <div
            ref="recwave"
            style="height: 40px; width: 248px"
          />
        </div>
      </div>
      <!-- <audio v-if="localUrl && !isSound" :src="localUrl" controls /> -->
    </div>
  </div>
</template>
<script>
// 引用后台上传接口
import upload from '@/api/upload.js'

import Recorder from 'recorder-core'

// 引入mp3格式支持文件;如果需要多个格式支持,把这些格式的编码引擎js文件放到后面统统引入进来即可
import 'recorder-core/src/engine/mp3'
import 'recorder-core/src/engine/mp3-engine'
// 录制wav格式的用这一句就行
import 'recorder-core/src/engine/wav'

// 可选的插件支持项,这个是波形可视化插件
import 'recorder-core/src/extensions/waveview'

export default {
  name: 'sound',
  components: {},
  props: {},
  data () {
    return {
      localUrl: '', // 本地试听录音文件
      isSound: false, // 是否录制完成
      isStop: false // 是否停止录制
    }
  },
  watch: {},
  computed: {},
  mounted () { },
  methods: {
    // 开始录音
    recStart () {
      this.isSound = true
      // 创建录音对象
      this.rec = Recorder({
        type: 'wav', // 录音格式,可以换成wav等其他格式
        sampleRate: 16000, // 录音的采样率,越大细节越丰富越细腻
        bitRate: 16, // 录音的比特率,越大音质越好
        onProcess: (
          buffers,
          powerLevel,
          bufferDuration,
          bufferSampleRate,
          newBufferIdx,
          asyncEnd
        ) => {
          // 录音实时回调,大约1秒调用12次本回调
          // 可实时绘制波形,实时上传(发送)数据
          if (this.wave) {
            this.wave.input(
              buffers[buffers.length - 1],
              powerLevel,
              bufferSampleRate
            )
          }
        }
      })

      // 打开录音,获得权限
      this.rec.open(
        () => {
          console.log('录音已打开')
          if (this.$refs.recwave) {
            // 创建音频可视化图形绘制对象
            this.wave = Recorder.WaveView({ elem: this.$refs.recwave })
          }
          this.rec.start()
          this.$toast({
            message: '已开始录音',
            type: 'success'
          })
        },
        (msg, isUserNotAllow) => {
          // 用户拒绝了录音权限,或者浏览器不支持录音
          this.isSound = false
          this.$toast({
            message: (isUserNotAllow ? 'UserNotAllow,' : '') + msg,
            type: 'fail'
          })
        }
      )
      if (!this.rec) {
        this.isSound = false
        this.$toast({
          message: '未打开录音',
          type: 'fail'
        })
        return
      }
    },
    // 结束录音
    recStop () {
      // 控制频繁点击暂停录制按钮导致报错问题
      if (this.isStop) {
        return
      }
      if (!this.rec) {
        this.isSound = false
        this.$toast({
          message: '未打开录音',
          type: 'fail'
        })
        return
      }
      // envInLast 录制结束时间   envInFirst 录制开始时间
      var time = this.rec.envInLast - this.rec.envInFirst
      console.log('sound 【共录制time:', time, 'ms】')
      // 获取录制时间 需求至少录制三秒
      if (time < 3000) {
        this.$toast({
          message: '至少录制三秒',
          type: 'fail'
        })
        return
      } else {
        this.$toast.clear()
        this.isStop = true
      }
      this.rec.stop(
        (blob, duration) => {
          this.$emit('loadingTrue')
          // blob就是我们要的录音文件对象,可以上传,或者本地播放
          this.recBlob = blob
          // 简单利用URL生成本地文件地址,此地址只能本地使用,比如赋值给audio.src进行播放,赋值给a.href然后a.click()进行下载(a需提供download="xxx.mp3"属性)
          this.localUrl = URL.createObjectURL(blob)
          console.log('录音成功blob', blob)
          // console.log('localUrl', this.localUrl)
          console.log('时长:' + duration + 'ms')

          this.upload(blob, this.localUrl) // 把blob文件上传到服务器(请求后台接口)
        },
        (err) => {
          console.error('结束录音出错:' + err)
          this.isSound = false
          this.$toast({
            message: '结束录音出错:' + err,
            type: 'fail'
          })
          this.reset('now')
        }
      )
    },
    // 上传录音
    upload (blob, localUrl) {
      var params = new FormData()
      params.append('file', blob)
      params.append('token', decodeURIComponent(JSON.parse(window.localStorage.getItem('token')).value))
      // 请求后台上传接口
      upload
        .upload(params)
        .then((res) => {
          console.log('data', res.data)
          var obj = {
            voice_url: res.data.url,
            voice_duration: res.data.time
          }
          // 给父页面传值 页面赋值
          this.$emit('onMenu', 1, obj)
          this.isSound = false
          this.$emit('loadingFalse')
          this.reset('now')
        })
        .catch((err) => {
          this.isSound = false
          this.$emit('loadingFalse')
          this.$toast({
            message: '语音上传失败' + err.message,
            type: 'fail'
          })
          this.reset('now')
        })
    },
    // 本地试听
    recPlay () {
      // 本地播放录音试听,可以直接用URL把blob转换成本地播放地址,用audio进行播放
      var localUrl = URL.createObjectURL(this.recBlob)
      var audio = document.createElement('audio')
      audio.controls = true
      document.body.appendChild(audio)
      audio.src = localUrl
      audio.play() // 这样就能播放了

      // 注意不用了时需要revokeObjectURL,否则霸占内存
      setTimeout(function () {
        URL.revokeObjectURL(audio.src)
      }, 5000)
    },
    // 重置
    reset (type) {
      // 当在录音时 如页面退出需重置否则再次进入页面录音会报错(同时清除toast提示)
      if (!type) {
        this.$toast.clear()
      }
      if (this.rec) {
        this.rec.close() // 关闭录音,释放录音资源,当然可以不释放,后面可以连续调用start
        this.rec = null
        this.isStop = false
        this.isSound = false
      }
    }
  }
}
</script>
<style lang="scss" scoped>
i {
  color: #707070;
  font-size: 26px;
}
img {
  width: 27px;
  height: 27px;
  cursor: pointer;
  margin-bottom: 2px;
}
</style>

父页面引用该组件:

<template>
  <div class="upload_media_box">
    <Sound
      ref="sound"
    />
  </div>
</template>

<script>
import Sound from '@/components/sound'
export default {
  components: {
    Sound
  },
  methods: {
    // 停止录音
    resetSound () {
      this.$nextTick(() => {
        this.$refs.sound.reset()
      })
    },
  },
}
</script>

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>