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

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 中指定“静音输出设备”,以最大限度地降低能耗。这次,请向 AudioContext.setSinkId() 传递 { type: "none" },而不是字符串值。

请注意,通过 audioContext.currentTime 访问的音频时钟仍会前进以渲染音频图。静音 AudioContext 的主要目标是在不产生可听声音的情况下渲染音频图。主要使用场景是在不发出声音的情况下分析麦克风输入。

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

功能检测

如需检查是否支持 AudioContext.setSinkId(),请使用:

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

示例

您可以访问 https://codepen.io/web-dot-dev/pen/emNwEaN/ 体验 AudioContext.setSinkId() 的演示。

浏览器支持

AudioContext.setSinkId() 在 Chrome 110 或更高版本中提供。

反馈

Chrome 团队和 Web 标准社区希望了解您使用 AudioContext.setSinkId() 的体验。请通过评论现有 GitHub 问题或提交新的 GitHub 问题来提供反馈。

致谢

感谢 Hongchan ChoiMichael Wilson 审核本文。

日历图片照片由 Steve Harvey 拍摄,选自 Unsplash