AWS EC2とS3でライブ配信環境構築

# 内容

- EC2インスタンスにnginx rtmpモジュールインストール
- hlsでブラウザから見れるように
- nginxをhttps化
- 配信用静的ページをS3にホスト

# EC2インスタンス構築

- パブリックサブネットにEC2インスタンスを作成したらSSHログインして以下の通りnginx rtmpモジュールを使えるように構築する。（詳しくは参考記事参照）

```bash
sudo su
yum update
yum groupinstall "Development Tools"
yum -y install pcre-devel zlib-devel openssl-devel

cd /usr/local/src/
wget http://nginx.org/download/nginx-1.8.0.tar.gz
sudo wget http://nginx.org/download/nginx-1.8.0.tar.gz
tar -zxvf nginx-1.8.0.tar.gz
wget https://github.com/arut/nginx-rtmp-module/archive/master.zip
unzip master.zip

# build
cd nginx-1.8.0
./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-master
```

ここでエラー対策で以下makefileを編集、ccのオプションを-Weerorから-Wに変更する。続きの手順を実施。

```bash
vi objs/Makefile #ccオプションの編集
make
make install
```

- nginx設定ファイル末尾に以下を追加。

```
# vi /usr/local/nginx/conf/nginx.conf
#ファイル末尾に追記
rtmp {
   server {
      listen 1935;
      chunk_size 4096;
      buflen 30s;
      drop_idle_publisher 5s;

      application live {
         live on;
         record off;
	 hls on;
	 hls_path /usr/local/nginx/html;
	 hls_fragment 5s;
	 hls_type live;
      }
   }
}
```

- nginxサービス化（詳しくは参考記事参照）

```
# vi /usr/lib/systemd/system/live_nginx.service
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
```

- nginx起動し、http接続してみる。

```
# systemctl start live_nginx.service
# curl http://<EC2インスタンスのPublicIP>/
```

- HLSでブラウザから配信を見られるように

```
# vi /usr/local/nginx/html/livetest.html
<!DOCTYPE html>
<html lang="en" class="">
<head>
  <link href="http://vjs.zencdn.net/7.10.2/video-js.css" rel="stylesheet">
  <script src="http://vjs.zencdn.net/7.10.2/video.js"></script>
</head>
<style type="text/css">
  #live {
    position: absolute;
    left: 0;
    top: 0;
    min-width: 100%;
    min-height: 100%;
    width: 100%;
    height: 100%;
    z-index: 1;
  }
</style>
<body>
  <video id="live" class="video-js vjs-default-skin" controls autoplay fullc preload="auto" data-setup='{}'>
    <source src="<配信時のストリーミングキー>.m3u8" type='application/x-mpegURL'>
    <source src="rtmp://<EC2インスタンスのPublicIP>:1935/<nginx設定時のapplication設定(上記の場合はlive)>/<配信時のストリーミングキー>" type='rtmp/mp4'>
    <p class="vjs-no-js">Not Suppoted</p>
  </video>
</body>
</html>
```

# nginxをhttps化

- ドメイン取得する。  
お金をかけたくないので、[Freenom](https://my.freenom.com/clientarea.php)で取得する。
  - 登録を終えたら Services > Register a New Domain を開く。
  - 取得したいドメイン名を入力し、Check Availavility をクリック。
  - 使われていなければいくつかのドメインが無料で利用できる。Freeとなっている好きなドメインの Get it Now! をクリック。(.tkや.mlなど無料で取得できるドメイン名も含めた形で検索しないと取得できない)
  - Availableなドメインだったこと、対象ドメイン名が Selected となっていることを確認し、Checkout をクリック。
  - Period がデフォルトでは3ヶ月となっている。必要に応じて期間を調整する。(無料なのは12ヶ月間。都度更新していけば無料で使い続けることはできる。)あとで変更するが、Use DNSをクリックして、FreenomのNameServerの方で、登録したいGIPを入力。Continueをクリック。
  - 確認画面に遷移するので、Complete Orderをクリック。
  -  Services > MyDomains から取得したドメインが見れる。DNS Management からDNS登録情報の編集が可能。

- Let's Encryptで証明書発行＆nginxに適用

```
# wget -r --no-parent -A 'epel-release-*.rpm' http://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/
# rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-*.rpm
# yum-config-manager --enable epel*
# yum repolist all
# yum install certbot
# certbot certonly --webroot -w /usr/local/nginx/html -d <取得したい証明書のFQDN（Common Name）>
# /usr/local/nginx/conf/nginx.conf
#HTTPSの記述を有効化し、証明書に先程発行したものを指定する。
～略～
    # HTTPS server
    #
    server {
        listen       443 ssl;
        server_name  localhost;

        ssl_certificate      /etc/letsencrypt/live/<FQDN>/fullchain.pem;
        ssl_certificate_key  /etc/letsencrypt/live/<FQDN>/privkey.pem;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
            root   html;
            index  index.html index.htm;
        }
    }
～略～

# systemctl restart live_nginx.service
# curl https://<FQDN>/
```

- 証明書更新を自動化する

```
# vi /etc/crontab
#以下を追記
40 4 * * * root certbot renew --no-self-upgrade && systemctl restart live_nginx.service
```

# 配信テスト（ローカルサーバー）

ここまでで配信テストができる。 
配信はiPhoneから無料アプリ「Airmix Solo」を利用する。

- Airmix Solo設定（下スワイプで設定画面の歯車マークがでるので、それをタップ）
  - Settings > Broadcastinng Destinations  
    Manage DestinationsからAdd Destinationを選択し、RTMP(S)をタップ。URLには「rtmp://\<FQDN\>:1935/\<nginx設定時のapplication設定\>」と設定し、Streamは"配信時のストリーミングキー"を入力、Auto-ReconnectをONにする。

  - Settings > Encoder Settings  
    720pを選択。

- Airmix Solo配信
  - 右スワイプでソース選択からカメラを選択。
  - 下スワイプでGo Live!をタップすると配信開始。

- ブラウザから閲覧
  作成したhtmlファイルにブラウザからアクセス(https://\<FQDN\>/livetest.html)、再生ボタンをクリックして再生が始まるか確認する。
  - 配信開始後しばらくたたないと読み込めない。
  - 自分の試した環境だと遅延は30sくらい。

# S3にhtmlファイルを配置
S3に公開用のhtmlファイルを配置し、ブラウザからのアクセス先をS3とする。

- 公開用のバケットを新しく作成（パブリックアクセスはすべて許可する。）
- 以下のように修正したindex.htmlをアップロードする。

```html:index.html
<!DOCTYPE html>
<html lang="en" class="">
<head>
    <link href="https://vjs.zencdn.net/7.10.2/video-js.css" rel="stylesheet">
    <script src="https://vjs.zencdn.net/7.10.2/video.js"></script>
</head>
<style type="text/css">
    #live {
        position: absolute;
        left: 0;
        top: 0;
        min-width: 100%;
        min-height: 100%;
        width: 100%;
        height: 100%;
        z-index: 1;
    }
</style>
<body>
    <video id="live" class="video-js vjs-default-skin" controls autoplay fullc preload="auto" data-setup='{}'>
        <source src="https://<FQDN>/<配信時のストリーミングキー>.m3u8" type='application/x-mpegURL'>
        <source src="rtmp://<FQDN>:1935/<nginx設定時のapplication設定(上記の場合はlive)>/<配信時のストリーミングキー>" type='rtmp/mp4'>
        <p class="vjs-no-js">Not Suppoted</p>
    </video>
</body>
</html>
```
- アップロードしたhtmlファイルのアクセス許可で、全員に読み込み権限を付与する。（ファイルをアップロードし直すと設定によっては毎回外れてしまうので注意）

# CORS対応
S3とnginxでcors対応の設定を行う。

- nginx側  
  以下のようにconfigを修正する。

```
# vi /usr/local/nginx/conf/nginx.conf
～略～
    # HTTPS server
    #
    server {
        listen       443 ssl;
        server_name  localhost;

        ssl_certificate      /etc/letsencrypt/live/<FQDN>/fullchain.pem;
        ssl_certificate_key  /etc/letsencrypt/live/<FQDN>/privkey.pem;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
            root   html;
            index  index.html index.htm;
            add_header Access-Control-Allow-Origin *;
            add_header Access-Control-Allow-Methods "POST, GET, OPTIONS";
            add_header Access-Control-Allow-Headers "Origin, Authorization, Accept";
            add_header Access-Control-Allow-Credentials true;
        }
    }
```

- S3側  
バケットのアクセス許可設定から「Cross-Origin Resource Sharing (CORS)」の箇所に以下のように設定する。

```
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "POST",
            "DELETE"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [],
        "MaxAgeSeconds": 3000
    }
]
```

# 配信テスト（S3）
S3にアップロードしたhtmlファイルの詳細画面オブジェクトURLから閲覧用URLをブラウザで開く。再度Airmix Soloで配信を行い、閲覧できることを確認する。


# 参考
1. EC2インスタンス構築
  - [nginx-rtmp-moduleでお試しLive配信環境を作る](https://qiita.com/sparkgene/items/c3ac042f30cc5d0fe324) サーバー環境構築は基本的にこちらの手順。
  - [make[1]: *** [objs/Makefile:445: objs/src/core/ngx_murmurhash.o] Error
 解消](https://programmerah.com/make1-objs-makefile445-objs-src-core-ngx_murmurhash-o-error-36001/) makefileのccオプションを-Werrorから-Wへ書き換える。
  - [Live配信サーバの簡単構築](https://qiita.com/MMaru76/items/e2495a87b871bc9cbefe) nginxサービス化
  - [ストリーミングサーバーを10分で作る (ubuntu 18.04 + nginx)](https://qiita.com/bellx2/items/4239bb2fc2f47469ee4d)　配信ページ作成
  - [Nginx rtmp module予期せぬ切断への対応　長時間映像配信を実現](https://techlive.tokyo/archives/1343)
2. nginxをhttps化
  - [Let's Encrypt で Nginx にSSLを設定する](https://qiita.com/HeRo/items/f9eb8d8a08d4d5b63ee9) Let's Encryptの設定
  - [AWS EC2(Amazon Linux 2 × nginx) に SSL を設定する](https://qiita.com/ntm718/items/37d1d0a7de2d1edb4e7c)
  - [SSL 証明書を取得する (Let's Encrypt)](https://www.server-world.info/query?os=Rocky_Linux_8&p=ssl&f=2)
3. CORS対策
  - [CloudFrontとS3のCORS対応](https://qiita.com/b_a_a_d_o/items/2fa94f5e929b396a24ad) s3のCORS設定
  - [メモ: nginxのAccess-Control-Allow-Origin設定](https://qiita.com/tukiyo3/items/8124d5066737debdc6bb)