远程播放 API

W3C 候选推荐标准草案

关于本文档的更多详细信息
此版本:
https://www.w3.org/TR/2024/CRD-remote-playback-20240430/
最新发布版本:
https://www.w3.org/TR/remote-playback/
最新编辑草案:
https://w3c.github.io/remote-playback/
历史记录:
https://www.w3.org/standards/history/remote-playback/
提交历史
实现报告:
https://www.w3.org/wiki/Second_Screen/Implementation_Status#Remote_Playback_API
编辑:
Mark Foltz (Google)
前编辑:
Mounir Lamouri (Google)
Anton Vayvod (Google)
反馈:
GitHub w3c/remote-playback (拉取请求, 新议题, 开放议题)
测试套件
GitHub web-platform-tests/remote-playback
w3c-test.org/remote-playback/

摘要

本规范定义了一个扩展 HTMLMediaElement 的 API,使其能够从网页控制媒体的远程播放。

本文档的状态

本节描述本文档 发布时的状态。当前 W3C 出版物列表以及本技术报告的最新修订版可在 https://www.w3.org/TR/ 的 W3C 技术 报告索引中找到。

本文档由第二屏幕工作 组使用 推荐标准轨道发布为 候选推荐标准草案。

本文档建立在该工作组将 Web 内容呈现在外部演示类显示器上的经验之上,并在适当情况下复用 Presentation API 规范中的模式 和设计考虑因素 [PRESENTATION-API]。

尽管本文档仍然是正在进行的工作,并且 可能发生变化,但工作组认为 API 接口已经 稳定。目前议题跟踪器上列出的其余大多数议题 在现阶段都被认为是次要问题,只有 议题 #41 除外。

议题 #41 讨论了远程播放 设备预期支持的一组媒体播放功能。该工作组将寻求更多开发者 反馈和实现经验,以确定这些功能在远程播放期间使用时 是否存在任何互操作性问题,并将 根据收到的反馈进一步澄清本规范。

对于其他议题或疑虑,可以提交错误报告,或 向邮件 列表发送电子邮件。对于拼写错误之类的小型编辑性更改, 欢迎发送拉取请求。

工作组邀请所有人审阅本文档,并将 与 W3C 的相关工作组合作,就 无障碍、国际化、隐私、安全和技术 架构原则开展横向审查。

尚未发现任何功能存在风险。

第二屏幕工作组将在候选推荐标准阶段为 Remote Playback API 开发测试套件,并 准备实现报告。要使本规范推进到 提议推荐标准阶段,必须证明每项功能都有两个独立且可互操作的实现, 具体要求详见候选推荐标准退出 标准一节。

作为候选推荐标准发布并不 表示获得 W3C 及其成员的认可。候选 推荐标准草案整合了 自上一份候选推荐标准以来工作组 打算纳入后续候选推荐标准快照的更改。

这是一份草案文档,可能随时由其他 文档更新、替换或废弃。除作为正在进行的工作外, 不宜以其他方式引用本文档。

本文档由一个 按照 W3C 专利 政策运作的工作组制作。 W3C 维护一份 与该工作组交付成果有关的所有专利 披露的公开列表; 该页面还包含 披露专利的说明。任何实际 知悉某项专利,并认为该专利包含 必要权利要求的个人, 必须按照 W3C 专利政策第 6 节披露相关信息。

本文档受 2023 年 11 月 3 日的 W3C 流程文档管辖。

1. 一致性

除标记为非规范性的章节外,本规范中的所有创作指南、图示、示例和注释均为非规范性的。本规范中的其他所有内容均为规范性的。

本文档中的关键词 可以、必须、不得 、建议 和 应该 应按照 BCP 14 [RFC2119] [RFC8174] 中的描述进行解释,但仅限于这些关键词像此处所示那样全部采用大写形式时。

本规范定义了适用于单一 产品的一致性标准:实现本规范所包含接口的用户代理。

使用 ECMAScript 暴露本 规范中定义的 API 的实现必须以与 Web IDL 规范中定义的 ECMAScript 绑定一致的方式实现这些 API [WEBIDL]。

2. 引言

本节为非规范性内容。

本规范旨在使联网电视、投影仪或纯音频扬声器等远程播放设备可供 Web 使用,并考虑通过有线 (HDMI、DVI 或类似技术)和无线技术(Miracast、 Chromecast、DLNA、AirPlay 或类似技术)连接的播放设备。

屏幕尺寸受限或扬声器音量较小的设备无法 向更多受众播放媒体内容,例如会议室中的一群 同事,或家中的朋友和家人。在外部更大和/或声音更响亮的远程播放 设备上播放媒体内容,有助于提高所播放媒体的 感知质量和影响力。

从本质上讲,本规范使充当 浏览 上下文的页面能够在选定的远程播放设备上发起和控制特定媒体元素的远程播放。 远程播放如何发起和控制由 UA 决定,以便 支持以多种不同方式连接的远程播放设备。例如,当远程播放 设备使用 HDMI 或 Miracast 连接时,充当 浏览 上下文的同一 UA 会渲染远程媒体。但是,它并非 在同一设备上播放媒体,而是可以使用操作系统提供的任何 方式来使用外部远程 播放设备。在这种情况下,浏览 上下文 和媒体播放器都运行在同一 UA 上,并使用操作系统 将播放器输出路由到远程播放设备。 这种情况通常称为媒体 镜像。本规范不对 以这种方式连接的远程播放设备提出任何要求。

如果远程播放设备能够播放媒体并 与浏览 上下文通信,但无法获取 媒体,则浏览 上下文需要获取媒体数据并 将其传递给远程播放设备进行渲染。这种情况 通常称为媒体远程传送。

如果远程播放设备能够获取并播放 媒体 并与浏览 上下文通信,则浏览 上下文无需获取或渲染远程媒体。在这种 情况下,UA 充当代理,通过传递媒体源等 必要数据,请求远程播放 设备自行播放媒体。这种情况通常称为媒体 投送。未来可以通过定义一种标准协议来增强 这种连接显示器的方式,以便传递 远程播放设备可以选择 实现的这类消息。

此处定义的 API 旨在供通过上述任一 方式连接到远程播放设备的 UA 使用。

3. 用例和要求

本节为非规范性内容。

本规范的用例和要求记录在一份 单独的文档中,可在此处获取。

4. 示例

本节展示了一些代码示例,重点说明 Remote Playback API 主要 功能的用法。在这些示例中, player.html 实现用于控制 远程播放的播放器页面,而 media.ext 是要 远程播放的媒体文件。页面和媒体均由域名 https://example.org 提供。有关更多详细信息,请参阅 代码示例中的注释。

4.1 监视远程播放设备可用性的示例

<!-- player.html -->
<!-- 支持远程播放并带有自定义控件的 video 元素。 -->
<video id="videoElement" src="https://example.org/media.ext" />
<button id="deviceBtn" style="display: none;">选择设备</button>
<script>
  // 如果至少有一个远程播放设备可用,则显示“选择设备”按钮。
  const deviceBtn = document.getElementById("deviceBtn");
  const videoElem = document.getElementById("videoElement");

  function availabilityCallback(available) {
    // 根据设备可用性显示或隐藏设备选择器按钮。
    deviceBtn.style.display = available ? "inline" : "none";
  }

  videoElem.remote.watchAvailability(availabilityCallback).catch(() => {
    // 平台不支持可用性监视,因此仅会在调用 remote.prompt() 后
    // 才发现远程播放设备。
    // 为简单起见,假装设备可用;或者,也可以为按钮实现
    // 第三种状态。
    deviceBtn.style.display = "inline";
  });
</script>

4.2 启动视频远程播放的示例

<!-- player.html -->
<script>
  deviceBtn.onclick = () => {
    // 请求用户选择一个远程播放设备。
    videoElem.remote.prompt()
      // 更新 UI 并监视连接状态。
      .then(updateRemotePlaybackState);
      // 否则,用户取消了选择 UI,或未找到任何屏幕。
  };
<script>

4.3 监视远程播放状态变化

<!-- player.html -->
<script>
  // 远程播放可能由用户代理发起,
  // 因此请检查初始状态,以使 UI 与其同步。
  if (videoElem.remote.state == "disconnected")
    switchToLocalUI();
  else
    switchToRemoteUI();

  videoElem.remote.onconnecting = switchToRemoteUI;
  videoElem.remote.onconnect = switchToRemoteUI;
  videoElem.remote.ondisconnect = switchToLocalUI;

  // 同时处理 'connecting' 和 'connected' 状态。多次调用
  // 不会执行任何操作。
  function switchToRemoteUI() {
    // 向用户指示当前状态为 'connecting' 或 'connected'。
    // 例如,隐藏 video 元素,因为只需要控件。
    videoElem.style.display = "none";

    // 停止监视远程播放设备的可用性。
    videoElem.remote.cancelWatchAvailability();
  };

  function switchToLocalUI() {
    // 显示 video 元素。
    videoElem.style.display = "inline";
    // 再次开始监视设备可用性。
    videoElem.remote.watchAvailability(availabilityCallback);
  };
<script>

5. API

5.1 常用惯用模式

本地 播放设备是浏览 上下文运行所在的设备,以及 该设备具有的默认视频/音频输出。

注
本地播放设备可能具有额外的输出, 例如 外部显示器或扬声器/耳机。只要使用何种输出的切换 发生在用户代理之外的 系统级别,就本规范而言,该播放就被视为发生在本地 播放设备上。

远程播放设备 是除本地播放设备之外, 浏览 上下文可用于播放媒体的任何其他设备。

媒体 元素状态是单个 媒体 元素 的所有属性的集合,这些属性可由页面和/或用户通过 用户代理实现观察到。为方便起见, 本规范引入的新属性不被视为媒体元素状态 的一部分。

例如,paused 属性或媒体 元素默认控件上反映该状态的暂停/继续 按钮,都属于媒体元素状态的一部分。

本地 播放状态是用户代理针对特定媒体元素状态的实现,用于在媒体元素 的本地播放设备上进行播放。

远程 播放状态是用户代理针对特定媒体元素状态的实现,用于在特定媒体元素 的某个远程播放设备上进行播放。

注

为获得良好的用户体验,当 媒体元素 状态发生变化时,state 不应意外变化。同样重要的是, 远程 播放状态应与媒体元素状态保持同步,这样 当媒体在 远程播放设备上暂停时,对于用户和 页面而言,它看起来都处于暂停状态。

本规范中提到的任务所使用的任务 源 是 媒体元素事件任务源。

5.2 RemotePlayback 接口

WebIDL[Exposed=Window]
interface RemotePlayback : EventTarget {
  Promise<long> watchAvailability(RemotePlaybackAvailabilityCallback callback);
  Promise<undefined> cancelWatchAvailability(optional long id);

  readonly attribute RemotePlaybackState state;

  attribute EventHandler onconnecting;
  attribute EventHandler onconnect;
  attribute EventHandler ondisconnect;

  Promise<undefined> prompt();
};

enum RemotePlaybackState {
  "connecting",
  "connected",
  "disconnected"
};

callback RemotePlaybackAvailabilityCallback = undefined(boolean available);

RemotePlayback 对象允许页面检测远程播放设备的可用性、 连接到这些设备并控制其上的播放。

RemotePlaybackState 枚举表示与远程播放设备连接时可能的 状态。

RemotePlaybackAvailabilityCallback 返回当前的 远程播放设备可用性。

5.2.1 观察远程播放设备可用性

RemotePlaybackAvailabilityCallback 是页面获取相应媒体元素的 远程播放设备可用性的方式。如果用户 代理能够在后台监视 可用远程播放设备列表 (而无需等待对prompt() 的请求),则用户代理 必须实现下文定义的 RemotePlaybackAvailabilityCallback 行为。否则, watchAvailability() 返回的 promise 必须以 NotSupportedError 拒绝。

5.2.1.1 可用性回调集合

用户代理必须跟踪通过 watchAvailability() 方法向每个媒体元素注册的可用性 回调集合。每个 RemotePlayback 对象的可用性 回调集合表示为一个元组集合 (callbackId, callback), 初始为空,其中:

  1. callbackId 是一个正整数,在给定浏览 上下文中 所有由 watchAvailability() 返回的 id 中唯一;
  2. callback 是一个RemotePlaybackAvailabilityCallback 对象。

由于每个媒体 元素都有且只有一个RemotePlayback 对象,因此可用性 回调集合 与该元素的 remote 属性所引用的 RemotePlayback 对象的可用性 回调集合是同一个集合。

浏览 上下文所知的所有RemotePlayback 对象的所有可用性 回调集合合并后的集合称为全局 可用性回调集合。

5.2.1.2 可用远程播放设备列表

用户代理必须维护一个可用远程 播放设备列表。此列表包含远程 播放 设备,并根据特定于实现的 发现机制进行填充。它被设置为监视 可用远程播放 设备列表算法的最新结果;如果该算法尚未运行, 则为空列表。

用户代理可以不支持持续运行 监视可用远程播放设备列表 的算法,例如,由于平台或功耗 限制。在这种情况下,由 watchAvailability() 返回的 promise 必须以 NotSupportedError 拒绝, 全局可用性 回调集合将为空,并且监视 可用远程播放设备列表的算法将仅作为 发起远程播放算法的一部分运行。

当全局 可用性回调集合非空时, 用户代理必须持续监视 可用远程播放设备列表,以便页面 可以跟踪通过已注册回调收到的最后一个值, 从而仅在存在可用设备时提供远程播放。

注

为满足 节能非功能性要求,用户代理应尽可能不监视 可用 远程播放设备列表。例如, 当全局 可用性回调集合为空时,或者当所有具有 非空可用性回调集合的媒体元素所在页面均处于 后台时,用户代理可能选择不运行监视 算法。

某些远程播放设备可能由于功能、安全或硬件限制, 只能播放一部分媒体资源。 例如,只能渲染特定视频和/或音频格式的 机顶盒、智能电视或联网扬声器。如果用户代理能够合理保证 由某媒体资源指定的媒体 能够在某设备上成功进行远程播放,我们就称该设备是该媒体资源的 兼容远程播放设备。

注

用户代理可以使用 track 元素的srclang 属性作为文本轨道数据语言的提示, 以帮助识别 兼容远程播放 设备。

用户代理为查找兼容远程 播放设备而考虑过的某媒体 元素的媒体资源 称为 可用性源集合。

某媒体 元素中用于在选定远程播放设备上发起远程 播放的媒体资源 称为远程播放源。远程播放 源必须属于该媒体元素的可用性源 集合。

从可用性源集合中选择远程播放源的 机制由具体实现决定, 但用户代理应该将 可用性源集合中的每个资源都视为潜在的远程 播放源。

注
为选定设备选择远程播放 源的算法 取决于用户代理以及所支持的远程 播放设备类型。例如,在媒体 镜像情况下,用户代理只需遵循 HTMLMediaElement 的 资源选择算法。但是,如果使用媒体 远程传送或媒体投送,最佳媒体 源可能取决于所选远程播放 设备 的获取和播放能力。

如果用户代理无法确定适用于远程播放设备的远程播放源, 则 建议用户代理将可用性源 集合中所有资源的元数据(例如 扩展 MIME 类型) 发送给远程播放设备,使其可以运行自己的 资源 选择算法并选择远程 播放 源。

如果可用远程 播放 设备列表为空,或者其中没有任何设备与媒体 元素的可用性源集合中的任何源兼容, 则该媒体 元素的远程播放是不可用的。否则,远程播放是 可用的。 对于某媒体元素,如果远程 播放不可用,则设置为 false, 如果可用,则设置为 true 的 boolean 称为该媒体元素的 可用性。

如果用户代理停止 监视可用远程播放设备列表 (例如由于用户控制或为节省电量),它应该 使用 false 调用全局可用性 回调集合中的所有回调,以便页面可以适当地更新 其用户体验。它还应该将所有媒体元素的 可用性值设置 为 false,以便如果用户代理稍后恢复 监视可用远程播放设备列表,可用性信息能够 正确传播。

5.2.1.3 获取远程播放设备可用性 信息

当调用 watchAvailability() 方法时,用户代理必须运行以下步骤:

输入
callback,将使用可用性信息 调用的回调。
输出
promise,一个Promise。
  1. 令 promise 为一个新的Promise。
  2. 返回 promise,并运行以下步骤:
  3. 如果disableRemotePlayback 属性存在于媒体元素上,则以 InvalidStateError 拒绝 promise 并中止所有剩余步骤。
  4. 如果用户代理在浏览 上下文的整个生命周期中都无法监视 可用 远程播放设备列表(例如,因为用户 禁用了此功能),则并行运行以下步骤:
    1. 兑现 promise。
    2. 将 一个任务排入队列,以使用 false 作为参数调用 callback。
    3. 中止所有剩余步骤。
  5. 如果用户代理无法持续监视 可用远程播放设备列表,但可以在 发起远程播放时短暂执行,则:
    1. 以 NotSupportedError 异常拒绝 promise。
    2. 中止所有剩余步骤。
  6. 令 callbackId 为一个正整数,在该媒体 元素的浏览 上下文中, 它在这些步骤之前返回的所有 callbackIds 中都是唯一的。
  7. 创建一个元组 (callbackId, callback),并 将其添加到此媒体元素的可用性 回调集合中。
  8. 使用 callbackId 兑现 promise,并 并行运行以下步骤:
    1. 将 一个任务排入队列,以使用该媒体 元素当前的可用性作为参数调用 callback。
    2. 如果用户代理当前未监视 可用远程播放设备列表,则运行 监视 可用远程播放 设备列表的算法。
注

为 callbackId 分配值的一种简单算法是 为每个浏览 上下文维护一个计数器,并 在步骤 6 中递增该计数器。

注
为避免泄露可用于对用户进行指纹识别的信息, 用户代理不应分配使用来自浏览器配置文件或 远程播放设备的任何持久信息的 callbackId。
5.2.1.4 监视可用远程播放设备列表

如果可用性回调集合 非空,或者 存在等待中的 发起远程播放请求,则用户代理 必须通过运行以下步骤来监视可用远程播放 设备列表:

  1. 检索可用的远程播放设备(使用 特定于实现的机制),并令 newDevices 为此列表。
  2. 对浏览 上下文所知的每个媒体元素:
    1. 如果disableRemotePlayback 属性存在于 mediaElement 上,则中止 此元组的所有 剩余步骤并继续处理下一个元组。
    2. 将 newAvailabilityValue 设置为该媒体元素的 可用性值,但在计算时 使用 newDevices 列表,而不是可用 远程播放设备列表。
    3. 如果当前可用性不等于 newAvailabilityValue,则对于该元素可用性 回调集合中的每个 (callbackId, callback):
      1. 将 一个任务排入队列,以使用 newAvailabilityValue 作为参数调用 callback。
  3. 将可用 远程播放设备列表设置为 newDevices 的值。
5.2.1.5 停止观察远程播放设备可用性

当调用 cancelWatchAvailability() 方法时,用户代理必须运行以下步骤:

输入
id,回调标识符。
输出
promise,一个Promise。
  1. 令 promise 为一个新的Promise。
  2. 返回 promise,并运行以下步骤:
  3. 如果disableRemotePlayback 属性存在于 媒体元素上,则以 InvalidStateError 拒绝 promise, 并中止所有剩余步骤。
  4. 如果参数 id 为 undefined, 则清空可用性 回调集合。
  5. 否则,如果 id 与可用性 回调集合中任一条目的 callbackId 匹配,则从集合中移除 该条目。
  6. 否则,以 NotFoundError 拒绝 promise,并 中止所有剩余步骤。
  7. 如果可用性回调集合 现在为空,并且 没有等待中的 发起远程 播放请求,则为节省电量,取消任何 等待中的监视 可用远程 播放设备列表的任务。
  8. 兑现 promise。
注
用于监视远程播放 设备 可用性,以及确定远程 播放设备与所选可用性源 集合兼容性的机制,由用户代理决定。

5.2.2 提示用户更改远程播放状态

当调用 prompt() 方法时, 用户代理必须运行以下步骤:

输入
无,但该算法会引用媒体元素、其 remote 属性及其 可用性源集合。
输出
一个Promise。
  1. 令 promise 为一个新的Promise。
  2. 返回 promise,并并行 继续运行这些步骤。
  3. 如果disableRemotePlayback 属性存在于 媒体元素上,则以 InvalidStateError 拒绝 promise,并中止所有剩余步骤。
  4. 如果对于同一 媒体 元素,甚至同一浏览 上下文,之前对 prompt() 的调用已经存在一个 尚未敲定的 promise,则用户代理可以以 OperationError 异常拒绝 promise,并中止所有 剩余步骤。
    注
    此处的理由是,用户代理可能会显示一个 对媒体元素或 浏览 上下文而言是模态的对话框。在这种情况下,第二次调用 prompt() 将无法显示任何 UI。
  5. 如果文档的活动 window没有 瞬态 激活,则以 InvalidAccessError 异常拒绝 promise 并中止这些步骤。
  6. 可选地,如果用户代理预先知道此特定媒体元素的远程播放 不可行(与当前state或可用远程 播放设备列表无关),则以NotSupportedError 拒绝 promise,并中止所有剩余步骤。
    注
    这种情况的一个示例是,用户代理仅 支持媒体投送,而媒体元素的源 不是可以传递给远程播放设备的 URL。
  7. 如果用户代理需要显示可用远程 播放设备列表,并且当前未监视 可用 远程播放设备列表,则并行运行 监视 可用远程播放设备列表的步骤。
  8. 如果远程播放不可用,并且在 用户许可请求完成前仍将保持不可用, 则以 NotFoundError 异常拒绝 promise,并 中止所有剩余步骤。
  9. 请求用户许可,以更改远程播放 状态。
    注
    请求许可的一种示例 UI 可以允许用户 选择新的远程播放 设备、在本地 和远程播放设备之间切换,或者与远程 播放设备断开连接。
    注
    用户可能已经为相关用途选择了远程播放 设备,例如镜像 显示器或当前页面的内容。在这种情况下, 用户代理可以选择跳过用于选择设备的 UI,并 立即继续下一步。
  10. 如果用户选择了一个远程播放设备 device 来发起远程播放,则 用户代理必须运行以下步骤:
    1. 将 remote 对象的state 设置为connecting。
    2. 兑现 promise。
    3. 将一个 任务排入队列,以在remote 属性上触发一个事件,该事件名为 connecting,该属性属于媒体 元素。该事件不得冒泡,不得 取消,并且没有默认操作。
    4. 为媒体元素 与远程播放设备建立 连接 device。
    注

    通过选择远程播放 设备,用户即授予 许可以使用该设备。

  11. 否则,如果用户选择与远程 播放设备 device 断开连接,则用户代理必须运行 以下步骤:
    1. 兑现 promise。
    2. 对 device 运行与远程 播放设备断开连接 算法。
  12. 否则,视为用户拒绝许可 使用该设备,因此以 NotAllowedError 异常拒绝 promise,并隐藏用户代理显示的 UI。
注
UI 和设备选择的实现细节由 用户代理决定;例如,它可以向用户显示一个对话框,并允许 用户选择可用设备(授予 许可),或取消选择(拒绝 许可)。在大多数情况下,可用设备会公布 一个用户友好的名称,以及该名称的区域设置和文本方向 信息。建议用户代理呈现 此用户友好的名称,并在区域设置和文本方向已知时 使用这些信息。

5.2.3 state 属性

state 属性表示 RemotePlayback 连接的当前状态。根据连接 状态,它可以取RemotePlaybackState 的以下值之一:

  • connecting 表示 用户代理正在尝试与所选远程播放设备发起远程 播放。这是 prompt() 返回的 promise 被兑现时的初始状态。在此状态下, 媒体元素的本地播放会继续,并且媒体命令仍然 作用于本地播放状态。
  • connected 表示 从本地播放到远程播放的转换已经完成,所有 媒体命令现在都作用于远程播放 状态。
  • disconnected 表示 远程播放尚未发起、发起失败或已经 停止。所有媒体命令都将作用于本地 播放状态。可以通过调用 prompt() 发起远程播放。

5.2.4 与远程播放设备建立连接

当用户代理要与 远程播放设备建立连接时,它必须运行以下步骤:

输入
remote,要建立 连接的RemotePlayback 对象。
device,要 连接到的远程 播放设备。
  1. 如果 remote 的state 不等于 "connecting",则中止所有 剩余步骤。
  2. 请求将 remote 连接到 device。此步骤的实现 由用户代理决定。
  3. 如果连接成功完成,则将一个任务排入队列 以 运行以下步骤:
    1. 将 remote 的state设置为 "connected"。
    2. 在 remote 上触发一个 事件,事件名为connect。
    3. 将当前媒体元素状态 与 远程播放状态同步。此步骤的 实现 由用户代理决定。
  4. 如果连接失败,则将一个任务排入队列 以运行以下 步骤:
    1. 将 remote 的远程播放 状态设置为 "disconnected"。
    2. 在 remote 上触发一个 事件,事件名为disconnect。

当远程播放状态为 "connected" 时,用户代理应该暂停媒体元素的本地音频和视频输出。

如果用户代理 正在为媒体元素向用户公开 用户界面(即使用 默认控件),则用户代理应该通过图标或 其他方式传达远程播放状态为 "connected" 这一事实。

注
用于将用户代理与 远程播放设备连接、选择远程播放 源以及发起播放的机制,均由 用户代理自行实现。该连接很可能必须提供一种双向 消息抽象,能够将媒体命令传递到 远程播放设备并接收媒体播放状态,从而 保持媒体元素状态和远程播放 状态同步(除非使用媒体镜像)。
注
建议用户代理尽可能将区域设置和文本方向 信息传递给远程播放设备,以便 远程播放设备能够调整其用户 界面和操作功能,以适应反映 用户偏好的特定于区域设置的属性。例如,远程 播放 设备可以使用该信息选择与用户代理相同的默认文本 轨道,还可以设置它在获取媒体资源时发送的 HTTP Accept-Language 标头。
注
当媒体元素处于 "connected" 状态且其内容 正在远程播放设备上渲染时, 用户代理不应渲染该媒体元素的输出。

5.2.5 浏览器发起的远程播放

用户代理可以支持从浏览器连接 到远程播放设备。这可以通过 向向用户 公开的用户界面添加适当的媒体控件,或者当用户激活系统范围的 显示镜像时来实现。此功能称为浏览器 发起的远程播放。支持 浏览器发起的远程播放的用户代理应该仅在用户通过 用户手势表达了这样做的意图时发起远程 播放,例如点击浏览器中的按钮。

如果用户代理支持浏览器发起的 远程播放, 则 state 属性必须反映与远程播放设备连接的当前状态。当浏览器 发起或终止远程播放时,它必须按照与远程播放设备建立 连接以及 与远程播放 设备断开连接的算法触发相应事件。

如果浏览器将 在新创建的媒体元素上发起远程播放,则它 应该将其 state 属性的值初始化为 "connecting",然后按照 与远程播放 设备建立连接的步骤操作。

注
实现浏览器发起的远程播放的用户代理 应考虑它与影响媒体播放的其他浏览器策略之间的交互, 例如哪些媒体元素 被允许播放 以及后台媒体播放优化。

5.2.6 媒体命令和媒体播放状态

一旦与远程 播放 设备的连接建立, HTMLMediaElement 接口就会与远程 播放的媒体进行交互。

当 RemotePlayback 对象的state 为 "connected" 时,以下条件将 本地播放状态、媒体元素状态和 远程播放状态关联起来:

如果发送任何命令失败,用户代理可以 与远程播放 设备断开连接。

注

远程播放设备可以仅实现用户 代理播放引擎的一部分 功能,并且某些HTMLMediaElement API 在远程播放期间并不总是 适合使用。在这种情况下,在远程播放期间不受支持的 媒体命令执行后, 本地播放状态应尽可能 准确地反映实际远程播放状态。

例如,当连接到不支持 fastSeek() 的远程播放 设备时调用它, HTMLMediaElement 的 seeking 属性应保持为 false,并且不应触发任何 seeking 事件。

5.2.7 与远程播放设备断开连接

当用户代理要与远程 播放设备断开连接时,它必须执行以下操作:

输入
remote,表示要停止的播放的RemotePlayback 对象。
device,要与之 断开连接的远程 播放设备。
  1. 如果 remote 的state 为 disconnected,则中止所有 剩余步骤。
  2. 将一个任务排入队列 以运行以下步骤:
    1. 请求断开 remote 与 device 的连接。此 步骤的实现由用户代理决定。
    2. 将 remote 的 state 更改为 disconnected。
    3. 在 remote 上触发一个 事件,事件名为disconnect。
    4. 将当前媒体元素状态 与 本地播放状态同步。此步骤的实现 由用户代理决定。

如果远程播放设备在播放期间突然断开连接 (例如由于断电或网络断开), 用户代理应该先运行监视 可用远程播放设备列表的步骤,再运行 与远程播放 设备断开连接的步骤。这使得 可用性 回调集合中的回调可以在触发 disconnect 事件之前被调用,从而使 页面可以更新自身,以表明无法恢复播放。

注
当用户代理请求远程播放设备停止播放时,该设备 实际上可能不会停止媒体播放;这取决于 用户代理和远程播放设备的实现。 在这种情况下,停止远程播放意味着用户代理 仅与远程播放设备断开连接,而 媒体 元素切换到 disconnected 状态。

5.2.8 事件处理程序

以下是实现 RemotePlayback 接口的对象必须作为 事件处理程序 IDL 属性支持的事件处理程序 (以及它们对应的 事件 处理程序事件类型):

事件处理程序 事件处理程序事件类型
onconnecting connecting
onconnect connect
ondisconnect disconnect

5.3 对 HTMLMediaElement 的扩展

WebIDLpartial interface HTMLMediaElement {
  [SameObject] readonly attribute RemotePlayback remote;

  [CEReactions] attribute boolean disableRemotePlayback;
};

remote 属性必须 返回与该 媒体元素 关联的RemotePlayback 实例。

5.3.1 disableRemotePlayback 属性

某些页面可能希望禁用某个媒体 元素的远程播放;例如,它们可能更愿意使用 PresentationRequest 在演示屏幕上呈现完整文档。为支持 此用例,在 audio 和 video 元素的内容属性列表中 添加了新的 disableRemotePlayback 属性。

对应的disableRemotePlayback IDL 属性会 反映每个元素的 disableRemotePlayback 内容属性值,并被添加到 HTMLMediaElement 接口中。 disableRemotePlayback IDL 属性必须 反映同名内容属性。

5.3.2 禁用远程播放

如果disableRemotePlayback 属性存在于 媒体 元素上,则用户代理不得远程播放 该媒体元素,也不得提供任何用于执行此操作的 UI。

当disableRemotePlayback 属性被添加到 媒体 元素时,用户代理必须运行以下步骤来 禁用远程播放:

  1. 以 InvalidStateError 拒绝所有由 RemotePlayback 方法返回的等待中 promise。
  2. 清空该媒体 元素的可用性回调集合。
  3. 如果其 state 不是 disconnected,则对媒体元素已连接或正在连接的远程 播放设备运行与远程 播放设备断开连接算法。

6. 安全和隐私考虑

本节为非规范性内容。

6.1 个人身份信息

调用通过 watchAvailability() 方法提供的 callback,会泄露通常通过 局域网发现的 远程播放设备是否存在的一位 信息。这可能与其他 信息结合使用来对用户进行指纹识别。不过,此信息 也取决于用户的本地网络环境,因此风险 得以降低。此外,按照设计,远程 播放设备的人类可读名称不会透露给页面。

该 API 支持监视可用远程播放 设备列表。用户代理如何确定远程播放设备与媒体 元素的资源 之间的兼容性和 可用性属于实现细节。如果用户代理将 媒体资源 与特定类型的设备进行匹配以确定其可用性, 则此功能可用于在未经用户 同意的情况下探测用户拥有哪种 远程播放设备的信息。

如果用户通过浏览器设置禁用了后台监视, 用户代理就不应监视可用远程 播放设备列表。

6.2 用户界面指南

源显示

当在更改远程播放 状态的步骤中请求用户许可使用远程 播放 设备时,用户代理应明确说明该 请求来自哪个源。

显示请求远程播放的源有助于 用户了解是什么内容发出了请求,尤其是 当请求是从子 可导航对象发起时。例如, 嵌入内容可能会试图诱使用户点击,以 触发启动不需要的远程播放的请求。

显示将要呈现的源有助于用户了解 该内容是否来自潜在 可信源 (例如 https:),以及它是否对应已知或预期的网站。

6.3 设备访问

Remote Playback API 抽象了显示器中的“本地” 含义,也就是说,它将可通过网络访问的显示器公开为 如同本地显示器一样。Remote Playback API 要求 页面获得用户许可后才能访问任何显示器,以缓解 可能出现的问题,例如在其他人可看到的显示器上 显示不需要的内容。

6.4 本地与远程播放设备之间的消息传递

本规范不会强制规定 本地播放设备与远程播放 设备之间的通信协议,但用户代理应对它们之间的消息 保密性和真实性提供一定保证。

6.5 安全上下文

Remote Playback API 并不限于 [SECURE-CONTEXTS],因为 它向 Web 应用公开了一项用户代理通常 在所有媒体上原生提供的功能,而不考虑浏览 上下文。 用户代理可以将 API 限制为 [SECURE-CONTEXTS],方法是在 非安全上下文中执行监视可用远程播放设备列表 算法时始终返回空列表。

A. 候选推荐标准退出标准

要使本规范推进到提议推荐标准阶段, 每项功能都必须至少有两个独立且可互操作的 实现。每项功能可以由一组不同的 产品实现,并不要求所有功能都由 单个产品实现。此外,实现必须证明支持 媒体远程传送和媒体投送这两种情况, 可以 在同一产品中实现,也可以在不同产品中实现。

就这些标准而言,我们定义以下术语:

独立
每个实现必须由不同的参与方开发,并且 不得共享、复用或派生自另一个符合条件的 实现所使用的代码。与 本规范实现无关的代码部分不受此 要求约束。
可互操作
通过官方测试套件中相应的测试用例。
实现
符合以下条件的用户代理:
  1. 实现本规范。
  2. 可供公众使用。该实现可以是 正式发布的产品或其他公开可用版本(即 beta 版本、预览版或“每日构建版”)。非正式发布的产品 版本必须已经实现相关功能至少 一个月,以证明其稳定性。
  3. 不是实验性的(即不是专门设计用于 通过测试套件而无意在今后正常使用的版本)。

B. 参考文献

B.1 规范性参考文献

[dom]
DOM 标准. Anne van Kesteren. WHATWG. 现行标准. URL: https://dom.spec.whatwg.org/
[HTML]
HTML 标准. Anne van Kesteren; Domenic Denicola; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. 现行标准. URL: https://html.spec.whatwg.org/multipage/
[PRESENTATION-API]
演示 API. Mark Foltz; Dominik Röttsches. W3C. 2023 年 10 月 16 日. W3C 候选推荐标准. URL: https://www.w3.org/TR/presentation-api/
[RFC2119]
用于 RFC 中指示 要求级别的关键词. S. Bradner. IETF. 1997 年 3 月. 当前最佳实践. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
RFC 2119 关键词中大写与小写的歧义. B. Leiba. IETF. 2017 年 5 月. 当前最佳实践. URL: https://www.rfc-editor.org/rfc/rfc8174
[WEBIDL]
Web IDL 标准. Edgar Chen; Timothy Gu. WHATWG. 现行标准. URL: https://webidl.spec.whatwg.org/

B.2 资料性参考文献

[SECURE-CONTEXTS]
安全上下文. Mike West. W3C. 2023 年 11 月 10 日. W3C 候选推荐标准. URL: https://www.w3.org/TR/secure-contexts/
[url]
URL 标准. Anne van Kesteren. WHATWG. 现行标准. URL: https://url.spec.whatwg.org/