web音頻流轉發之音頻源

前言

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

createMediaElementSource

下面是一個簡單到極點的例子,完成了從audio獲取音頻源,而後輸出到你的揚聲器設備。
這個方法咱們在直播中作用不到。api

//建立音頻上下文
let audioCtx = new (window.AudioContext || window.webkitAudioContext)(),
    //獲取audio節點
    myAudio = document.querySelector('audio'),
    //建立音頻源
    source = audioCtx.createMediaElementSource(myAudio),
    //將音頻源直接鏈接到輸出設備
    source.connect(audioCtx.destination);

createMediaStreamSource

這個方法介紹的是用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

這個方法相對前面兩個稍微複雜一點點。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的屬性和方法

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

相關文章
相關標籤/搜索