前端录入音频并上传 (插件 recorder-core)

纯 js 实现(有问题)

上传音频文件时 blob 数据中 size 一直是0,导致上传之后音频不可播放(本地录制后本地是可以播放的)在这里插入图片描述

<template>
  <div>
    <button v-if="!isRecording" @click="startRecording">开始录音</button>
    <button v-else @click="stopRecording">停止录音</button>
    <audio v-show="recordedAudio" ref="audioPlayer" controls></audio>
    <!-- <audio src="./法老-百变酒精.mp3" controls></audio> -->
  </div>
</template>

<script>
import { UploadOssFiles } from '@/api/service'

export default {
  data() {
    return {
      isRecording: false,
      recordedAudio: null,
      mediaRecorder: null,
      chunks: []
    }
  },
  methods: {
    startRecording() {
      navigator.mediaDevices
        .getUserMedia({ audio: true })
        .then((stream) => {
          this.isRecording = true
          this.mediaRecorder = new MediaRecorder(stream)
          this.mediaRecorder.addEventListener('dataavailable', this.handleDataAvailable)
          this.mediaRecorder.start()
        })
        .catch((error) => {
          console.error('无法访问麦克风:', error)
        })
    },
    stopRecording() {
      this.isRecording = false
      this.mediaRecorder.stop()
      // this.mediaRecorder.state = 'inactive'

      const blob = new Blob(this.chunks, { type: 'audio/webm' })
      // const blob = new Blob(this.chunks, { type: 'audio/mp3' })
      console.log('blob----', blob)
      const formData = new FormData()
      // formData.append('audio', blob, 'recording.webm')
      formData.append('files', blob, 'recording.webm')
      // formData.append('files', blob, 'recording.mp3')
      // 发送音频数据到后端的API接口
      UploadOssFiles(formData)
        .then((response) => {
          // 处理后端返回的响应
        })
        .catch((error) => {
          // 处理请求错误
        })
    },
    handleDataAvailable(event) {
      this.chunks.push(event.data)
      if (this.mediaRecorder.state === 'inactive') {
        this.processRecordedAudio()
      }
    },
    processRecordedAudio() {
      const blob = new Blob(this.chunks, { type: 'audio/webm' })
      // const blob = new Blob(this.chunks, { type: 'audio/mp3' })
      this.recordedAudio = URL.createObjectURL(blob)
      console.log('this.recordedAudio----', this.recordedAudio)
      this.$refs.audioPlayer.src = this.recordedAudio
    }
  }
}
</script>

代码来源

使用插件 recorder-core (没问题)

在这里插入图片描述

<template>
  <div>
    <!-- 按钮 -->
    <button @click="recOpen">打开录音,请求权限</button>
    | <button @click="recStart">开始录音</button> | <button @click="recStop">结束录音</button> |
    <button @click="recPlay">本地试听</button>
    <div style="padding-top: 5px">
      <!-- 波形绘制区域 -->
      <div style="border: 1px solid #ccc; display: inline-block; vertical-align: bottom">
        <div ref="recwave" style="height: 100px; width: 300px" />
      </div>
    </div>
  </div>
</template>

<script>
import { UploadOssFiles } from '@/api/service'

// 必须引入的核心
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'

// ts import 提示:npm包内已自带了.d.ts声明文件(不过是any类型)

export default {
  name: '',
  components: {},

  data() {
    return {
      rec: null,
      recBlob: null,
      wave: null
    }
  },

  methods: {
    // 申请录音权限
    recOpen() {
      // 创建录音对象
      this.rec = Recorder({
        type: 'mp3', // 录音格式,可以换成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 })
          }
        },
        (msg, isUserNotAllow) => {
          // 用户拒绝了录音权限,或者浏览器不支持录音
          console.log((isUserNotAllow ? 'UserNotAllow,' : '') + '无法录音:' + msg)
        }
      )
    },
    // 开始录音
    recStart() {
      if (!this.rec) {
        console.error('未打开录音')
        return
      }
      this.rec.start()
      console.log('已开始录音')
    },
    // 结束录音
    recStop() {
      if (!this.rec) {
        console.error('未打开录音')
        return
      }
      this.rec.stop(
        (blob, duration) => {
          // blob就是我们要的录音文件对象,可以上传,或者本地播放
          this.recBlob = blob
          // 简单利用URL生成本地文件地址,此地址只能本地使用,比如赋值给audio.src进行播放,赋值给a.href然后a.click()进行下载(a需提供download="xxx.mp3"属性)
          var localUrl = (window.URL || webkitURL).createObjectURL(blob)
          console.log('录音成功', blob, localUrl, '时长:' + duration + 'ms')

          this.upload(blob) // 把blob文件上传到服务器

          this.rec.close() // 关闭录音,释放录音资源,当然可以不释放,后面可以连续调用start
          this.rec = null
        },
        (err) => {
          console.error('结束录音出错:' + err)
          this.rec.close() // 关闭录音,释放录音资源,当然可以不释放,后面可以连续调用start
          this.rec = null
        }
      )
    },
    // 上传录音
    upload(blob) {
      console.log('blob----', blob)
      // 使用FormData用multipart/form-data表单上传文件
      // 或者将blob文件用FileReader转成base64纯文本编码,使用普通application/x-www-form-urlencoded表单上传
      var form = new FormData()
      form.append('files', blob, 'recorder.mp3') // 和普通form表单并无二致,后端接收到upfile参数的文件,文件名为recorder.mp3

      UploadOssFiles(form)
        .then((response) => {
          // 处理后端返回的响应
        })
        .catch((error) => {
          // 处理请求错误
        })
    },
    // 本地播放录音
    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)
    }
  }
}
</script>

<style lang='scss' scoped>
</style>

代码来源

封装 mixins

import { UploadOssFiles } from '@/api/service'

// 必须引入的核心
import Recorder from 'recorder-core'

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

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

// ts import 提示:npm包内已自带了.d.ts声明文件(不过是any类型)

export const soundRecordingMixins = {
  name: '',
  components: {},

  data() {
    return {
      rec: null,
      wave: null,
      isSoundRecording: false,
      rowData: {},
      audioDuration: ''
    }
  },

  methods: {
    // 申请录音权限
    recOpen() {
      // 创建录音对象
      this.rec = Recorder({
        // type: 'mp3',
        type: '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('rec.open------', '录音已打开')
          this.recStart()
          if (this.$refs.recwave) {
            // 创建音频可视化图形绘制对象
            this.wave = Recorder.WaveView({ elem: this.$refs.recwave })
          }
        },
        (msg, isUserNotAllow) => {
          // 用户拒绝了录音权限,或者浏览器不支持录音
          console.log((isUserNotAllow ? 'UserNotAllow,' : '') + '无法录音:' + msg)
          this.$message.error('暂无录音权限,请稍后再试!')
        }
      )
    },
    // 开始录音
    recStart() {
      if (!this.rec) {
        console.error('未打开录音')
        return
      }
      this.$message.success('开始录入声纹')
      this.rec.start()
      this.isSoundRecording = true
    },
    // 结束录音
    recStop() {
      this.isSoundRecording = false
      if (!this.rec) {
        console.error('未打开录音')
        return
      }
      this.rec.stop(
        (blob, duration) => {
          // this.audioSrc = URL.createObjectURL(blob)

          this.$message.success('声纹录入完成')
          this.audioDuration = duration / 1000

          this.uploadOssHandler(blob) // 把blob文件上传到服务器

          this.rec.close() // 关闭录音,释放录音资源,当然可以不释放,后面可以连续调用start
          this.rec = null
        },
        (err) => {
          this.$message.error('声纹录入失败,请重试!')
          console.error('结束录音出错:' + err)
          this.rec.close() // 关闭录音,释放录音资源,当然可以不释放,后面可以连续调用start
          this.rec = null
        }
      )
    },
    // 上传录音
    uploadOssHandler(blob) {
      var form = new FormData()
      form.append('relativePath', 'voiceprint/')
      // form.append('files', blob, `${this.rowData.xm + +new Date()}.mp3`)
      form.append('files', blob, `${this.rowData.xm + +new Date()}.wav`)

      UploadOssFiles(form)
        .then((response) => {
          if (response.data && !response.data.fileUploadInfoList.length) {
            this.$message.error(`声纹上传失败,请重试!`)
            this.fileList = []
          }
          // 处理后端返回的响应
          const fileList = response.data.fileUploadInfoList
            ? response.data.fileUploadInfoList.map((item) => {
                return {
                  wjmc: item.filename,
                  wjlj: item.path,
                  wjgs: item.fileType
                }
              })
            : []

          this.voiceprintImportList = []
          this.voiceprintImportList.push(...fileList)
          this.fileList = []
          this.audioSrc = this.sysConfigData.mon_sys_ossurl + this.voiceprintImportList[0].wjlj
          this.addVoiceHandler()
        })
        .catch((error) => {
          console.log('error----', error)
          this.$message.error('声纹上传失败!')
        })
    }
  }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 安装 recorder-js 可以通过 npm 包管理工具进行安装: ``` npm install recorder-js ``` 2. 导入 recorder-js 在需要使用 recorder-js 的文件中,可以通过以下方式导入 recorder-js: ``` import Recorder from 'recorder-js'; ``` 3. 创建 Recorder 实例 创建 Recorder 实例的方式如下: ``` const recorder = new Recorder({ sampleRate: 44100, numChannels: 2, }); ``` 在创建实例时,可以传递一个包含采样率和声道数的配置对象。 4. 开始录制 要开始录制,可以使用 Recorder 实例的 `start` 方法: ``` recorder.start(); ``` 5. 停止录制 停止录制可以使用 Recorder 实例的 `stop` 方法: ``` recorder.stop(); ``` 6. 导出录制的音频 可以使用 Recorder 实例的 `exportWAV` 方法导出录制的音频文件: ``` recorder.exportWAV((blob) => { const url = URL.createObjectURL(blob); // do something with the audio blob URL }); ``` 在导出音频时,需要传递一个回调函数,该函数接收一个包含音频文件数据的 Blob 对象。可以使用 `URL.createObjectURL` 方法将 Blob 对象转换为可用于播放或下载的 URL。 7. 可选步骤:添加事件监听器 可以为 Recorder 实例添加事件监听器,以便在录制或导出音频时获取一些状态或错误信息。例如,可以添加 `dataAvailable` 事件监听器,在导出音频时获取 Blob 对象: ``` recorder.addEventListener('dataAvailable', (e) => { const url = URL.createObjectURL(e.detail); // do something with the audio blob URL }); ``` 8. 完整示例 以下是一个使用 recorder-js 录制音频并导出音频文件的完整示例: ``` import Recorder from 'recorder-js'; const recorder = new Recorder({ sampleRate: 44100, numChannels: 2, }); let isRecording = false; // start recording document.getElementById('start').addEventListener('click', () => { isRecording = true; recorder.start(); }); // stop recording and export audio document.getElementById('stop').addEventListener('click', () => { isRecording = false; recorder.stop(); }); // export audio when data is available recorder.addEventListener('dataAvailable', (e) => { const url = URL.createObjectURL(e.detail); // do something with the audio blob URL }); // continuously record audio while isRecording is true recorder.addEventListener('dataAvailable', (e) => { if (isRecording) { recorder.start(); } }); // play recorded audio document.getElementById('play').addEventListener('click', () => { recorder.exportWAV((blob) => { const url = URL.createObjectURL(blob); const audio = new Audio(url); audio.play(); }); }); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值