nginxでストリーミングサーバを立ててライブ配信する。

この記事は[nginxアドベントカレンダー](http://qiita.com/advent-calendar/2015/nginx)の22日の記事です。

nginxを利用してストリーミングサーバを構築したいと思います。

今回のテスト環境：
**さくらのクラウド**
**1 GB / 1 仮想コア**
**20 GB SSDプラン**
**OS:CentOS7.1**

#はじめに
現在様々な配信サービスがありますが、自前サーバでの配信を今回は行いたいと思います。
主にPC用の配信システムとしてRTMPサーバを立て、
RTMPで入ってきた動画をモバイル（iOS/Android）用の配信システムとしてHLSの動画に変換→HTTPサーバに置く
という一連の動作をnginxで実現したいと思います。

#インストール・設定
まずはnginxをソースからインストールするために必要なツールを入れます。
>$ sudo yum install wget gcc pcre-devel openssl openssl-devel

任意の場所にgitでRTMPモジュールをダウンロード
>$ git clone https://github.com/arut/nginx-rtmp-module.git

nginxのソースをダウンロード（今回は2015/12/22時点で最新のstableを利用）
>$ cd ~/
>$ wget http://nginx.org/download/nginx-1.8.0.tar.gz
>$ tar zxf nginx-1.8.0.tar.gz
>$ cd nginx-1.8.0

ソースコンフィグは好きなように書いてもらえればいいと思いますが、
最後の行に先ほどダウンロードしたRTMPモジュールのパスを入れてください。
>$ ./configure --sbin-path=/usr/sbin/nginx \
>--conf-path=/etc/nginx/nginx.conf \
>--error-log-path=/var/log/nginx/error.log \
>--http-log-path=/var/log/nginx/access.log \
>--pid-path=/var/run/nginx.pid \
>--lock-path=/var/run/nginx.lock \
>--prefix=/usr/local/nginx \
>--user=nginx \
>--group=nginx \
>--with-http_ssl_module \
>--with-http_realip_module \
>--with-http_addition_module \
>--with-http_sub_module \
>--with-http_dav_module \
>--with-http_flv_module \
>--with-http_mp4_module \
>--with-http_gzip_static_module \
>--with-http_random_index_module \
>--with-http_secure_link_module \
>--with-http_stub_status_module \
>--with-ipv6 \
>--add-module=[gitでダウンロードしたRTMPモジュールのパス]

（2018/04/02追記）
2018/04現在のnginx最新版は
>--with-ipv6 \
を入れなくともipv6がデフォルト有効になっているのでエラーがでます。

makeとインストール、nginxユーザの追加
>$ make
>$ sudo make install
>$ sudo groupadd nginx
>$ sudo useradd -g nginx nginx
>$ usermod -s /bin/false nginx

これでnginxのインストールが終わりました。

次に/etc/nginx/nginx.confにRTMPの設定を追加でいれます。

```lang:/etc/nginx/nginx.conf
rtmp {
    server {
        listen 1935;
        access_log /var/log/nginx/rtmp_access.log;
         application live1 {
            live on;
            wait_video on;
            hls on;
            hls_path /usr/local/nginx/html/;
            hls_fragment 5s;
        }
    }
}
```
hlsのパスは今回、nginxのデフォルトのHTTPサーバのディレクトリに設定しています。

設定が終わったら起動します。
>$ sudo /usr/sbin/nginx

立ち上がっているか確認。CentOS6.x等で利用の場合はnetstatを使ってください。
>$ ss -an | egrep '1935|80'

（別途iptablesやfirewalldの設定を行ってください。）

#配信側設定
配信側のソフトウェアは基本的にrtmpで配信できるものであればなんでも大丈夫です。
CerevoのLiveShellシリーズがあればPCレスで配信できますね。
今回はMacOSX上で[OBS](https://obsproject.com/)を利用します。

起動後にカメラなどの設定は済ませておきます。
右下の設定をクリックすると各種設定画面が表示されます。
![スクリーンショット 2015-12-22 14.15.21.png](https://qiita-image-store.s3.amazonaws.com/0/28655/23268b6f-889c-f1a1-6172-51ab1cf4ef25.png)

配信項目に”配信種別”がありますのでこちらを「カスタムストリーミングサーバ」に、
URLはrtmp://サーバのIPアドレス/アプリケーション名に設定
上記のnginx.confの5行目の場合はアプリケーション名が「live1」となります。

ストリームキーは単純に配信するだけであれば任意でかまいません。
設定がおわれば前画面に戻って配信を押せば配信が始まります。
![スクリーンショット 2015-12-22 14.15.10.png](https://qiita-image-store.s3.amazonaws.com/0/28655/b65bd5e6-5a9b-ca68-42b5-96dccf9e4b80.png)

#配信確認
配信はフラッシュプレーヤなどで利用ができるrtmp形式とiOSやAndroidなどで利用できるhls形式の二通りが排出されています。

まずはrtmpで確認。
今回は[VLC](https://www.videolan.org/vlc/index.ja.html)を使って確認をします。

rtmp://サーバのIPアドレス/アプリケーション名/ストリームキー
![スクリーンショット 2015-12-22 16.35.33.png](https://qiita-image-store.s3.amazonaws.com/0/28655/f9f90a35-bfb4-5e20-b89d-4b45920abc4c.png)

開くと無事再生できると思います。

hlsでの確認もVLCで同様に確認できます。iOS端末でブラウザ直接下記URLを入れても再生ができます。
こちらはアプリケーション名が必要ありません。
http://サーバのIPアドレス/ストリームキー.m3u8
![スクリーンショット 2015-12-22 16.40.13.png](https://qiita-image-store.s3.amazonaws.com/0/28655/d8273e3b-757b-4809-3bda-ad9bdf931ae3.png)

こちらをオープンソースのFLVプレイヤーや、m3u8のリンクをWebに掲載することでライブ配信ができるのでお手軽です。

#IPv6でも配信してみる
nginxのIPv6対応と同様です。
（各自IPv6が利用できる環境に設定お願いします。）

nginx.confの設定を
>listen 80;
を
>listen [::]:80;

>listen 1935;
を
>listen [::]:1935 ipv6only=off;

にするだけ。
(1935をipv6onlyオプション入れなかったらうちの環境だと何故かエラー吐いた)

#UstreamやYoutubeLive、ニコニコなどにも同時配信したい。
サーバを経由して複数のチャンネルに同時再送信もできます。

>         application live1 {
>            push rtmp://Ustreamのアドレス; #追加
>            push rtmp://Youtubeライブのアドレス; #追加

配信アドレスとストリームキーが分かれて表示されている場合も繋げて1列で書いてしまってください。

#他のストリーミングサーバからライブ映像をコピーしたい。
上記とは逆に他で配信しているアドレスから再送信を受けることもできます。

>         application live1 {
>            pull rtmp://Ustreamのアドレス; #追加

この際の注意点としてはhls配信をする場合、必ずrtmpが1つ以上再生されている必要があります。
rtmpのアクセスが来た時点でpullの動作を行い、rtmpの再生が終わるとpull動作が停止します。
そのため、hlsの動画生成ができません。

#ライブ配信をサーバに録画したい
配信ソフトによっては録画機能がありますが、ライブ配信サーバ自体に録画するという方法があります。

>         application live1 {
>            record all;
>            record_path /usr/local/nginx/html/rec;
>            record_unique on;

この場合配信を行うと、/usr/local/nginx/html/recに
record_unique onが無い場合は
[ストリームキー].flv
で作られます。
record_unique onが合った場合は
[ストリームキー]-[UNIX時間].flv
という命名規則で作成されます。

録画した動画をそのまま配信・・・という事もできます。（RTMPのみ、HLS配信はできません。）

>         application rec1 {
>            live on;
>            play /usr/local/nginx/html/rec;
>         }

この場合はrtmp://[IPアドレス]/rec1/ストリーミングファイル名.flv

で配信ができます。
環境によるかもしれませんが試した限りでは追っかけ再生的な事もできました。

ちなみに出来たファイルを移動して、ffmpegでHLS用に分割して吐き出す事でHLSをオンデマンドで提供もできます。
（ffmpegがインストールできている状態で）
>$ cd /usr/local/nginx/html/rec
>$ ffmpeg -i [ストリームキー]-[UNIX時間].flv -codec copy -map 0 \
>-f segment -vbsf h264_mp4toannexb -segment_format mpegts \
>-segment_time 10 -segment_list [ストリームキー].m3u8 [ストリームキー].ts


#MPEG-DASHで配信してみる。
新しいストリーミング規格で、マルチデバイス配信を行えるMPEG-DASHも配信ができます。
受信ソフト環境は各自用意をしてください。（実は私もまだファイル作成された所まで確認していませんので後日やります。）

>         application live1 {
>            dash on;
>            dash_path /usr/local/nginx/html/dash;

#さいごに
細部まで説明ができなかったのですが、これで一通りライブ配信ができるようになります。
nginxでの配信自体は非常に優秀で有償のAdobeMediaServer（AMS）と同様レベルで捌くことができました。
（1000以上の同時アクセスも耐えられました）
また、HLSを配信においてはAMSでの配信以上のアクセスに対応ができました。
（AMS自体がApacheのモジュール上でHLSを配信している事も関係しています。）

接続制限など、まだ必要な機能などもありますが、勉強会の配信等であればこの機能を使って配信というのは広告などもでませんし、有用ではないかなと思います。
ほんとは取ったログをgeoipで可視化できるところまでやりたかったのですが続きは来年のアドベントカレンダーにでも・・・