HTMLMediaElement.play() 会返回 promise

在网络上自动播放音频和视频是一项非常强大的功能,且该功能在不同平台上受不同限制。如今,大多数桌面浏览器将始终允许网页通过 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 绝不会拒绝。仅当没有有效来源时,才会发生这种情况。

Chromium 错误