Edited at

HLSライブストリーミングサーバーの構築 (ABR対応)

More than 1 year has passed since last update.

こんにちは、動画チームのhagi@streampackです。


はじめに

HLSのストリーミングサーバーをAWS上で構築する手順を記載します。

最近では無料や低額で利用できるストリーミングサービスもありますが、ここはあえて自分で管理したいなー、広告入れたくない、完全公開はいやだなーといった人向けです。

またサーバー側で録画すれば撮影側で録画せずともハードコピーを残すことも可能です。

今回はAWSのEC2上に構築しABR(Adaptive Bitrate)の手順も記述します。


ABR(Adaptive Bitrate)とは

日本デジタル・プロセシング・システムズ株式会社のサイトより


ABR(アダプティブ・ビットレート)は、動画コンテンツを視聴環境(デバイスや回線速度など)に合わせて、可能な限り品質高くスムースに再生できるようにするための動画配信技術です。具体的には視聴端末の処理能力や解像度、回線速度などに応じて届ける動画の品質を自動的に上げたり下げたりすることで、視聴者に可能な限り快適な視聴体験を提供します。


サーバー側の処理としては複数の異なるビットレートのストリームを一斉に提供しクライアント(プレイヤー)が視聴環境に合わせて選択できるようになる。


環境

今回はAWSのEC2で作成します。


EC2

インスタンスタイプ:t2.small

OS:Amazon Linux AMI 2017.09


必要パッケージ

gcc pcre-devel openssl-devel

yum install gcc pcre-devel openssl-devel

*上記をインストールすれば依存関係でその他の必要パッケージもインストールされます。


nginx

nginx-1.13.8 (1.16.2017時点 最新)


nginx rtmp モジュール

nginxのrtmpモジュールは下記を利用。

nginx-rtmp-moduleのgitページ


nginx-rtmp-module概要

nginx-rtmp-moduleは1935ポートでrtmpストリームを受けてHLSやmpeg−dashに出力や録画することができます。


ffmpeg

ffmpegはrtmpを加工して再配信するのに利用します。

今回の例だと入力ストリームを異なるビットレートのストリームを生成。

ffmpeg version: N-89773-g7fcbebbeaf-static (1.16.2017時点 最新)


インストール


nginx


nginxソースダウンロード

# cd /usr/local/share

# wget http://nginx.org/download/nginx-1.13.8.tar.gz
# tar zxf nginx-1.13.8.tar.gz


nginx rtmp module ダウンロード

# cd /usr/local/share/nginx-1.13.8

# wget https://github.com/arut/nginx-rtmp-module/archive/master.zip
# unzip -q master.zip


確認

# /usr/local/nginx/sbin/nginx -V

nginx version: nginx/1.13.8
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --with-http_ssl_module --with-http_stub_status_module --add-module=nginx-rtmp-module-master


ffmpeg

ffmpegは常に更新されているためソースからコンパイルが推奨されていますが、ここでは比較的新しいコンパイル済み版(static)を利用します。


static バージョンダウンロード

FFmpeg Static Builds

# cd /usr/local/share/

# wget https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-64bit-static.tar.xz
# tar Jxf ffmpeg-git-64bit-static.tar.xz


インストール

cpやmvでも良さそうだが入れ替えることを考えシンボリックリンクにします。

# ln -s /usr/local/share/ffmpeg-git-20180111-64bit-static/ffmpeg /usr/bin/ffmpeg


確認

# ffmpeg -version

ffmpeg version N-89773-g7fcbebbeaf-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 6.4.0 (Debian 6.4.0-11) 20171206
configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc-6 --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gray --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-librtmp --enable-libsoxr --enable-libspeex --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-libzimg
libavutil 56. 7.100 / 56. 7.100
libavcodec 58. 9.100 / 58. 9.100
libavformat 58. 3.100 / 58. 3.100
libavdevice 58. 0.100 / 58. 0.100
libavfilter 7. 11.101 / 7. 11.101
libswscale 5. 0.101 / 5. 0.101
libswresample 3. 0.101 / 3. 0.101
libpostproc 55. 0.100 / 55. 0.100


設定

上記手順でインストールした場合、設定ファイルの場所は/usr/local/nginx/conf/nginx.confです。

rtmpモジュールに該当する部分はrtmp{}の部分です。

各ディレクティブについてはこちらから確認


単ストリーム出力の場合

複数ストリームはインスタンスにも負荷がかかるし大体の視聴者にはこの設定で見てもらいたいときは下記設定を放り込んで終わり。

/usr/local/nginx/conf/nginx.conf

worker_processes 1;

error_log logs/error.log error;

events {
worker_connections 1024;
}

rtmp {
server {
listen 1935;
allow play all;
application live {
live on;
hls on;
hls_path /var/www/vhosts/live/;
}
}
}

http {

server {
listen 80;
include mime.types;
default_type application/octet-stream;
server_name localhost;
add_header Access-Control-Allow-Origin *;

location /live {
types {
application/vnd.apple.mpegurl m3u8;
}
root /var/www/vhosts/;
}
}
}


rtmpディレクティブ

live on|off: rtmp配信を受け取るかどうかの設定。未設定の場合port1935が空いていても処理が始まらない。デフォルトはoff

hls on|off: hlsを有効にするかどうか。

hls_path [directory]: hlsのファイルをどこに格納するかどうかの設定hls onであれば必須。またディレクトリーが存在しない場合はエラー


ABR設定

rtmpモジュールではrtmpストリームを受け取り,ffmpegで複数のrtmpストリームを作成してからHLSファイルを作成しています。

ここで注意が必要なのはffmpegのフィルターやオプションです。配信するターゲットや内容を加味しながら設定する必要があります。

場合によってはフィルターやオプションが足りなかったりffmpegに負荷が必要以上に高くなる可能性があります。

worker_processes 1;

error_log logs/error.log error;

events {
worker_connections 1024;
}

rtmp {
server {
listen 1935;
allow play all;
application live {
live on;
exec ffmpeg -i rtmp://localhost/live/$name -async 1 -vsync cfr
-acodec copy -c:v libx264 -b:v 128K -f flv rtmp://localhost/live2/$name_low
-acodec copy -c:v libx264 -b:v 512k -f flv rtmp://localhost/live2/$name_mid
-acodec copy -c:v libx264 -b:v 1024k -f flv rtmp://localhost/live2/$name_high;
}

application live2 {
live on;
hls on;
hls_path /var/www/vhosts/live_stream;
hls_variant _low BANDWIDTH=300000;
hls_variant _mid BANDWIDTH=700000;
hls_variant _high BANDWIDTH=1200000;
}

}
}

http {

server {
listen 80;
include mime.types;
default_type application/octet-stream;
server_name localhost;
add_header Access-Control-Allow-Origin *;

location /live_stream {
types {
application/vnd.apple.mpegurl m3u8;
}
root /var/www/vhosts/;
}
}
}


rtmpディレクティブ

live on|off: rtmp配信を受け取るかどうかの設定。未設定の場合port1935が空いていても処理が始まらない。デフォルトはoff

exec コマンド: ストリームに実行するコマンド。ここではrtmpストリームから3つのrtmpストリームを作成

hls on|off: hlsを有効にするかどうか。

hls_path [directory]: hlsのファイルをどこに格納するかどうかの設定hls onであれば必須。またディレクトリーが存在しない場合はエラー

hls_variant [接尾辞 EXT-X-STREAM-INF]:tsやプレイリストの識別用接尾辞とEXT-X-STREAM-INFに記述する内容を記。


生成されるファイル

上記ABR設定だとhls_pathで指定したディレクトリーに下記のようなファイルが作成されます。

# ls -la /var/www/vhosts/live_stream/

total 11900
drwxr-xr-x 2 nobody root 12288 Jan 19 03:26 .
drwxr-xr-x 4 root root 4096 Jan 17 08:07 ..
-rw-r--r-- 1 nobody nobody 1648760 Jan 19 03:25 obs_test_high-0.ts
-rw-r--r-- 1 nobody nobody 1674516 Jan 19 03:25 obs_test_high-1.ts
-rw-r--r-- 1 nobody nobody 1390448 Jan 19 03:25 obs_test_high-2.ts
-rw-r--r-- 1 nobody nobody 1713996 Jan 19 03:26 obs_test_high-3.ts
-rw-r--r-- 1 nobody nobody 364532 Jan 19 03:26 obs_test_high-4.ts
-rw-r--r-- 1 nobody nobody 179 Jan 19 03:26 obs_test_high.m3u8
-rw-r--r-- 1 nobody nobody 351372 Jan 19 03:25 obs_test_low-0.ts
-rw-r--r-- 1 nobody nobody 342536 Jan 19 03:25 obs_test_low-1.ts
-rw-r--r-- 1 nobody nobody 323548 Jan 19 03:25 obs_test_low-2.ts
-rw-r--r-- 1 nobody nobody 344980 Jan 19 03:26 obs_test_low-3.ts
-rw-r--r-- 1 nobody nobody 106032 Jan 19 03:26 obs_test_low-4.ts
-rw-r--r-- 1 nobody nobody 176 Jan 19 03:26 obs_test_low.m3u8
-rw-r--r-- 1 nobody nobody 225 Jan 19 03:26 obs_test.m3u8
-rw-r--r-- 1 nobody nobody 935112 Jan 19 03:25 obs_test_mid-0.ts
-rw-r--r-- 1 nobody nobody 911236 Jan 19 03:25 obs_test_mid-1.ts
-rw-r--r-- 1 nobody nobody 777380 Jan 19 03:25 obs_test_mid-2.ts
-rw-r--r-- 1 nobody nobody 964252 Jan 19 03:26 obs_test_mid-3.ts
-rw-r--r-- 1 nobody nobody 282376 Jan 19 03:26 obs_test_mid-4.ts
-rw-r--r-- 1 nobody nobody 176 Jan 19 03:26 obs_test_mid.m3u8


マニフェスト

ストリーム名にm3u8がついたファイルはマニフェスト(manifest)となります。

HLS動画(ABR)を再生する際プレイヤーが最初にみるファイルです。

この中に各プレイリスト情報が含まれます。

obs_test.m3u8

#EXTM3U

#EXT-X-VERSION:3
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=400000
obs_test_low.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=700000
obs_test_mid.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1200000
obs_test_high.m3u8


プレイリスト

プレイリストには個々のストリーム再生に必要なデータファイル情報が記述されます。

プレーヤーは順次にこちらのデータファイル(ts)をダウンロードし再生します。

またマニフェストは更新されませんがフレイリストは新しいデータファイルが作成される都度更新されます。

単ストリームの場合はプレイリストのみとなります。

またプレイリストのみをプレイヤーで指定した場合再生は可能です。

obs_test_low.m3u8

#EXTM3U

#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:10
#EXTINF:10.000,
obs_test_low-0.ts
#EXTINF:10.000,
obs_test_low-1.ts
#EXTINF:10.000,
obs_test_low-2.ts


データファイル

tsファイル:mpeg-2 tsファイル


でどうやってrtmpを投げるの?


エンコーダー

有料ではPCソフトウエアのWirecastやデバイスではliveshellスマホアプリだとBroadcastMeなどが使いやすくハードルが低いです。

無料のOBSもありインターネット上に多くの利用方法が投稿されております。軽くですがOBSの利用方法を記します。使い方の詳細が気になる方はobsprojectをご参考ください。


配信の設定

配信を行う際、rtmpで投げるのですがOBSの場合は配信種別はカスタムストリーミングサーバーをご指定ください。Wirecastなど多くはrtmpサーバーとなっています。

今回の例では約1Mbps相当の配信を想定しています。


エンコーダーから投げる先(URL)

エンコーダーの投げ先はこのようになります。必ずffmpegが実行(ABRの場合)されるapplicationをご指定ください。上記単ストリーム、ABRの場合applicationは"live"となります。

URL rtmp://[nginxのグローバルIP]:1935/live/

ストリーム名 [任意ストリーム名]


URL  rtmp://XXX.XXX.XXX.XXX:1935/live/

ストリーム名  obs_test


視聴は?

safariやedgeの場合マニフェストやプレイリストを直接入力することで再生することが可能ですが他のブラウザーなどは場合によっては視聴にvideojsなどのプレイヤーを利用することが必要です。


単ストリーム

http://XXX.XXX.XXX.XXX/live/obs_test.m3u8


ABR

http://XXX.XXX.XXX.XXX/live_stream/obs_test.m3u8