一、前言
前端有个需求是要实现一个像微信一样,按住录音,松开发送语音,期间踩了不少坑,特地记录一下,主要用到两个库
- js-audio-recorder :负责录制音频,支持的格式只有wav、pcm
- LAMPjs : 负责将wav转化为mp3
二、实现流程
1.安装库
# lampjs一定要安装1.2.0这个版本,最新版本少了一个库,后面会报错说MPEGMode is not defined"npminstall [email protected]
npminstall js-audio-recorder
2.代码
首先开启权限,本地locallhost是支持获取的,但是放到服务器没有http的话,getUserMedia是获取不到这个函数,有两种办法,一个是服务器换https协议,另一个就是设置一下浏览器:
- chrome地址栏输入:chrome://flags/#unsafely-treat-insecure-origin-as-secure
- edge地址栏输入:edge://flags/#unsafely-treat-insecure-origin-as-secure
- 开启权限,然后在灰色框框里输入你的网站访问地址,如 http:xxxxxxx/3060
初始化一下Recorder,判断一下是否存在录音权限
initRecorder(){// 服务器需要https协议或者设置一下浏览器if(typeof(navigator.mediaDevices.getUserMedia)=="undefined"){this.$message.error('当前没有语音权限!')return}if(navigator.mediaDevices.getUserMedia){const constraints ={audio:true}; navigator.mediaDevices.getUserMedia(constraints).then(()=>{ console.log("授权成功!");},()=>{ console.error("授权失败!");});}else{ console.error("浏览器不支持 getUserMedia");}this.recorder =newRecorder({sampleBits:16,// 采样位数,支持 8 或 16,默认是16sampleRate:16000,// 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000numChannels:1,// 声道,支持 1 或 2, 默认是1});},
按钮监听mousedown和mouseup事件执行函数,按下的时候弹出正在speaking,抬起就处理数据然后发送给后端
<el-buttonicon="el-icon-mic"@mousedown.native="onSpeak"@mouseup.native="sendSpeak"circle></el-button>
// 录音喊话onSpeak(){this.recorder.start().then(function(){this.$message('speaking...')});},sendSpeak(){// 结束录音this.recorder.stop();// 录音播放this.recorder.play();// 获取 WAV 数据(Blob)// let blob = this.recorder.getWAVBlob();// 将WAV转化,获取 MP3 数据(Blob),函数wavToMp3、blobToBase64见下两个代码块const mp3Blob =wavToMp3(this.recorder.getWAV(),this.recorder.getChannelData());this.blobToBase64(mp3Blob).then(stream=>{
console.log('语音打印', stream)// 下面发送数据})},
wav转化为mp3函数wavToMp3
exportconstwavToMp3=function(recorderData){// new Int16Array(this.recorder.getWAV().buffer) 取录音的bufferconst channels =1;//1 单声道 2 立体声const sampleRate =44100;//44.1khzconst kbps =128;//128kbps mp3var mp3encoder =newlamejs.Mp3Encoder(channels, sampleRate, kbps);var mp3Data =[];var samples =newInt16Array(recorderData.buffer);// 从源中获取数据const sampleBlockSize =1152;//576的倍数for(var i =0; i < samples.length; i += sampleBlockSize){var sampleChunk = samples.subarray(i, i + sampleBlockSize);const mp3buf = mp3encoder.encodeBuffer(sampleChunk);if(mp3buf.length >0){
mp3Data.push(mp3buf);}}var mp3buf = mp3encoder.flush();//finish writing mp3if(mp3buf.length >0){
mp3Data.push(newInt8Array(mp3buf));}var blob =newBlob(mp3Data,{type:'audio/mp3'});return blob;}
Blob转Base64函数
blobToBase64(blob){returnnewPromise((resolve, reject)=>{const fileReader =newFileReader();
fileReader.onload=(e)=>{resolve(e.target.result);};
fileReader.readAsDataURL(blob);
fileReader.onerror=()=>{reject(newError('blobToBase64 error'));};});},
三、参考
- vue实现录音功能js-audio-recorder带波浪图
- 录音为wav格式转mp3格式
- (前端)录音功能实现js-audio-recorder
版权归原作者 GIS_宇宙 所有, 如有侵权,请联系我们删除。