AWS でライブ配信システムを構築する（４）CloudFront による配信

#1. この記事で扱う内容
この記事では、AWS の各種サービスを使用してライブ配信システムを構築する方法について紹介します。

今回は、MediaStore に保存された動画ファイルを CloudFront を経由して配信する方法について紹介します。　

記載した内容は、私が開発中に試行錯誤した結果であって、使用する環境や目的によっては必ずしも最善ではないかもしれませんので、その点をご注意ください。

##1-1. システム構成
「[（１）概要](https://qiita.com/mas_yam/items/9d4f491b3a1e310476f0)」に掲載のシステム構成図を参照してください。

##1-2. 環境
- AWS Elemental MediaLive（東京リージョン）
- AWS Elemental MediaSotre（東京リージョン）
- Amazon CloudFront
- Windows 10
- OBS Studio (23.1.0)

##1-3. 前提
- AWS のアカウントを取得済みであること
- 前回までの記事を参考に MediaLive, MediaStore の設定が一通り終わっていること
- CloudFront の基本的な設定方法がわかること（「[AWS + Rails で動画配信サイトを作る （4）S3 上の動画ファイルを CloudFront で配信する方法](https://qiita.com/mas_yam/items/7116de3c795b4dc8c015)」に簡単な設定方法を紹介しています）

#2. CloudFront の設定
MediaLive から出力された動画ファイルは MediaStore のコンテナに保存されます。MediaStore のコンテナにはそれぞれ URL が割り当てられるので、その URL にアクセスすることでコンテナ上の動画ファイルを参照することができます。

今回は、直接 MediaStore のコンテナにアクセスせずに、コンテンツ配信に特化した CloudFront を経由してアクセスする構成とします。

CloudFront の基本的な設定方法については、「[AWS + Rails で動画配信サイトを作る （4）S3 上の動画ファイルを CloudFront で配信する方法](https://qiita.com/mas_yam/items/7116de3c795b4dc8c015)」を参照してください。ここでは、オンデマンド配信時の設定と異なる箇所について説明します。

**(1)**
CloudFront のダッシュボードから Web ディストリビューションを作成します。

**(2)**
Originの設定で以下の項目を設定します。

- Origin Domain Name : リストの中から MediaStore のコンテナ（URLのドメイン名部分）を選択します
- Origin Path : パスを限定したい場合はパスを入力します（ここでは空にしておきます）
- Origin SSL Protocols : 許可する SSL プロトコルバージョンを選択します（ここでは、デフォルトのままにしておきます）
- Origin Protocol Policy : 許可するプロトコルを選択します（今回は https でのアクセスのみを許可したいので、「HTTPS Only」を選びます）

<img width="500" alt="fig29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/c54c7a38-f48f-a7d2-acfd-77f1e37d43d2.png">

**(3)**
その他の項目は「[AWS + Rails で動画配信サイトを作る （4）S3 上の動画ファイルを CloudFront で配信する方法](https://qiita.com/mas_yam/items/7116de3c795b4dc8c015)」に従って設定してください。


**【署名付き Cookie を使用する場合の注意点】**
CloudFront には署名付き Cookie を使用してアクセス制限をする機能がありますが、本記事執筆時点では、オリジンである MediaStore は Cookie での認証に対応していません。　

そのため、クライアントからのプリフライトリクエストに対するレスポンスに「Access-Control- Allow-Credentials」ヘッダが含まれておらず、そのままでは動画ファイルにアクセスすることができません。　したがって、ライブ配信の視聴を署名付き Cookie を使用して制限するには、CloudFront の Lambda@Edge 機能を用いて MediaStore からのレスポンスに「Access-Control- Allow-Credentials」ヘッダを追加する処理をする必要があります。

この処理をするための Lambda@Edge の関数は以下のようになります。

```javascript
'use strict';

exports.handler = (event, context, callback) => {
   const response = event.Records[0].cf.response;
   const headers = response.headers;

   headers['access-control-allow-credentials'] = [{
      key: 'Access-Control-Allow-Credentials',
      value: 'true'
   }];

   callback(null, response);
};
```

なお、Lambda@Edge 自体の作成方法については、以下の AWS のドキュメント等を参考にしてください。

- [Lambda@Edge を使用したエッジでのコンテンツのカスタマイズ - Amazon CloudFront](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/lambda-at-the-edge.html)
- [Lambda@Edge 関数の作成と使用の開始 - Amazon CloudFront](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/lambda-edge-how-it-works.html)

#3. ライブ配信をする
これまでの一通りの設定によって、想定していた CloudFront 経由でライブ配信をする準備が整いましたので、以下で実際にライブ配信をする手順を紹介します。

##3-1. MediaLive の Input の URL を確認する
「[（３）MediaLive の設定](https://qiita.com/mas_yam/items/ed01102b8a996bfc5774)」 で作成した MediaLive の input には URL が割り当てられており、撮影端末の動画配信アプリはこの URL に接続して動画を送信します。

**(1)**
AWS で MediaLive のコンソールを開き、Channel 一覧から「[（３）MediaLive の設定](https://qiita.com/mas_yam/items/ed01102b8a996bfc5774)」で作成した Channel を選択し、詳細画面を開きます。

**(2)**
詳細画面の「Details」タブに input の名前が表示されていますので、その下のリンクをクリックして詳細画面を開きます。

![fig30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/8c08fbc0-60c8-7ed7-c0d1-c2ea6246cded.png)

**(3)**
input 詳細画面の中央にある「Endpoints」欄に URL が表示されていますので、メモしておきます。

![fig24png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/1306aede-8fda-3193-4e90-02408e581a8d.png)

※ このURLのうち、末尾の「live_stream」は動画ファイルの接頭辞（Key）に割り当てられますので、動画配信アプリで送信先を指定する場合は、以下のように指定します。

- URL : rtmp://xxx.xxx.xxx.xxx:1935/livetest
- Key : live_stream


##3-2. 動画配信アプリの設定
今回、撮影側の構成は、Windows PC に USB の Web カメラをつなげて、撮影した動画を OBS Studio で MediaLive の Channel に転送する構成としています。

※ OBS Studio とは、ビデオ録画とライブ配信用の無料のソフトウェアです。 OBS Studio で使用する用語には以下のようなものがあります。

- ソース ： 映像入力デバイスを管理する項目。Webカメラ以外にも画面キャプチャやブラウザなども指定することができます。
- シーン ： ソースを1つにまとめた画面構成。それぞれに異なるソースを割り当てた複数のシーンを用意し、それらを切り替えることで、映像入力を好きなタイミングで切り替えることができます。


**(1)**
OBS Studio のサイト（ https://obsproject.com/ja/ ）から Windows 用のインストーラをダウンロードし、PC にインストールします。

**(2)**
インストールが完了したら OBS Studio を起動します。　初回起動時に「自動構成ウィザード」が開きますので、「配信のために最適化し、録画は二次的なものとする」を選んで、「次へ」ボタンを押します（自動構成ウィザードを使用すると配信設定を簡単に行うことができますが、「キャンセル」して手動で設定することもできます）。

**(3)**
「映像設定」画面では、デフォルトの設定のままで「次へ」ボタンを押します。

**(4)**
「配信情報」画面で、次の項目を入力し、「次へ」ボタンを押します。

- サービス：ドロップダウンメニューから「カスタム」を選択します
- サーバー：3-1 でメモした URL のうち、末尾の「/live_stream」を除く部分を入力します。
- ストリームキー：3-1 でメモした URL のうち、末尾の「live_stream」を入力します。
- ハードウェアエンコードを優先する：デフォルトの設定のままにしておきます。
- 帯域幅のテストでビットレートを推定する：映像ビットレートを自動で推定する場合は ON にします（テストで MediaLive に接続しますので、この後紹介する 3-3 の手順で事前にチャンネルを開いておく必要があります）。ここでは映像ビットレートを手動で設定しますので、OFF にします。
- 映像ビットレート：デフォルトの設定（10000）のままにしておきます。

![fig31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/31c3e556-8cc3-ecb7-c4e0-27ce11c16d2a.png)

**(5)**
「最終結果」画面に設定内容が表示されますので、内容に間違いなければ「設定を適用」ボタンを押します。

**(6)**
OBS Studio のメイン画面が表示されるので、画面下部にある「ソース」欄の「＋」ボタンを押して表示されるメニューから「映像キャプチャデバイス」を選択します（外付けのカメラを使用する場合は、事前に接続して使用できる状態にしておいてください）。

![fig32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/3889892b-45ba-2707-ef0f-122ad3b1a682.png) ![fig33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/37dbd809-284b-fc3e-91bd-eac366e0b9a3.png)

**(7)**
「ソースの作成/選択」画面が表示されるので、「新規作成」を選択し、適当なソース名を入力して「OK」ボタンを押します。

![fig34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/2e6c2665-25eb-20dd-a9e3-dbbca7dc7681.png)

**(8)**
作成したソースのプロパティ画面が表示されるので、「デバイス」欄で使用するカメラを選択します。　その他の設定はデフォルトのままで「OK」ボタンを押します。

<img width="500" alt="fig35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/101f966a-aca6-4833-b4ab-e1a9e6365a41.png">

**(9)**
メイン画面のソース欄に今作成したソースの名前が追加され、中央の画面プレビュー部分に、カメラで撮影した映像が表示されていることを確認します。

<img width="600" alt="fig36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/ad43f127-40cb-5d6f-c17f-b9f9dbf594db.png">

##3-3. MediaLive の Channel スタート/ストップ
動画配信アプリから MediaLive に動画を送信するには、MediaLive の Channel が開いている必要があります。

MediaLive の Channel の状態は大きく分けて次の2種類あります。

- Idle ： Channel が停止している状態で、動画配信アプリから動画を受信することができません。
- Running ： Channel が開いている状態で、動画配信アプリから動画を受信することができます。

###Channel のスタート
以下の手順で MediaLive の Channel を開きます。

**(1)**
AWS で MediaLive のコンソールを開き、Channel 一覧から「[（３）MediaLive の設定](https://qiita.com/mas_yam/items/ed01102b8a996bfc5774)」で作成した Channel を選択し、詳細画面を開きます。

**(2)**
詳細画面の右上にある「Start」ボタンを押します。

![fig37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/d967c16c-c855-7fc0-a593-001b6095f324.png)


**(3)**
Status 欄の Channel state の項目が「Starting」に変わります。

<img width="500" alt="fig25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/45e157d8-2fee-2b4b-69d0-6f4b39fb86fb.png">

起動処理が完了し、動画を受信できる状態になると「Running」に変わります。

<img width="600" alt="fig27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/eafe6184-0a87-f2a6-7752-fe94f5858d09.png">

###Channel のストップ
以下の手順で MediaLive の Channel を停止します。

**(1)**
AWS で MediaLive のコンソールを開き、Channel 一覧から「[（３）MediaLive の設定](https://qiita.com/mas_yam/items/ed01102b8a996bfc5774)」で作成した Channel を選択し、詳細画面を開きます。

**(2)**
詳細画面の右上にある「Stop」ボタンを押します。

![fig38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/38f23345-1e4f-1dc9-f65c-daef9efc5eae.png)

**(3)**
Status 欄の Channel state の項目が「Stopping」に変わります。

<img width="500" alt="fig28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/569bc861-10f5-e31f-7952-f778bfe34c77.png">

停止処理が完了すると「Idle」に変わります。

<img width="500" alt="fig39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/7e89a159-836b-a88f-c5e9-c6a35e24f49d.png">

##3-4. ライブ動画の配信
3-3 の手順で Channel をスタートして配信準備ができましたら、動画配信アプリからライブ動画を配信します。

**(1)**
動画配信アプリが動いているデバイスのグローバル IP アドレスを「[（３）MediaLive の設定](https://qiita.com/mas_yam/items/ed01102b8a996bfc5774)」の「2-4. Input の作成」で紹介した Input security group に事前に登録しておきます。

**(2)**
OBS Studio を起動し、画面中央の動画プレビューにカメラの映像が表示されていることを確認します。

**(3)**
右側にある「配信開始」ボタンを押して、配信を開始します。

![fig40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/5ae21024-6e68-85ee-22ee-5b28757d5232.png)

**(4)**
MediaLive への接続に成功し配信が開始されると、「配信開始」ボタンが「配信終了」に変わります。　また、ウィンドウ下部に配信開始からの経過時間が「LIVE」として、映像の転送レートが「kb/s」として表示されます。

![fig41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/4608eee2-a7e6-a252-7a2b-36f5135f8c9c.png)

**(5)**
ライブ配信を終了するには、OBS Studio の「配信終了」ボタンをクリックします。 OBS Studio の配信を停止したら、MediaLive の Channel もストップします。　

※ ライブ配信を終了したら、MediaLiveの Channel も停止するようにしてください。 Channel が開いたままだと、実際に配信していなくても、配信時の金額が課金され続けます。


**（補足）**
Web ブラウザなどでライブ配信を視聴するには、video タグなどの source に以下のように URL を指定します。

Output の URL が
`mediastoressl://xxxx.data.mediastore.ap-northeast-1.amazonaws.com/livetest/live_stream`
の場合、video タグ等の source には
`https://yyyyy.cloudfront.net/livetest/live_stream.m3u8`
と指定します（「yyyyy.cloudfront.net」の部分には、2 で作成した CloudFront のディストリビューションのドメインを指定してください）。

###CloudFront のキャッシュについて
テストで繰返しライブ配信を行う場合は、配信開始前に都度 CloudFront のキャッシュをクリアしてください。 CloudFront にキャッシュが残っていると動画ファイルを正しく再生できない場合があります。
参照 ： [ファイルの無効化 - Amazon CloudFront](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html)

<br/>
以上で、ライブ配信のための一通りの作業は終わりです。

次回は、MediaLive でアーカイブを出力する方法、 Railsアプリから MediaLive の Channel を操作する方法、ライブ配信の遅延解消法について紹介します。

#目次
（１）[概要](https://qiita.com/mas_yam/items/9d4f491b3a1e310476f0)
（２）[MediaStore の設定](https://qiita.com/mas_yam/items/20c8b524ebd87595e88e)
動画ファイルを保管する MediaStore の設定について紹介します。
（３）[MediaLive の設定](https://qiita.com/mas_yam/items/ed01102b8a996bfc5774)
カメラからのライブ動画を受信して、動画ファイルに変換する MediaLive の設定について紹介します。
（４）[CloudFront による配信](https://qiita.com/mas_yam/items/c3d1dde987afa50479d1) : このページ
（５）[MediaLive の設定 その２](https://qiita.com/mas_yam/items/9bdfdb2091fb12ab4c77)
MediaLive でアーカイブを出力する方法、 Railsアプリから Channel を操作する方法、ライブ配信の遅延軽減法について紹介します。