在网络上自动播放音频和视频是一项非常强大的功能,且该功能在不同平台上受不同限制。如今,大多数桌面浏览器将始终允许网页通过 JavaScript 开始播放 <video>
或 <audio>
,而无需用户干预。不过,大多数移动浏览器要求先执行显式用户手势,然后才允许 JavaScript 发起的播放。这有助于确保移动用户(其中许多用户需支付带宽费用或可能身处公共环境中)不会在没有与网页明确互动的情况下意外开始下载和播放媒体。
过去,确定是否需要用户互动才能开始播放,以及检测(自动)播放尝试但失败时发生的失败情况一直很困难。存在各种权宜解决方法,但它们并不是理想的方法。为解决这种不确定性而对底层 play()
方法进行改进已久,现在,这已发布到 Web 平台,在 Chrome 50 中进行了初始实现。
现在,对 <video>
或 <audio>
元素的 play()
调用会返回 Promise。如果播放成功,系统会执行 promise;如果播放失败,则 promise 将被拒绝,并显示一条说明失败的错误消息。这样,您就可以编写如下所示的直观代码:
var playPromise = document.querySelector('video').play();
// In browsers that don’t yet support this functionality,
// playPromise won’t be defined.
if (playPromise !== undefined) {
playPromise.then(function() {
// Automatic playback started!
}).catch(function(error) {
// Automatic playback failed.
// Show a UI element to let the user manually start playback.
});
}
除了检测 play()
方法是否成功之外,基于 Promise 的新接口还允许您确定 play()
方法何时成功执行。在某些情况下,网络浏览器可能会决定延迟开始播放的内容。例如,桌面版 Chrome 只有在标签页显示后才会开始播放 <video>
。只有在播放实际开始播放后,Promise 才会执行;也就是说,在播放媒体内容之前,系统不会执行 then()
中的代码。之前用于确定 play()
是否成功的方法(例如,在 playing
事件等待一段时间后假定未触发时假定失败)在延迟播放场景中很容易出现假负例。
我们发布了这项新功能的实际示例。在支持这一基于 Promise 的界面的浏览器(例如 Chrome 50)中查看。预先警告:当您访问该网页时,该网页会自动播放音乐。(除非不是!)
危险区域
<video>
中的 <source>
使 play()
promise 永远不会拒绝
对于 <video src="not-existing-video.mp4"\>
,play()
promise 会按预期拒绝,因为视频不存在。对于 <video><source src="not-existing-video.mp4" type='video/mp4'></video>
,play()
promise 绝不会拒绝。仅当没有有效来源时,才会发生这种情况。