AWS Elemental MediaLive を使用したライブ動画配信アプリの基盤開発

技術部開発基盤グループの @ganmacs です。 クッキング LIVE アプリ cookpadTV のライブ動画配信基盤(以下配信基盤)を AWS Elemental MediaLive を使用して開発した話を紹介します。

cookpadTV 上のライブ動画配信基盤の役割と機能

cookpadTV では配信基盤を使ってライブ動画機能を実現しています。 cookpadTV とは料理家や料理上手な有名人による料理番組のライブ配信を視聴できるアプリです。 Cookpad Tech Kitchen #15 や、すでにクックパッド開発者ブログに書かれた記事 1, 2 を見るとどのようなアプリかをイメージがしやすいと思うのであわせてご覧ください。 配信基盤は cookpadTV 用というよりも様々なサービスで使える共通基盤になっています。 cookpadTV と配信基盤との関係は以下の図のようになっています。

f:id:ganmacs:20180509160937p:plain

配信基盤の大きな機能として

  • ライブ動画を配信できるようにする機能
  • ライブ動画を保存しておき後から見られるようにする機能

があります。ライブ動画を配信するときの配信基盤の動きは次のようになります。 配信基盤が番組の配信開始時間と終了時間を受け取って配信用 URL と購読用 URL を返します。 配信用 URL とはライブ配信したい動画を配信する URL で、購読用 URL とは配信された動画を視聴できる URL のことです。 配信プロトコルには RTMP を、購読には HLS をそれぞれ使用しています。 配信基盤は受け取った配信時間と終了時間をもとにライブ動画を配信できるように準備をします。 開始時間になると配信用 URL に対して動画のストリーミングが始まるので、配信基盤はその動画を様々な解像度にエンコードして配信しています。

ライブ動画を保存しておき後から見られるようにするために、ライブ動画を S3 に保存しておきます。 その動画を社内の動画変換サービスを使用して HLS に変換することでライブ動画をあとから見られる形にしています。

設計方針

動画を受け取りエンコードしているサーバから視聴者に配信するのではなく、配信についてはすべて S3 のようなマネージドサービスに任せられるように設計しました。 通常の動画配信の場合、コンテンツ全てを CDN で返してしまえばオリジンサーバへのアクセスをほぼ無くすことは可能です。 しかし、HLS でライブ動画を配信するにはプレイリストを頻繁に更新する必要があるため長期間キャッシュできないエンドポイントが存在し、オリジンにも高頻度にアクセスされる可能性があります。 そのような大量のアクセスに耐えられる必要があるため、ライブ動画やプレイリストを一度 S3 などにアップロードしてそこから配信できるように設計しました。 こうすることで、急に大量のアクセスが来た場合にも配信サービスのスケールをマネージドサービスに任せられるので運用が非常に楽になります。

採用理由

配信基盤で AWS Elemental MediaLive(以下 MediaLive) を使用してライブ動画配信を実現しています。 MediaLive を採用したのは、はじめに決めた設計方針を素直に実現できるからです。また、他にも以下の採用理由もあります。

  • マネージドサービスに任せられる部分は任せたい
  • S3 / AWS Elemental MediaStore(後述) とのインテグレーション
  • その他 AWS サービスとのインテグレーション

MediaLive は動画の配信先を AWS Elemental MediaPackage(以下 MediaPackage), AWS Elemental MediaStore (以下 MediaStore), S3 などから選べます。 MediaPackage は今回使用していないので紹介は割愛しますが、 MediaStore はメディア向けに最適化された S3 のようなもので、動画コンテンツをより効率よく配信可能です。 デフォルトで S3 や MediaStore を使用した配信をサポートしていることで、他のアプリケーションを使用した場合に比べてシンプルな実装で要求を実現可能なのが採用の最大の理由です。 また、MediaLive もマネージドサービスなので管理しているサーバのリソースを気にしなくていいこと、配信中のメトリクス3が Amazon CloudWatch(以下 CloudWatch) を使用して確認できることなども採用理由の一つです。

他の方法で実現不可能だったのか

MediaLive 以外にも、Wowza Streaming Engine(以下 Wowza) や nginx-rtmp-module などを使用することでライブ動画配信を実現するアプリケーションを作ることは可能です。 実は配信基盤の開発当初は MediaLive はまだ発表されていなかったため Wowza で動画配信をしようと考えており、実際にプロトタイプを作っていました。 しかし、Record HLS Packet and Upload to S3 each time. にあるように S3 へのアップロードは公式でサポートがされていないことや、その他アプリケーションを自分で管理しなくてはいけないことなどもあり、MediaLive を使用したアプリケーションに作り直しました。 MediaLive が発表された当初は、MediaLive についての記事などはほとんどなく知見が溜まっていないという欠点もありましたがドキュメントがしっかりと書かれていたので特に困りませんでした。

最終的なアーキテクチャ

配信基盤の大まかな役割として、ライブ動画を流すこと、そのアーカイブ動画を後から見れるようにとっておくことがあります。 それぞれについて最終的にどのように実現したかについて説明します。 以下がアーキテクチャの概要図になります。

f:id:ganmacs:20180509161423p:plain

配信基盤は配信の準備のために、開始時間より少し前に MediaLive を放送可能状態に変更したり、放送開始/終了検知をするために CloudWatch のアラームを設定したりします。 これらはバッチ処理によって行われています。 余談ですが配信が開始されたか/終了したかを取得する API が MediaLive には存在しません。 配信基盤では開始は S3 Event を、終了は CloudWatch を使用して、それぞれの情報を元に配信検知用のデーモンを起動しておき放送開始/終了を検知しています。 開始時間になると 配信用 URL に RTMP で動画が流れてくるので MediaLive が受け取り、設定した解像度に変換して MediaStore にアップロードします。 そして MediaStore をオリジンサーバとして CDN を経由して視聴者まで配信するようにしています。

アーカイブ動画は MediaLive の Archive Output Group を使用して、S3 にアップロードしておき、それを配信可能な形に変換して配信しています。 ライブ配信の終了時間になると、バッチ処理で S3 に保存されている動画をすべて集めてきて社内の動画変換サービスで変換して、アーカイブ動画として使用しています。 アーカイブ動画もライブ動画と同様に S3 をオリジンサーバとして CDN を経由して視聴者に配信されるようになっています。

まとめ

cookpadTV のライブ動画配信基盤の機能と、開発するうえで気をつけたことを紹介しました。 クックパッドでは AWS を利用して新たなサービスを作り出していける仲間を募集しています

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/