lxyuma BLOG

開発関係のメモ

androidでHTML5 audio使ったHLS形式のストリーミング再生が上手くいかない

スマホのブラウザ上で、音声のstreaming配信がしたい。

そこでhtml5 audioでHLS形式のURL(*.m3u8)指定して再生した時に

動かないandroid端末が一部あった。その対応した話。

結論は、単に、audio.type指定すれば良かったというだけの話だけど、

せっかくなので、スマホのストリーミング配信の話から、まとめる。

目次

flashスマホ

ストリーミング配信というと、PCは未だ、flash使う事が多いと思われる。

試しに、amazonの視聴見てみると、やっぱりflash

スマホflashは、どうかというと、

そこで、HLS使うのが選択肢として出て来る。

HLS

HLSはappleの作ったhttp経由でストリーミングを実現する技術。

IETFで標準化しようとしている。

所謂、擬似的なストリーミング技術で、

progressive downloadに、帯域制御を追加した物になる。

公式sampleの中身を見てみる

例えば、公式のsampleを見てみると、以下のm3u8ファイルをDLしてる。

#EXTM3U

#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=232370,CODECS="mp4a.40.2, avc1.4d4015"
gear1/prog_index.m3u8

#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=649879,CODECS="mp4a.40.2, avc1.4d401e"
gear2/prog_index.m3u8

・・・省略・・・

帯域幅(Bandwidth)毎に音声ファイルを切り替えていて、

最後の部分がその音声ファイル(別のm3u8ファイル)なので、それをURLに打ってみる。

例えば、一行目は、https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear1/prog_index.m3u8

#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:9.97667,    
fileSequence0.ts
#EXTINF:9.97667,    
fileSequence1.ts
#EXTINF:9.97667,    
fileSequence2.ts

・・・省略・・・

約10秒毎に切り替える音声ファイル(tsファイル)を指定している。

なので、これを直接、また、urlに入れてみる。

例えば、一つ目であれば、https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear1/fileSequence0.ts

このURLをDLすると、ストリーム配信の癖に、実はダウンロード出来てしまう。

また、このコンテンツは、キャッシュ禁止を書かない限りクライアント次第ではキャッシュする事がありえるらしい ※公式doc参照

こんな感じでprogressive downloadは、ファイルがクライアントに残ったり辿れたりする。

これが、問題無いのかは確認しないといけない。

著作権上の問題と、それ以外の契約等。wikipediaに軽く書かれている。

公式doc によると、断片化ファイルを作る時に暗号化する事は出来るらしい。

HLSの対応状況

HLSは、appleの仕様なので、iosは問題無く一通り動くが、androidが端末毎に色々出てきてしまう。

  • HLS対応状況は、ここのページを参考にすると
    • iosは、3.0以上
    • android
      • 3.0でサポートしたが、頻繁にcrashするらしい。
      • 4.x以降で使えるが、特にvideo再生周りで不具合が多いみたい

やっぱり、後でandroidで苦労する事になった。

html5 audio

今回は、最終的にブラウザで再生したかったので、html5のaudioタグを使った。

再生は単純で、単にこのHLS形式のURLを埋め込めば良いだけ。

一応、このaudioタグの対応状況も書いておくと、

という事で、HLS対応とhtml5 audio対応状況から、大体、ios4とandroid4以降で行けるはずだが…

androidの一部の端末(ver4以降も含む)でHLS形式のm3u8ファイルの再生が出来なかった。

一部のandroidでHLS再生出来ない

沢山android端末で再生確認して、確か1,2割くらい再生不可の端末があった気がする。

超ありがたかったのが、ここの個人のデモページ

これを見ていて気付いたが、実は、一部のandroidでは、

ストリームのresponseのcontent-typeが以下の場合、そのままでは再生出来ない

  • application/x-mpegurl
  • application/vnd.apple.mpegurl

これらの、content-typeは、appleの仕様的にも正しいし、

ietf上も、特に後者のcontent-type使えと書いてあるので正しい。(ただ、その記述の前にand/orと曖昧に書かれているのが、ちょっと気になるが)

仕様上正しいのだが、何故か、androidの一部端末は受け付けない。

これは予想だけど、おそらく、google的にそもそもandroid内のブラウザとしては、apple的な仕様で気に入らない所は拒否する仕様にしていて、それに気付いている多くのメーカーがブラウザをカスタマイズして変えていて、逆にこの対応をしていない端末が再生できないのでは?(予想ね)

対応

さて、html5 audioのtypeで単にaudioを指定してあげたら、動いた。

audio.type = "audio/mpeg";

こうすると、殆どの端末で動いた。

判定箇所

同じく、canPlayTypeとか判定している所も、上記x-mpegurlやvnd.apple.mpegurlだと拒否られるので、

audio/mpegでチェックするように変えた。

となると、どこで再生可否判定するんだよ、という話だが、

errorイベントでキャッチする事で、判定するようにした。

(再生前にエラーが起きる)

はまってる人々

やっぱり同じくハマってる人々がいるけど、原因や対応等、ふわふわしてる感じ。

参考