接上篇,说到第一步获取本地音频流,咱们都知道,H5有一个新增的接口专门来处理音频流相关方法,他就是大名鼎鼎的AudioContext
,至于这个对象具体能作什么,各位看官自行百度。我这边主要用到的是createMediaStreamSource
方法createScriptProcessor
方法,createMediaStreamDestination
方法。此三个方法最终能够获取到咱们想要的本地设备拉出来的音频流,代码以下 :浏览器
let ac =new AudioContext(); let source = this.ac.createMediaStreamSource(stream); let scriptNode =ac.createScriptProcessor(2048, 1, 1); let dest = this.ac.createMediaStreamDestination();
//当你想触发音频采集时候,就执行下面两行代码 source.connect(scriptNode); scriptNode.connect(dest);
而后scriptNode有一个方法onaudioprocess
能够监听到音频流采样函数
scriptNode.onaudioprocess = (audioProcessingEvent) => { const { inputBuffer } = audioProcessingEvent; const inputData = inputBuffer.getChannelData(0); }
这里咱们能够获得inputData.sampleRate
这个是音频流的采样率,通常默认是44000,而后到这里咱们基本就完成了第一步,拿到音频流以及音频流的采样率。知识点不足的各位自行百度恶补。this
接着第二步骤,由于浏览器拉出来的音频流的采样率过高,会给传输带来压力,再说也不须要那么高的采样率,和后台商定采样率定为8K,那接下来就是压缩采样率编码
function compress(sampleRate, data) { if (sampleRate < outSampleRate) return data; const compressRatio = Math.floor(sampleRate / outSampleRate); const compressLen = data.length / compressRatio; const result = new Float32Array(compressLen); let index = 0; let k = 0; while (index < compressLen) { result[index] = data[k]; k += compressRatio; index++; } return result; }
以上代码相信你们都看得懂,sampleRate就是咱们获得的 44000的音频采样率,data就是咱们前面获得的inputData,这个函数方法return的东西就是咱们压缩后的8K的采样率code
接下来就是最重要的一步,封装FLV格式,FLV格式比较简单,前面都有一个flv的头占9位,而后4位默认都是0的previouSize(默认第一个都是0)。接下来都是tag数据,tag数据氛围两个部分tagheader,封装了一些tagdata信息 占11位,tagData第一位为解码数据,剩下的就是音频数据,最后四位为previouseSize,为data数据的大小。
以上就是基本的概念,接下来就是封装了上代码:对象
const payloadLen = data.length * 1; const buffer = (tagCount == 0)? new ArrayBuffer(9 + 4 + 11 + 1 + payloadLen + 4): new ArrayBuffer(11 + 1 + payloadLen + 4); const output = new DataView(buffer); setFlvHeader(output, payloadLen, tagCount); //flv 流 tagCount默认为0
以上就是压缩代码了,经过setFlvHeader的方法,能够把咱们的音频流进行flv的片断封装。接口
接下来也是重要的一步,进行g711a编码封装,上代码 :ip
let offset = tagCount == 0 ? 25 : 12; for (let i = 0; i < data.length; i++, offset += 1) { const s = Math.max(-1, Math.min(1, data[i])); const int16 = s < 0 ? s * 0x8000 : s * 0x7FFF; const alawUint8 = encodeALawSample(int16); output.setUint8(offset, alawUint8); }
由于咱们是先封装格式,再进行编码压缩,因此根据tagCount,咱们有一个offset的变量来记录编码位置。咱们先把32位浮点类型转成16位int型,再而后经过方法encodeAlowSample方法进行编码操做。
最后咱们获得的就是 g711a编码 而且有flv格式封装的音频流了get