編碼,打包,CDN交付和視頻播放器端的延遲優化

摘要:

在本系列上一篇文章《定義和測量延遲》中,介紹了爲什麼延遲是OTT傳輸的一個問題以及如何測量端到端延遲中不同傳輸步驟所佔的延遲比重。 本文接下來介紹可能的延遲優化,從編碼,打包,CDN交付以及視頻播放器這些過程,通過調整其中的參數,可以爲觀衆提供一個經過精心優化的低延遲直播流。

編碼(Encoding)

本文仍舊以AWS的產品爲例,來說明傳輸過程中延遲優化的情況。

上一篇文章已經通過使用低延遲模式(Low Latency Mode)參數瞭解瞭如何使用AWS Elemental Live優化捕獲延遲,但是,此參數可能會導致輸入時間戳不連續,丟失更多音頻數據包。輸入緩衝區大小(Input Buffer Size)參數可用於將輸入級緩衝的幀數減少到最小,但存在丟棄某些幀的風險。

圖 1. 視頻編碼相關參數設置

在視頻編碼部分,有幾個參數會影響延遲:

  • Lookahead: 將其設置爲Low將改善延遲,同時降低要求苛刻的場景的輸出質量。如果沒有或幾乎沒有場景變化,Low這種模式會工作得較好。
  • GOP parameters: 建議使用1秒持續時間的GOP,如果需要,可以在2秒內重新打包。 沒有B幀的小GOP通常會降低視頻質量。
  • B Frames: 在GOP中使用的B幀越多,爲每個添加的B幀增加幾幀編碼延遲的概率就越高,因爲編碼引擎將向後看P幀以構建B幀。使用零B幀可以避免這種延遲影響,但是需要提高編碼比特率以保持與使用B幀時相同的視頻質量。
  • Temporal Adaptive Quantization: 關閉它會將延遲減少幾幀。 其他自適應量化選項不會影響延遲。
  • Encoder Buffer Size編碼器緩衝大小: 默認值是視頻比特率的兩倍,這會在解碼器上產生2秒的延遲。如果設置爲1倍比特率,則會產生1秒的延遲並略微影響視頻質量。對於要求很高的低延遲目標,緩衝區大小可以設置爲比特率的一半,這會導致半個GOP(1/2秒)的延遲,也會使視頻質量會受到更大的影響。
  • Video Preprocessors: 如果需要Deinterlacer處理器,則應選擇低延遲插值算法。

就編碼階梯而言,建議在階梯的下端添加一個輕量級流,切片的大小比通常的要小一些,以便在困難網絡條件下,移動設備仍然能夠訪問流。

打包(Packaging)

對於幾乎每個播放器而言,切片(segment)的持續時間對延遲有機械效應。使用1秒的切片,可能會達到5秒的延遲。使用2秒的切片,但這種情況一般不會發生,延遲將始終在7到10秒之間,除非對播放器設置進行嚴格的優化。1秒的切片將自動生成較小的播放器緩衝區,因此除非播放器提供快速克服空緩衝區的特定機制,否則播放過程的穩健性將會較差。

根據用戶的要求選擇合適的切片大小非常重要。如果不是絕對需要達到低於7秒的延遲,請不要使用1秒切片,而是使用2秒切片。如果播放器使用2秒切片,那麼它也有益於:

  • 將GOP長度從1秒提高到2秒,這樣就可以在恆定比特率下提高編碼質量。
  • 在origin端攝取時使用2秒切片(如果使用HLS作爲攝取格式),可以減少origin處存儲和packaging計算的壓力。

CDN交付(CDN Delivery)

對於HLS的playlist和DASH的manifest,如果播放器支持此類壓縮,則應檢查CDN配置是否允許以gzip格式提供。如果在HLS或DASH / SegmentTimeline中使用長DVR窗口,這將簡化加載操作。

由於低延遲模式下的播放器與實時邊緣時間相比,它們的請求通常更加迫切,因此它們很有可能還未傳輸就請求切片,從而導致邊緣處的404。每個CDN都有一個唯一的默認TTL值用於緩存這些404,並且通常這個值對低延遲流不友好,因此需要對其進行調整。比如對於Amazon CloudFront,可以在配置面板的“錯誤頁面”部分中將其設置爲1秒。

與低延遲無關,但對流的傳輸過程仍然很重要:需要將“origin”的傳入標頭列入白名單,以便CDN將其轉發到origin處,因爲它是origin返回的所有下游CORS策略的關鍵觸發器。

最後,如果在CDN端設置了HLS playlist或DASH manifest的TTL,則應驗證它們是否短於或等於HLS切片間隔或DASH manifest更新間隔。

視頻播放器端的延遲優化

現在看一下最重要的延遲改進領域 - 視頻播放器的參數,即使在工作流程的上游優化了工作流參數,但這些優化可能會對未集成低延遲導向機制的視頻播放器無效。

視頻播放器通常經過優化,可爲最終用戶提供不間斷的播放,這意味着播放器會優先考慮緩衝區長度而不是降低流延遲。但並不意味着完全缺乏啓用低延遲的選項,而是在每個播放器的初始化設置中默認不啓用這些選項。

以下是一個非詳盡的相關設置列表,這些設置會影響播放器爲傳輸提供儘可能低的延遲:

  • 初始緩衝區大小:大多數播放器設計用於在觸發流播放之前緩衝特定數量的切片,秒或一些兆字節(MB)。通常使用1秒和2秒的切片,並且如果播放器不緩衝超過三個切片的時長,則播放器能達到不到10秒的延遲。但是,如果在實時播放列表/清單中呈現長DVR窗口,則某些播放器可能被設計爲緩衝特定時間量。在這種情況下,即使切片長度爲1秒,最終也會緩衝30到40秒,這會導致較高延遲。這就是爲什麼應該檢查播放器默認緩衝策略,並在播放器過於保守的情況下尋找限制啓動時緩衝區長度的方法。通常,將緩衝區限制爲3或4秒是延遲和播放穩定性之間的合理折衷。低於3秒可以顯着改善延遲,但也會影響用戶體驗,導致在播放期間會發生定期的重複緩衝階段。
  • 與實時邊緣時間(live edge time)相比,播放器在實時播放中的初始定位(initial position):對於大多數播放器來說,它與前一點相比是多餘的,但也並非總是如此。如果利用強制播放頭以x切片或延遲x秒開始播放,在播放器設置中設置較低緩衝時間就可能效率比較低。但這是一個補充設置,需要自定義。
  • 實時邊緣時間粘性(Live Edge-Time stickiness):即使播放器以預期延遲開始播放,也可能在重新緩衝的情況下,在重新緩衝之前的最後已知時刻恢復播放。這意味着如果播放器只需要100毫秒的時間來重新緩衝,那麼在重新緩衝階段之後,與實時邊緣時間相比,將自動延遲相同的時間。這通常是默認情況下在所有播放器中發生的情況,但是一些播放器提供了在空緩衝區後重新加載播放列表/清單的選項(當音頻或視頻軌道的緩衝區變爲零秒並且卡在其上時),或者及時向前尋求播放並且同時關注實時邊緣時間。如果優先級是在整個播放會話中保持儘可能低的延遲,並且用戶不會在實時會話中瀏覽每一秒內容,那麼如果播放器是開源的話,這是一種可以利用或添加的選項。在任何情況下,如果不希望延遲隨着時間的推移而變化,那麼在播放器中擁有這一功能至關重要。
  • 對不可用切片的恢復能力(Resilience to segments unavailability):可能是某個特定的媒體切片根本不可用,或者與播放器的期望相比有一些延遲。 在這種情況下,如果在所有重試嘗試之後切片還是不可用,則播放器將重試多次加載切片並且可能停止播放連接。對於這種情況,用戶可能希望查找播放器選項以增加重試次數,或者切換到較低的比特率,或者跳過時間線中缺少的片段。

下面以一些開源播放器爲例說明延遲相關的參數設置。

hls.js

這個用於MSE(媒體源擴展Media Source Extensions)環境的開源HLS播放器確實在其config.js初始化文件中公開了許多不同的參數。下面爲它可以調整的一些參數:

  • maxBufferLength(默認值:30秒)這是播放器嘗試緩衝的最大秒數
  • maxBufferSize(默認值:60MB)這是播放器嘗試緩衝的最大內容大小(MB)
  • maxStarvationDelay(默認值:4s)這是重新緩衝的最大允許秒數。 減少它可以通過強制播放器切換到較低的比特率來防止較大的重新緩衝階段。
  • liveSyncDurationCount(默認值:3)這是啓動時最後引用的切片後面的切片數。 降低它將使播放器開始接近實時邊緣時間。

在hls.js 0.9.1版本之前,如果需要使用低於一秒的playlist重新加載間隔,那麼可以減少level-controller.js中的硬編碼1000的值:

dash.js

這種用於MSE環境的開源DASH播放器提供了幾種方法來設置與實時邊緣時間相比的初始延遲。 player.setLiveDelayFragmentCount(默認值:4)允許指定實時邊緣時間後面的切片數,而player.setLiveDelays指定它以秒爲單位。可以自定義的其他方法參數是:

  • player.setFragmentLoaderRetryInterval(默認值:1000毫秒)將失敗的片段加載嘗試間隔變爲切片長度的三分之一
  • player.setFragmentLoaderRetryAttempts(默認值:3),可以增加以補償以前的自定義
  • player.setBandwidthSafetyFactor(默認值:0.9),可以降低到0.5以強制執行更保守的吞吐量計算
  • player.setStableBufferTime(默認值:12s),可以大幅降低以限制後啓動/搜索緩衝區目標並簡化更快的比特率切換
  • player.setBufferToKeep(默認值:20s),可以大幅降低以限制緩衝區長度並允許緩衝比特率變化的更具反應性
  • player.setBufferTimeAtTopQuality(默認值:30秒),可以大幅降低以在播放最高質量視頻時限制內部緩衝區
  • player.setLowLatencyEnabled(默認值:false):從v.2.6.8開始,可以將此參數設置爲“true”,以便利用瀏覽器提取API而不是傳統的XHR加載機制。它對長DVR窗口延遲有非常有效的影響。

Exoplayer

這款適用於Android的開源播放器兼容多種流媒體格式,包括HLS和DASH。 在HLS中,Exoplayer在引用太少切片的playlist時會遇到一些問題。在DASH中,默認情況下會對manifest中包含的recommendedPresentationDelay表示支持。 可以修改一些參數以優化低延遲體驗:

  • 可以在HlsMediaSource和DashMediaSource類中增加DEFAULT_MIN_LOADABLE_RETRY_COUNT(default 3),以便允許在404中對切片進行更多請求重試
  • 可以減少ChunkedTrackBlacklistUtil類中的DEFAULT_TRACK_BLACKLIST_MS(default 60000),以降低由於連續404而將比特率變量列入黑名單的可能性
  • 最後,減少DefaultLoadControl類中的默認緩衝區值:DEFAULT_MAX_BUFFER_MS(default 3000) DEFAULT_BUFFER_FOR_PLAYBACK_MS(default 2500) DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS(default 5000) 以便更準確地控制在播放會話啓動時加載的內容量。

Shakaplayer

這個用於MSE環境的開源HLS和DASH播放器提供了幾個可以修改的參數選項,以實現更低的延遲,因爲默認值是比較保守的:

  • streaming.bufferingGoal(默認值:10s)是播放器嘗試緩衝的內容秒數,它會影響加載的切片數
  • streaming.rebufferingGoal(默認值:2s)是播放器在開始播放之前需要緩衝的內容秒數。它適用於啓動和重新緩衝階段。如果DASH的manifest中minBufferTime大於此值,將會覆蓋它
  • retryParameters.maxAttempts(默認值:2)是播放器失敗之前給定切片的最大請求數
  • retryParameters.baseDelay(默認值:1000ms)是重試之間的基本延遲
  • retryParameters.timeout(默認值:0,等於never)是定義請求超時的ms的延遲
  • retryParameters.backoffFactor(默認值:2)是應用於baseDelay的乘數,用於放大重試之間的延遲

所有retryParameters也可以應用於manifest中。

參考資料

[1]https://aws.amazon.com/cn/blogs/media/how-to-compete-with-broadcast-latency-using-current-adaptive-bitrate-technologies-part-2/

[2]https://aws.amazon.com/cn/blogs/media/part-3-how-to-compete-with-broadcast-latency-using-current-adaptive-bitrate-technologies/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章