web音频流转发之音视频直播
web音频流转发之AudioNode
app能直播,web为何不能够?看完本系列文章,你就能作一个直播,真正的直播,包括音频流的转发,这也是我最近查看web audio api发现有相关api能实现音频流的转发,全部打算分享系列文章供你们交流,若有不对之处请指正。看完本系列文章能完成一个web直播,固然包括视频流。固然webrtc也能实现web直播,可是实现原理有所差异。文章也很简单就是对web audio api的灵活使用。web
兼容性是有必要看下,顺便看一下ie,和安卓Android Browse的兼容性,然而我想说个人荣耀8 安卓6.0 仍是嵌套的chrome 37大家信吗?究竟是做为一个渐渐加强的功能,仍是做为一个装逼技能就看你们的使用啦!chrome
一个简单而典型的web audio流程以下:
1.建立音频上下文
2.在音频上下文里建立源 — 例如 <audio>, 振荡器, 流
3.建立效果节点,例如混响、双二阶滤波器、平移、压缩
4.为音频选择一个目地,例如你的系统扬声器
5.链接源到效果器,对目的地进行效果输出
这段话引用自MDN,这一章我主要讲解inputs中的3个api。segmentfault
下面是一个简单到极点的例子,完成了从audio获取音频源,而后输出到你的扬声器设备。
这个方法咱们在直播中作用不到。api
//建立音频上下文 let audioCtx = new (window.AudioContext || window.webkitAudioContext)(), //获取audio节点 myAudio = document.querySelector('audio'), //建立音频源 source = audioCtx.createMediaElementSource(myAudio), //将音频源直接链接到输出设备 source.connect(audioCtx.destination);
这个方法介绍的是用navigator.mediaDevices.getUserMedia(navigator.getUserMedia已经废弃)获取到的音频流做为音频流。在直播时咱们会采用此方法做为,音频流的采集方法;固然在这里咱们也会获取到咱们须要的视频流数据app
//简单兼容 let getUserMedia = navigator.mediaDevices.getUserMedia || navigator.getUserMedia; //获取麦克风,摄像头权限 getUserMedia({audio: true, video: true}).then(stream => { let audioCtx = new AudioContext(), //以流媒体做为音频源 source = audioCtx.createMediaStreamSource(stream); //将音频源直接链接到输出设备 source.connect(audioCtx.destination); });
这个方法相对前面两个稍微复杂一点点。createBufferSource是由存储器中的音频数据组成的音频源,它经过AudioBuffer来进行存储,解释一下:它是经过一个固定的音频数据的二进制做为音频源,好比一首歌的二进制数据。dom
let audioCtx = new (window.AudioContext || window.webkitAudioContext)(), source = audioCtx.createBufferSource(); //myArrayBuffer是一个AudioBuffer source.buffer = myArrayBuffer; source.loop = true; //循环播放 source.connect(audioCtx.destination); source.start(); //开始播放音频源
下面讲讲myArrayBuffer的几种来源方式异步
//1.经过input=file 获取的音频文件 let fileInput = document.querySelector('input'), audioCtx = new (window.AudioContext || window.webkitAudioContext)(); fileInput.onchange = function(ev){ let file = ev.target.files[0], fr = new FileReader(); fr.readAsArrayBuffer(file); fr.onload = function(data){ //result是一个arraybuffer类型二进制数据 let result = data.target.result; //解析数据 analyticBuffer(result); }; }; //2.经过XHR获取音频数据(注意须要返回arraybuffer类型) let request = new XMLHttpRequest(); request.open('GET', 'xxx.mp3', true); //指定文件返回数据类型 request.responseType = 'arraybuffer'; //请求成功时执行 request.onload = function() { //这是一个arraybuffer var buffer = request.response; //解析数据 analyticBuffer(buffer ) } request.send(); //解析二进制数据 function analyticBuffer(buffer){ //将ArrayBuffer异步转换为一个AudioBuffer类型 audioCtx.decodeAudioData(buffer, (myArrayBuffer) => { let source = audioCtx.createBufferSource(); source.buffer = myArrayBuffer; source.connect(audioCtx.destination); source.start(); }); } //3.本身创造一个AudioBuffer //采样率sample/s let sampleRate = audioCtx.sampleRate, //帧数,音频时间 = frameCount / sampleRate frameCount = audioCtx.sampleRate * 2.0, //建立一个两通道的音频数据,这是一个没有声音的音频数据 myArrayBuffer = audioCtx.createBuffer(2, frameCount , sampleRate); //随机填充白噪音 //两个通道循环2次 for (var channel = 0; channel < 2; channel++) { //获取每一个通道的array数据 var nowBuffering = myArrayBuffer.getChannelData(channel); for (let i = 0; i < frameCount; i++) { //对每一帧填充数据 nowBuffering[i] = Math.random() * 2 - 1; } }
AudioBuffer的方法在咱们直播的时候须要用到,在后面的AudioNode(音频处理模块)中也会出现AudioBuffer数据,咱们须要它是获取和传输数据ide
let myArrayBuffer = audioCtx.createBuffer(2, 4096, sampleRate); myArrayBuffer.sampleRate //采样数 myArrayBuffer.length //采样帧率 也就是4096 myArrayBuffer.duration //时长 myArrayBuffer.numberOfChannels //通道数 //返回x通道的Float32Array类型的数据,x表示是哪一个通道0或1 myArrayBuffer.getChannelData(x) //将myArrayBuffer第x通道的数据复制到anotherArray中,y表示数据复制开始的偏移量 let anotherArray = new Float32Array; myArrayBuffer.copyFromChannel(anotherArray,x,y); //将anotherArray数据复制到myArrayBuffer的X通道中,y偏移量 let anotherArray = new Float32Array; myArrayBuffer.copyToChannel(anotherArray,x,y); //关于copyToChannel,copyFromChannel,getChannelData在下一章看见例子就明白了
这一章大概就说到这么多吧,都是一些简单的api使用,下一章结合之后例子讲解部分AudioNode。oop