サイトの動画がスマホで再生されないとき|必要な属性3つと、読み込み中を埋める待機画像の作り方
サイトの動画がスマホで再生されないとき|必要な属性3つと、読み込み中を埋める待機画像の作り方
「PCでは動くのに、スマホで開くとトップの動画が真っ黒のまま」「iPhoneだけ再生されない」という相談は、ホームページに動画を置いたサイトで定期的に発生します。動画ファイル自体は壊れていないことがほとんどで、原因はHTMLの書き方とスマホ側の再生条件にあります。
先に結論をお伝えします。スマホで動画を自動再生させるには、autoplay・muted・playsinline の3つの属性が同時に揃っている必要があります。このうち1つでも欠けると再生されません。そのうえで、読み込みが終わるまでの黒画面を埋める待機画像(poster)と、スマホ用に軽くした動画の出し分けを用意すると、実機での見え方が安定します。
この記事では、名古屋の革製品ブランドのサイトで41秒のオープニング動画をトップページに組み込んだときの実測データをもとに、必要な属性、iPhone特有の対処、公開後の検証手順までを解説します。
手順0:サイト側の問題か、見ている環境の問題かを先に切り分ける
修正に入る前に必ずやることがあります。そのブラウザで、自分のサイト以外の動画が再生できるかを確かめることです。
実際に、デプロイ後の確認で動画が黒画面になり、サイト側の実装を疑って調査を始めたケースがありました。ところが、まったく無関係な外部のサンプル動画を同じブラウザで開いても再生できませんでした。原因はブラウザ(Chrome)のメディア処理プロセスの不調で、ブラウザを再起動しただけで解消しています。サイトのコードには一切問題がありませんでした。
この切り分けは30秒で終わります。順番はこうです。
- 別のサイトの動画(外部の既知の動画)を、同じブラウザで開く
- 再生できなければブラウザ側の問題。再起動するか、別のブラウザで確認する
- 再生できるなら、次にサーバーからファイルが正しく配信されているかを確認する
3つ目のサーバー確認は、ブラウザではなくコマンドで見るのが確実です。
curl -sI https://example.com/movie/hero.mp4
ここで見るのは3点です。ステータスが 200 であること、content-type が video/mp4 であること、accept-ranges: bytes が返っていることです。3つ目のaccept-rangesは、動画を途中から部分的に読み込む「範囲リクエスト」への対応で、これが無いと動画全体をダウンロードするまで再生が始まりません。
サーバーもブラウザも問題なければ、原因はHTMLの側にあります。
手順1:スマホの自動再生に必要な属性は3つ
スマホのブラウザは、通信量とユーザー体験を守るために動画の自動再生を強く制限しています。制限を解除する条件が、次の3つの属性です。
<video autoplay muted playsinline preload="metadata" poster="/movie/hero-poster.jpg">
<source src="/movie/hero.mp4" type="video/mp4">
</video>
muted(消音)は必須です。音が出る動画の自動再生は、スマホでもPCでも原則ブロックされます。「音を鳴らしたい」という要望があっても、自動再生と両立はできません。再生ボタンを押してもらう設計に変えるか、消音で自動再生して音声はあきらめるか、どちらかの選択になります。
playsinline が抜けていると、iPhoneでは全画面プレーヤーが起動します。この属性は「ページ内でそのまま再生する」という指定で、背景動画やヒーロー動画には必ず必要です。抜けていると、意図せず動画プレーヤーが画面を占拠するか、そもそも自動再生されずに止まります。古いiOSも対象に入れるなら、同じ意味の webkit-playsinline を併記しておくと安全側に倒せます。
preload="metadata" は、ページを開いた瞬間に動画全体を読みに行かせないための指定です。動画は数MB〜数十MBあるため、無条件に全部読み込ませるとスマホの通信量を圧迫し、ページ全体の表示も遅くなります。まず長さや解像度といった情報だけを読み、本体は再生に合わせて取得させるのが基本形です。
手順2:読み込み中の黒画面は待機画像で埋める
属性が正しくても、動画の最初のフレームが表示されるまでには時間があります。その間、<video> の領域は黒く塗られます。ファーストビューに動画を置いた場合、サイトを開いた瞬間に画面が真っ黒という状態が数秒続くことになります。
これを埋めるのが poster 属性で指定する待機画像です。作り方は単純で、動画の1フレーム目を静止画として書き出すだけです。実際の案件では、1280×720・約37KBのJPEGを使いました。動画の先頭フレームそのものなので、動画が再生を始めた瞬間に画像から映像へ継ぎ目なく切り替わります。
待機画像を用意するときの基準は3つです。
- 動画の先頭フレームから作る。別の写真を使うと、再生開始の瞬間に画が飛んで見えます
- 動画と同じ縦横比にする。比率が違うと、待機中と再生中でレイアウトが変わります
- 容量は数十KB程度に抑える。ここが重ければ黒画面を埋める役に立ちません
なお、待機画像は「動画が読めなかったとき」の保険にもなります。通信が細い環境や、動画の配信に失敗したときも、静止画は表示されたままになるため、画面が真っ黒になる最悪のケースを構造的に防げます。
手順3:iPhoneで黒いままのときに追加する初期化処理
ここまでの設定で多くは解決しますが、iPhone・iPadでは1つ追加の対処が必要になる場合があります。
iOSのSafariは、停止状態の動画のデータ読み込みを省略することがあります。preload="auto" と書いてあっても、その動画が一度も再生されていなければ、映像フレームがデコードされないままになり得ます。結果として、動画は「存在するが1フレームも描画されていない」状態になり、領域が黒く残ります。
この症状は、スクロール量に合わせて再生位置(currentTime)だけを動かす実装で特に起こります。動画を一度も play() していないためです。
対処は、ページ読み込み時と最初のタッチ操作のタイミングで、消音のまま一度だけ再生してすぐ止めることです。これでフレームのデコードが走り、以降は再生位置を動かすだけで正しく描画されます。あわせて、動画データの読み込み完了イベント(loadeddata)でも表示位置を再反映させておくと、読み込み順による取りこぼしを防げます。
実際にこの初期化処理と待機画像を追加した案件では、報告されていた「iPhoneで動画が表示されない」がそのまま解消しました。
手順4:スマホには軽い動画を出し分ける
同じ動画ファイルをPCとスマホに配信すると、スマホ側で「読み込みが終わらない」「途中で止まる」という別の問題が出ます。解像度と容量を分けて配信するのが正解です。
実際の案件で採用した構成は次の通りです。
| 表示環境 | 解像度 | 容量 |
|---|---|---|
| PC | 1920×1080 | 21.6MB |
| スマホ(767px以下) | 1280×720 | 11.0MB |
書き方はこうなります。
<video autoplay muted playsinline poster="/movie/hero-poster.jpg">
<source media="(max-width: 767px)" src="/movie/hero-720p.mp4" type="video/mp4">
<source src="/movie/hero.mp4" type="video/mp4">
</video>
<source> の順序が結果を決めます。ブラウザは上から順に条件を判定し、最初に条件を満たしたものを採用します。したがってスマホ用の指定を先頭に書きます。PC用を先に書くと、条件のない指定が先にマッチしてしまい、スマホでも大きいファイルが読み込まれます。この書き間違いは画面上まったく気づけないので、後述する実測で確認します。
なお、スマホ用に用意する動画は、単純に解像度を落とせばよいというものではありません。もともと解像度の低い素材を全画面の背景に引き伸ばすと、粗さが目立ちます。背景として全面に敷くなら、最低でも1280×720の素材を用意し、それが無い場合はぼかしを重ねる、静止画に差し替えるといった設計側の判断が必要になります。
手順5:動画ファイル側の条件を確認する
HTMLが正しくても、動画ファイルの作り方によって再生されないことがあります。確認すべきは3点です。
エンコード形式。 映像はH.264、色空間は yuv420p にします。特に yuv420p は見落とされやすく、これ以外の色空間で書き出された動画は、環境によってはまったく再生されません。動画編集ソフトの書き出し設定を「Web用」「H.264」にしておけば通常は満たされます。
Fast Start化。 MP4ファイルには、再生に必要な情報をまとめた moov という領域があります。これがファイル末尾にあると、ブラウザはファイルを最後まで読み込むまで再生を開始できません。この領域を先頭に移動させるのがFast Start化です。実際の案件でも、Web配信用の動画は必ずこの状態にしてから設置しています。動画変換ツールの「Fast Start」「ストリーミング最適化」に相当する設定です。
キーフレームの間隔(スクロール連動の場合のみ)。 通常の自動再生であれば気にする必要はありませんが、スクロール量に合わせて再生位置を動かす実装では話が変わります。実測した41秒の動画は991フレーム中キーフレームが11個しかなく、終盤には約8.4秒間キーフレームが無い区間がありました。再生位置を連続的に動かす場合、その位置に近いキーフレームから映像を組み立て直すため、キーフレームが疎だと追従が重くなります。スクロール連動をやるなら、キーフレーム間隔を1秒(または0.5秒)に固定した専用の書き出しを別途用意します。
逆に言えば、通常の autoplay muted loop で全編を流す方式にすれば、この再エンコードは不要です。実際の案件でも、途中でスクロール連動方式をやめて通常再生に切り替えたことで、画質を落とさずに軽くできました。演出方式の選択が、そのままファイル要件を決めます。
手順6:公開後の検証は「見た目」ではなく実測で行う
動画は「表示されているように見える」状態でも、意図と違うファイルが読み込まれていることがあります。特にスマホ用の出し分けは、見た目では絶対に判別できません。公開後は次の4点を数字で確認します。
1. 実際に読み込まれたファイル(currentSrc)。 ブラウザの開発者ツールで動画要素を選び、currentSrc を確認します。スマホ幅(390×844など)でスマホ用のファイル名が返っていれば、出し分けが効いています。ここでPC用のファイル名が返っていたら、<source> の順序が逆です。
2. 読み込み状態(readyState)。 4 であれば、最後まで再生できる状態でデータが揃っています。ここが小さい値で止まっていれば、配信側かファイル側に問題があります。
3. HTTPステータスと範囲リクエスト。 動画ファイルのURLを直接叩いて 200 が返ること、範囲を指定したリクエストで 206 が返ることを確認します。206 は、動画を部分的に読み込む仕組みが働いている証拠です。
4. コンソールのエラー。 動画の再生失敗はエラーとして記録されていることが多く、実機で開いてエラーが出ていないことまで見て完了とします。
これらは全て、PC・スマホそれぞれの画面幅で確認します。片方だけ見て終えると、もう片方で黒画面が出ている状態に気づけません。
起こりうる事故と、その予防策
動画の設置には定番の落とし穴があります。あらかじめ知っていれば防げるものばかりです。
ファイルの権限を落としたまま公開してしまう。 クラウドストレージからコピーした動画をそのままFTPで転送すると、所有者しか読めない権限のまま公開されることがあります。この状態だと、ファイルは確かにサーバー上に存在するのに、ブラウザからのアクセスは拒否されます(403エラー)。実際にこの状態が発生した案件では、転送直後の確認で検知して権限を修正しました。バイナリファイルを公開する前に、ローカル側の権限を「誰でも読める」状態に揃えてから転送するのが予防策です。そして、転送後に必ずURLを直接叩いて200が返ることを確認します。
古いスクリプトがキャッシュされ続ける。 動画の制御をJavaScriptで行っている場合、修正したのに反映されないことがあります。ブラウザが以前のファイルを保持しているためです。読み込むファイルのURLに更新ごとに変わる印を付ける(app.js?v=16 のように末尾を変える)ことで、修正が確実に配信されます。「直したのに直っていない」の多くはこれです。
動画を差し替えたのに古い動画が表示され続ける。 同名のファイルで上書きした場合も同じ理屈でキャッシュが残ります。確認するときは、キャッシュを持たない状態のブラウザで開くか、コマンドでファイルを取得して、サイズや解像度が新しいものになっているかを直接確かめます。
公開前のバックアップを取らない。 動画の組み込みはHTML・スクリプト・動画ファイル・待機画像と複数のファイルにまたがるため、戻し先が複数あります。差し替え前に対象ファイル一式を控えておけば、想定外の挙動が出たときに即座に戻せます。実際の案件でも、公開前にローカルの変更前状態と本番全体の2系統をバックアップしてから反映しています。
まとめ
スマホで動画が再生されないときの確認順は次の通りです。
- 別のサイトの動画で環境を切り分ける。ブラウザ側の不調であることが実際にある
autoplay・muted・playsinlineの3属性が揃っているかを見る。1つでも欠けると再生されないposterで待機画像を置く。動画の先頭フレームから作り、読み込み中の黒画面を消す- iPhoneで黒いままなら、消音で一度再生して止める初期化処理を入れる
- スマホ用に軽い動画を用意し、
<source media="...">を先頭に置いて出し分ける - ファイル側はH.264・yuv420p・Fast Start化を満たしているか確認する
- 公開後は
currentSrc・readyState・HTTPステータスを実測する。見た目では判別できない
動画は、写真や文章と違って「置いただけでは正しく動かない」要素です。逆に言えば、条件が明確なので、一度型を作ってしまえば次からは迷いません。ファーストビューに動画を置く判断をしたなら、実機での見え方の確認までを制作の工程に含めておくことをおすすめします。
graciautoでは、ホームページ制作と改修において、こうした実機での表示検証まで含めて対応しています。「スマホで見ると崩れている」「制作会社に伝えても直らない」といった状態でお困りでしたら、現状の確認からご相談ください。