本文背景是需要通过浏览器进行录音,生成可供百度语音识别api使用的pcm音频文件,根据百度语音识别api文档要求,音频文件为pcm格式,单音道,16k采样率,16位深。本文仅就以上功能做最基本的实现。
1.三个基本概念
音频源,也就是音频输入,可以是直接从设备输入的音频,也可以是远程获取的音频文件。
处理节点,分析器和处理器,比如音调节点,音量节点,声音处理节点。
输出源,指音频渲染设备,一般情况下是用户设备的扬声器,即context.destination。其实,音频源和输出源也都可以视为节点,这三者的关系可以用这张图表示:
注:1.AudioContext的详细介绍可以参考AudioContext说明文档
2.实际使用中可以存在多个处理节点,都可以使用connect依次关联起来
3.输入源和输出源实质上也是节点,整个音频处理的过程就是每经过一个节点,就对音频信号做一次处理
2.使用Web Audio进行录音
按照上述流程顺序,依次讲解录音过程
2.1 输入源 getUserMedia
首先调用用户的麦克风设备,需要用到navigator.mediaDevices.getUserMedia()
这个方法,该方法会返回一个promise,成功回调的参数是一个MediaStream对象,该对象就是麦克风采集的语音。
然后该MediaStream流媒体对象需要传入createMediaStreamSource()方法中,用于创建一个新的MediaStreamAudioSourceNode对象,也就是创建了一个输入源节点,从而使得来自MediaStream的音频可以被播放和操作。
navigator.mediaDevices.getUserMedia({
audio: true }).then(function (stream) {
// 务必分开写then
var audioContext = new AudioContext()
var sourceNode = audioContext.createMediaStreamSource(stream) //sourceNode就是得到的输入源节点
})
2.2 处理节点createScriptProcessor
createScriptProcessor()方法用于创建一个处理节点,该处理节点有三个参数:
- bufferSize,缓冲区大小,以样本帧为单位。一般有以下值 256,512,1024,2048,4096,8192,16384。当传0时,系统会取当前环境最合适的缓冲区大小。每当缓冲区满时,则会触发audioprocess事件,即bufferSize控制着回调事件的频率。注:mdn提示 chrome 31版本的不支持传0的方式。
- numberOfInputChannels,值为整数,用于指定输入node的声道的数量,默认值是2,最高能为32,且不能为0。
- numberOfOutputChannels,值为整数,用于指定输出node的声道的数量,默认值是2,最高能取32,不能为0。
由于百度语音识别api要求使用单音道,且采样率为16k,位深为16bit;而实际麦克风的录音的采样率为44.1k,双音道,故需要对输入源的音频进行处理,即通过监听onaudioprocess即可对音频信号进行处理
var scriptNode = audioContext.createScriptProcessor(4096, 1, 1)
scriptNode.onaudioprocess = event => {
audioData.input(event.inputBuffer.getChannelData(0)) //取单音道信号
}
//对音频信号进行处理
var audioData = {
size: 0,
buffer: [],
input: function (data) {
this.buffer.push(new Float32Array((data)))
this.size += data.length
},
//得到格式为pcm,采样率为16k,位深为16bit的音频文件
getData: function () {
var sampleBits = 16
var inputSampleRate = 44100
var outputSampleRate = 16000
var bytes = this.decompress(this.buffer, this.size, inputSampleRate, outputSampleRate)
var dataLen = bytes.length * (sampleBits /