読者です 読者をやめる 読者になる 読者になる

Carpe Diem

備忘録。https://github.com/jun06t

HLSでストリーミング

概要

スマホでストリーミングを再生する場合はHLS(HTTP Live Streaming)が流行っています。
なので今回はHLSでのストリーミングを試してみます。
HLSで再生する場合、以下のファイルが必要になります。

  • プレイリストファイル(.m3u8
  • セグメント化した動画ファイル群(.ts

ffmpegを使えばmp4から上記のファイル群に変換できるので、その流れで進めます。

環境

ffmpegのインストール

Ubuntu 14.04から標準リポジトリffmpegが無くなったので以下のリポジトリを追加してインストールします。

$ sudo add-apt-repository ppa:mc3man/trusty-media
$ sudo apt-get update
$ sudo apt-get install ffmpeg

バージョンを確認します。

$ ffmpeg -version
ffmpeg version 2.5.3 Copyright (c) 2000-2015 the FFmpeg developers
built on Jan 11 2015 17:53:45 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1)
configuration: --extra-libs=-ldl --prefix=/opt/ffmpeg --enable-avresample --disable-debug --enable-nonfree --enable-gpl --enable-version3 --enable-libpulse --enable-libopencore-amrnb --enable-libopencore-amrwb --disable-decoder=amrnb --disable-decoder=amrwb --enable-libx264 --enable-libx265 --enable-libfdk-aac --enable-libvorbis --enable-libmp3lame --enable-libopus --enable-libvpx --enable-libspeex --enable-libass --enable-avisynth --enable-libsoxr --enable-libxvid --enable-libvo-aacenc --enable-libvidstab
libavutil      54. 15.100 / 54. 15.100
libavcodec     56. 13.100 / 56. 13.100
libavformat    56. 15.102 / 56. 15.102
libavdevice    56.  3.100 / 56.  3.100
libavfilter     5.  2.103 /  5.  2.103
libavresample   2.  1.  0 /  2.  1.  0
libswscale      3.  1.101 /  3.  1.101
libswresample   1.  1.100 /  1.  1.100
libpostproc    53.  3.100 / 53.  3.100

MP4ファイルをHLS用ファイルに変換

$ ffmpeg -i test.mp4 -codec copy -map 0 -f segment -vbsf h264_mp4toannexb -segment_format mpegts -segment_time 10 -segment_list playlist.m3u8 stream-%03d.ts

自分で設定する部分としては以下です。

項目 説明 今回の例
-i 変換元の動画 test.mp4
-segment_time 何秒ごとに分割するか 10
-segment_list 出力するプレイリスト playlist.m3u8
最後のパラメータ 出力する動画ファイル群 stream-%03d.ts

30分の動画ですが、分割するだけなのでほぼ一瞬で変換できます。

生成したファイルを/usr/local/nginx/の以下のフォルダ構造のように設置します。

html/hls
├── playlist.m3u8
├── stream-000.ts
├── stream-001.ts
├── stream-002.ts
├── stream-003.ts
├── stream-004.ts
├── stream-005.ts
├── stream-006.ts
├── stream-007.ts
├── stream-008.ts
~~~~~~~~~~~~~~~~~
├── stream-143.ts
└── stream-144.ts

ちなみにplaylist.m3u8の中身は以下のような感じです。

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:20
#EXTINF:10.276933,
stream-000.ts
#EXTINF:10.268600,
stream-001.ts
#EXTINF:10.994322,
stream-002.ts
#EXTINF:8.742067,
stream-003.ts
#EXTINF:10.377033,
stream-004.ts
#EXTINF:9.617944,
stream-005.ts
#EXTINF:12.112100,
stream-006.ts
#EXTINF:11.853511,

~~中略~~

stream-138.ts
#EXTINF:5.213544,
stream-139.ts
#EXTINF:10.510500,
stream-140.ts
#EXTINF:7.148811,
stream-141.ts
#EXTINF:12.178833,
stream-142.ts
#EXTINF:11.027689,
stream-143.ts
#EXTINF:6.648311,
stream-144.ts
#EXT-X-ENDLIST

見ると分かるのですが、きっちり10秒で分割されたわけではないようです。フレームレートとか関係するんですかね。

Webサーバの設定

/usr/local/nginx/conf/mime.typeに以下のmime設定を追記

types {
... 省略
    application/x-mpegURL                 m3u8;
    video/MP2T                            ts;

m3u8の方はapplication/vnd.apple.mpegurl m3u8;でもOKです。
一応IANA公認はapplication/vnd.apple.mpegurlの方 みたいですね。
最新版のNginxをソースからビルドした場合、最初から上記のmimeは設定されています。

追記したらNginxを再起動しておいてください。

表示ページの作成

HTML5videoタグで試します。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <div>
        <video width="640" height="360" src="hls/playlist.m3u8" preload="none" controls />
    </div>
</body>
</html>

※JWPlayerはプレミアムじゃないとHLSは使えないみたいです。以下のように怒られます。

Playlist could not be loaded: No playable sources found

※ただしSafariで検証したところ再生できました。はて。

動作検証

iOSの場合

iPhoneの場合再生すると強制的に全画面になるみたいですね。

f:id:quoll00:20150115001313p:plain

Androidの場合

Androidではシークバーでの移動が動きませんでした。デフォルトプレーヤーのバグでしょうか。

f:id:quoll00:20150115001352p:plain

PCの場合

PCブラウザではSafari(Mac)以外HLSに対応していないそうです。
なのでVLCファイル->ネットワークで開くで以下のようにm3u8ファイルの位置を指定します。

f:id:quoll00:20150114231333p:plain

これで再生が確認できます。

Nginxのログを見ると以下のように順にロードされていきます。

10.0.2.2 - - [14/Jan/2015:13:59:28 +0000] "GET /hls/stream-000.ts HTTP/1.1" 206 3137532 "-" "VLC/2.1.5 LibVLC/2.1.5"
10.0.2.2 - - [14/Jan/2015:13:59:28 +0000] "GET /hls/stream-001.ts HTTP/1.1" 206 2803080 "-" "VLC/2.1.5 LibVLC/2.1.5"
10.0.2.2 - - [14/Jan/2015:13:59:28 +0000] "GET /hls/stream-002.ts HTTP/1.1" 206 4192776 "-" "VLC/2.1.5 LibVLC/2.1.5"
10.0.2.2 - - [14/Jan/2015:13:59:29 +0000] "GET /hls/stream-003.ts HTTP/1.1" 206 2795936 "-" "VLC/2.1.5 LibVLC/2.1.5"
10.0.2.2 - - [14/Jan/2015:13:59:29 +0000] "GET /hls/stream-004.ts HTTP/1.1" 206 2508860 "-" "VLC/2.1.5 LibVLC/2.1.5"
10.0.2.2 - - [14/Jan/2015:13:59:29 +0000] "GET /hls/stream-005.ts HTTP/1.1" 206 3110084 "-" "VLC/2.1.5 LibVLC/2.1.5"
10.0.2.2 - - [14/Jan/2015:13:59:29 +0000] "GET /hls/stream-006.ts HTTP/1.1" 206 3502628 "-" "VLC/2.1.5 LibVLC/2.1.5"

シークバーを移動させるとそのセグメントから再開していきます。

参考