View a markdown version of this page

使用 CloudFront 串流影片 - FSx for OnTAP

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 CloudFront 串流影片

媒體工作流程通常會將隨需影片 (VOD) 檔案、HTTP 即時串流 (HLS) 套件、映像和圖形,存放在編輯器、生產者和自動化系統使用 NFS 或 SMB 寫入 的 ONTAP 磁碟區的 FSx 上。

透過將 Amazon S3 存取點連接至 FSx for ONTAP 磁碟區,CloudFront 可以直接從磁碟區提供內容。編輯器和生產系統一律以 NFS 或 SMB 的方式發佈至磁碟區,CloudFront 會透過存取點擷取內容,檢視器會從最近的 CloudFront 節點接收內容。

在本教學課程中,您將範例影片編碼為 HLS 適應性位元速率套件、將輸出上傳至連接至 FSx for ONTAP 磁碟區的存取點、使用原始存取控制設定 CloudFront 分佈,讓檢視器無法繞過 CloudFront 直接到達磁碟區,並確認串流播放端對端。

注意

本教學課程大約需要 40 到 60 分鐘才能完成。 AWS 服務 使用的 會針對您建立的資源產生費用。如果您立即完成所有步驟,包括清除區段,則美國東部 (維吉尼亞北部) 的預期成本低於 1 美元。 AWS 區域此預估不包含 FSx for ONTAP 磁碟區本身的持續費用。

模式的運作方式

請求流程為:

  • 檢視器的播放器 (瀏覽器、行動應用程式、智慧型電視) 會從 CloudFront 網域請求 HLS 主播放清單。

  • CloudFront 會檢查其邊緣快取。錯過時,CloudFront 會使用 Signature 第 4 版 (SigV4) 搭配其原始存取控制 (OAC) 簽署請求,並將其轉送至存取點的 Amazon S3 端點。

  • 存取點會針對其存取政策授權請求,允許 CloudFront 服務主體範圍限定於您的分佈,並從 FSx 傳回 ONTAP 磁碟區的請求物件。

  • CloudFront 會在邊緣快取回應,並將其傳回給檢視器。

HLS 套件會混合兩種可從不同快取政策中受益的檔案類型:

  • 播放清單 (.m3u8) 說明哪些區段組成串流。使用短 Cache-Control TTL,讓您可以快速發佈更新的播放清單。

  • 區段 (.ts) 包含編碼的視訊和音訊。一旦寫入,區段的內容永遠不會變更,因此請使用不可變的長 Cache-Control TTL。

先決條件

  • 已連接 Amazon S3 存取點的 ONTAP 磁碟區的 FSx。存取點必須具有網際網路原始伺服器,以便 CloudFront 可以連接它。如需說明,請參閱建立存取點

  • AWS CLI 第 2 版已安裝並設定了可建立 CloudFront 分佈、原始存取控制和存取點政策的登入資料。

  • FFmpeg 安裝在本機,用於將範例影片編碼為 HLS。

  • 來源影片檔案。本教學課程使用 Blender Foundation 的 Sintel 預告片,這是在 Creative Commons 下發行的 52 秒 1080p 剪輯。

步驟 1:將來源視訊編碼為 HLS 套件

使用 FFmpeg 以 360p、720p 和 1080p 產生具有逼真的over-the-top(OTT) 位元速率的三變式 HLS 套件。產生的套件包含一個主播放清單,參考每個變數的播放清單,每個播放清單都列出四秒的傳輸串流區段。

  1. 下載來源影片。

    $ mkdir -p ~/media && cd ~/media curl -sSL -o sintel-1080p.mp4 \ https://download.blender.org/durian/trailer/sintel_trailer-1080p.mp4
  2. 使用三種適應性位元速率變體將影片編碼至 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"

    命令會產生目錄樹狀目錄,其中包含一個主播放清單、三個變體播放清單,以及每個變體的傳輸串流區段。

    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 套件上傳至存取點

上傳套件兩次:使用短 TTL 的播放清單一次,使用長不可變 TTL 的區段一次。正確設定Content-Type很重要:大多數玩家需要 application/vnd.apple.mpegurl .m3u8video/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 分佈。使用 CachingOptimized受管快取政策,該政策會遵守您在步驟 2 中設定的Cache-Control標頭。

  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:連接允許 CloudFront 的存取點政策

存取點政策會授予 CloudFront 服務主體使用 AWS:SourceArn條件讀取物件的許可,範圍限定於您的特定分佈。

  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"

回應應列出三個變體。

#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/mp2tcache-control: max-age=31536000,immutablex-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,或使用 JavaScript 播放器將其內嵌在網頁中,例如 hls.js。

擴展模式

  • 搭配 HTTPS 使用自訂網域。為您的網域請求 ACM 憑證,將其連接到 分佈,然後新增指向 CloudFront 網域的 CNAME 記錄。如需說明,請參閱搭配 CloudFront 使用自訂 URLs

  • 使用簽章的 URLs Cookie 保護高級內容。對於需要授權的內容 (訂閱服務、早期存取預覽、地理圍欄內容),請使用 CloudFront 簽章的 URLs Cookie。請參閱使用簽章的 URLs Cookie 提供私有內容

  • 當您發佈新內容時,快取會失效。當您取代播放清單或上傳新的 HLS 套件時,請使用 從 CloudFront 邊緣aws cloudfront create-invalidation移除舊版本。對於具有長 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 服務主體的存取。檢視器只能透過分發網域存取內容。

清除

停用並刪除分佈,然後刪除剩餘的資源。必須先停用分佈,才能將其刪除,這需要幾分鐘的時間。

停用需要來自 的兩個值get-distribution-configETag適用於 的 --if-match,以及適用於 的內部DistributionConfig物件 --distribution-config(完整回應也包含update-distribution不接受的 ETag)。

$ # 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