Macでnginxを使って生中継システムを構築する

生中継がしたい！
ということで、何も知らないところから開発を始める。

#nginxのインストール
nginxをrtmp-module付きでインストール
普通にやるとエラーが出る

```terminal
$ brew install nginx-full --with-rtmp-module
Error: No available formula with the name "nginx-full" 
```
ので、tapをしてから実行

```terminal
$ brew tap marcqualie/nginx
$ brew install nginx-full --with-rtmp-module
```
完了

```terminal
$ nginx -V
nginx version: nginx/1.14.0
```
(参考)
[Mac - homebrewでnginxを入れるときはnginx-fullを入れよう](http://kannokanno.hatenablog.com/entry/2014/02/10/134920)
[Macでnginxを使ったRTMP配信のテスト環境を用意する](https://qiita.com/Takumi_Mori/items/5cacd5678f88b6218808)

#RTMPの設定


macの場合configファイルは `/usr/local/etc/nginx/nginx.conf`
(参考)
[Installing Nginx in Mac OS X Maverick With Homebrew](https://medium.com/@ThomasTan/installing-nginx-in-mac-os-x-maverick-with-homebrew-d8867b7e8a5a)

**サーバーのポートを変更**

```terminal
http{
    server {
        listen       80;  ##8080 → 80に変更
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }
    }
}
```
(参考)[macでもnginxを動かしてみた](https://jp.axtstar.com/?p=363)


**一番最後にRTMPの設定を追加**
(参考)
[nginxでrtmp配信サーバを構築する【完全版】](http://variedtastefinder.jp/blog/?p=1782)

```/usr/local/etc/nginx/nginx.conf
rtmp {
        server {
                listen 1935;
                application live {
                    live on;
                    hls  on;
                    record off;
                    hls_path /usr/local/Cellar/nginx-full/1.14.0/html/;

                    hls_fragment 1s;

                    hls_type live;
                }
        }
}
```
sudoで実行

```terminal
$ sudo nginx
```
これで、`localhost:80`に接続し、welcomが表示されれば完了

(エラー)ポート8080のままでやるとこうなる

```terminal
$ sudo nginx
nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
nginx: [emerg] still could not bind()
```
#配信テスト
基本このサイトを見ながら進めていきました。
[nginxでストリーミングサーバを立ててライブ配信する。](https://qiita.com/hagane5563/items/842afe6d6e7100db3a28)

1. nginxをスタート
2. OBSの設定、映像のリアルタイム配信
    - preference/Stream
        - URL : `rtmp://127.0.0.1/live`
        - Stream_Key : `STREAM_NAME`
3. VLCで受信
    - File/Open Network
        - URL : `rmtp://127.0.0.1/live/STREAM_NAME`

これで、rtmpは受信ができました。 
しかし、なぜかHLS形式が再生できない。。。

```
Your input can't be opened
VLC is unable to open the MRL 'http://127.0.0.1/STREAM_NAME.m3u8'. Check the log for details.
```
VLCのlogを`command+shift+M`で確認できる。

```
Failed reading http://127.0.0.1:80/STREAM_NAME-775.ts: HTTP/1.1 404 Not Found
```

ファイルがNot Foundになっていた。。。なぜだ？？
同じ症状が報告されていて、解決方法を試したが効果が得られなかった。
[HLS_can't_play_live_stream](https://github.com/arut/nginx-rtmp-module/issues/737)

しかし！Safariで確認
    URL : `http://127.0.0.1/STREAM_NAME.m3u8`

再生できてる！ので良しとして先に進む。

#ブラウザに埋め込む
##HLS形式
Flash Playerがなくても再生が可能なので、スマホ向け。遅延がかなり発生してしまうのが欠点
基本的に下記のサイトに従った。
[[メモ]video.jsでHLS配信をやってみた](https://qiita.com/t114/items/c7fdffaa2e7fdf406a7b)

HLS配信にネイティブ対応してるsafariの場合は数行で完了する。

```hls_safari.html
<!DOCTYPE html>
<html>
    <body><video width="640" height="360" src="output.m3u8" controls />
    </body>
</html>
```
簡単！
その他の非ネイティブのChromeなどのブラウザではvideo.jsを使用する。
ローカルに置く場合アップロード先はmacの場合`/usr/local/var/www`以下にディレクトリを作成

```terminal
www
├── index.html
└── static
    ├── css
    │   └── video.min.js
    └── js
        ├── videojs-contrib-hls.min.js
        └── videojs-contrib-media-sources.min.js
```
上記サイトからほぼコピペ

```hls_multi.html
<!DOCTYPE html>
<html>
    <head>
        <link href="/static/css/video-js.min.css" rel="stylesheet">
        <script src="/static/js/video.min.js"></script>
        <script src="/static/js/videojs-contrib-media-sources.min.js"></script>
        <script src="http:/static/js/videojs-contrib-hls.min.js"></script>
    </head>

    <body>
        <video id="test" class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" width="640" height="360" data-setup="{}">
            <source src="/STREAM_NAME.m3u8" type="application/x-mpegURL">
        </video>
    </body>
</html>

```
これで、HLS形式は完了！
rtmpの設定でデフォルトから動かした場合、404 Not Foundが出て再生できないことがあるので注意
上記の設定で遅延は30秒ほど

なんかインターフェースがちょっとかっこよくなった！
Safari, Chromeで動作を確認。
Android, iPadでも動作確認！


##RTMP方式
Flash Player必須のため、スマホでは再生不可
こちらもvideo.jsでできるのだがvideo.jsが6.0以降flashに対応しなくなったため、
別途videojs-flashが必要となる。
6.0以前の場合も、ブラウザがFlash Playerの自動実行をしなくなったため、エラーが出る。
下記サイトを参考に書き直した
[Playing RTMP stream with VideoJS player](https://stackoverflow.com/questions/45146146/playing-rtmp-stream-with-videojs-player)

```rtmp.html
<!DOCTYPE html>
<html>
    <head>
        <link href="http://vjs.zencdn.net/6.2.0/video-js.css" rel="stylesheet">

        <!-- If you'd like to support IE8 -->
        <script src="http://vjs.zencdn.net/ie8/1.1.2/videojs-ie8.min.js"></script>
    </head>
    <body>
        <video id="my-video" class="video-js" controls preload="auto" width="640" height="360" data-setup='{"techorder" : ["flash"]}'>
            <source src="rtmp://127.0.0.1:1935/live/STREAM_NAME" 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>
        <script src="http://vjs.zencdn.net/6.2.0/video.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/videojs-flash@2/dist/videojs-flash.min.js"></script>
    </body>
</html>
```
ChromeでFlash Playerを有効にするか聞かれるので、有効にして、再生！
再生された！！
Safariでも動くことを確認
遅延は2~3秒ほど
HLSの遅さに比べたら感動モノ。


#まとめ
1日かけて無知からなんとか生中継できるところまで行った。
nginxはいまだになんて読めばいいかわからない。

今後、遅延をもっと減らす方法を探したい。

全体的に参考になったサイト
[低遅延ビデオストリーミングの現在](https://www.dpsj.co.jp/tech-articles/low-latency)
[フロントエンドエンジニアのための生放送と RTMP 通信基礎](https://ygoto3.com/posts/live-streaming-and-rtmp-for-frontend-engineers/)