Web Audio API 最佳實踐
在編寫創意程式碼時,沒有嚴格的對錯之分。只要你考慮了安全性、效能和可訪問性,就可以適應你自己的風格。在本文中,我們將分享一些最佳實踐——關於使用 Web Audio API 的指南、技巧和竅門。
載入聲音/檔案
使用 Web Audio API 載入聲音有四種主要方式,哪種最適合你可能會讓人有些困惑。
在處理檔案時,你可以選擇從 HTMLMediaElement(即 <audio> 或 <video> 元素)獲取檔案,或者獲取檔案並將其解碼為緩衝區。這兩種方式都有效,但前者更常用於處理完整長度的音軌,而後者更常用於處理較短、更像樣本的聲音。
媒體元素開箱即用地支援流式傳輸。當瀏覽器認為它可以在播放結束前載入檔案的其餘部分時,音訊就會開始播放。你可以在 使用 Web Audio API 教程 中找到如何使用此功能的示例。
但是,使用緩衝區節點會給你更多的控制權。你必須請求檔案並等待其載入(我們 高階文章的這一部分 展示了很好的方法),然後你就可以直接訪問資料,這意味著更高的精度和更精確的控制。
如果你想處理來自使用者攝像頭或麥克風的音訊,可以透過 Media Capture and Streams API 和 MediaStreamAudioSourceNode 介面進行訪問。這對於 WebRTC 以及你可能想要錄製或分析音訊的場景很有用。
最後一種方式是生成自己的聲音,這可以透過 OscillatorNode 或建立緩衝區並用自己的資料填充緩衝區來完成。有關使用振盪器和緩衝區建立聲音的資訊,請參閱 此處建立自己的樂器的教程。
跨瀏覽器和舊版支援
Web Audio API 規範在不斷發展,就像網路上的大多數事物一樣,它在跨瀏覽器工作方面存在一些問題。在這裡,我們將研究繞過跨瀏覽器問題的選項。
有一個名為 standardized-audio-context 的 npm 包,它可以在不同瀏覽器之間一致地建立 API 功能,填補發現的空白。它處於不斷開發中,並致力於跟上當前規範。
還可以選擇使用庫,根據你的用例有幾種選擇。對於一個不錯的全能型庫,howler.js 是一個不錯的選擇。它支援跨瀏覽器,並提供了一個有用的功能子集。雖然它沒有利用 Web Audio API 提供的全部濾鏡和其他效果,但你可以做到大部分你想要做的事情。
如果你正在尋找聲音創作或更基於樂器的選項,tone.js 是一個很棒的庫。它提供了高階的排程功能、合成器和效果,以及建立在 Web Audio API 之上的直觀的音樂抽象。
來自 BBC 的研發部門 的 R-audio 是一個 React 元件庫,旨在提供“更直觀、宣告式地訪問 Web Audio”。如果你習慣編寫 JSX,它可能值得一看。
自動播放策略
瀏覽器已開始實施自動播放策略,總的來說可以概括為
"從使用者手勢內部建立或恢復上下文"。
但這對實際意味著什麼?使用者手勢被解釋為使用者發起的事件,通常是 click 事件。瀏覽器供應商決定不允許 Web Audio 上下文自動播放音訊;相反,它們應該由使用者啟動。這是因為自動播放音訊可能非常煩人且令人反感。但是我們該如何處理呢?
當你建立一個音訊上下文(無論是離線還是線上)時,它會以一個 state 建立,該狀態可以是 suspended、running 或 closed。
在使用 AudioContext 時,如果你在 click 事件內部建立音訊上下文,狀態應自動設定為 running。這是在 click 事件內部建立上下文的示例
const button = document.querySelector("button");
button.addEventListener("click", () => {
const audioCtx = new AudioContext();
// Do something with the audio context
});
但是,如果你在使用者手勢之外建立上下文,其狀態將設定為 suspended,並且在使用者互動後需要啟動它。我們可以在此處使用相同的點選事件示例,測試上下文的狀態,並在其被掛起時使用 resume() 方法啟動它。
const audioCtx = new AudioContext();
const button = document.querySelector("button");
button.addEventListener("click", () => {
// check if context is in suspended state (autoplay policy)
if (audioCtx.state === "suspended") {
audioCtx.resume();
}
});
你可能正在使用 OfflineAudioContext,在這種情況下,你可以使用 startRendering() 方法恢復掛起的音訊上下文。
使用者控制
如果你的網站或應用程式包含聲音,你應該允許使用者控制它,否則它將再次變得令人討厭。這可以透過播放/停止和音量/靜音控制元件來實現。使用 Web Audio API 教程將介紹如何做到這一點。
你可能會發現一些有用的控制元件是:用於播放/暫停的 <button> 元素,用於選擇播放速度等選項的 <select> 元素,用於切換靜音的 <input type="checkbox"> 元素,以及用於音量控制和輸入其他數值的 <input type="range"> 元素。
所有關於表單可訪問性的常見注意事項都適用。在使用 <button> 元素時,應確保它們具有清晰的 label。這將幫助螢幕閱讀器和其他輔助技術理解按鈕的用途。如果你有開關音訊的按鈕,在按鈕上使用 ARIA role="switch" 屬性是向輔助技術指示按鈕確切用途的好方法,從而使應用程式更具可訪問性。
設定 AudioParam 值
有兩種方法可以操縱 AudioNode 值,它們本身就是 AudioParam 介面型別的物件。第一種方法是透過屬性直接設定值。例如,如果我們想更改 GainNode 的 gain 值,我們會這樣做:
gainNode.gain.value = 0.5;
這將把我們的音量設定為一半。但是,如果你使用 AudioParam 的任何已定義方法來設定這些值,它們將優先於上面的屬性設定。例如,如果你希望 gain 值在 2 秒後增加到 1,你可以這樣做:
gainNode.gain.setValueAtTime(1, audioCtx.currentTime + 2);
它將覆蓋之前的示例(應該如此),即使它出現在你程式碼的後面。
考慮到這一點,如果你的網站或應用程式需要定時和排程,最好堅持使用 AudioParam 方法來設定值。如果你確定不需要,使用 value 屬性設定是可以的。