iPhone・iPadでWordPressのMP4動画が再生できない原因と対処法

カテゴリ: WordPress / Web技術
タグ: WordPress, iPhone, iPad, iOS, 動画, mp4, WebKit, Cloudflare

はじめに

WordPressにアップロードしたMP4動画が、PCやAndroidでは問題なく再生できるのに、iPhoneやiPadでは一切再生できないというトラブルに遭遇しました。

ChromeでもBraveでもダメ——そう気づいたとき、問題はブラウザではなくOSレベルにあることがわかりました。本記事では原因の特定から解決策の検討まで、実際のトラブルシューティングの過程をまとめます。

結論を先に

iOSデバイス(iPhone・iPad)上のすべてのブラウザはWebKitエンジンを使用しており、動画再生時に Accept-Ranges: bytes HTTPヘッダーを必須とします。このヘッダーが返らないサーバー環境では、動画は完全に再生できません。

原因:iOSはすべてWebKitエンジン

Appleの規約により、iOS/iPadOS上のすべてのブラウザ(Chrome・Brave・Firefox含む)はSafariと同じWebKitレンダリングエンジンを使用します。

デバイスブラウザエンジン再生結果
PCChrome / FirefoxBlink / Gecko✅ OK
AndroidChromeBlink✅ OK
iPhone / iPadChromeWebKit(強制)❌ NG
iPhone / iPadBraveWebKit(強制)❌ NG

AndroidのBlinkエンジンはHTTP 200レスポンスでも動画を再生できますが、WebKitは動画のストリーミング再生のために HTTP 206 Partial Content(バイト範囲リクエスト) を必須とします。サーバーが Accept-Ranges: bytes ヘッダーを返さないと、WebKitは再生を拒否します。

診断方法:curl -I でヘッダーを確認する

問題の切り分けには curl -I コマンドが有効です。動画ファイルのURLに対してHEADリクエストを送り、レスポンスヘッダーを確認します。

curl -I https://your-site.com/wp-content/uploads/xxxx/your-video.mp4

curl -I https://your-site.com/wp-content/uploads/xxxx/your-video.mp4

問題が発生している場合のレスポンス例:

HTTP/2 200 content-type: video/mp4 server: cloudflare

← accept-ranges: bytes がない

HTTP/2 200
content-type: video/mp4
server: cloudflare
# ← accept-ranges: bytes がない

accept-ranges: bytes が含まれていない場合、iOSデバイスでの再生に失敗します。

Cloudflare環境での落とし穴

さくらインターネットなどのサーバーにCloudflareを前段に置いている場合、問題はより複雑になります。

今回の構成(さくらインターネット RSプレミアム + Cloudflare)では次の現象が起きました。

Transform Rule を設定しても効かない

CloudflareのTransform Rule(レスポンスヘッダー変換ルール)で Accept-Ranges: bytes を付与するルールを作成・有効化しましたが、ヘッダーが反映されませんでした。

キャッシュのパージが必要

cf-cache-status: HIT の状態では新しいルールが適用されないため、Cloudflareのキャッシュパージ(Purge Cache)が必要です。ただし今回はパージ後も解決しませんでした。

.htaccessへの追記でも解決しない

Apacheの .htaccess にオリジンからヘッダーを返す設定を追記しましたが、Cloudflareのプロキシ経由ではヘッダーが消える現象が継続しました。

# 試みた設定(.htaccess末尾に追記) <FilesMatch ”\.(mp4|m4v|mov)$”> Header always set Accept-Ranges bytes

# 試みた設定(.htaccess末尾に追記)
<FilesMatch "\.(mp4|m4v|mov)$">
    Header always set Accept-Ranges bytes
</FilesMatch>

⚠️ 注意: <IfModule mod_headers.c> で囲むと既存のCocoon設定と競合してHTTP 500エラーが発生することがあります。

最終的な解決策:YouTube埋め込みへの切り替え

Cloudflareプロキシ経由での解決が困難と判断し、YouTubeに動画をアップロードして埋め込む方法に切り替えました。

この方法のメリット

  • iPhoneを含むすべてのデバイス・ブラウザで動作保証
  • CloudflareやWebサーバーの設定に依存しない
  • WordPressはYouTubeのURLを貼るだけで自動的に埋め込みになる

手順

  1. YouTubeに動画をアップロード(限定公開推奨)
  2. 動画のURLをコピー
  3. WordPressのブロックエディタで「埋め込み」ブロックにURLを貼り付け

自動再生・ループなどの制御が必要な場合

埋め込みURLにパラメータを追加することで細かい制御が可能です。

https://www.youtube.com/embed/VIDEO\_ID?autoplay=1&loop=1&mute=1&controls=0&playlist=VIDEO\_ID

https://www.youtube.com/embed/VIDEO_ID?autoplay=1&loop=1&mute=1&controls=0&playlist=VIDEO_ID
パラメータ意味
autoplay1自動再生(muteが必要)
loop1ループ再生
mute1ミュート
controls0コントロール非表示
playlistVIDEO_IDloopに必要

事前対策:faststart変換

動画をWordPressに直接アップロードする場合、MP4ファイルのmoov atom(メタデータ)がファイル末尾にあると、WebKitはファイル全体をダウンロードするまで再生できません。

ffmpegで事前に変換しておくことで、WebKitでもストリーミング再生が可能になります。

ffmpeg -i input.mp4 -c copy -movflags faststart output.mp4

ffmpeg -i input.mp4 -c copy -movflags faststart output.mp4

これにより、メタデータがファイル先頭に移動します。動画をアップロードする前の定番処理として覚えておくと便利です。

まとめ

チェック項目確認方法
Accept-Ranges: bytes が返っているかcurl -I でレスポンスヘッダーを確認
MIMEタイプが video/mp4同上
moov atomがファイル先頭にあるかffmpegで faststart 変換
Cloudflareがヘッダーを削除していないかMISS状態でcurl確認

iOSデバイスでのみ再生できない場合は、まず curl -I でヘッダーを確認することが診断の第一歩です。Cloudflareを使用している環境では、オリジンからのヘッダーが意図通りに届かないケースがあるため、YouTube埋め込みへの切り替えが最も確実な解決策になります。


この記事はITQが実際に遭遇したトラブルシューティングの記録です。同じ問題で困っている方の参考になれば幸いです。

← ITQ Lab トップに戻る