在網路音訊中變更目的地輸出裝置

法蘭索瓦博福
François Beaufort

目前,在 <video><audio> 上使用 HTMLMediaElement.setSinkId() 設定目的地音訊輸出裝置時,只能設定目標音訊輸出裝置。在網路音訊中,AudioContext 會使用預設裝置,讓使用者手動變更系統音訊輸出裝置。

自 Chrome 110 版本起,你可以使用 AudioContext.setSinkId(),透過程式輔助方式將網路音訊的音訊輸出裝置導向任何許可裝置。

這對各種即時通訊情境特別實用。舉例來說,網頁應用程式可利用此功能,透過程式輔助方式將輸出裝置輸出至特定音訊輸出裝置,例如藍牙耳機或擴音器。

將音訊輸出轉送至特定裝置

首先,請備妥要做為目的地的音訊輸出裝置 ID。使用 navigator.mediaDevices.enumerateDevices() 取得可用的媒體裝置清單、只篩選音訊輸出裝置,以及取得所選音訊輸出裝置的 deviceId 屬性。空字串 "" 值也可以用做 deviceId 的預設裝置。

取得音訊輸出裝置的 ID 後,請建立 AudioContext 並呼叫 audioContext.setSinkId(deviceId)。成功之後,如果音訊轉送至所選連接的輸出裝置,傳回的承諾會解決問題。如果 AudioContext 關閉,則可能會失敗。

以下範例說明如何視需要要求麥克風存取權,並將網路音訊的音訊輸出裝置導向第一個可用的輸出裝置。

const permission = await navigator.permissions.query({ name: "microphone" });
if (permission.state == "prompt") {
  // More audio outputs are available when user grants access to the mic.
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
  stream.getTracks().forEach((track) => track.stop());
}

// Request a list of media devices and filter audio output devices.
const devices = await navigator.mediaDevices.enumerateDevices();
const audioOutputs = devices.filter(device => device.kind == "audiooutput");

const audioContext = new AudioContext();

// Pick the first available audio output.
const deviceId = audioOutputs[0].deviceId;
await audioContext.setSinkId(deviceId);

請注意,您也可以在建立 AudioContext 時,將 deviceId 做為 sinkId 參數傳遞。

const audioContext = new AudioContext({ sinkId: deviceId });

使用設為靜音的 AudioContext 算繪音訊

您現在可以在網路音訊中指定「靜音輸出裝置」,將耗電量降到最低。這次請將 { type: "none" } 傳遞至 AudioContext.setSinkId(),而不是字串值。

請注意,透過 audioContext.currentTime 存取的音訊時鐘仍會繼續執行,以顯示音訊圖表。這個靜音 AudioContext 的主要目標是在不產生有聲的情況下算繪音訊圖表。主要用途是在分析麥克風輸入時不會發出聲音。

// Silent Web Audio output.
await audioContext.setSinkId({ type: "none" });

特徵偵測

如要檢查是否支援 AudioContext.setSinkId(),請使用:

if ("setSinkId" in AudioContext.prototype) {
  // AudioContext.setSinkId() is supported.
}

範例

前往 https://sinkid.glitch.me/ 即可觀看 AudioContext.setSinkId() 的示範教學。

瀏覽器支援

Chrome 110 以上版本支援「AudioContext.setSinkId()」。

意見回饋

Chrome 團隊和網路標準社群想瞭解您使用「AudioContext.setSinkId()」的經驗。如要提供意見回饋,請留言現有的 GitHub 問題

特別銘謝

感謝 Hongchan ChoiMichael Wilson 撰寫這篇文章。

日曆圖片由 Steve HarveyUnsplash 提供。