初識HTML5 Web Audio API

黑金團隊發表於2019-04-24

前言

自從上次在趣講CDN一文中講了一個"傳東奶"的故事之後,就再也沒有發過部落格。或許有些朋友還以為我們被抓了呢,哈哈哈~

很久以前,趙忠祥老師就告訴我們,雨季,是個好時節。雨季來了,春暖花開,萬物復甦,又到了大草原上程式猿們XX的季節。好吧,扯遠了。說到底,就是團隊中的小哥哥小姐姐都忙著談戀愛,都沒時間寫部落格了。

獲取音訊的時長

有這樣的一個需求,上傳一個音訊檔案,同時獲取其大小及時長。

常規方法

這很簡單,使用記憶中的那些方法,寫出下面的程式碼:

function getAudioDuration(url) {
  const audio = document.createElement('audio');
  audio.src = url;
  audio.addEventListener("canplay", function () {
		console.log(audio.duration);
  });
}

const file = document.getElementById('file');
file.addEventListener('change', (e) => {
  const file = e.target.files[0];
  console.log(file.size);
  getAudioDuration(URL.createObjectURL(file));
})
複製程式碼

當我擼完上面這段程式碼的時候,回想起總工的批判:這方案太簡單了。菊花一緊,嚇得我趕緊找找其他的方案。

ArrayBuffer

在電腦中,當我們選中一個MP3檔案的時候,通常可以看到一些元資訊,比如播放時長、取樣速率等。既然如此,我們是否可以通過讀取二進位制資料來獲取對應的資訊呢?

在查詢相關資料之後,發現了decodeAudioData這個API可以滿足我們的需求,於是有了下面的方案。

function getAudioDurationByAudioApi(file) {
    const fileReader = new FileReader();
    const audioContext = new AudioContext();
    fileReader.readAsArrayBuffer(file);
    fileReader.onload = () => {
        audioContext.decodeAudioData(fileReader.result, (result) => {
            console.log(result);
        });
    }
}

const file = document.getElementById('file');
file.addEventListener('change', (e) => {
    const file = e.target.files[0];
    console.log(file.size);
    getAudioDurationByAudioApi(file);
})
複製程式碼

被忽略的Web Audio API

通過以上的探索,發現了一直被我忽略的Web Audio API。以往在處理音訊相關的需求,大多是通過audio標籤,播放一段音訊,很簡單。所以也就沒有關注到早已存在的Audio API。

舉個例子

實際應用一下,舉個簡單的播放音訊栗子:

function playAudio(file) {
    const fileReader = new FileReader();
    const audioContext = new AudioContext();
    fileReader.readAsArrayBuffer(file);
    fileReader.onload = () => {
        audioContext.decodeAudioData(fileReader.result, (result) => {
          //建立播放源
          const source = audioContext.createBufferSource();
          source.buffer = result;
          //連線輸出終端
          source.connect(audioContext.destination);
          //開始播放
          source.start();
        });
    }
};

const file = document.getElementById('file');
file.addEventListener('change', (e) => {
    playAudio(e.target.files[0]);
});
複製程式碼

以上例子簡單使用相關的API進行了音訊的播放,分析一下關鍵的程式碼。

AudioContext

直接翻譯,就是"音訊上下文"。類似於canvas中的context。其中包含了一系列用來操作音訊的API。

上面的程式碼中,通過const audioContext = new AudioContext();建立了一個AudioContext物件,於是我們就可以進行各種各樣的操作。

建立播放源

上面的例子中,我們通過AudioContext.createBufferSource()建立了播放源。除此之外,我們還可以使用其他的資料作為播放源:

具體介紹可點選連結檢視。

連線輸入輸出

我們可以看到,在設定好播放源之後,進行了一個connect操作。這個操作就是將播放源連結到播放終端。

AudioContext的destination屬性返回一個AudioDestinationNode表示context中所有音訊(節點)的最終目標節點,一般是音訊渲染裝置,比如揚聲器。

有趣的玩法

在學習AudioContext相關API的過程中,發現了createAnalyser這個方法。

createAnalyser方法能建立一個AnalyserNode,可以用來獲取音訊時間和頻率資料,以及實現資料視覺化。

要看看效果吧,demo

以前,需要標識一個音訊正在播放,我們經常會放一個跳動的gif。比如:

初識HTML5 Web Audio API

是的,這一點都不酷。不禁又回想起總工的那句話:這方案太簡單了。

以後,我們再做這樣的需求的時候,就可以做成跟隨音樂頻率跳動的動畫效果了。

總結

魯迅先生說:"從來如此,便對嗎?"

是啊,我們應該對現有方案多點思考。

以上所述,僅僅只是Web Audio API的冰山一角,還有更多高階的玩法,有興趣的可以檢視相關的文件。

相關文章

@Author:TDGarden

相關文章