地獄のvideo/audio要素
| Comments
- [ JavaScript ]
- [ video ]
- [ audio ]
- [ media ]
video/audioにハマりまくったメモ。作ってたのは、Flashでやってたような、複数の動画ファイルを、途中の選択肢によって色々変えながら見せるというようなインタラクティブムービーみたいなの。なので、ハードにvideoを使いまくるという意味で、普通に一本動画を見せるという用途よりももっと色々する必要があったわけだけれども、そうでない場合でも、videoが色々厄介であるということは知っておく必要があると思う。
とりあえず、videoやaudioを使いたい人は、以下の2ページを熟読せよ。
videoのイベントは HTML5 Video を眺めてるとなんとなく分かる。
audioライブラリ試してうまくいったやつはこれ。
videoのライブラリ、使ってないけど良さげなのはこれ。自分の場合、こまいことしたかったので、これじゃなくてもろもろ自分で書いた。
以下メモ。
Q: mp4やwebmが再生されない
AddType video/ogg .ogv
AddType video/mp4 .mp4
AddType video/webm .webm
AddType audio/mpeg .mp3
AddType audio/ogg .oga .ogg
をapacheに設定。設定しないとtextとかで返しちゃうから。(超重要)
Q: preload="auto"
にして、コントロールバー見ると、途中までしかダウンロードされてないんだけど
videoは全部をダウンロードしない。それが正常。
Q: プリロードはできるの?
たぶん完全にはできない。その代わり、このネットワーク速度なら再生がダウンロードを追い越さないというぐらいまでダウンロードが完了したら、canplaythrough
イベントが発火する。実質これがプリロードで、上記の途中までしかダウンロードされないのもこのため。さっぱりダウンロードさせたくなかったらvideo要素にprealod=”none”を指定しておき、element.load()
で読み込み開始。画像のプリロードみたいな風に単純には行かない。
Q: 時間をすごい先にしたら全部プリロードできちゃったりするんじゃないの?
できない。videoのレスポンスはPartial Contentで、よくわからんけどXHRみたいなもので、断片的に送られて来るらしい。なので、先まで時間すっ飛ばしたらその辺からダウンロードが開始される。
ちなみに、XHRで全部とってきておけばキャッシュするだろとか、とってきてdataURIとしてsrcに指定すれば全部プリロードできるだろとか思ってやってみたらブラウザが落ちたのでそういうアプローチはだめげ
Q: canplaythrough
が発火しない
FirefoxとOperaはelement.load()
しても読み込まない風。一度ビデオを再生させなければならない。element.play()
element.muted = true
して、50ms後ぐらいにelement.pause()
element.muted = false
すれば読み込みを開始する。ひどい。あと、element.readyState
が4以上になるのも監視したほうがいい。(よくわかってない。canplaythroughはreadyStateのラッパ?)
そして、上記をやり、再生し、すぐストップさせるっていうのをやるわけだけど、ここでまたOperaがpause()
、muted=true
を失敗し、プリロード中にvideoの音が垂れ流されるという現象が発生する。これはスペックにも依存するのだけれども、videoのプリロードは1つずつ行ったほうが良さそう。こんなこともあるため、ビデオの初め2秒ぐらいは無音状態にしておいたほうがいい。このへんがうまくいくか行かないかは、ビデオのクオリティにもよりそう。
また、このプレイポーズのプリロードキックは、非常に処理負荷の高い動作。そして、FirefoxとOperaでしか必要のないことなので、ブラウザ判別して、この2つのブラウザだけにこれを行ったほうがいい。具体的にはこれを全ブラウザに対してやると、IE9やら10が落ちる可能性がある。
Q: element.pause()
とかelement.muted = true
とかelement.currentTime=0
とか失敗する。
try
/catch
せよ。これらは失敗する可能性がある。IE9ではelement.currentTime
をいじれるのは再生した後。そして、可能な限り必要のない時にvideoのメソッドを呼ばないほうがいい。たぶん、ビデオ関連の操作は、ブラウザにとって特殊な操作であると考えられるのかなと感じた。外部のAPIを呼んだり、ハードウェアに近い部分を操作するという意味で。
Q: canplaythrough
って信じられるの?
なぜか特定のネットワークだとバッファで止まったりしまくったことがあった。また、マシンスペックがへぼいと、回線速度が良好でも処理が追いつかなくて止まる事がある。ブラウザの実装次第。そんなこんなで、重すぎるコンテンツは低スペックPCだと無理になる。そしてマシンスペックを知る方法とかたぶん無い。しかしまぁ、大抵の場合はcanplaythrough
を信じてやるしか無いし、概ね問題ない。
Q: フォーマットって何用意すればいいの?
video: webmとh264。audio: mp3とogg。Firefox、Opera、Chromeがwebm/ogg、IE9、IE10、iOS、Chromeがh264/mp3。(2013年2月時点)
Q: エンコードって何ですればいいの?
これが楽。Miro Video Converter
Q: webmの最後のフレームが静止状態で1秒ぐらい続いちゃうんだけど
多くのエンコーダーではそのようになってしまう。気になるならこれでエンコードする。XMedia Recode
Q: video要素をそのままHTMLに書いた方がいいの?オンザフライで作った方がいいの?
状況によるけど、沢山のvideo要素を扱う場合は、必要な物だけオンザフライで作ったほうが良かった。videoにpreload="none"
を指定していても、IE9, 10ではそれを全部、はじめの部分だけ読みに行き、メモリ不足がどうとか言い出してエラー出しまくって最悪フリーズした。オンザフライで作る場合は、Modernizr.video.webm
、Modernizr.video.h264
で判別して対応するファイルへのパスをvideoのsrcに指定する。っていうのをやった。
Q: 読込中にブラウザがフリーズします
自前でキュー作って順番にロードせよ。
Q: element.play()
しても0.5秒ぐらい再生が始まらない (IE10)
マシンスペックによる。低スペックなマシンだと起こる。回避無理そう。
Q: videoのプレイ進捗が知りたい
element.currentTime
に現在の再生位置時間が入ってる。timeupdate
イベントがプレイ中に起こり続ける。ただし、timeupdate
は1秒間に1〜4回ぐらいしか発火しない。もっと細かく取りたかったらtimeupdate間でタイマー回して取るのが吉か。
Q: ended
イベントが発火しない(IE10)
低スペックPCで発生する。element.play()
時にnew Date
して、タイマー回して、element.duration
分経ったかを合わせてチェックするっていうのをやった。
Q: Safari5でelement.load()
が効かない
Safari5のvideoの実装は不十分すぎでめちゃくちゃ微妙。element.preload = 'auto'
で読み込みが開始される。
Q: Safari5/6でブラウザがフリーズする
Mac OSX 10.8(Moutain Lion)未満では、複数のvideo要素を扱う時、Safari5でvideoのロード等の処理負荷が一定以上になると、ブラウザがフリーズする。まずは、video要素自体はpreload="none"
で作っておき、一定の間隔を置いて一つずつpreload="auto"
にしていくとかして、慎重に扱わないとフリーズする。作るものによっては、Mac OS X 10.8未満のSafari(5/6)は非サポートとしたほうが良さそう。ちなみに、HTMLにvideo要素を直接書いた方が安定した気がしたかも。Mac OSX 10.8のSafari6ではこの現象は起こったことがない。
そして、この、10.7 (Lion)、10.6 (Snow Leopard) のSafari5/6では、マシンによってこの現象が起こるものと起こらないものがあるみたい。要するにスペックやらCPUやらグラボに起因する問題なのかなと思われた。
Q: IE10が落ちる
IE10はChromeの次ぐらいに優秀なんだけれども、処理性能はマシンスペック依存。でかすぎるvideoはIE10を落としたり不安定にするんで、控えめにvideo使わないとダメかもしれない。低スペックPCでも見れるコンテンツを安全に作りたかったら重いコンテンツはNGかと思う。
Q: 読み込みに失敗するんだけど
error
イベントをしっかり取ってエラーを出しましょう。あと、同時にいっぱい読むとエラーが起こりやすい。ビデオ読み込みのエラーはどこでもいずこかで発生するものと思ったほうがいい。
Q: 複数タブで同じページを表示すると片方でvideoを読み込まない
たぶんブラウザが悪いけどなぜかそうなる。
Q: IE10/9で「この操作を完了するための十分な記憶域がありません」
IE10ではvideoを18個作って、ひと通り再生してリロードしたら、このエラーが出て、関係ないところのJSがエラー出しまくりました。これを14個にしたらこのエラーが出なくなった。これは、動画のクオリティには関係ない話らしい。高画質でも低画質でも18個だとエラー出たし、14個だとエラー出なかった。videoはいっぱい作っちゃダメっぽいですな。ちなみにこれもマシンによって出たり出なかったりするんで…。
Q: 連続してSEみたいな短いaudioを鳴らせない
5個ぐらい作って代わる代わるplayさせるといいんじゃない… 僕はそうしました…
Q: Safariで短いaudioが鳴らない
videoだのaudioだのと言っても、Safariにとってそれは、QuickTimeのAPIを内部的に呼んでいる風。QuickTime自体が短すぎるmp3を鳴らせない。無音部分を後ろに追加せよ…
Q: canvasにvideoを取り込みたい
context.drawImageすればいい
Q: muted
属性がきかない
たぶんブラウザの実装が不十分で効かないのがある。playさせてからelement.muted = true
なりなんなりしてやると効いたりする?
Q: Safariでdisplay:none
にしたvideoの読み込みが開始されない
display:block
にしたら読み込んだ気がした確か。
Q: Operaでやたら重い
videoをopacity:0
で隠しておくとOperaでやたら重くなる。display:none
の方がいい。
Q: Safariでなんかしらんけど真っ暗
displayをblock
にしたりnone
にしたりしてるとなった。だから隠すにはopacity:0
のほうがいいのかも。えーっとOperaは諦めた。
Q: windows XPでやたら変
同じバージョンのブラウザであっても、windows XPでは音や映像が飛びまくったり止まったりなどして、何か色々おかしい。Vista以上だと大丈夫。要するにXPだとかなり無理。
Q: ちょっと前のブラウザで何かおかしい
Modernizr.video
がtrue
を返したとしても、ブラウザの実装が完璧なわけではない。動かない可能性があるとかなんとか、常に出したほうがいいかも。
Q: iOSでvideoをvisibility:hidden
にしてるけどなんか表示されちゃう
videoがHTML内にある時点で、ブラウザは何かしら処理を始めちゃうって思ったほうがいい。document.createElement('video')
からオンザフライで色々してください
Q: ビデオの再生がダウンロードに追っつかなくなった時に何かしたい
stalled
というイベントがあるようだけど試してない。対応していないブラウザに対してはtimeupdate
毎に、3000ms以内にまた発生しないか等をチェックしたりする必要があるかもしれない。
Q: サーバーが落ちます/負荷が高すぎて耐えられない
普通のサーバーでアクセス数が多いなら死にます。フロントだけでなく、バックエンドも色々と検討する必要があるでしょう。
Q: Chromeでビデオの読み込みに失敗する
stackoverflowによれば、Chromeでは7本以上のビデオを一つのページに読み込むとエラーになるらしい。
この現象は、自分の環境では、Windows端末にて確認できた。しかし、全てのWindows端末で起こるわけではないようだ。この現象が起こるChromeを判別するのは、多分ムリだろう。アップデートを待つしか無い。
Q: IE10を閉じるとIEが強制終了されましたと出る
window onunload時に全てのvideoをremoveしたら直ったかもしれない
Q: ユーザーにvideoやmp3をダウンロードさせたくないんですけど
諦めろ(よく聞かれる)
もしくはすっごい予算かけてなにかすごいサーバーの仕組みを作る
Q: モバイルでvideoやaudioを使いたい
ただの動画再生ならYouTubeを使いましょう。もしくはかなり工数がかかることを覚悟して望まないとダメかも。iOSはそもそもvideoを再生すると全画面表示なってしまうので、それ以外の用途では無理。audioは最初に紹介したSoundJSがそこそこなんとかしてくれるっぽいけど、これもまた大変そうな感じ。よく聞かれるのが、スマホ向けにも動画を見せたいとか言うやつなんだけれども、その問いに対する自分の答えはだいたい
- YouTube使え
- h264とwebm用意して見れないやつはあきらめたほうがいい
- 無限に工数と予算が増えることを許可してくれるならやりますけど動作は保証できないんでほとんどコストに見合わないと思う
PCでは、いくつかのフォーマットを用意すれば、モダンブラウザで動作させることが可能だろう。しかし、iOSやAndroidは、バージョンや端末により、高ビットレート、フレームだと再生できないことがあるらしい(私自身は試してない。聞いた話、ググった内容等から)。Youtubeの中の人によると、Youtubeでは、ひとつの動画に対し、20本近くのトランスコードを行なっているそうだ。端末の解像度やUAなどにより、出す動画を選択しているとのこと。それをおおよそ普通の案件で行うのは無理だろう…。おおよそほとんどの端末で見れるようにするためには、低ビットレートの動画になってしまうのかなと思う(それでも再生されるかは分からない)
Q: videoを使うのは大変なんでしょうか
ただの再生ならそこまでではないけども、APIやイベントを使って色々したいのであれば、かなり大変という印象。まだまだこれからっていう感じ。Chromeだけならとても楽しく利用できる…。canvasと組み合わせたりするとかなり夢広がる。2012年2月時点での自分の感想は、一番マシなのはChromeで、Chrome以外は全部微妙で不具合がある(それでも動かないChromeもある)。特に多数のvideoを使うとどれでもかなりダメ。
そんでもって、video非対応なブラウザ、videoが微妙なブラウザに対しても色々メッセージ出したりなんのしないといけないんでそのへんも地味に大変。
そんなvideoに苦労したサイトはこちら。
Comments