电脑浏览器录制出来的是webm音频编码格式、手机浏览器录制出来的是mp4音频编码格式。如后端指定格式需要把它们的音频编码格式转一下。以下,以转mp3音频编码格式为例。
首先我们先使用 npm 安装一下 js-audio-recorder 库。
npm i js-audio-recorder
还需要用到一个库 lamejs 这个npm下载的会有bug,也可以在node_modules修改bug,个人开发改改还行,多人开发还是算了。所以可以使用cdn来引入。注:可以把它下载到本地引入,这样就无关cdn的链接是否正常,都可使用。
<script src="https://cdn.jsdelivr.net/npm/lamejs@1.2.0/lame.all.js"></script>
一般需求都是长按录音。这里写一个开始触摸调用的方法。
下面有几个参数,比如 sampleRate (采样率)越低,录制的音频文件就越小。numChannels (声道) 1 就是单声道,2就是立体声,当然 1 的文件会小很多。
async startRecording() {
try {
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
throw new Error("当前浏览器不支持音频录制");
}
this.recorder = new Recorder({
sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
sampleRate: 8000, // 采样率,支持 11025、16000、22050、24000、44100、48000。
numChannels: 1, // 声道,支持 1 或 2, 默认是1
});
this.recorder.start();
} catch (error) {
// 如果拒绝 getUserMedia 会在这里返回错误
console.log("error", error);
}
},
这里是手指松开,结束长摁的方法。1、首先要把录音给停止了。2、调用下个版块的函数 wavToMp3 来把生成的音频处理成 mp3。3、下面数据有 Blob、URL、base64,看你需要哪种数据格式。
sendEndAudio() {
this.recorder.stop(); // 录音停止
let mp3Blob = this.wavToMp3( // blob 文件格式。
this.recorder.getWAV(),
this.recorder.getChannelData()
);
this.audioData = URL.createObjectURL(mp3Blob); // 转为链接,可以把它赋值给audio元素听一下效果。
this.blobToDataURI(mp3Blob, (base64) => { // 把 map3 Blob 文件转为 base64 格式。
console.log('base64=', base64)
})
this.recorder.stream.getTracks().forEach(track => track.stop()) // 这一步很关键,说完话,要把麦克风给释放掉。
},
wavToMp3 函数。注意:channels、sampleRate 要与上面的 new Recorder 的参数 numChannels、sampleRate 一致。要不然编译出来的音频听着很怪。
wavToMp3(recorderData) {
const channels = 1; // 1 单声道 2 立体声
const sampleRate = 8000; // 采样率
const kbps = 128; // 128kbps mp3
var mp3encoder = new lamejs.Mp3Encoder(channels, sampleRate, kbps); // 初始化 MP3 编码器
var mp3Data = [];
var samples = new Int16Array(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(); // 完成map3音频编码的编写
if (mp3buf.length > 0) {
mp3Data.push(new Int8Array(mp3buf));
}
var blob = new Blob(mp3Data, { type: "audio/mp3" });
return blob; // 返回这个 map3 的 Blob 对象
},
把 Blob 转为 base64 格式。
blobToDataURI(blob, callback) {
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function (e) {
callback(e.target.result);
};
},