在网络上自动播放音频和视频是一项强大的功能,但在不同平台上受到不同的限制。目前,大多数桌面浏览器始终允许网页通过 JavaScript 开始播放 <video>
或 <audio>
,而无需用户互动。不过,大多数移动浏览器都要求用户明确执行手势,JavaScript 才能发起播放。这有助于确保移动用户(其中许多用户需要付费使用带宽或可能身处公共环境)不会在未明确与网页互动的情况下意外开始下载和播放媒体。
过去,很难确定是否需要用户互动才能开始播放,以及检测尝试(自动)播放失败时发生的失败情况。虽然存在各种权宜解决方法,但效果并不理想。我们早就应该对底层 play()
方法进行改进来解决此不确定性问题,而这项改进现已应用于网络平台,并在 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()
承诺永不拒绝
对于 <video src="not-existing-video.mp4"\>
,由于视频不存在,play()
承诺会按预期遭拒。对于 <video><source src="not-existing-video.mp4" type='video/mp4'></video>
,play()
promise 永远不会拒绝。只有在没有有效来源时,才会出现这种情况。