Safari 11 の Auto-Play Blocking を試してみた

TL; DR

Auto-Play Blocking は音声つき動画が自動再生されないよう Safari を設定できる機能ですが、 「音声なし動画の自動再生」「音声つき動画をミュートで自動再生」「音声つき動画を、ユーザ操作を契機として再生」することは可能です。

Auto-Play Blocking とは

macOS 10.13 High Sierra に搭載される Safari 11.0 に、動画の自動再生を抑制する Auto-Play Blocking 機能が採用されます。 Auto-Play Blocking は、 Web サイトごとに以下 3 種類のルールを適用することができます。

  • Allow All Auto-Play
    • 自動再生を許可します。これまでの Safari の動作です。
  • Stop Media with Sound
    • 音声ありの動画の自動再生を抑制します。デフォルトではこのルールが適用されます。
  • Never Auto-Play
    • すべての自動再生を抑制します。

これは macOS 向けの機能で、 iOS 11 の Mobile Safari には採用されていません。

試してみた

音声なし動画の自動再生

Auto-Play Blocking は「音声つき動画を自動再生しない」機能なので、まずは音声なし動画を再生してみます。 検証に使用する HTML タグは以下のとおりです。

<video autoplay>
    <source src="https://example.com/video.mp4" type="video/mp4">
</video>

結果は以下のようになりました。 音声なし動画なので Stop Media with Sound は再生され、音声有無を問わない Never Auto-Play は再生されませんでした。

ルール 再生可否
Allow All Auto-Play
Stop Media with Sound
Never Auto-Play ×

音声つき動画の自動再生

ここからが本題です。音声つき動画を自動再生してみます。

<video autoplay>
    <source src="https://example.com/video.mp4" type="video/mp4">
</video>

Stop Media with Sound も再生されません。

ルール 再生可否
Allow All Auto-Play
Stop Media with Sound ×
Never Auto-Play ×

音声つき動画をミュートで自動再生

音声つき動画の音声を OFF にした場合はどうでしょうか。

<video autoplay muted>
    <source src="https://example.com/video.mp4" type="video/mp4">
</video>

今度は Stop Media with Sound でも再生できました。

ルール 再生可否
Allow All Auto-Play
Stop Media with Sound
Never Auto-Play ×

音声つき動画を JS で再生

autoplay 属性を付けなければいいのでは?と思い、 autoplay ではなく JS で再生を試みました。

<script>
    window.addEventListener('load', function() {
        let video = document.getElementById('v');
        video.play();
    });
</script>
<video id="v">
    <source src="https://example.com/video.mp4" type="video/mp4">
</video>

結果は autoplay 属性を指定した場合と変わらず、 Stop Media with Sound は再生されません。 play メソッドでエラーが発生していました。

Unhandled Promise Rejection: NotAllowedError (DOM Exception 35): The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.
ルール 再生可否
Allow All Auto-Play
Stop Media with Sound ×
Never Auto-Play ×

音声つき動画をページロード後数秒待ってから再生

ページロード時に自動再生されないなら、ロード完了後に少し時間をおいて再生するのはどうでしょうか。

<script>
    window.addEventListener('load', function() {
        window.setTimeout(function() {
            let video = document.getElementById('v');
            video.play();
        }, 3000);
    });
</script>
<video id="v">
    <source src="https://example.com/video.mp4" type="video/mp4">
</video>

これもダメで、 Stop Media with Sound は再生されず、 play メソッドでエラーが発生しました。

ルール 再生可否
Allow All Auto-Play
Stop Media with Sound ×
Never Auto-Play ×

音声つき動画を画面がクリックされたら再生

ページロード契機が全くダメなので、ユーザ操作を契機としてみました。

<script>
    window.addEventListener('mousedown', function() {
        let video = document.getElementById('v');
        video.play();
    });
</script>
<video id="v">
    <source src="https://example.com/video.mp4" type="video/mp4">
</video>

今度は Stop Media with Sound も再生されました。 ユーザ操作を契機とする場合は「自動再生」にあたらないようで、 Never Auto-Play でも再生されました。

ルール 再生可否
Allow All Auto-Play
Stop Media with Sound
Never Auto-Play

音声つき動画を画面がスクロールされたら再生

何らかの操作を契機にすればいいなら、と思い、ページスクロールも試してみました。

<script>
    window.addEventListener('scroll', function() {
        let video = document.getElementById('v');
        video.play();
    });
</script>
<video id="v">
    <source src="https://example.com/video.mp4" type="video/mp4">
</video>

Stop Media with Sound も Never Auto-Play も再生されず、 play メソッドでエラーが発生しました。 scrollTo() を使えばユーザが操作しなくてもスクロールを行えるからでしょうか..?

ルール 再生可否
Allow All Auto-Play
Stop Media with Sound ×
Never Auto-Play ×

音声つき動画をミュートで自動再生したあと、ミュート解除

最後に、自動再生を開始したあとにミュートを解除できるのか試してみました。

<script>
    window.addEventListener('load', function() {
        let video = document.getElementById('v');
        video.addEventListener('play', function() {
            video.muted = false;
        });
    });
</script>
<video id="v" autoplay muted>
    <source src="https://example.com/video.mp4" type="video/mp4">
</video>

結果はダメで、 Stop Media with Sound も Never Auto-Play も以下のエラーが発生し、

Unhandled Promise Rejection: [object DOMError]

以下のいずれかの動作となりました。

  • ミュートを解除できず、音声 OFF のまま再生を続ける
  • 再生自体止まってしまう

( どちらの動作となるかはタイミング依存のようです )

ルール 再生可否
Allow All Auto-Play
Stop Media with Sound ×
Never Auto-Play ×

まとめ

まとめると、 3 種類のルールはそれぞれ以下の動作となります。

  • Allow All Auto-Play
    • これまで通り、自動再生可能
  • Stop Media with Sound
    • 「音声なし動画」「音声つき動画をミュート」は自動再生可能、それ以外はユーザ操作が必要 ( = iOS 10 の Mobile Safari のインライン再生と同じ挙動 )
  • Never Auto-Play
    • すべての動画はユーザ操作を契機としたときのみ再生可能

デフォルトは Stop Media with Sound なので、音声なしでの再生はユーザが設定を変更しない限りこれまで通り可能です。 音声つき動画を再生したい場合や、 Never Auto-Play でも動画を再生したい場合は、ユーザ操作イベントを契機に再生開始する必要があります。 ( この機能が採用された意図を考えると、再生制御をやめてビデオコントロールを表示するのが一番素直な対応だとは思いますが.. )

WKWebView と SFSafariViewController の見分け方

iOS アプリに搭載されているアプリ内ブラウザが WebView なのか SafariViewController なのかは、実は見た目で判別することができます。 iOS エンジニアでない方にはあまり馴染みがないようなので、まとめました。

WKWebView とは

ウェブコンテンツを表示するための view です。アプリ内にウェブコンテンツを埋め込むことができ、全画面表示である必要はありません。 ( アプリ内に HTML 広告を表示するケースなどでも使われていますね。 )

表示内容の制御など、ウェブコンテンツにアプリが関与したいときは、こちらを使います。

SFSafariViewController とは

Safari の機能 ( リーダー表示、オートフィル、コンテンツブロックなど ) を持つ view controller です。基本的に全画面で表示します。

クッキーやウェブサイトのデータは Safari と共有されます。 SFSafariViewController 上でのユーザ操作などはアプリからは見えず、オートフィルや閲覧履歴などのデータを取得することはできません。 SFSafariViewController は最早アプリではなく、 Safari の一部と言ってよいでしょう。

ウェブサイトを表示するだけでよければ、こちらを使います。

見分け方

SFSafariViewController の UI には以下の特徴があります。

  • 読み取り専用のアドレスバー、鍵マーク、リーダー表示モード
  • アクションボタン
  • 完了ボタン、履歴を進む・戻る、 Safari で開く
f:id:takasfz:20170529184616p:plain

また、 Safari をプライベートブラウズモードに変更すると、 SFSafariViewController も黒ベースの配色に変わります。

f:id:takasfz:20170529184606p:plain

これらの特徴をすべて備えていれば、それは SFSafariViewController です。

まとめ

判断に迷ったら、 Safari をプライベートブラウズモードに変更してみて配色が変わるかを確認するのが一番手軽で確実です。

出典:

CAMPFIRE Android #1 に参加しました

CAMPFIRE Android とは

CAMPFIRE Androidは、Androidにおける技術情報を共有するイベントです。 今回はYahoo! JAPANの技術情報に特化して開催します。

Yahoo! JAPANでは様々な分野のアプリを開発しており、 エンジニアの持つ知見もアプリ設計論からIoTまで多岐に渡ります。 本イベントでは、現場のエンジニアの様々な挑戦の中から、 特に役立つ取り組みやTipsを紹介いたします。

yj-meetup.connpass.com

セッション

RxJava を 1 年使って見えてきたこと

中里 直人 / Yahoo! 知恵袋アプリエンジニア

RxJava / RxAndroid を使ってみて良かったこと、失敗だったことを、具体的なコードとあわせて紹介してくださいました。 「こうしておけば良かった!」なポイントは、開発が進んで初めて気がつく ( そして後戻りできない ) ことが多いですよね..

資料中に出てくる記事はこちらです qiita.com

大規模アプリケーションを支える設計

牧 竜也 / Yahoo! JAPAN アプリエンジニア

www.slideshare.net

Yahoo! JAPAN アプリはレイヤアーキテクチャを採用しており、レイヤ間を疎結合にするためにモジュールで分割しているとのこと。 CAMPFIRE iOS #1 のほうでも、レイヤごとに Framework で分割しているという話がありましたね → マネーフォワードの設計へのアプローチ // Speaker Deck

アーキテクチャ選定はコスト ( 学習 / メンテナンス ) とメリットのトレードオフなので、一般的にはアンチパターンとされる Activity や Fragment にビジネスロジックを書くやり方も 単発や小規模な開発ではむしろ採用したほうが良い場合もあるとのことでした。

Android Things で勤怠連絡ボタンを作ってみた

松田 優貴 / myThings

Android Things は NXP Pico / Raspberry Pi 3 / Intel Edison に対応しており、イメージを書き込んだ SD カードを挿入するだけで使えるとのこと。 LAN で繋いで adb connect で接続し、 Activity などの APIAndroid アプリと同じ感覚で開発可能、 GCP との親和性もよいなど、 Android エンジニアに IoT がぐっと身近になったとのことでした。

Yahoo! JAPAN アプリのデータベース処理改善

森脇 聖太 / Yahoo! JAPAN アプリエンジニア

www.slideshare.net

歴史のあるアプリのデータベース処理を、モダンな環境へ安全に移行するための技術選定のお話。 SQLiteOpenHelper → SQLBrite の移行であればマイグレーションが要らず、さらに SQLDelite を組み合わせると SQL を文字列で扱う必要がなくなり、 少ないコストで安全に移行することができたとのことでした。

ニュースアプリで起きた不具合から学んだ最適への一歩

矢端 智光 / Yahoo! ニュースアプリエンジニア

www.slideshare.net

ユーザ / プロダクトに対する最適化に比べると、開発者自身に対する最適化は後回しになりがち。 不具合に対するナレッジを共有し、類似の不具合が発生したときに素早く対応できるようにしておくことも大事ですよね、ということを、 実際にあった不具合の例を挙げながらお話しくださいました。

タブブラウザ SDK を作った話

小林 俊 / Yahoo! JAPAN アプリエンジニア

www.slideshare.net

複数のアプリ向けに、共通化されたブラウザ機能を提供する SDK で、エラーダイアログ等の UI は持っておらず通知はすべてリスナ経由でアプリに返しているとのこと。 タブと WebView を別々に管理し、不要な WebView をこまめに破棄することで 3 桁数のタブも扱うことができ、 カルーセルや全面表示の地図のスワイプ、ピンチイン・ピンチアウトを考慮して細かくタッチイベントを制御することで快適な操作を実現させているとのことでした。

まとめ

普段は SDK の開発をしているため、アプリ界隈の技術や設計の話は新鮮でとても勉強になりました。 中里さんの発表だけでなく、他の方のお話しでも RxJava で開発することを前提にアーキテクチャや技術を選定しているような印象でした。 ( SDK の開発では、種々のアプリに柔軟に導入してもらえるよう、ライブラリ等は極力使用せず Pure Java でイチからすべてゴリゴリ実装することが多いのです.. )

小林さんのタブブラウザ SDK も技術選定は制限されるとのことでしたが、こちらは社内プロダクト向けの SDK なのである程度は自由が効くとのこと。 Yahoo! さんにはライブラリを社内標準として制定 (?) する仕組みがあり、ここに含まれるライブラリは SDK 開発であっても利用することが出来るのだそうです。 うらやましい..!!