你猜猜JS 如何进行音频流的编码封装?下

接上篇,说到第一步获取本地音频流,咱们都知道,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

相关文章
相关标签/搜索