到目前为止,只有 <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 Choi 和 Michael Wilson 审核本文。
日历图片照片由 Steve Harvey 拍摄,选自 Unsplash。