Amazon IVS の録画機能を動画配信プラットフォームサービスに組み込む

## 概要
Amazon IVSが 2020/04/08 に S3 への録画機能を開始した。
https://aws.amazon.com/jp/about-aws/whats-new/2021/04/amazon-interactive-video-service-adds-support-recording-live-streams-amazon-s3/

今まではライブ配信機能のみを提供していたが S3への録画機能が提供されたことでライブ配信とアーカイブの両方が利用可能になる。
本記事では、S3の録画機能を自前の動画配信プラットフォームと連携するために必要な処理について解説する。
なお最新版のAWS SDKで本機能は利用可能である。

本記事で作成した動画配信プラットフォームに関しては以下を参照されたい。
https://qiita.com/clom/items/697d5fe87461d633d043

## S3への録画設定
S3 への録画を行う場合は IVS へ記録設定を行う必要がある。
その際、バケットを新規作成するか、既存のバケットを利用するか選択が可能になるが、利用するIVSのAPIと同じリージョンに属していることが必須である。
今回の場合はIVSがオレゴンに作成しているためS3バケットもオレゴンに作成している。
![2スクリーンショット 2021-04-08 225318.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61893/7276c182-d2c0-cfcd-9f41-323060c2c1a7.jpeg)

この記録設定と既存のチャネルや新規チャネルを連携させてS3への録画設定が可能になる。

録画を行った場合、動画データは以下に格納される

```
/ivs/v1/{AWSアカウントID}/{チャネルARNのリソースID}/{年}/{月}/{日}/{ライブ配信単位のユニークID}/
```

## 録画されるS3ファイルの構成
録画された動画データはIVS側から提供される events, 1分おきに生成されるサムネイル画像や各解像度別のtsファイルが格納されている media の2つが存在する。録画完了した動画データを再生する場合は `media/hls/master.m3u8`をHLSなどが再生できるプレイヤーに入れて再生すると視聴が可能になる。

`events` には以下のデータが格納されており、録画の開始・終了時刻、レンディションの情報やサムネイルの情報などが含まれている。録画開始時には`recording-started.json`、 録画終了時には`recording-ended.json` が生成される。

- recording-ended.json
- recording-started.json

```json
{
  "version": "v1",
  "recording_started_at": "2021-04-12T14:49:15Z",
  "recording_ended_at": "2021-04-12T15:00:30Z",
  "channel_arn": "arn:aws:ivs:us-west-2:0000000000:channel/aaaaaaaaaa",
  "recording_status": "RECORDING_ENDED",
  "media": {
    "hls": {
      "duration_ms": 672133,
      "path": "media/hls",
      "playlist": "master.m3u8",
      "renditions": [
        {
          "path": "480p30",
          "playlist": "playlist.m3u8",
          "resolution_width": 852,
          "resolution_height": 480
        },
        {
          "path": "360p30",
          "playlist": "playlist.m3u8",
          "resolution_width": 640,
          "resolution_height": 360
        },
        {
          "path": "160p30",
          "playlist": "playlist.m3u8",
          "resolution_width": 284,
          "resolution_height": 160
        },
        {
          "path": "720p30",
          "playlist": "playlist.m3u8",
          "resolution_width": 1280,
          "resolution_height": 720
        }
      ]
    },
    "thumbnails": {
      "path": "media/thumbnails"
    }
  }
}
```

## チャネル発行時連携
PHPの場合、チャネルを発行する際に `recordingConfigurationArn` を追加し、記録設定を作成した際の ARN を用いることで、チャネル発行時に記録設定に設定したS3バケットに対して録画したデータを格納している。

```php5
    $result = $ivs->createChannel([
      'latencyMode' => 'LOW',
      'name' => $uuid->toString(),
      'type' => 'STANDARD',
      'recordingConfigurationArn' => env('AWS_RECORDING_CONFIGURATION'),
    ]);
```

記録設定で使用する ARN は↓の形式で登録されている。

```
arn:aws:ivs:us-west-2:123456789012:recording-configuration/aabbccddeeff
````

## 録画開始・終了の通知受け取り
AWSから録画開始、録画終了の通知は EventBridge を通じて受け取ることが可能である。
`IVS Recording State Change`  のイベントを通じて処理が進むためEventBridgeでルールの設定を行い、
Lambdaなどのターゲットを設定して以降の処理を実行させる。
なお、イベントパターンは事前定義がまだ追加されていないためカスタムパターンで追加を行う。

```json
{
  "source": ["aws.ivs"],
  "detail-type": ["IVS Recording State Change"]
}
```

![スクリーンショット 2021-04-09 010357.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61893/9a4bfac7-fc2f-c2b4-2ccb-a03c4b41ac40.jpeg)

`IVS Recording State Change` では 4種類のイベントタイプを提供している。

event | description
------|---------
Recording Start | ストリームへの処理が開始され S3 への putObject 開始時に通知されるイベント
Recording End | ストリームへの処理が終了し S3への putObject が終了した際に通知されるイベント
Recording Start Failure | S3にバケットがない場合などで録画開始が出来ない場合に通知されるイベント
Recording End Failure | 録画中にエラーが発生し、録画が中止した場合などに通知されるイベント

録画開始、終了のみを検知できればいい場合は `Recording Start`, `Recording End` のイベントを受け取り処理を行えるようにする。
通知されるイベントの内容に関しては以下の内容で通知される。

```json
{
    "version": "0",
    "id": "12345678-1a23-4567-a1bc-1a2b34567890",
    "detail-type": "IVS Recording State Change",
    "source": "aws.ivs",
    "account": "123456789012",
    "time": "2020-06-23T20:12:36Z",
    "region": "us-west-2",
    "resources": [
        "arn:aws:ivs:us-west-2:123456789012:channel/AbCdef1G2hij"
    ],
    "detail": {
        "channel_name": "Your Channel",
        "stream_id": "st-1F6jDj0t3zV01cXKe5dScIJ",
        "recording_status": "Recording Start",
        "recording_status_reason": "",
        "recording_s3_bucket_name": "r2s3-dev-channel-1-recordings",
        "recording_s3_key_prefix": "ivs/123456789012/AbCdef1G2hij/2020-06-23T20-12-32.152Z/a1B2345cdeFg"
    }
}
```
イベントは `recording_status` に記載されており、この値を用いて必要な処理を行う。

`recording_s3_key_prefix` に該当の動画情報が記録されるためこの値を利用する。
prefixのデータのみでは再生はできないため、動画プレイヤーで再生が行えるようにプレイリスト用のURLを別途生成する必要がある。
受け取ったイベントの値を元に以下のURLを構成することで動画プレイヤーでの再生が可能になる。

```
https://${s3 URL}/${recording_s3_key_prefix}/media/hls/master.m3u8
```

`stream_id` は1配信においては終了まで同一IDとして処理が行われるため、ライブ配信単位でデータを管理したい場合にstream_idをkeyとして持っておくと生成開始・終了イベントが追いやすくなる。

EventBridge から Lambda Function でイベントを受け取り、録画開始・終了に対応したエンドポイントをサービス側に定義している場合、以下のような形でハンドリングが可能になる。
※実装コードに合わせてパラメーターを定義しているため、実際に運用する場合は送られてくるイベントに合わせて定義する必要がある。

```js
var request = require('request');

const HOST = '';
const EVENT_RECORD_START = 'Recording Start';
const EVENT_RECORD_END = 'Recording End';
const ARCHIVE_START_ENDPOINT = '';
const ARCHIVE_STOP_ENDPOINT = '';

exports.handler = function(event, context) {

    var actionEndpoint = null;
    const params = {
      arn: event.resources[0],
      stream_id: event.detail.stream_id,
      playback_path: event.detail.recording_s3_key_prefix
    }

    console.log(event.detail.recording_status);
    console.dir(params);

    switch (event.detail.recording_status) {
      case EVENT_RECORD_START:
        actionEndpoint = ARCHIVE_START_ENDPOINT;
        break;
      case EVENT_RECORD_END:
        actionEndpoint = ARCHIVE_STOP_ENDPOINT;
        break;
      default: 
        return;
    }

    const options = {
      uri: HOST + actionEndpoint,
      headers: {
        "Content-type": "application/json",
      },
      json: params
    };

    request.post(options, function(error, response, body){});
}
```

## まとめ
本記事では、Amazon IVS をすでに利用している場合に今回追加された録画機能を組み込む処理について紹介した。
今まではライブ配信のみの提供でアーカイブ機能を作成する場合は自前でライブ配信を録画する必要があったが、この機能追加により気軽にライブ配信のアーカイブ化が容易となった。

再生時の認証(Playback Auth)やS3への録画(Auto-Record to AmazonS3)などの機能が増えてきたことで動画配信サービスとしてのSaaSの選択肢の一つとして選ばれるようになるのではと思われる。

## 参考
https://docs.aws.amazon.com/ja_jp/ivs/latest/userguide/record-to-s3.html


## 実装コード
https://github.com/clom/yu-streaming/