MediaRecorder语音输入转wav格式,可设置采样率

项目中需要语音录入,以及转为wav格式进行后端提取语音文字,强制转wav格式不能满足需求,所以记录一下解决方法

 if (window.navigator.mediaDevices.getUserMedia) {
        const constraints = { audio: true };
        window.navigator.mediaDevices.getUserMedia(constraints).then(
          stream => {
            console.log("授权成功!");
             //绑定点击按钮
            const recordBtn = document.querySelector(".record-btn");
            const mediaRecorder = new MediaRecorder(stream);
            recordBtn.onclick = () => {
              mediaRecorder.start();
              console.log("录音中...");
            };
            recordBtn.onclick = () => {
              if (mediaRecorder.state === "recording") {
                mediaRecorder.stop();
                recordBtn.textContent = "开始录音";
                console.log("录音结束");
              } else {
                mediaRecorder.start();
                console.log("录音中...");
                recordBtn.textContent = "停止录音";
              }
              console.log("录音器状态:", mediaRecorder.state);
            };
            this.chunks = [];
            mediaRecorder.ondataavailable = (e) => {
              console.log(e.data, 'e')
              this.chunks.push(e.data);
            };
            mediaRecorder.onstop = e => {
              const reader = new FileReader();
              reader.onload = async (event) => {
               //设置采样率为16000,不设置会根据浏览器自己来判断设置
                const audioContext = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: 16000 });
                const arrayBuffer = event.target.result;
                const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
                //设置wav的头
                const wavData = encodeWAV(audioBuffer);
                const wavBlob = new Blob([wavData], { type: 'audio/wav' });
                const formData = new FormData();
                formData.append('file', wavBlob, 'recording.wav');
                 //生成本地的访问地址
                var audioURL = window.URL.createObjectURL(wavBlob);
                console.log(audioURL, 'audioURL')
                this.chunks = [];
                //调用接口存储
                uploadFileSystem(formData).then(res => {
                  if (res.data.code == 0) {
                    this.chunks = [];
                    this.message.videoUrl = res.data.data;
                    ElMessage({
                      type: 'success',
                      message: '语音录入成功',
                    })
                  } else {
                    ElMessage({
                      type: 'error',
                      message: '语音上传失败,请重试',
                    })
                    this.chunks = [];
                  }
                })

              };
              reader.readAsArrayBuffer(this.chunks[0]);
              function encodeWAV(audioBuffer) {
                const numOfChan = audioBuffer.numberOfChannels,
                  length = audioBuffer.length * numOfChan * 2 + 44,
                  buffer = new ArrayBuffer(length),
                  view = new DataView(buffer),
                  sampleRate = audioBuffer.sampleRate,
                  samples = audioBuffer.getChannelData(0);
                let offset = 0;
                const writeString = (str) => {
                  for (let i = 0; i < str.length; i++) {
                    view.setUint8(offset++, str.charCodeAt(i));
                  }

                };
                writeString('RIFF');
                view.setUint32(offset, length - 8, true);
                offset += 4;
                writeString('WAVE');
                writeString('fmt ');
                view.setUint32(offset, 16, true);
                offset += 4;
                view.setUint16(offset, 1, true);
                offset += 2;
                view.setUint16(offset, numOfChan, true);
                offset += 2;
                view.setUint32(offset, sampleRate, true);
                offset += 4;
                view.setUint32(offset, sampleRate * 2 * numOfChan, true);
                offset += 4;
                view.setUint16(offset, numOfChan * 2, true);
                offset += 2;
                view.setUint16(offset, 16, true);
                offset += 2;
                writeString('data');
                view.setUint32(offset, length - offset - 8, true);
                offset += 4;
                for (let i = 0; i < samples.length; i++) {
                  view.setInt16(offset, samples[i] * 0x7FFF, true);
                  offset += 2;
                }
                return view;
              }
            };

          }
          () => {
            console.error("授权失败!");
          }

        );

      } else {
        console.error("浏览器不支持 getUserMedia");
      }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值