Amazon Web Services ブログ
Amazon CloudFront、Lambda@Edge、AWS Elemental MediaConvertによるオンザフライ動画変換
はじめに
メディアライブラリ内の動画が、長編の特集ムービー、もしくは短編の「ハウツー」クリップであっても、通常、動画アセットの人気は視聴者の好みによって決まります。 AWSは、メディアサプライチェーンの自動化やコンテンツ配信の合理化など、お客様がオンライン動画コンテンツを配信する際に使用できる複数のソリューションを提供しています。
オンザフライ動画変換ワークフローを導入することで、メディア配信にかかる全体的なコストをさらに最適化できます。単一品質のレンディションで、まれにしか視聴されない、またはまったく視聴されない動画アセットについて考えてみてください。例えば、動画処理や配信の投資収益率(ROI)が動画コンテンツの人気と直接結びつく、広告付きの「無料視聴可能」モデルはオンザフライ動画変換の検討対象となるでしょう。また、次のようなユースケースにも適しています 。
- 人気のないユーザー生成コンテンツ (UGC)
- 注目の映画に関連するクリップ(解説や批評レビューなど)
- ストックフッテージのプレビュー版
- 後で見返すために録画されたテレビ電話会議
- 再生頻度の少ない、オンラインDVR(デジタルビデオレコーダー)プログラム
このブログ記事では、オンザフライ動画変換のためのサーバーレスワークフロー(Amazon S3のバケットに格納されたMP4ビデオソースファイルから、Amazon CloudFront を介して配信されるHTTP Live Streaming (HLS)までのフロー)を紹介します。このワークフローでは、Lambda@Edge 関数を使用して、AWS Elemental MediaConvertのジョブを呼び出します。
オンザフライ動画変換ワークフローの概要
- エンドユーザークライアントは、HLSビデオストリームのリクエストをAmazon CloudFrontに送信します(このリクエストのクエリ文字列に解像度とmp4ビデオソースファイル名パラメータが含まれます)。
- CloudFrontはユーザーリクエストをオリジンに転送し(キャッシュミスを前提として)、「オリジンリクエスト」イベント上でLambda@Edge関数をトリガーします。
- Lambda@Edge関数はクエリ文字列パラメータを解析し、HLSストリームのAmazon S3メディアバケット(オリジン)から要求されたマニフェストを取得しようとします。
- マニフェストが見つかった場合、Lambda@Edge関数はマニフェストを返します。マニフェストが見つからない場合、Lambda@EdgeはMediaConvert ジョブを呼び出します (ジョブ設定で解像度とmp4ビデオソースファイル名パラメータを提供します)。
- MediaConvertは変換ジョブリクエストを受け取り、メディアソースS3バケットからmp4ビデオソースを取得しようとします。
- MediaConvertは、HLSマニフェストとセグメントの生成を開始します。それらは、HLSストリームはS3バケットに格納バケットに格納され、変換プロセスが完了するまでマニフェストのアップデートが続行されます。
- MediaConvertが変換ジョブを開始している間、Lambda@Edge関数はイントロビデオセグメントを示すHLSマニフェストを生成し、すぐにそれを返します。
- CloudFrontは、再生のためにイントロマニフェストをエンドユーザーに転送します。
エンドユーザーのプレーヤーが更新マニフェストリクエストを送信すると仮定し、再度このプロセスが手順1で開始されます。今回は、Lambda@Edge関数がHLSストリームS3バケットで新しく生成されたマニフェストを検索し、取得してCloudFrontに戻り、エンドユーザーに配信します。
ソリューション導入の前提条件
- 新しい AWSアカウントを作成するか、既存のアカウントを使用します。
ウォークスルー:CloudFormationのデプロイ
ステップ 1: [Launch Stack] ボタンを選択して、テンプレートがプリロードされたAWS CloudFormationコンソールを開きます。
CloudFormationコンソールはus-east-1リージョンで開きます。[次へ]を選択してスタックオプションを設定します。
ステップ 2: メディアソースS3バケットとHLSストリームS3バケットの名前を指定します。
テンプレートを使用し、AWSアカウントIDをサフィックスとして次の形式で追加します。
your-hls-stream-bucket- <yourAWSAccountId>
your-media-source-bucket- <yourAWSAccountId>
[スタック名]には、デフォルト名[on-the-fly-video-convert]が設定されます。デフォルト名をそのまま使用することも、任意の名前に変更することもできます。
ステップ 3: このステップではデフォルトの設定オプションを使用し、[ 次へ ] を選択します。 (オプション — スタック内のリソースにタグを指定することもできます)。
ステップ 4: スタック設定を見直して確認し、[スタックの作成]を選択します。
CloudFormationのデプロイが完了するまで、最大10分かかる場合があります。
CloudFormationがデプロイされたリソースのレビュー
CloudFormationのデプロイが完了した際に[Outputs]タブの値を確認すると、次の4つのリソースKey Valueを確認してください。
- メディアソースのS3バケット名
- HLSストリームのS3バケット名
- CloudFrontディストリビューションエンドポイントのドメイン名
- Lambda@Edge関数のARN(Amazonリソースネーム)
Amazon CloudFront
CloudFrontディストリビューションは、オリジンとしてHLSストリームS3バケットを使用し、さらに以下2つのキャッシュ動作を使用しデプロイされます。
0 — HLSマニフェストリクエストの*.m3u8パスパターン。
1 — HLSビデオセグメントリクエストの*.tsパスパターン。
キャッシュ動作ごとに、キャッシュポリシーとオリジンリクエストポリシーがアタッチされます。
どちらのキャッシュ動作ポリシーもCORSヘッダーが有効になっています。 *.m3u8キャッシュ動作では、クエリ文字列パラメータ(幅、高さ、およびメディアファイル名)も転送されます。
Lambda@Edge関数
デプロイされたLambda@Edge関数は、CloudFront*.m3u8キャッシュ動作に関連付けられ、「オリジンリクエスト」イベントでトリガーされます。
Lambda@Edge関数は、次の2つのアクセス権限ポリシーを持つIAMロールを使用します。
- 基本的なLambdaロールに関するAWS管理ポリシー
- デプロイされたHLSストリームS3バケット、MediaConvertCreateJob、およびIAM PassRoleからのGet Objectアクション、List BucketアクションアクションをMediaConvertに対して行うことを許可し、デプロイされたS3バケットとの間で読み取り/書き込みを許可するインラインポリシー。
Helper Lambda関数
「Helper」Lambda関数は、CloudFormationスタックのデプロイ中に、1回だけ実行されます。 このLambda関数は、CloudFront オリジン設定において、AWS MediaConvert APIエンドポイントをカスタムヘッダーとして追加します。CloudFrontは、ユーザーリクエストをオリジンに転送するときにカスタムヘッダーを追加します。これにより、Lambda@Edge関数の実行時にこれらのカスタムヘッダーをパラメータとして使用できるようになります。また、CloudFormationスタックがデプロイされているus-east-1リージョンだけでなく、グローバルエッジロケーションのいずれかのCloudFrontがトリガーすることで、これは可能になります。
このデプロイには、さらに3つのCloudFrontオリジンカスタムヘッダーが追加され、Lambda@Edge関数の実行時に使用されます。その3つとは、メディアソースS3バケット名、HLSストリームS3バケット名、およびMediaConvertジョブロールです。
AWS Elemental MediaConvert APIエンドポイント
このデプロイでは、us-east-1のMediaConvert APIエンドポイントを使用します。MediaConvertコンソールの [アカウント] で確認できます。
CloudFormationは、ジョブが呼び出されたときにMediaConvertが使用するロールを作成します。 このロールには、Get ObjectアクションとPut Objectアクションを許可するインラインポリシーがあり、これはメディアソースバケットとHLSバケットのみに制限されます。
{
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::your-source-media-bucket-<yourAccountId>/*",
"arn:aws:s3:::your-hls-media-bucket-<yourAccountId>/*"
],
"Effect": "Allow"
}
]
}
Amazon S3バケット
ステップ2では、CloudFormationによってデプロイされた、2つのAmazon S3バケットの名前を指定しました。
HLSストリームS3バケットは、アクセス権限ポリシーがアタッチされた状態でデプロイされます。これは、次の方法で制限されます。
- 直接的なパブリックアクセスからバケットを保護するための、CloudFront オリジンアクセスアイデンティティ(OAI)
- このデプロイでのみ使用できる、Lambda@EdgeおよびMediaConvertからの読み取り/書き込み権限
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E2FXXXXXYYYYYY"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-media-bucket/*"
},
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::AWSAccountId:role/LambdaFunctionRoleARN",
"arn:aws:iam::AWSAccountId:role/MediaConvertRoleARN"
]
},
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3::: your-media-bucket/*"
}
]
}
以下はメディアソースS3バケットにアタッチされたバケットポリシーで、MediaConvertのジョブ実行時ロールからの読み取りのみに制限します。
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "PolicyForMediaConvertJobRole",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::Your-Account-ID:role/otf-video-convert-MediaConvertJobRole-Your-Stack-ID"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::Your-Media-Source-Bucket-Your-Account-ID/*"
}
]
}
このデプロイをテストする
- MP4メディアファイルをメディアソースS3バケット(yourMediaSourceBucket–<yourAWSAccountId>)にアップロードします。
- 6秒のイントロHLSビデオセグメントを、以下の解像度で作成します:416×234、640×360、768×432、960×540、1280×720、1920×1080
- イントロセグメントのファイル名には、次の形式を使用します。(例:640×360の解像度の場合、’intro640x360.ts’)
- 作成したイントロセグメントをHLSストリームバケットにアップロードします。
メディアファイルとイントロセグメントをアップロードすると、バケットは次のようになります。
メディアソースバケット:
HLSストリームバケット:
5. 次の形式でHLSプレーヤーからHTTPSリクエストを作成します 。
https://d1abcd.cloudfront.net/your-media-file768x432.m3u8?width=768&height=432&mediafilename=your-media-file.mp4
- このデプロイでは、HTTPSリクエストのフォーマットにおいて、次のパラメータが必要です。
- マニフェストファイル名は、ソースファイル名(mp4拡張子を除く)とストリームの画質を組み合わせたものにします(例:your-media-file768x432.m3u8)
- クエリ文字列内の解像度のパラメータは、マニフェストファイル名の解像度と一致する必要があります(例:width=768&height=432)
- クエリ文字列内のソースビデオファイル名パラメータは、オンザフライで変換したいファイル名を示している必要があります(例:your-media-file.mp4)
- ‘your-media-file’をメディアソースバケット内のmp4ファイル名に変更します。
- CloudFrontのドメインを、CloudFrontのディストリビューションドメイン名(CloudFormationスタックの出力タブに記載されています)に変更します。
これで、異なるレンディションでストリームを取得する際に、異なる解像度を使用しつつ、同じHTTPSリクエストの形式を使ってより多くのリクエストを作成できます。
コスト
全体的に、オンザフライのビデオ変換ワークフローのコストモデルは、動画アセットがリクエストされた場合にのみ、特定の解像度で変換できることを前提としています。
例えば、次のリクエストレートに基づき、動画ライブラリをオンザフライで変換する場合:
- アセットの30%は、6xのレンディション (3xHD、3xSD) でリクエストされている
- アセットの30%は、4xのレンディション (2xHD、2xSD) でリクエストされている
- アセットの40%は、2xのレンディション (1xHD、1xSD) でリクエストされている
同じライブラリを100%変換した場合と比較して、トランスコーディング時間は36.6%短縮できます。
- アセットの100%を6xレンディション (3xHD、3xSD) で変換した場合
このブログ内で紹介したCloudFormationによってデプロイされたサービスの料金を計算する際は、以下のサービス料金を確認してください。
- AWS Elemental Media Convertの料金: このデプロイでは、MediaConvert accelerated transcodingを使用して、ジョブの実行に必要なトランスコーディングの時間を短縮しています。
- Amazon CloudFrontの料金
- AWS Lambda@Edgeの料金
- Amazon S3の料金
スケーリング
規模を拡大してこのソリューションを使用する場合は、今回紹介したデプロイではカバーされていない点を追加で考慮する必要があります。
- マルチリージョンMediaConvertエンドポイント
- レイテンシーを低減し、リージョン間のデータ転送コストを節約するために、S3メディアバケットと同じリージョンでMediaConvertを使用することをお勧めします。
- 異なるEdgeロケーションからの重複リクエスト
- Amazon CloudFrontは、リクエストをグローバルエッジロケーションからオリジンに転送します。視聴者が同じコンテンツレンディションに対して同時にリクエストを送信する場合があります。 各コンテンツレンディションにつきMediaConvertジョブが1つだけ呼び出されるように、変換処理中の状態をキープすることをお勧めします。
- CloudFront Origin Shieldを使用し、さまざまな地域リージョンの視聴者からのオリジンリクエストを統合することを検討してください。
- DynamoDBテーブルを使用して、現在の変換処理中の状態を保存することを検討してください。 データを使用して、ジョブが進行中かどうか、およびMediaConvertジョブを呼び出すかどうかを判別します。
- Amazon CloudFrontは、リクエストをグローバルエッジロケーションからオリジンに転送します。視聴者が同じコンテンツレンディションに対して同時にリクエストを送信する場合があります。 各コンテンツレンディションにつきMediaConvertジョブが1つだけ呼び出されるように、変換処理中の状態をキープすることをお勧めします。
- 新しく作成したレンディションでメインマニフェストを更新
- MediaConvertジョブは、変換ごとに新しいメインマニフェストとプレイリスト(子)マニフェストを生成し、それをHLSバケットに格納します。 メインマニフェストに複数のレンディションを含めたい場合は、メインマニフェストの書き換えを検討する必要があります。S3イベントを使用して、変換が完了するたびにLambda関数をトリガーできます。 Lambda関数は、アダプティブビットレート(ABR)で使用できる新しいレンディションを別のメインマニフェストに追加します。また、MediaConvert自動生成ABRパッケージを使用すれば、一度に複数のレンディションを生成することができます。
クリーンアップ
今回紹介したソリューションによって生成されたアーティファクトをクリーンアップするには、まずこのデプロイで作成されたAmazon S3バケット内のすべてのファイルを削除します(このケースでは次の2つを削除します)
- YourHLSStreamBucket- <yourAWSAccountId>
- Your MediaSourceBucket- <yourAWSAccountId>
次に、このプロセスの開始時にプロビジョニングされたCloudFormationスタックを削除して、残りのインフラストラクチャをすべてクリーンアップします。
スタックの削除が失敗した場合は、スタックの削除を再実行します。 CloudFormationによってダイアログが開き、Lambda@Edge関数リソースの[削除]または[保持]を選択するオプションが表示されたら、[削除]を選択します。
結論
このブログでは、オンザフライ動画変換のソリューションをデプロイする方法を学びました。このワークフローを適用して、mp4ビデオソースファイルを異なる解像度のHLSビデオストリームに変換することができます。MediaConvertは、クリッピング、トリミング、品質フィルタの追加(ブロック解除/ノイズ除去)など、他の変換機能もサポートしています。 同じオンザフライワークフローを使用してMediaConvertジョブを呼び出し、ビジネス要件に応じてその他の変換にも応用することができます。MediaConvertの変換機能およびAPIの使用方法の詳細については、MediaConvertのドキュメントを参照してください。
AWS Media & Entertainment 参考コンテンツ
・AWS Media & Entertainment Blog (日本語)
・AWS Media & Entertainment Blog (英語)
AWSのメディアチームの問い合わせ先: awsmedia@amazon.co.jp
※毎月のメルマガをはじめました。最新のニュースやイベント情報を発信していきます。購読希望は上記宛先にご連絡ください。
翻訳は BD山口 賢人とSA金目 健二、斎藤 兼一が担当しました。原文はこちらをご覧ください。