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

François Beaufort
François Beaufort

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

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

这在各种实时通信场景中特别有用。例如,Web 应用可以使用此接口以编程方式将输出定向到特定音频输出设备,例如蓝牙耳机或免提电话。

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

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

获取音频输出设备的标识符后,创建 AudioContext 并调用 audioContext.setSinkId(deviceId)。成功时,当音频路由到所选的已连接输出设备时,返回的 promise 会解析。如果 AudioContext 已关闭,则可能会失败。

以下示例展示了如何根据需要请求麦克风访问权限,以及如何将 Web Audio 中的音频输出定向到第一个可用的输出设备。

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 团队和 Web 标准社区希望了解您使用 AudioContext.setSinkId() 的体验。如需提供反馈,请对现有问题发表评论或提交新的 GitHub 问题

致谢

感谢 Hongchan ChoiMichael Wilson 审核本文。

日历图片由 Unsplash 用户 Steve Harvey 拍摄。