🧊

videoやaudioを扱う場合は、本番と同等のサーバーで開発すべし

とある案件で動画を`video`要素で表示するっていうごくごく普通なことをしてました。

ただ、特定の条件が重なると動画がうまく再生されないことがあって、その原因を突き止めたうえでの学びをメモ(˘ω˘ )

Range Requests

開発中のサーバーは、pythonで立ててました。

python -m SimpleHTTPServer 8888

便利ですよね。
ってなわけでコレで開発してました。

するとどうでしょう。
特定の動画だけうまく再生されません。

というのも、このSimpleHTTPServerはいわゆるHTTPのRangeヘッダに対応していない模様。
videoやaudioはその性質上、1リクエストで全てを取得するのではなく、再生するのに必要な部分を区切ってリクエストするようになってます。

もちろん、1リクエストで取得できるような短いものであれば問題なし。

そのため、ちょっと長い動画の場合にRangeリクエストがさばけなくて動画が再生されなかったというわけ。

localhostとfile://

外部ネットワークに依存しないサイトだったので、localhostの1オリジンで開発してました。

てことはそもそも、file:// でアクセスしても動くのでは・・ということで試した。

そしたら全部動いた!

まぁ file:// ということで、http関係ないからRangeリクエストも何も関係なかったってわけですかね。

Chrome DevTools

DevToolsを開いてるとダメで、閉じると再生されるっていう意味不明な状況にも遭遇しました。
ただこれも結果がわかるとまぁ納得で・・。

DevTools開いてるときって、たいていSettingで`Disable cache (while DevTools is open)`にしてません?
犯人コレです。

DevTools閉じててキャッシュが効いてるうちは、Rangeリクエストに対応してないサーバーでもなんかの拍子に動画がキャッシュされてしまうと、そっから読まれてしまう。

デバッグしててあれやこれやと試すうちに、本来ありえない経路でキャッシュに貯めてたりするよねーっていう。

さようなら python こんにちは Node.js

上述の学びを得て、pythonでサーバー立てるのをやめました。
代わりに使ったのが https://github.com/cloudhead/node-static です。

RFC 2616準拠!ってことでRangeリクエストも安心の対応!これで怖いものなし!

さくっと立てたり落としたりしたかったので、この時点ではローカルにNginx立てたりっていう発想には至りませんでした。

まぁPCでさっきまで見れなかったやつが、全部見れるようになった!よかった!

iOSだとまた微妙に違う?

ここまでは良かったんですが、まだiPadで見るとダメなんですねー。
というわけで以下のことを検証しました。

  • `autoplay`とか`preload="auto"`とか、モバイルで無効な設定のせいではないか
  • 動画ファイル自体が非対応のフォーマットではないか

Dropboxに動画を置いてチェックしたところ、ちゃんと再生されたので動画自体は悪く無いことがわかった。
属性値についても特に問題はなさそう。(もちろん`autoplay`は効かないけども。)

ここでピンとくる、またサーバーのせいでは・・。

ローカルにNginxを立てる

DropboxのPublicなファイルを返してたのはNginxだったので、それを模してローカルにNginxを立てる。
普通にhomebrewで入れたやつ。

そしたら・・ちゃんと再生されたー!

どういう仕組かわかりませんが、node-staticがiOSからの動画に関するリクエストがうまくさばけてなかった・・?

というわけで

ApacheならApache、NginxならNginxと、最初から本番環境と同等のサーバーを使って開発してればこんな沼にハマる必要はなかったのにねーという話でした。
もちろん動画やら音声を扱うケースには限るけども。

もう調べる気ないけど、Nodeでちゃんと動画を返せてるサーバー実装ってあるのかしら?