nginxで動画配信(RTMP)サーバーを構築して、OBSの映像ソースとして取り込む

nginxのnginx-rtmp-moduleモジュールを使うと、簡単に配信サーバーが建てられるということでやってみました。
今回は、一時利用かつ非公開用なのと、準備時間があまり確保出来なかったため、必要最低限の設定で構築しています。

# 利用ケース
複数の配信主が参加する生放送企画で、各配信主に同じタイミングで画像の表示切替をしたかった。
そこで、RTMPサーバーに対して画像(映像)を配信し、各配信主にはサーバーからの配信映像を視聴してもらう方式を取りました。

# サーバーの用意
AWSのAmazonLinux2を利用しました。
タイプはt3.microです。

# nginx構築

## OS設定

```.sh
login as: ec2-user
Authenticating with public key "imported-openssh-key"

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
No packages needed for security; 1 packages available
Run "sudo yum update" to apply all updates.

# 以下rootで作業
[ec2-user@rtmp-server ~]$ sudo su -

# swap追加
# (とりあえず最初に追加しましたが、今回の場合搭載メモリだけでも十分足りてそうでした。)
[root@rtmp-server ~]# sudo dd if=/dev/zero of=/swapfile bs=1024 count=2048k
2097152+0 records in
2097152+0 records out
2147483648 bytes (2.1 GB) copied, 14.1385 s, 152 MB/s
[root@rtmp-server ~]# sudo chmod 600 /swapfile
[root@rtmp-server ~]# mkswap /swapfile
Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)
no label, UUID=412e18b2-5c33-4283-8dc7-f56064a86a12

[root@rtmp-server /]# swapon /swapfile
[root@rtmp-server /]# free -h
              total        used        free      shared  buff/cache   available
Mem:           959M         54M         60M        304K        844M        748M
Swap:          2.0G          0B        2.0G

# 自動マウント設定
[root@rtmp-server /]# vi /etc/fstab
# 下記を追記
/swapfile  none   swap   defaults 0 0

# タイムゾーン設定
timedatectl set-timezone Asia/Tokyo

# 日本語設定
localectl set-locale LANG=ja_JP.UTF-8
localectl set-keymap jp106
```

## nginxインストール



```.sh
# rtmpプラグインダウンロード
wget https://github.com/arut/nginx-rtmp-module/archive/master.zip
unzip master.zip

# nginxダウンロード
wget http://nginx.org/download/nginx-1.14.0.tar.gz
tar zxf nginx-1.14.0.tar.gz

# コンパイルに必要そうなモジュールを入れておく
yum install -y gcc pcre-devel openssl openssl-devel

# nginxコンパイル＆インストール
cd nginx-1.14.0
./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 \
--add-module=/root/nginx-rtmp-module-master
make
make install
```

## nginx設定

```.sh
# confファイルを修正
vi /etc/nginx/nginx.conf

# 下記を追加する
rtmp {
    server {
        listen 1935;
        chunk_size 4096;
        access_log /var/log/rtmp_access.log;

        application live { #ここで指定している「live」という名前が、後ほど使うURLの一部になる
            live on;
            record off;
        }
    }
}

```

# 起動ファイル作成

https://www.nginx.com/resources/wiki/start/topics/examples/systemd/
ここから拝借

```.sh
# サービスファイル作成
vi /lib/systemd/system/nginx.service

# 以下記載内容
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
```

## 起動確認＆自動起動設定

```.sh
# nginx起動
systemctl start nginx

# 起動出来てるか確認
systemctl status nginx

# 自動起動設定ON
systemctl enable nginx
```

# 再生プレーヤーの配置
手軽に導入出来そうなVideo.jsを使いました
https://videojs.com/
下記HTMLをカスタマイズして、サーバーに配置する
https://videojs.com/getting-started/

配置場所：/usr/local/nginx/html/player.html

```.html
<!DOCTYPE html>
<html lang="en" class="">
<head>
  <link href="https://vjs.zencdn.net/7.1.0/video-js.min.css" rel="stylesheet">
  <script src="https://vjs.zencdn.net/7.1.0/video.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-flash/2.1.1/videojs-flash.min.js"></script>
</head>

<body>
  <video id="my-video" class="video-js" controls autoplay
   preload="auto" width="1280" height="720" data-setup='{}'>
    <source src="rtmp://13.115.174.186:1935/live/livekey" type='rtmp/mp4'>
    <p class="vjs-no-js">
      To view this video please enable JavaScript, and consider upgrading to a web browser that
      <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
    </p>
  </video>
</body>
</html>
```

下記項目は環境毎に変更すること
**rtmp://サーバーIP:1935/（nginx.confで指定した文字列）/（ストリームキー）**
※ストリームキーは、後のOBS設定で指定します

```.html
<source src="rtmp://13.115.174.186:1935/live/livekey" type='rtmp/mp4'>
```

# 動作確認
## OBSで配信してみる
OBSの配信設定で、URLとストリームキーを設定する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279041/10721fe3-8c6e-c1ee-422d-758acfb0303e.png)

配信開始を押すと、配信が流れる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279041/0416a1d5-d80e-7210-f675-ba3e8755279d.png)

ブラウザで先ほど用意したplayer.htmlにアクセスしてみる
※RTMP配信を見るにはAdobe Flashが必要なので、インストールと有効化を行うこと
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279041/fbfc3226-1148-527c-0309-6cf518eb88d2.png)

OBSで設定した映像が見えればOK
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279041/78ba045e-8096-27f3-ae73-276b1e2c2f17.png)

# OBSのメディアソースへの追加
今回の場合、配信サーバーの映像を、各配信者側で映像として取り込む必要があったため、そのやり方も記載

ソースの追加から「メディアソース」を追加する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279041/910f3b95-582f-d134-3f81-84d929e7afe6.png)

ローカルファイルのチェックを外すと、入力・入力フォーマットの項目が出てくるので、
下記のようにURLとフォーマットを記載する
入力：rtmp://13.115.174.186/live/livekey
入力フォーマット：rtmp
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279041/25d2020a-37f3-898c-39f2-0e94354a88b2.png)

配信映像が表示された
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279041/8c254172-a994-b927-6a01-588c27b33c5e.png)

## OBS上でRTMPソース追加時の注意

- 映像の遅延が5～10秒ほどある
- 配信から時間が経つにつれて遅延時間が延びていく
- 配信を一度切ると、再接続がうまくいかないことが多い
    - メディアソースを再設定すると直る？

ブラウザ(Video.js)で確認すると、遅延は2～3秒で終始安定していたため、OBSのRTMPソース追加は不安定な印象でした。

# 別の方法でキャプチャする方法

## 範囲指定キャプチャを使う
手軽な方法で、ブラウザ(Video.js)の画面を範囲指定キャプチャする方法があります。
ただし、ブラウザを表示させておく必要があるため、配信主からすると使い勝手が悪いです。
(別のウィンドウが重なると配信に映りこむ可能性がある)

## OBSのウィンドウキャプチャを使う
ブラウザ(Video.js)の画面をウィンドウキャプチャする方法もあります。
この場合、Webブラウザのハードウェアアクセラレーションを無効にしないと映らないことが多いです。

参考URL：https://www18.atwiki.jp/live2ch/pages/562.html#id_34badb41

ただ、上記設定をしても、自分の環境ではFlash部分が黒くなってしまい、キャプチャが出来なかったです。

## SCFH + FireFoxを使う
ウィンドウキャプチャと原理は一緒だと思いますが、この組み合わせだとFlash部分もキャプチャ可能でした。
Chrome・EdgeはFlash部分が黒くなってしまったので、うまくいったのはFireFoxだけです。

## RTMPではなくHLSで配信する
nginx-rtmp-moduleはHLSでの配信にも対応しています。
HLSであればFlashではなくHTML5プレーヤーで再生可能なので、キャプチャ可能なはずです。(未検証)
ただ、HLSだと遅延が40秒～ほどかかってしまうため、今回の利用ケースには適合しませんでした。

# 最後に
今回RTMPサーバーの構築自体は簡単に出来ました。負荷もメモリ・CPU共にほとんど使っていなかった印象です。
手軽に構築できる反面、Flashが必要だったりと、視聴側のハードルが高く感じたので、時間があったらWebRTCでも組んでみたいと思います。

# おまけ
今回作成したplayer.htmlをそのまま使うと、外からストリームキーが見えてしまうので注意が必要です。
nginxの設定で、配信側IPの制限も可能なので、合わせて設定すると良さそうです。

```.sh
rtmp {
    server {
        listen 1935;
        chunk_size 4096;
        access_log /var/log/rtmp_access.log;

        application live {
            live on;
            record off;
            # 配信可能なIPを制限可能
            allow publish 192.168.1.0/24;
            allow publish 172.16.0.0/24;
            deny publish all;

            # 同様に視聴IPも制限可能
            allow play 192.168.1.0/24;
            allow play 172.16.0.0/24;
            deny play all;
        }
    }
}
```