1. 引言
大多数用户代理都有自己的机制来阻止自动播放媒体,这些机制依赖于具体实现。网页开发者需要一种方法来检测媒体是否允许自动播放,以便采取相应措施,例如选择备用内容或在媒体不允许自动播放时提升用户体验。例如,如果某个用户代理仅阻止有声音的自动播放,网页开发者可以用无声媒体替代有声媒体,从而保持媒体播放,而不是展示一个看起来像静止图片的被阻止媒体。如果用户代理不允许任何自动播放媒体,网页开发者则可以停止加载媒体资源及相关任务,以节省用户的带宽和CPU使用率。当前,本规范仅处理 HTMLMediaElement
(video
和
audio)
以及 Web Audio API。本规范不处理
Web Speech API 和动画
image
(GIF动画)。
2. 自动播放检测API
可通过Navigator
对象进行自动播放检测。检测结果可让作者了解具有相同类型的媒体,或文档中存在的指定媒体类型,是否允许自动播放,或了解某一特定元素是否允许自动播放。
2.1. 自动播放政策枚举
enum {AutoplayPolicy "allowed" ,"allowed-muted" ,"disallowed" };
| 枚举值 | 描述 |
|---|---|
"allowed"
| 媒体允许自动播放。 |
"allowed-muted"
|
无声媒体
允许自动播放。
无声媒体元素
是满足以下任一条件的 HTMLMediaElement:
|
"disallowed"
| 不允许任何媒体自动播放。 |
disallowed),
那么当用户在页面或媒体上执行支持的用户手势后,政策可变更为
allowed
或 allowed-muted。
2.2. 自动播放检测方法
enum {AutoplayPolicyMediaType "mediaelement" ,"audiocontext" }; [Exposed =Window ]partial interface Navigator {AutoplayPolicy (getAutoplayPolicy AutoplayPolicyMediaType );type AutoplayPolicy (getAutoplayPolicy HTMLMediaElement );element AutoplayPolicy (getAutoplayPolicy AudioContext ); };context
| 枚举值 | 描述 |
|---|---|
mediaelement
|
用于查询 HTMLMediaElement
及其扩展(如 HTMLVideoElement
和 HTMLAudioElement)
的状态。
|
audiocontext
|
用于查询 AudioContext
的状态。
|
2.2.1. 按媒体类型查询
getAutoplayPolicy(type)
方法返回媒体元素或音频上下文的大致状态,这些对象存在于与所查询
Window
相关联的
Navigator
对象所包含的 document
中,是否允许自动播放。这里的大致状态意味着对于每个具有给定媒体类型的元素,返回结果不一定总是正确。
disallowed,
还是有可能存在于同一个文档中的某些媒体被允许自动播放。在这种情况下,建议作者同时按具体元素查询,以获得更精确的结果。
例如,初始时,按类型查询和按对象查询的结果均为
disallowed。
当用户点击媒体元素后,如果用户代理认为该行为是用户意图而允许该元素自动播放,则对该媒体元素查询结果变为
allowed,
但按类型查询或对其他尚未被点击的媒体元素查询,仍返回
disallowed。
当调用 getAutoplayPolicy(type)
方法时,用户代理必须执行以下步骤:
-
如果
type为mediaelement, 则返回当前状态结果,表示存在于Window相关联Navigator的document中的HTMLMediaElement及其扩展(如HTMLVideoElement和HTMLAudioElement) 的自动播放状态。 -
如果
type为audiocontext, 则返回当前状态结果,表示存在于Window相关联Navigator的document中AudioContext的自动播放状态。
- 如果返回值为
allowed - 所有对应类型的媒体均允许自动播放。
- 如果返回值为
allowed-muted -
所有对应类型的无声媒体均允许自动播放。
说明:当前,只有当媒体类型为
mediaelement时才会返回该属性。 无声媒体指无声媒体元素。 - 如果返回值为
disallowed - 所有对应类型的媒体都不允许自动播放。
foo.com)返回 allowed,
它嵌入了一个iframe,iframe中为 B 文档(来自 bar.com)。用户代理可以让子文档B的查询结果和顶级文档A一致(继承自顶级文档),也可以让文档B返回不同的结果(例如
disallowed)。
统一处理(继承结果)有助于降低复杂度,且能让自动播放阻止行为更一致。差异化处理则有助于提供更精细化的自动播放控制。
2.2.2. 按元素查询
getAutoplayPolicy(element)
和 getAutoplayPolicy(context)
方法返回给定元素当前是否允许自动播放的状态。
- 如果返回值为
allowed - 此元素在当前执行上下文中允许自动播放。
- 如果返回值为
allowed-muted -
仅当此元素为无声时才允许自动播放。
说明:当前,只有当指定元素为
HTMLMediaElement或其扩展(如HTMLVideoElement或HTMLAudioElement)时才会返回该属性。 无声媒体指无声媒体元素。此外,如果作者在无声媒体元素播放后立刻使其变为有声,则建议用户代理立即暂停该媒体元素,因为它已不再是无声。
- 如果返回值为
disallowed -
此元素不允许自动播放。
说明:对于
HTMLMediaElement, 如果作者调用其play(), 则play()返回的 promise 会被NotAllowedError异常拒绝。对于
AudioContext, 其AudioContextState会始终处于suspended状态。
如果按媒体类型查询的结果和按元素查询结果不同,作者应以后者为准。示例2展示了可能场景。
HTMLMediaElement
(或其扩展,如 HTMLVideoElement
和 HTMLAudioElement)
或 AudioContext,
则这些方法将抛出 TypeError。
3. 示例
if ( navigator. getAutoplayPolicy( "mediaelement" ) === "allowed" ) { // 创建并播放一个新的媒体元素。 } else if ( navigator. getAutoplayPolicy( "mediaelement" ) === "allowed-muted" ) { // 创建一个新的媒体元素并以静音方式播放。 } else { // 不允许自动播放,或许可以显示一张海报。 }
AudioContext
是否可以启动。
if ( navigator. getAutoplayPolicy( "audiocontext" ) === "allowed" ) { let ac= new AudioContext(); ac. onstatechange= function () { if ( ac. state=== "running" ) { // 启动音频应用。 } } } else { // audio context 不允许启动,显示UI引导用户启动。 // 用户通过事件调用 ac.resume() 启动音频,onstatechange 可用于感知音频栈准备好。 }
function handlePlaySucceeded() { // 更新控件UI为正在播放。 } function handlePlayFailed() { // 显示按钮让用户显式启动视频,同时用图片元素显示为海报替代视频。 } let video= document. getElementById( "video" ); switch ( navigator. getAutoplayPolicy( video)) { case "allowed" : video. src= "video.webm" ; video. play(). then( handlePlaySucceeded, handlePlayFailed); break ; case "allowed-muted" : video. src= "video.webm" ; video. muted= true ; video. play(). then( handlePlaySucceeded, handlePlayFailed); break ; default : // 不允许自动播放,无需下载资源。 handlePlayFailed(); break ; }
AudioContext
是否可以启动。
let ac= new AudioContext(); if ( navigator. getAutoplayPolicy( ac) === "allowed" ) { ac. onstatechange= function () { if ( ac. state=== "running" ) { // 启动音频应用。 } } } else { // 显示UI引导用户启动音频应用。 // 用户通过事件调用 ac.resume() 启动音频,onstatechange 可用于感知音频栈准备好。 }
4. 安全与隐私注意事项
安全与隐私自查表 § 问题。本规范介绍的API在安全和隐私方面几乎没有影响。它不会暴露任何可用于识别用户的敏感信息,也不会暴露任何控制传感器和用户设备的能力,不会引入任何会在多个浏览会话中持续存在的原点状态,也不会允许原点向底层平台发送任何数据,亦不会引入或启用新的脚本执行和加载机制,不允许原点在用户代理的原生UI上绘制内容,也无法检测用户是否处于隐私或非隐私浏览模式。
5. 致谢
本规范由W3C媒体工作组共同编写。编辑对 Alastor Wu、Becca Hughes、Christoph Guttandin、Chris Needham、Chris Pearce、Dale Curtis、Eric Carlson、François Daoust、Frank Liberato、Gary Katsevman、Jean-Yves Avenard、Jer Noble、Mattias Buelens、Mounir Lamouri、Paul Adenot 和 Tom Jenkinson 对本规范的贡献表示感谢。