HTMLMediaElement.play() が Promise を返す

ウェブ上での音声と動画の自動再生は強力な機能であり、プラットフォームによってさまざまな制限を受けます。現在、ほとんどのパソコンのブラウザでは、ユーザーの操作なしでウェブページが 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.
    });
}

新しい Promise ベースのインターフェースでは、play() メソッドが成功したかどうかを検出できるだけでなく、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 のバグ