View a markdown version of this page

CloudFront を使用してビデオをストリーミングする - FSx for ONTAP

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

CloudFront を使用してビデオをストリーミングする

メディアワークフローは、通常、ビデオオンデマンド (VOD) ファイル、HTTP Live Streaming (HLS) パッケージ、イメージ、グラフィックスなどの完成したコンテンツを、エディタ、プロデューサー、オートメーションシステムが NFS または SMB を使用して に書き込む FSx for ONTAP ボリュームに保存します。

Amazon S3 アクセスポイントを FSx for ONTAP ボリュームにアタッチすると、CloudFront はボリュームから直接コンテンツを提供できます。エディタと本番システムは、常にあるように NFS または SMB 経由でボリュームにパブリッシュし、CloudFront はアクセスポイントを介してコンテンツを取得し、ビューワーは最も近い CloudFront エッジロケーションからコンテンツを受け取ります。

このチュートリアルでは、HLS アダプティブビットレートパッケージとしてサンプルビデオをエンコードし、FSx for ONTAP ボリュームにアタッチされたアクセスポイントに出力をアップロードし、ビューワーが CloudFront をバイパスしてボリュームに直接到達できないようにオリジンアクセスコントロールを使用して CloudFront ディストリビューションを設定し、ストリームがエンドツーエンドで再生されることを確認します。

注記

このチュートリアルの所要時間は約 40~60 分です。 AWS のサービス 使用する には、作成したリソースの料金が発生します。クリーンアップセクションを含むすべてのステップをすぐに完了すると、米国東部 (バージニア北部) の予想コストは 1 USD 未満になります。 AWS リージョンこの見積もりには、FSx for ONTAP ボリューム自体の継続的な料金は含まれません。

パターンの仕組み

リクエストフローは次のとおりです。

  • ビューワーのプレイヤー (ブラウザ、モバイルアプリ、スマートテレビ) は、CloudFront ドメインから HLS マスタープレイリストをリクエストします。

  • CloudFront はエッジキャッシュをチェックします。CloudFront は、オリジンアクセスコントロール (OAC) で Signature Version 4 (SigV4) を使用してリクエストに署名し、アクセスポイントの Amazon S3 エンドポイントに転送します。

  • アクセスポイントは、アクセスポリシーに対してリクエストを承認します。これにより、CloudFront サービスプリンシパルがディストリビューションの範囲を指定し、FSx for ONTAP ボリュームからリクエストされたオブジェクトを返します。

  • CloudFront はレスポンスをエッジにキャッシュし、ビューワーに返します。

HLS パッケージには、さまざまなキャッシュポリシーの利点となる 2 種類のファイルが混在しています。

  • プレイリスト (.m3u8) は、ストリームを構成するセグメントを記述します。短い Cache-Control TTL を使用して、更新されたプレイリストをすばやく公開できます。

  • セグメント (.ts) には、エンコードされたビデオとオーディオが含まれています。一度書き込まれると、セグメントの内容は変更されないため、長く不変の Cache-Control TTL を使用します。

前提条件

  • Amazon S3 アクセスポイントがアタッチされた FSx for ONTAP ボリューム。 Amazon S3 CloudFront がアクセスポイントに到達できるようにするには、アクセスポイントにインターネットネットワークオリジンが必要です。手順については、「アクセスポイントの作成」を参照してください。

  • AWS CLI CloudFront ディストリビューション、オリジンアクセスコントロール、アクセスポイントポリシーを作成できる認証情報を使用してインストールおよび設定されたバージョン 2。

  • サンプルビデオを HLS にエンコードするために、FFmpeg がローカルにインストールされます。

  • ソースビデオファイル。このチュートリアルでは、Blender Foundation の Sintel トレーラーを使用します。これは、Creative Commons でリリースされた 52 秒の 1080p クリップです。

ステップ 1: ソースビデオを HLS パッケージとしてエンコードする

FFmpeg を使用して、リアルなover-the-top (OTT) ビットレートで 360p、720p、1080p の 3 種類の HLS パッケージを生成します。結果のパッケージには、バリアントごとのプレイリストを参照するマスタープレイリストが含まれており、それぞれに 4 秒のトランスポートストリームセグメントが一覧表示されます。

  1. ソースビデオをダウンロードします。

    $ mkdir -p ~/media && cd ~/media curl -sSL -o sintel-1080p.mp4 \ https://download.blender.org/durian/trailer/sintel_trailer-1080p.mp4
  2. 3 つのアダプティブビットレートバリアントを使用してビデオを HLS にエンコードします。

    $ mkdir hls && cd hls ffmpeg -i ../sintel-1080p.mp4 \ -filter_complex "[0:v]split=3[v1][v2][v3]; \ [v1]scale=w=640:h=360[v1out]; \ [v2]scale=w=1280:h=720[v2out]; \ [v3]scale=w=1920:h=1080[v3out]" \ -map "[v1out]" -c:v:0 libx264 -b:v:0 800k -maxrate:v:0 856k -bufsize:v:0 1200k \ -map "[v2out]" -c:v:1 libx264 -b:v:1 3000k -maxrate:v:1 3200k -bufsize:v:1 4500k \ -map "[v3out]" -c:v:2 libx264 -b:v:2 5500k -maxrate:v:2 5900k -bufsize:v:2 8250k \ -preset veryfast -g 48 -keyint_min 48 -sc_threshold 0 \ -map a:0 -map a:0 -map a:0 -c:a aac -b:a:0 96k -b:a:1 128k -b:a:2 128k \ -f hls -hls_time 4 -hls_playlist_type vod -hls_flags independent_segments \ -hls_segment_filename "stream_%v/seg_%03d.ts" \ -master_pl_name master.m3u8 \ -var_stream_map "v:0,a:0,name:360p v:1,a:1,name:720p v:2,a:2,name:1080p" \ "stream_%v/playlist.m3u8"

    コマンドは、1 つのマスタープレイリスト、3 つのバリアントプレイリスト、および各バリアントのトランスポートストリームセグメントを含むディレクトリツリーを生成します。

    hls/ ├── master.m3u8 ├── stream_360p/ │ ├── playlist.m3u8 │ ├── seg_000.ts │ └── ... ├── stream_720p/ │ ├── playlist.m3u8 │ ├── seg_000.ts │ └── ... └── stream_1080p/ ├── playlist.m3u8 ├── seg_000.ts └── ...

ステップ 2: HLS パッケージをアクセスポイントにアップロードする

パッケージを 2 回アップロードします。1 回は短い TTL のプレイリスト用、もう 1 回は長いイミュータブル TTL のセグメント用です。正しい設定Content-Typeは重要です。ほとんどのプレイヤーは に .m3u8application/vnd.apple.mpegurlvideo/mp2t が必要です.ts

access-point-alias をアクセスポイントエイリアスに置き換えます。

$ # Playlists: short TTL, m3u8 content type aws s3 cp ~/media/hls/ "s3://access-point-alias/content/sintel/" \ --recursive --exclude "*" --include "*.m3u8" \ --content-type "application/vnd.apple.mpegurl" \ --cache-control "max-age=60" # Segments: long immutable TTL, ts content type aws s3 cp ~/media/hls/ "s3://access-point-alias/content/sintel/" \ --recursive --exclude "*" --include "*.ts" \ --content-type "video/mp2t" \ --cache-control "max-age=31536000,immutable"

両方のファイルが、予想されるコンテンツタイプとキャッシュヘッダーでアップロードされていることを確認します。

$ aws s3api head-object --bucket access-point-alias \ --key content/sintel/master.m3u8 \ --query '{ContentType:ContentType,CacheControl:CacheControl}'

ステップ 3: オリジンアクセスコントロールを作成する

オリジンアクセスコントロール (OAC) を使用すると、CloudFront のみがオブジェクトを取得できるようにCloudFront はアクセスポイントへのリクエストに署名できます。OAC がない場合、ビューワーはアクセスポイントエンドポイントから直接オブジェクトをリクエストすることで CloudFront をバイパスできます。

$ aws cloudfront create-origin-access-control \ --origin-access-control-config \ 'Name=fsxn-media-oac,SigningProtocol=sigv4,SigningBehavior=always,OriginAccessControlOriginType=s3'

レスポンス内の Id を書き留めます。これは次のステップで使います。

ステップ 4: CloudFront ディストリビューションを作成する

アクセスポイントエイリアスをオリジンドメインとして CloudFront ディストリビューションを作成します。ステップ 2 で設定したCache-Controlヘッダーを優先する CachingOptimizedマネージドキャッシュポリシーを使用します。

  1. 次の設定を という名前のファイルに保存しdist.json、プレースホルダーを置き換えます。

    { "CallerReference": "fsxn-media-1", "Comment": "FSx for ONTAP media delivery", "Enabled": true, "DefaultRootObject": "", "Origins": { "Quantity": 1, "Items": [{ "Id": "fsxn-ap", "DomainName": "access-point-alias.s3.region.amazonaws.com", "S3OriginConfig": {"OriginAccessIdentity": ""}, "OriginAccessControlId": "oac-id", "ConnectionAttempts": 3, "ConnectionTimeout": 10 }] }, "DefaultCacheBehavior": { "TargetOriginId": "fsxn-ap", "ViewerProtocolPolicy": "redirect-to-https", "AllowedMethods": { "Quantity": 2, "Items": ["GET", "HEAD"], "CachedMethods": {"Quantity": 2, "Items": ["GET", "HEAD"]} }, "Compress": true, "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6" }, "PriceClass": "PriceClass_100", "ViewerCertificate": {"CloudFrontDefaultCertificate": true} }
    注記

    PriceClass_100 は、北米と欧州でのみ CloudFront エッジロケーションを使用するため、このチュートリアルのコストは低くなります。グローバルエッジカバレッジの場合は、値を に変更しますPriceClass_All。詳細については、CloudFront ディストリビューションの料金クラスの選択」を参照してください。

  2. ディストリビューションを作成します。

    $ aws cloudfront create-distribution --distribution-config file://dist.json \ --query 'Distribution.{Id:Id,DomainName:DomainName,ARN:ARN}'

    レスポンスのディストリビューション ID、ARN、ドメイン名を書き留めます。ディストリビューションのデプロイには約 5 分かかります。デプロイ中は、ステップ 5 に進むことができます。

ステップ 5: CloudFront を許可するアクセスポイントポリシーをアタッチする

アクセスポイントポリシーは、 AWS:SourceArn条件を使用して特定のディストリビューションにスコープされたオブジェクトを読み取るアクセス許可を CloudFront サービスプリンシパルに付与します。

  1. 次のポリシーを という名前のファイルに保存しap-policy.json、プレースホルダーを置き換えます。

    { "Version": "2012-10-17", "Statement": [{ "Sid": "AllowCloudFrontServicePrincipal", "Effect": "Allow", "Principal": {"Service": "cloudfront.amazonaws.com"}, "Action": "s3:GetObject", "Resource": "arn:aws:s3:region:account-id:accesspoint/access-point-name/object/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::account-id:distribution/distribution-id" } } }] }
  2. ポリシーをアクセスポイントにアタッチします。

    $ aws s3control put-access-point-policy \ --account-id account-id \ --name access-point-name \ --policy file://ap-policy.json

ステップ 6: 再生を確認する

ディストリビューションが Deployed ステータスになるまで待ちます。

$ aws cloudfront get-distribution --id distribution-id \ --query 'Distribution.Status'

CloudFront を介してマスタープレイリストを取得します。

$ curl -sS "https://distribution-domain/content/sintel/master.m3u8"

レスポンスには 3 つのバリアントが一覧表示されます。

#EXTM3U #EXT-X-VERSION:6 #EXT-X-STREAM-INF:BANDWIDTH=1031744,RESOLUTION=640x360,CODECS="avc1.64001e,mp4a.40.2" stream_360p/playlist.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=3497301,RESOLUTION=1280x720,CODECS="avc1.64001f,mp4a.40.2" stream_720p/playlist.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=6311285,RESOLUTION=1920x1080,CODECS="avc1.640028,mp4a.40.2" stream_1080p/playlist.m3u8

レスポンスヘッダーで、正しいコンテンツタイプ、キャッシュコントロール、キャッシュステータスを確認します。

$ curl -sSI "https://distribution-domain/content/sintel/stream_1080p/seg_000.ts"

レスポンスが成功するとcontent-type: video/mp2t、、cache-control: max-age=31536000,immutable、およびレスポンスがエッジから送信されたかオリジンから送信されたかを示す x-cache ヘッダーが表示されます。

最後に、FFmpeg でストリームをエンドツーエンドで再生し、すべてのセグメントが正しくフェッチおよびデコードすることを確認します。

$ ffprobe -v error \ -show_entries stream=codec_name,width,height \ -show_entries format=duration \ "https://distribution-domain/content/sintel/master.m3u8"

Safari または VLC でマスタープレイリスト URL を開くことも、hls.js などの JavaScript プレイヤーを使用してウェブページに埋め込むこともできます。

パターンの拡張

  • HTTPS でカスタムドメインを使用します。ドメインの ACM 証明書をリクエストし、ディストリビューションにアタッチして、CloudFront ドメインを指す CNAME レコードを追加します。手順については、CloudFront でのカスタム URLs」を参照してください。

  • 署名付き URLsまたは署名付き Cookie を使用してプレミアムコンテンツを保護します。認可が必要なコンテンツ (サブスクリプションサービス、早期アクセスプレビュー、ジオフェンスコンテンツ) には、CloudFront 署名付き URLsまたは署名付き Cookie を使用します。「署名付き URLs」を参照してください。

  • 新しいコンテンツを公開するときにキャッシュを無効にします。プレイリストを置き換えるか、新しい HLS パッケージをアップロードするときは、 aws cloudfront create-invalidation を使用して CloudFront エッジから古いバージョンを削除します。TTLs が長いイミュータブルなセグメントの場合、セグメントファイル名はパッケージごとに一意であるため、通常は無効化は不要です。

  • ブラウザベースのプレイヤーの CORS を有効にします。別のドメインのブラウザベースの HLS プレイヤーがストリームをロードする場合は、CloudFront レスポンスAccess-Control-Allow-Originヘッダーポリシーを使用してレスポンスにヘッダーを追加します。

  • ビューワーリクエストをログに記録します。CloudFront 標準ログ記録またはリアルタイムログを有効にして、分析、請求、不正使用検出のビューワーリクエストをキャプチャします。

トラブルシューティング

403 CloudFront から禁止

アクセスポイントポリシーがないか、CloudFront サービスプリンシパルが含まれていないか、AWS:SourceArn条件が間違ったディストリビューション ARN を参照しています。でポリシーを確認しaws s3control get-access-point-policy、ディストリビューション ARN がaws cloudfront create-distributionレスポンス内のポリシーと一致することを確認します。

プレイヤーはマスタープレイリストをロードしますが、再生に失敗します

セグメントファイルに Content-Type: video/mp2tがあり、プレイリストに があることを確認しますContent-Type: application/vnd.apple.mpegurl。一部のプレイヤーは、汎用コンテンツタイプのセグメントを拒否します。正しい--content-typeフラグで再アップロードします。

新しいプレイリストがビューワーに到達するまでに時間がかかる

CloudFront は、 Cache-Controlヘッダーによって設定された TTL のプレイリストをキャッシュします。短い TTL が必要な場合は、プレイリストを小さいmax-age値で再アップロードするか、無効化を作成します。セグメントのコンテンツは変更されないため、この問題はありません。

x-cache: Miss from cloudfront すべてのリクエストで

これは、リージョン内のビューワーが初めてファイルをリクエストするときに正常です。CloudFront はオリジンからミスをフェッチし、TTL のレスポンスをキャッシュします。そのエッジロケーションから同じファイルに対する後続のリクエストは、 を返しますHit from cloudfront

アクセスポイントへの直接アクセスが拒否される

これは通常の動作です。OAC には CloudFront からの SigV4-signed付きリクエストが必要であり、アクセスポイントポリシーは CloudFront サービスプリンシパルへのアクセスを制限します。ビューワーは、ディストリビューションドメインを介してのみコンテンツにアクセスできます。

クリーンアップ

ディストリビューションを無効にして削除し、残りのリソースを削除します。削除する前にディストリビューションを無効にする必要があります。これには数分かかります。

を無効にするには、 の --if-matchと の内部DistributionConfigオブジェクトget-distribution-configの 2 ETag つの値が必要です --distribution-config (完全なレスポンスには ETag も含まれていますが、 update-distributionは受け入れません)。

$ # Capture the current ETag and the DistributionConfig body GET_ETAG=$(aws cloudfront get-distribution-config --id distribution-id \ --query 'ETag' --output text) aws cloudfront get-distribution-config --id distribution-id \ --query 'DistributionConfig' --output json \ | jq '.Enabled = false' > dist-updated.json # Disable the distribution. The response returns a new ETag. UPDATE_ETAG=$(aws cloudfront update-distribution --id distribution-id \ --if-match "$GET_ETAG" --distribution-config file://dist-updated.json \ --query 'ETag' --output text) # Wait for Status to reach Deployed before deleting. aws cloudfront get-distribution --id distribution-id \ --query 'Distribution.Status' # Delete the distribution using the ETag from the update call. aws cloudfront delete-distribution --id distribution-id \ --if-match "$UPDATE_ETAG" # Fetch the OAC ETag, then delete the OAC. OAC_ETAG=$(aws cloudfront get-origin-access-control --id oac-id \ --query 'ETag' --output text) aws cloudfront delete-origin-access-control --id oac-id \ --if-match "$OAC_ETAG" aws s3control delete-access-point-policy \ --account-id account-id --name access-point-name aws s3 rm "s3://access-point-alias/content/sintel/" --recursive