Safari, Chromeの自動再生ポリシー変更のまとめ

# 概要

本記事は、[AbemaTV Advent Calendar 2017](https://adventar.org/calendars/2216) の12/23分の投稿です。

Safari, Chromeにおいて、メディア要素（ `<video>`, `<audio>` ）の自動再生におけるポリシーが変更が発表されました。Safariは `11.0` で既に適用済み、Chromeは2018年3月頃予定の `65` で適用されます。

自動再生が許可される条件は、大まかに以下です。

- タップやクリック等のユーザーインタラクションをきっかけに再生される（＝自動再生ではない）
- ミュートされている、またはビデオ要素の場合は音声トラックを含んでいない
- その他、ブラウザ毎の条件（後述）を満たしている

本記事では、自動再生可否の確認方法と、ブラウザ毎の詳細について紹介します。

# 自動再生可否の確認方法

自動再生の条件を満たしていない場合には、再生しようとしても一時停止 `paused=true` の状態になります。

実際にこちらのプロパティを確認する以外の手段として、メディア要素の `play()` 実行時に、Promiseが得られるようになっており、再生が成功したかどうかが判別できます。

```js
var promise = document.querySelector('video').play();

if (promise !== undefined) {
    promise.catch(error => {
        // Auto-play was prevented
        // Show a UI element to let the user manually start playback
    }).then(() => {
        // Auto-play started
    });
}
```

例えば、音声つきが許可されていなければミュート状態で自動再生したい、といった場合は以下のように振り分けることができます。

```js
var video = document.querySelector('video');
var promise = video.play();

if (promise !== undefined) {
    promise.catch(error => {
        video.muted = true;
        video.play();
    });
}
```

# ブラウザ毎の詳細

## Safari

Safariでは、自動再生の振る舞いについて、設定できるようになりました。

環境設定の `環境設定` → `Webサイト` → `自動再生` もしくは、アドレスバーを右クリックして `このWebサイトでの設定` より、以下の中から指定できます。

- すべてのメディアを自動再生
- サウンド付きメディアは再生しない（デフォルト）
- 自動再生しない

![スクリーンショット 2017-12-23 19.56.24.png](https://qiita-image-store.s3.amazonaws.com/0/36456/3a71bf59-3d69-7f1d-4a09-2c0ad38a5678.png)

さらに `自動再生しない` を指定された場合はミュート状態に関わらず、自動再生されないため、こちらの考慮も求められます。

_なお、YouTube, Netflixあたりはデフォルトが「すべてのメディアを自動再生」になっている様子..._

## Chrome

Chromeの場合は、Safariよりも条件が複雑です。

まず、デスクトップでは新たに `Media Engagement Index`（以下、MEI）という指標が追加されており、これに基いて自動再生の可否が変化します。他方、モバイルではホームスクリーンに追加されていることが条件になります。

このMEIについて見ていきましょう。

### Media Engagement Index

MEIは [chrome://media-engagement/](chrome://media-engagement/) （※）から確認でき、Webサイト毎にそのユーザーによって重要なメディア（Significant playback）が再生されていたかどうかを元にスコアを決定します。

![スクリーンショット 2017-12-23 19.49.09.png](https://qiita-image-store.s3.amazonaws.com/0/36456/c29ab484-b261-3d4d-af13-e5df846b93b2.png)

Significant playback かどうかは、1回の訪問毎に判別され、訪問数と共にオリジン別に記録されます。 `<iframe>` の場合はメインフレームのオリジンに記録されます。

以下がその判別の条件です。

- 以下を7秒以上満たしていること
  - ビデオ要素の大きさが `200 x 140` 以上であること
  - 音声トラックがあること
  - 再生されていること
  - ミュートされていないこと
- タブが最後の2秒間に音声を出していること（Androidを除く）
- タブが表示されていること
- タブがミュートされていないこと

記録された結果より、さらに以下の通りMEIのスコアが算出され、次回の訪問時に適用されます。

| 訪問数|MEI|
|:--|:--|
| 5未満 |0|
| 5以上 |`Significant playbacks` / `Visits`（0 〜 1）|

MEIが `0.7` に達すると音声つきの自動再生が許可され、 `0.5` を下回ると拒否されます。例えば、一度 `0.7` で許可状態になれば `0.5` を下回らない限り、すなわち `0.51` などでも許可状態のままです。MEIの収集は既に開始されているため、自動再生ポリシーの適用時点では既に相応のスコアが算出されている状態になります。

これによって、ユーザーの閲覧状況に応じ、頻繁にビデオを視聴しているWebサイトのみで音声つきの自動再生が許可されるようになります。違う見方をすると、自動で決められるため、頻度は少ないが音声つきで構わない、といった設定をユーザー側が任意にすることはできません。

※ `Canary 65.0.3301.0 時点` では `Significant Playbacks` はスコアに使われず、代わりに `Playbacks` が用いられています。違いについての情報は見つけられていませんが、 `Playbacks` でも先程の条件と同様に考えてよさそうです。また、訪問数やMEIの閾値については、変更される可能性があるとのことです。

### iframe
`<iframe>` は https://www.chromium.org/audio-video/autoplay より、ミュートもしくは音声トラックなしのビデオのみ自動再生可能、 `gesture="media"` 属性の付与で自動再生の権限を渡すことができるそうです。が、同じくcanaryで検証した結果では、付与の有無に関わらず、呼び出し元のWebサイトのポリシーが適用されていたようでした。不明瞭な点もあるため、分かり次第加筆修正しますmm

# 参考

- Safari
  - https://webkit.org/blog/7734/auto-play-policy-changes-for-macos/
- Chrome
  - https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
  - https://www.chromium.org/audio-video/autoplay
  - https://docs.google.com/document/d/1_278v_plodvgtXSgnEJ0yjZJLg14Ogf-ekAFNymAJoU/edit#heading=h.c1rqulonmckg