【Apache/Nginx/PHP/Monosnap】iPhone(iOS) の video タグで mp4 の動画が再生されない問題

前回のエントリーで、サジェストの動作結果を動画にして配信したのですが、iPhone(iOS)で表示されていませんでした。思ったよりカオスだったのでまとめておきます。

PHP経由で配信する場合は Content-Length と Content-Range の設定が必須。

動画ファイルを PHP 経由で配信する場合。Content-Length と Content-Range の設定が必須とのこと。詳しいことはわかっていませんが、「ドキュメントルート外の動画ファイルをvideoタグで公開する際の注意点(HTTP_RANGE)」のコードで問題ありません。

Content-Range の記事ばかり出ていますが、「apacheはContent-LengthレスポンスヘッダがないとRangeリクエストが有効にならない」ので、あわせて確認しましょう。

mp4 を gzip しない

少し調べた感じだと、mp4 を gzip するとパフォーマンスが悪くなるということと、gzip されたものは Content-Length が表示されないため、gzip されていたら無効にします。

<IfModule mod_deflate.c>
     SetOutputFilter DEFLATE
     (略)
     # gifやjpgなど圧縮済みのコンテンツは再圧縮しない
     SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico|mp4)$ no-gzip dont-vary
     (略)
</IfModule>

cloudflare だと mp4 は標準サポート外(非推奨)

どうやらパフォーマンスが悪くなるかもということで、cloudflare で mp4 をキャッシュすることは標準では行っておらず非推奨だそうです。そのため私も行っていません。公式フォームを少し覗いた感じだと、正常にストリーミング配信できるかも謎のようです。

Monosnap が出力する MP4 は、本当は mov(video/quicktime)

少し脱線ですが、動画キャプチャを撮るのに Mac の Monosnap というソフトを使っていたのですが、ここで出力される mp4(拡張子も.mp4)は本当は mov(video/quicktime) でした…。ターミナルからMIMEタイプを確認できるので、念のため調べましょう。

file --mime 【動画のパス】

変換するには、ffmpeg を使ったほうが速いですね。

ffmpeg -i 【動画のパス】 【MP4にする動画のパス】.mp4