every Tech Blog

株式会社エブリーのTech Blogです。

ライブの録画配信にAmazonIVSを活用する

はじめに

こんにちは。DELISH KITCHEN 開発部の村上です。 DELISH KITCHENでは、AmazonIVSを用いて去年ライブ機能をリリースしました。AmazonIVSやライブ配信基盤については以前こちらのブログで紹介しているので気になる方はぜひみてください。

tech.every.tv

今回はこのライブ機能の録画配信にAmazonIVSの録画機能を活用する機会があったのでその取り組みを紹介させていただきます。 なお、社内ではライブの録画配信機能をアーカイブ配信と呼んでいるので、これ以降はアーカイブ配信という言葉を使わせていただきます。

S3への録画機能

AmazonIVSではS3への自動録画を機能として提供しています。AmazonIVSではライブストリームに関する設定情報をチャンネルという単位で提供をしていますが、録画設定はチャンネルから独立しており、複数のチャンネルで同じ録画設定を紐付けることができるようになっています。

以下のような項目を自動録画の設定としてカスタマイズすることができます。

  • 記録するビデオのレンディション
  • サムネイルの記録
    • 記録の間隔
    • 解像度
    • 保存方法
  • フラグメント化されたストリームのマージ
  • 録画動画の格納先S3

コンソール上の設定画面

実際に録画を有効にしたチャンネルでライブストリームを開始すると指定したS3にこのような形で記録したものが保存されていきます。

/ivs/v1/<aws_account_id>/<channel_id>/<year>/<month>/<day>/<hours>/<minutes>/<recording_id>

保存されるものは大きく分けて二つのカテゴリに分かれています。

  • /events
    • 開始、終了、失敗といった録画イベントに対応するJSON形式のメタデータファイル
  • /media
    • hls 配下には再生可能なHLSマニフェスト、メディアファイル
    • thumbnails 配下にはライブ中に記録されたサムネイル画像

このようにAmazonIVSでは録画設定を作成し、チャンネルに紐づけるだけでそこで配信されるライブストリームを自動で録画し、そのまま配信可能な形にS3に保存することができます。

アーカイブ配信での活用

録画されたものをそのままアーカイブ配信に使う場合はすでにHLS配信可能な状態になっているため、あとはCloudFront経由でアクセスできるようにしてしまえば簡単に終わりそうです。しかし、今回DELISH KITCHENが提供するライブでは以下二つの理由からそのまま配信することができませんでした。

  • アプリでライブ配信をする前から配信テストでストリームを繋ぐ関係で録画内容に自動で不必要な映像が録画されてしまう
  • アーカイブ配信を行う前に内容の編集を行いたいニーズがある

そこで今回はこの順序で処理をすることによってIVSの録画機能を活用しつつ、アーカイブ配信まで行えるようにしました。

  1. 録画終了をEventBridge経由でAPI通知
  2. MediaConvertのjobを作成して録画映像をmp4に変換し、ダウンロードと編集可能な状態にする
  3. 再編集したものをS3にアップロードして、EventBridge経由でAPI通知
  4. MediaConvertのjobを作成して、hlsに変換し、アーカイブ配信をCloudFront経由で行う

本記事では前半のmp4変換するまでをAmazonIVSの録画機能が関わるところとして話していきます。注意点として、AmazonIVSの録画機能自体は録画自体を必ず成功させることが担保されているわけではないのでそこのみに依存することはせずに予備として配信ソフトウェアの録画機能だったり、別の仕組みを準備することは前提としています。

録画終了をEventBridge経由でAPI通知

AmazonIVSはEventBridgeと連携して録画の開始や終了、失敗をイベントとして検知し、他システムと連携することが可能になっています。イベントパターンを指定すると録画終了をモニタリングすることができ、適切なターゲットに通知を行います。

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

通知内容には録画内容の保存先の情報やチャンネルやストリーム情報が入ります。

{
    "version": "0",
    "id": "test-test",
    "detail-type": "IVS Recording State Change",
    "source": "aws.ivs",
    "account": "11111111",
    "time": "2020-06-24T07:51:32Z",
    "region": "ap-northeast-1",
    "resources": [
        "arn:aws:ivs:ap-northeast-1:11111111:channel/AbCdef1G2hij"
    ],
    "detail": {
        "channel_name": "Channel",
        "stream_id": "st-1111aaaaabbbbb",
        "recording_status": "Recording End",
        "recording_status_reason": "",
        "recording_s3_bucket_name": "dev-recordings",
        "recording_s3_key_prefix": "ivs/v1/11111111/AbCdef1G2hij/2020/6/23/20/12/1111aaaaabbbbb",
        "recording_duration_ms": 99370264,
        "recording_session_id": "a6RfV23ES97iyfoQ",
        "recording_session_stream_ids": ["st-254sopYUvi6F78ghpO9vn0A", "st-1A2b3c4D5e6F78ghij9Klmn"]
    }
}

今回は recording_s3_bucket_namerecording_s3_key_prefix がわかっていれば、放映していたチャンネルIDと録画ファイルの格納先が特定できるのでこの二つにフィルターをかけてAPI通知を行いました。

MediaConvertのjobを作成してmp4変換処理を行う

APIサーバーに通知された録画終了イベントをもとにMediaConvertのjobを作成してmp4変換を行っていきます。MediaConvertではHLS入力をサポートしており、HLSのマニフェストファイルを入力として指定できるようになっています。AmazonIVSでは recording_s3_key_prefix に続く形で /media/hls/master.m3u8 にマニフェストファイルが保存されているのでこちらを入力とします。

これだけでもjobは作成可能なのですが、今回はAmazonIVSのイベントメタデータを活用して変換する録画ファイルの軽量化を行ったのでその紹介をします。

冒頭で説明したようにDELISH KITCHENが提供するライブではライブ配信をする前から配信テストでストリームを繋ぐ関係で録画内容に自動で不必要な映像が録画されるという現象が起こっていました。つまり、実際にユーザーに見える形のライブは30分でも配信テストも含めると1時間録画されていることもあり、このままmp4変換すると無駄に大きいファイルサイズでS3に格納してしまいます。そこでAmazonIVSのイベントメタデータファイルから以下のような処理を行いました。

  1. recording_s3_key_prefix 配下の /events/recording-ended.json から実際の録画開始時間を取得
  2. マスターデータとして保持しているライブ開始時間と録画開始時間の差分を算出
  3. 算出された時間だけ動画の冒頭をクリッピングする設定をMediaConvertのjob設定に追加

/events/recording-ended.json にはこれらの情報が保存されており、recording_started_at に録画開始時間が保存されているのでこれが冒頭余分に録画された内容の差分検出に使うことができます。

{
    "version": "v1",
    "recording_started_at": "2023-12-10T10:16:24Z",
    "recording_ended_at": "2023-12-10T10:22:00Z",
    "channel_arn": "arn:aws:ivs:ap-northeast-1:11111111:channel/AbCdef1G2hij",
    "recording_status": "RECORDING_ENDED",
    "media": {
        "hls": {
            "duration_ms": 338839,
            "path": "media/hls",
            "playlist": "master.m3u8",
            "byte_range_playlist": "byte-range-multivariant.m3u8",
            "renditions": [
                {
                    "path": "480p30",
                    "playlist": "playlist.m3u8",
                    "byte_range_playlist": "byte-range-variant.m3u8",
                    "resolution_width": 480,
                    "resolution_height": 852
                },
                {
                    "path": "360p30",
                    "playlist": "playlist.m3u8",
                    "byte_range_playlist": "byte-range-variant.m3u8",
                    "resolution_width": 360,
                    "resolution_height": 640
                },
                {
                    "path": "160p30",
                    "playlist": "playlist.m3u8",
                    "byte_range_playlist": "byte-range-variant.m3u8",
                    "resolution_width": 160,
                    "resolution_height": 284
                },
                {
                    "path": "720p30",
                    "playlist": "playlist.m3u8",
                    "byte_range_playlist": "byte-range-variant.m3u8",
                    "resolution_width": 720,
                    "resolution_height": 1280
                }
            ]
        },
        "thumbnails": {
            "path": "media/thumbnails",
            "resolution_height": 1280,
            "resolution_width": 720
        }
    }
}

MediaConvertはInputClippingsという設定値で HH:mm:ss:ff 形式で動画のクリッピングを設定できるので検出した差分の時間を使って冒頭余分に録画した部分は切り取る設定をします。この設定を行うことによってmp4変換後のファイルを最大で半分まで軽量化することができ、コストカットも実現できました。

{
  "Inputs": [
    {
      "InputClippings": [
        {
          "StartTimecode": "00:20:04:00"
        }
      ],
      "TimecodeSource": "ZEROBASED",
    }
  ]
}

仕組み構築でのTips

以上がアーカイブ配信でのAmazonIVSの録画機能の活用だったのですが、細かいところで少し工夫があったので最後にそちらの紹介をします。

自動録画の設定項目のチューニング

冒頭で説明したようにAmazonIVSの録画機能はいくつか設定項目があり、今回あえてデフォルトから変えた設定値があります。

記録するビデオのレンディション

今回のように自動で録画されたものをそのままアーカイブ配信に使わない場合、AmazonIVSで記録されるビデオのレンディションは全て保存する必要がありません。そこでデフォルトのすべてのレンディション保存からHDのみを保存するような指定をすることで不必要に録画データを保存することを避けることができます。AmazonIVSでの録画機能はそれ自体に追加料金はかからないですが、S3へ保存されるデータへの従量課金は他と同じようにあります。こうした小さな工夫にも思えますが、ライブの頻度、時間によっては長い期間で大きな差になるところだと思ってます。

フラグメント化されたストリームのマージ

基本的に自動録画の設定はデフォルトでストリーム配信ごとの録画となっています。しかし、配信中に予期せぬトラブルでストリームが切断されてしまう場合もあるでしょう。その場合に再接後に録画が分かれてしまうと不便です。そこでウィンドウでの再接続を有効化し、再接続ウィンドウで再開までの最大間隔を秒数で指定することでその時間だけストリームが終了しても録画を完全に終了するまで待機することができます。つまり、その間での再接続は同じ録画になるためトラブル時に便利な設定となっています。

MediaConvertでのuserMetadataタグの活用

今回説明では省きましたが、MediaConvertでjobを作成したあとはそのまま何もしないというより多くの場合では成功や失敗をまたEventBridge経由で通知し、アプリケーション側で適切な処理をしていくと思います。そこで課題になったのが大きく2点あります。

  1. MediaConvertのjob作成時に判別していた内部のライブ情報やConvertの目的種別が通知されるjobIDなどでは判別できない
  2. MediaConvertが違う目的で複数あるとEventBridgeでは判別できずにどちらの場合でも同じターゲットに通知がいってしまう

そこでuserMetadataタグの活用です。userMetadataタグにはMediaConvertのjob作成時に任意のkey,valueを設定できるようになっており、通知時に受け取りたい情報に含めることができます。

例えば以下のような情報をuserMetadataタグに入れておけば、任意の情報を通知時に渡すことができ、EventBridgeの発火もフィルタリングできます。

{
  "UserMetadata": {
    "live_id": "77",
    "convert_type": "recording"
  },
}

EventBridge側のフィルタリング

{
  "detail": {
    "status": ["COMPLETE"],
    "userMetadata": {
      "convert_type": ["recording"] // メタデータでの種別でのフィルタリング
    }
  },
  "detail-type": ["MediaConvert Job State Change"],
  "source": ["aws.mediaconvert"]
}

おわりに

今回はライブ機能のアーカイブ配信におけるAmazonIVSの録画機能の活用についてご紹介させていただきました。AmazonIVSを使用することでライブ配信だけではなくアーカイブ配信でも活用ができたので、弊社独自の要件もあるとは思いますが参考になれば幸いです。

エブリーではまだまだ一緒にプロダクトを作っていける仲間を募集中です。テックブログを読んで少しでもエブリーのことが気になった方、ぜひ一度カジュアル面談でお話しましょう!!

corp.every.tv