Copyright © 2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
本文档定义了一组 JavaScript API,使 Web 应用程序能够管理音频在用户音频输出 设备上的呈现方式。
本节描述本文档在发布时的状态。当前 W3C 出版物列表以及本技术报告的最新修订版,可在 W3C 标准和草案 索引中找到。
WebRTC 和设备与传感器工作组打算很快将此 规范作为候选推荐发布。因此,本文档是 广泛审查请求。
本文档由 Web 实时 通信工作组 作为 候选推荐草案,使用 推荐轨道发布。
作为候选推荐发布并不 意味着 W3C 及其成员的认可。候选 推荐草案会整合工作组 打算包含在后续候选推荐快照中的、相对于上一候选推荐的变更。
这是一份草案文档,可能随时被其他 文档更新、替换或废弃。除作为进行中的工作外, 不宜引用本文档。
本文档由一个依据 W3C 专利 政策运作的小组 产生。 W3C 维护一份 与该小组交付物相关的任何专利披露的公开列表; 该页面还包括 披露专利的说明。若某人实际 知晓某项专利,并且该人认为该专利包含 必要权利要求, 则必须依照 W3C 专利政策第 6 节披露该信息。
本文档受 2025 年 8 月 18 日 W3C 流程文档约束。
本节是非规范性的。
此提案允许 JavaScript 将媒体元素的音频输出定向到系统或用户代理 默认设备之外的、被允许的设备。这在各种实时通信场景以及 通用媒体应用中都很有帮助。例如,应用程序可以使用此 API 以编程方式将输出定向到蓝牙耳机或免提扬声器之类的设备。
HTMLMediaElement
扩展当支持音频输出设备 API 时,本节规定对 HTMLMediaElement
[HTML]
的补充。
当调用 HTMLMediaElement
构造器时,用户
代理 MUST 添加以下初始化步骤:
让该元素具有一个 [[SinkId]]
内部槽,
初始化为 ""。
WebIDLpartial interface HTMLMediaElement {
[SecureContext] readonly attribute DOMString sinkId;
[SecureContext] Promise<undefined> setSinkId (DOMString sinkId);
};
sinkId,类型为 DOMString,只读
此属性包含正在通过其传送输出的音频设备的 ID;如果输出是
通过用户代理默认设备传送的,则为空字符串。如果非空,则此
ID 应等于
deviceId
属性,该属性属于
enumerateDevices()
返回的某个 MediaDeviceInfo
值。
获取时,该
属性 MUST 返回 [[SinkId]] 槽的值。
setSinkId如果应用程序被允许从给定 设备播放输出,则设置音频输出应通过其呈现的音频设备的 ID。
当调用此方法时,用户代理必须运行以下 步骤:
令 document 为 globalObject 的
关联 Document。
如果 document 不
被允许使用由
"speaker-selection"
标识的特性,则返回一个
使用新的 DOMException
拒绝的 promise,
其名称为 NotAllowedError。
如果 globalObject 没有瞬态
激活,
则用户代理 MAY 返回一个以
DOMException
对象拒绝的
promise,
该对象的 name
属性具有
InvalidStateError
值。
令 element 为调用此方法的 HTMLMediaElement
对象。
令 sinkId 为该方法的第一个参数。
如果 sinkId 等于 element 的
[[SinkId]],
则返回一个以 undefined 解决的 promise。
令 p 为一个新的 promise。
并行运行以下子步骤:
如果 sinkId 不是空字符串,并且不匹配
enumerateDevices()
结果会提供的任何音频输出设备,
则用新的
DOMException
拒绝 p,
其名称为
NotFoundError,
并中止这些子步骤。
如果 sinkId 不是空字符串,并且
若它不是当前用户代理默认设备,则应用程序不会被允许
通过 sinkId 标识的设备播放音频输出,
则用新的 DOMException
拒绝 p,
其名称为
NotAllowedError,
并中止这些子步骤。
将 element 的底层音频输出设备切换 到由 sinkId 标识的音频设备。
如果前一子步骤失败,则用新的 DOMException
拒绝 p,
其名称为
AbortError,
并中止这些子步骤。
排入一个任务,该任务运行以下步骤:
将 element 的 [[SinkId]] 设为
sinkId。
解决 p。
返回 p。
新的音频设备可能对用户代理可用,或者
先前变得不可用的音频设备(由媒体元素的 sinkId 属性标识)
可能再次变得可用,
例如,它被拔出后又重新插入。
在此场景下,用户代理必须运行以下步骤:
令 sinkId 为新可用 设备的标识符。
对于每个其 sinkId
属性等于
sinkId 的媒体元素:
以下段落是非规范性的。
如果应用程序希望对设备
变化作出反应,则应用程序可以监听
devicechange 事件并查询
enumerateDevices()
以获得更新后的
设备列表。
MediaDevices
扩展当支持音频输出设备 API 时,本节规定对 MediaDevices
的补充。
WebIDLpartial interface MediaDevices {
Promise<MediaDeviceInfo> selectAudioOutput(optional AudioOutputOptions options = {});
};
selectAudioOutput提示用户选择特定的音频输出设备。
当调用 selectAudioOutput
方法时,
用户代理 MUST 运行
以下步骤:
如果 相关
全局对象(属于 this)没有
瞬态
激活,则返回一个以
DOMException
对象拒绝的
promise,
该对象的 name
属性
具有 InvalidStateError
值。
令 options 为该方法的第一个参数。
令 deviceId 为 options.deviceId。
令 mediaDevices 为 this。
令 p 为一个新的 promise。
并行运行以下步骤:
令 descriptor 为一个 PermissionDescriptor,
其
name 设为
"speaker-selection"
如果 descriptor 的 权限
状态为
"denied",
则用新的
DOMException
拒绝
p,
其
name
属性具有
NotAllowedError
值,
并中止这些步骤。
探测 用户代理中 可用的音频输出设备。
如果没有音频输出设备,则用新的 DOMException
拒绝 p,
其 name
属性具有 NotFoundError
值,并中止
这些步骤。
如果 deviceId 不是 "",
则运行以下子步骤:
如果 deviceId 匹配
先前由
selectAudioOutput
在此浏览会话或更早浏览会话中暴露的设备 ID,
或匹配某个音频输出设备的设备 ID,且该设备与先前由
getUserMedia()
在此浏览会话或更早浏览会话中暴露的音频输入设备
具有相同的 groupId,
则用户代理 MAY 根据其先前
是否为此组来源持久保存此 ID 的决定,
决定运行以下子步骤:
令 device 为由 deviceId 标识的设备(如果可用)。
如果 device 可用,则用 deviceId 或该 device 的新轮换设备 ID 解决 p,并中止并行步骤。
使用 descriptor 提示 用户选择一个音频输出设备。
如果请求结果为 "denied",
则用新的 DOMException
拒绝
p,
其 name
属性
具有 NotAllowedError
值,并中止这些步骤。
令 selectedDevice 为用户选择的音频输出设备。
令 deviceInfo 为 创建 设备信息对象的结果,该对象用 mediaDevices 表示 selectedDevice。
将 deviceInfo.deviceId
添加到 [[explicitlyGrantedAudioOutputDevices]]。
用 deviceInfo 解决 p。
返回 p。
一旦设备在调用 selectAudioOutput
后被暴露,它
MUST 被
enumerateDevices()
为当前浏览上下文列出。
如果 selectAudioOutput 返回的
promise
被解决,
则用户代理 MUST 确保文档无需任何额外用户手势,
即刻既被允许播放
HTMLMediaElement
中的媒体,
又即刻被
允许启动
AudioContext。
由于当前浏览器中自动播放缺乏标准化, 这并不精确。
此字典描述可用于获取音频输出设备 访问权限的选项。
WebIDLdictionary AudioOutputOptions {
DOMString deviceId = "";
};
deviceId,类型为 DOMString,
默认为
""
当此字典成员的值
不是 "",并且匹配先前由
selectAudioOutput
暴露的 ID,或者匹配某个音频输出设备的设备 ID,
且该设备与先前由
getUserMedia()
在此会话或更早会话中暴露的音频输入设备
具有相同的 groupId 时,用户
代理 MAY 选择跳过提示用户,改为
用此 ID 或同一设备的新轮换 ID 解决,
前提是该设备当前可用。
希望依赖支持持久设备 ID 的用户代理的应用程序,
必须先将这些 ID 成功传给
selectAudioOutput,
然后它们才能与
setSinkId
一起工作。原因是这会
暴露指纹识别信息,但如果设备不可用,或用户代理
决定不接受该设备 ID,则可能会提示用户。
本文档扩展了 Web 平台,使其能够在获得用户许可时, 将音频输出定向到非默认设备。 用户许可是必要的,因为从非默认设备播放音频输出 可能是用户意想不到的行为,并且可能造成困扰。 例如,假设某用户在图书馆或其他安静公共场所, 她正使用一台将系统音频定向到 USB 耳机的笔记本电脑。 她的预期是笔记本电脑的音频是私密的,并且不会 打扰他人。如果任何 Web 应用程序都可以通过 任意输出设备定向音频输出,则恶意网站可能会在 未经用户同意的情况下,从笔记本电脑的外置扬声器播放大音量音频。
为防止这类困扰场景,用户代理必须 获取用户同意,以访问非默认音频输出设备。 这将防止前面概述的图书馆示例发生,因为该 应用程序不会被允许从系统扬声器播放音频输出。
本规范没有对默认音频 输出设备添加权限要求。
用户代理可以使用 selectAudioOutput
明确获取用户同意,以从非默认输出设备播放音频输出。
实现 MUST 还支持通过
getUserMedia()
权限提示进行隐式同意;当音频输入
设备通过 getUserMedia()
被允许并打开时,这也允许访问任何关联的
音频输出设备(即具有相同 groupId
的设备)。
这可以方便地处理希望将输入和输出音频
都路由到耳机或免提扬声器设备的常见情况。
页面加载时,运行以下步骤:
在相关全局
对象上,
创建一个内部槽:[[explicitlyGrantedAudioOutputDevices]],
用于存储用户通过 selectAudioOutput
明确授予的设备,
初始化为空集合。
本规范规定了 摄像头和麦克风之外设备的暴露决策算法。 该算法按如下方式运行,以 device、microphoneList 和 cameraList 作为输入:
令 document 为
当前设置对象的
相关全局对象的
关联 Document。
令 mediaDevices 为
当前设置对象的
相关全局对象的
关联 MediaDevices。
令 deviceInfo 为 创建 设备信息对象的结果,该对象用 mediaDevices 表示 device。
如果 document 不
被允许使用由 "speaker-selection" 标识的特性,
或者 deviceInfo.kind
不是 "audiooutput",
则返回 false。
如果 deviceInfo.deviceId
在 [[explicitlyGrantedAudioOutputDevices]]
中,
则返回 true。
如果 mediaDevices 上的麦克风
信息可以被暴露为 true,
则返回 true。
返回 false。
音频输出设备 API 是一个强大功能,由 名称 "speaker-selection" 标识。
它定义以下类型和算法:
权限涵盖对至少一个非默认扬声器输出设备的访问。
描述符的语义是它查询对任何非默认扬声器
输出设备的访问。因此,如果对 "speaker-selection" 强大功能 的查询返回
"granted",
则客户端知道先前与其共享的
deviceIds 中至少有一个
可以传给
selectAudioOutput
而不会产生权限提示;
如果返回 "denied",
则它知道任何针对音频输出设备的
selectAudioOutput
请求
都不会成功。
如果用户代理认为已授予对某些(但不是全部)音频输出设备的权限,
查询将返回 "granted"。
如果用户代理认为已拒绝对所有音频输出设备的权限,
查询将返回 "denied"。
本规范定义一个
策略控制
特性,由字符串
"speaker-selection"
标识。
它具有 "self" 的
默认
允许列表。
document 的权限
策略
决定该 document 中的任何内容是否
被允许
使用 selectAudioOutput
来提示用户选择
音频输出设备,或者是否
被允许
使用 setSinkId
来将音频输出应通过其呈现的设备
更改为非系统默认的、用户允许的设备。对于
selectAudioOutput,这
由提示用户
选择算法强制执行。
除标记为非规范性的各节外,本规范中的所有创作指南、图表、示例和注均为非规范性的。 本规范中的其他所有内容均为规范性的。
本文档中的关键词 MAY 和 MUST 应按 BCP 14 [RFC2119] [RFC8174] 中的描述解释,且仅当它们如这里所示 以全大写形式出现时才如此。
本规范定义了适用于单个产品的一致性准则: 实现其所包含接口的 用户 代理。
以算法或具体步骤表述的一致性要求,可以 以任何方式实现,只要最终结果等效即可。(特别是, 本规范中定义的算法旨在 易于理解,而非旨在具备高性能。)
使用 ECMAScript 来实现本规范中定义的 API 的实现, 必须以与 Web IDL 规范 [WEBIDL] 中定义的 ECMAScript 绑定一致的方式实现它们,因为 本规范使用该规范及其术语。
以下人员直接为本规范的开发做出了贡献: Harald Alvestrand、Rick Byers、Dominique Hazael-Massieux(通过 HTML5Apps 项目)、Philip Jägenstedt、Victoria Kirst、Shijun Sun、Martin Thomson、Chris Wilson。
Referenced in:
Referenced in:
Referenced in: