在网络音频中更改目标输出设备

弗朗索瓦·博福
François Beaufort

到目前为止,只有使用 HTMLMediaElement.setSinkId()<video><audio> 才能设置目标音频输出设备。在 Web Audio 中,AudioContext 使用默认设备,让用户可手动更改系统音频输出设备。

从 Chrome 110 开始,您可以使用 AudioContext.setSinkId() 以编程方式将网络音频中的音频输出定向到任何允许的设备。

这在各种实时通信场景中尤其有用。例如,Web 应用可以使用此 API 以编程方式将输出定向到特定的音频输出设备,例如蓝牙耳机或扬声器。

将音频输出路由到特定设备

首先,您需要要用作目的地的音频输出设备的标识符。使用 navigator.mediaDevices.enumerateDevices() 获取可用媒体设备的列表,仅过滤音频输出设备,然后获取所选音频输出设备的 deviceId 属性。空字符串 "" 值还可用作 deviceId 的默认设备。

获得音频输出设备的标识符后,创建一个 AudioContext 并调用 audioContext.setSinkId(deviceId)。成功后,返回的 promise 会在音频路由到所选的已连接输出设备时进行解析。如果关闭 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 渲染音频

现在,您可以在 Web Audio 中指定“静音输出设备”,以最大限度地降低功耗。这次,将 { 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()

浏览器支持

AudioContext.setSinkId()可在 Chrome 110 或更高版本中使用。

反馈

Chrome 团队和网络标准社区希望了解您使用 AudioContext.setSinkId() 的体验。请对现有问题发表评论或提交新的 GitHub 问题,以此提供反馈。

致谢

感谢 Hongchan ChoiMichael Wilson 审核本文。

日历图片,由 Steve Harvey 拍摄,来源:Unsplash 用户。