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