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() 内のコードは実行されません。playing イベントが設定された時間待機し、発生しなかった場合は失敗と見なすなど、play() が成功したかどうかを判断する以前の方法では、再生の遅延シナリオで誤検出が発生する可能性があります。

この新機能のライブ例を公開しました。この 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 は決して拒否されません。有効なソースがない場合にのみ発生します。

Chromium のバグ