傳統直播方案(http-flv、RTMP 等)的架構以及延遲量級如下圖所示:
以抖音直播為例,直播鍊路各環節延遲貢獻如下:
- 推流端——網絡延遲平均 20 ~ 30ms,編碼延遲依賴編碼參數設置而定
- 流媒體服務——在拉流轉碼的場景下,會額外引入 300ms ~ 2s 的轉碼延遲(大小與轉碼參數相關),如果直接播放源流,則不存在轉碼延遲
- 播放端——網絡延遲 100ms ~ 200ms 左右,主要是鍊路分發節點之間的傳輸延遲;防抖 buffer——5 ~ 8s
從各環節延遲貢獻看,容易得出一個直觀的結論:端到端延遲過大主要是播放器的防抖 buffer 造成,這個表面現象也經常會導緻很多同學,認為降低播放器的 buffer,就能降低延遲。這個說法的對錯,取決于從什麼角度解釋。在辯證這個結論前,我們先詳細拆解介紹下直播全鍊路的延遲:
上圖主要更細緻地拆解了流媒體服務環節,即 CDN 傳輸鍊路,拆解為上行(收流節點和上層節點)、源站、下行(上層節點和拉流邊緣節點)。各環節延遲歸因如下:
主播端(推流器)主要包含編碼延遲以及發送緩存引入的延遲(多數主播網絡情況良好,發送緩存延遲平均隻有 20 ~ 30ms),這個環節的延遲可優化空間不多,雖然通過調節編碼器參數可有效降低編碼延遲,但帶來的是畫質的損失,同時也影響壓縮效果,因此多數集中在優化弱網傳輸(不過出發點是為了提供用戶觀看流暢體驗,而不在于降低延遲)
收流邊緣節點&中間鍊路針對 http-FLV 不需要分片的協議,CDN 傳輸各節點都是在收到流數據就直接轉發到下一個節點,這個環節主要的延遲是由鍊路傳輸引起的,與鍊路長度正相關,一般平均不超過 200ms。
如果播放端拉轉碼流,那麼在網絡傳輸延遲基礎之上,會額外增加轉碼延遲(目前各大 CDN 廠商編碼延遲大概分布在 300ms ~ 2s),包括解碼延遲和轉碼延遲,其中對于無 B 幀的場景,解碼延遲較小,主要是編碼延遲。編碼延遲主要是受編碼器緩存幀數影響,假設 FPS=15,那麼緩存 6 幀,延遲就 400ms,該部分延遲與推流編碼延遲一樣,同樣可以通過調整轉碼參數來降低轉碼延遲,但也同樣會帶來畫質與壓縮率的損失,因此這部分延遲需要根據實際場景綜合來考慮,如果對延遲要求很高,可以調整下。
拉流邊緣節點不考慮回源的情況,這個環節主要影響延遲的是 gop cache 策略(有的 CDN 廠商也叫做快啟 buffer 策略或者快啟 cache),即在邊緣節點緩存一路流最新的幾個 gop(一般媒體時長平均為 5 ~ 7s),目的是為了在拉流請求建立時,可以有媒體數據即時發送,優化首幀和卡頓,這樣也就導緻了播放端收到的第一幀數據就是 5 ~ 7s 前的舊數據,第一幀的延遲就達到了 5 ~ 7s(這個環節才是端到端延遲過大的根因)。
CDN gopCache 的邏輯字節與 CDN 廠商溝通約定 gop cache 按照下限優先來下發數據,比如下限 6s,表示先在緩存數據中定位最新 6s 的數據,然後向 6s 前的舊數據查找第一個關鍵幀下發,保證下發第一幀距離最新幀之間的時長不低于 6s:
如上圖,如果不考慮生産端和中間鍊路的延遲,那麼 buffer 長度 7.2s 可以近似看作播放的初始端到端延遲,在播放器正常播放且無卡頓的前提下,這個延遲會一直持續到退出直播間,不會變化。這裡介紹幾個初始延遲計算的通用公式:
- 延遲分布區間[M,M gop]s,
- 平均延遲為 M gop/2,其中 M 為 gopCache 策略的下限,gop 即為編碼 gop 的固定大小值
例如抖音秀場 gop 大小是固定的 2s,假設 gopCache 下限為 6s,那麼觀衆的合理端到端延遲分布區間為:[6, 8]s,根據用戶請求的時間點,所有觀衆的延遲都會均勻分布在這個區間内,因此不同觀衆間的延遲 diff 最大不超過一個 gop 的長度 2s(這點是優化設備間延遲差的理論基礎)
觀衆(播放器)播放器在 io 模塊有分配緩存 buffer(抖音線上分配 buffer 最大為 20s,也就是最多可容納 20s 的媒體數據,這個 buffer 其實越大越好,抗網絡抖動能力也越強),用于存放從 CDN 邊緣節點下載到的流媒體數據。播放器下載是主動下載,在可分配的 buffer 隊列未充滿的前提下,io 線程是連續下載流媒體數據并存放到 buffer 中,直到沒有空閑 buffer 可利用為止。因此,觀衆網絡狀況良好的情況下,在用戶請求播放,建立鍊接後,CDN 的邊緣節點的快啟 buffer,會很快都被下載到播放器的 buffer 中,後續渲染環節消費速度遠低于 i/o 下載的速度,這樣端到端的延遲就主要分布到了播放器的 buffer 中。但隻說明啟播後,直播鍊路的延遲從 CDN 的 gopCache,轉移到了播放器,播放器 buffer 并不是延遲的根因,因此,降低播放器的最大緩存 buffer,并不能降低延遲。如果換個角度理解,降低播放器 buffer 中實際緩存的數據,會降低延遲這個說法是正确的,比如通過倍速播放或者丢幀。
現在了解了全鍊路延遲是怎麼産生的,我們可以确認以下幾點:
- 端到端延遲,在 CDN 邊緣節點收到 http-get 請求那一刻起,流數據未達到客戶端 buffer 前,初始延遲的大小就已經确定了,這個延遲對應于我們的 QoS 指标-首幀延遲
- 影響延遲大小的因素主要有兩點:CDN 邊緣節點 gop cache 策略(5~7s 延遲)以及視頻流 gop 大小(會造成一個 gop 大小的延遲 diff)
- 客戶端 buffer 大小與延遲大小之間沒有因果關系,buffer 的大小隻會影響延遲全鍊路的分布,但降低播放器 buffer 大小隻會降低防抖能力,惡化卡頓,并不會降低延遲
- 較低延遲的有效手段包括:
- 降低 CDN 的 gopCache,是根本手段
- 增加 buffer 中視頻數據的消費速度,也可以有效降低延遲,例如倍速播放或者直接丢棄媒體數據
- 在 gopCache 不變的前提下,降低 gop,也可以降低平均端到端延遲,比如 gop=4s 調整為 2s,平均端到端延遲下降 1s
傳統的直播技術延遲非常大,從觀衆評論到看到主播給出反饋一般要在 5-10 秒以上。幾個典型的尴尬場景:
- 單一用戶延遲大,導緻體驗差
在線教育,學生提問,老師都講到下一個知識點了,再返回來回答。
電商直播,詢問寶貝信息,主播“視而不理”。
打賞後遲遲聽不到主播的口播感謝。
假設端到端延遲為 6s,那麼在線教育和電商直播兩個場景,互動延遲由面對面的 0s,增加到了 12s,如下圖所示:
打賞場景,互動延遲由面對面的 0s,增加到了 6s,如下圖所示:
- 不同用戶延遲 diff 大,導緻體驗差
在别人的呐喊聲知道球進了,你看的還是直播嗎?
這個場景的延遲體驗問題,并不是某次拉流請求端到端高延遲導緻的,主要是因為不同用戶間的延遲不一緻導緻,如下圖:
可見,高延時影響了直播互動體驗,阻礙了直播在一些場景的落地,特别在電商直播,直播間的評論提問是觀衆和主播互動的一個重要手段,主播的實時互動反饋對直播間的活躍度和交易達成至關重要。
以上兩類由于延遲導緻體驗差的場景,分别對應我們 QoS 指标中的平均端到端延遲、延遲設備差兩個指标,延遲相關的優化也會以這兩個指标為标準。
延遲體驗優化實踐案例百萬英雄答題直播流鍊路延遲需求
需求分析
- 所有觀衆端到端時延在 6s 以内——對應首幀延遲和平均端到端延遲指标
- 不同觀衆 A,B,C 之間直播流時延差在 2s 以内,避免答題不同步——對應設備延遲差指标
解決方案
- 對于答題類活動直播場景,用戶主要集中精力在聽題、讀題、答題,與主播的互動不是強需求,因此端到端延遲不是優化重點,隻要滿足需求的 6s 即可
- 用戶使用場景多數是面對面或者實時語音組團答題,會對彼此之間延遲不一緻的現象很敏感,因此保證設備延遲差盡可能小是核心需求點
- 滿足時延 6s 以内——調整 gopCache 以及 gop 大小
gop=2s,gopCache 下限為 5s,那麼首幀延遲分布在[5s, 5 2s]内,平均延遲為(5 (5 2))/2=6s,具體措施如下:
- 各家 CDN 快啟策略需要設置為下限優先,并且快啟 buffer 阈值為 5s
- 推流參數設置需要設置 gop=2s,且保持穩定:保證觀看同一路流的用戶,時延 diff 在 2s 内
- 轉碼配置需要保持 gop=2s 的配置,并且 I 幀對齊:保證觀看不同轉碼流的用戶,時延 diff 在 2s 内
- 延遲差在 2s 以内
調整 gop=2s 後,僅能保證一直流暢播放無卡頓的 vv,彼此直接的延遲 diff 在 2s 以内,但對于觀播過程中發生卡頓的用戶,累計延遲增加的情況,延遲 diff 會越來越大,例如用戶 A 卡 4s 後,恢複正常播放,那麼 A 的端到端延遲會增加 4s,如果 A,B,C 是一個組隊答題的小夥伴,A 的題目解說會一直落後 B 和 C,這樣的體驗很不好。因此需要針對這類場景的設備延遲差做優化:這時候需要播放器追幀微調,使 A 的播放速度追上 B 和 C。具體措施如下:
效果驗收
- 追幀的原則是:在 A 的播放器 buffer 超過 6s 時,就開始倍速播放,直到 buffer 低于 6s,這時候 A 就追上了 B 和 C
- 追幀阈值 6s,追幀速度是 1.4,這樣設置的效果時,A 觀衆在延遲落後 4s 的情況下,追幀 10s 即可趕上 B 和 C,實際阈值的設置,可以根據需求來确定,原則上是在延遲滿足需求時,盡量不觸發追幀,保持正常速度播放
相對于第一屆百萬英雄答題,延遲不同步的用戶反饋大量減少
4s 低延遲字節内購會直播流鍊路類似于百萬英雄
延遲需求需求分析
- 所有觀衆端到端時延在 4s 以内——對應首幀延遲和平均端到端延遲指标
- 不同用戶在聽到主播說上鍊接時,與購物鍊接彈出時間盡量一緻——對應設備延遲差指标
解決方案
- 内購會有電商主播帶貨環節,因此對互動延遲敏感
- 内購會是大型組團搶購活動,員工都在工位面對面參與,因此對設備延遲差也會很敏感
- 推流&轉碼流配置
配置項value配置方式推流 gop2sOBS 推流器配置轉碼 gop2s轉碼模版
- CDN 側
相對于百萬英雄答題場景,内購會對互動延遲敏感,因此這裡相對于百萬英雄答題需要做特殊配置,由于各家廠商默認 gopCache 策略,平均端到端延遲在 6s 左右,不滿足需求的 4s,需要通過配置 url query 參數控制廠商的 gopCache 策略,保證延遲在 4s 左右
- 播放端參數配置詳情
- 延遲等級:4s
- 參數配置目标:降低不同設備間延遲差,控制用戶延遲分布在[3000ms, 4000ms]内,這樣保證設備間延遲差最大不超過 1s——延遲低的用戶慢放,延遲高的用戶追幀,從而更精确的控制設備延遲差低于 gop 長度 2s
- 倒計時确認時機
内購會上鍊接或者答題,是根據現場助理觀播的延遲來确定上鍊接或者發題的倒計時時機,由于有快慢放對齊設備延遲差的過程,建議助理看播 1min 後,延遲穩定後,再确定倒計時
效果驗收抖音直播-FLV 低延遲-3s直播流鍊路
- 線下演練以及正式場不同設備間的流内容延遲,進入觀播後通過快慢放調整後,延遲基本都穩定在 4s,且 diff 不超過 1s
- 主播口播“上鍊接”與實際鍊接彈出延遲 diff 在 1s 内,搶購體驗良好
- 基本無卡頓反饋 case
需求目标
需求分析
- 平均延遲達到 3s
- 播放時長、看播滲透、留存等核心業務指标顯著正向
- 電商 GMV、充值打賞等營收指标顯著正向
解決方案
- 傳統直播場景,不同觀衆同一時刻經常觀看不同主播的流,且經常是個人獨立觀播,對同一直播間,不同觀衆延遲一緻的訴求基本不存在,因此延遲設備差不是優化重點指标
- 秀場直播、直播帶貨等場景,是強互動場景,對互動延遲要求高,本需求核心優化點是端到端延遲
本次需求場景的受衆是抖音的所有直播用戶,網絡質量的優劣也是參差不齊的,在保證滿足降低延遲的需求目标,我們還需要保證觀播的流暢性不要負向太多。
延遲解決方案
- gop 下調為 2s
- 配置 gopCache 下限參數為 1800ms,延遲區間為[1800 200ms,3800 200ms],平均 3s
卡頓優化方案
先驗知識科普
- 啟播 buffer 策略:表示首幀渲染後,需要等到播放器 audio buffer 達到一定阈值後,再繼續播放,這樣可以增加網絡抗抖能力
- 網絡分級 1 ~ 8:
- 8—等效于非常好的 4G 網絡;
- 7—等效于較好的 4G 網絡;
- 6—等效于一般的 4G 網絡;
- 5—等效于較差的 4G 網絡;
- 1 ~ 4—網絡質量差
基于網絡質量的個性化啟播 buffer 策略
- 方案設計基本原理
- 基于網絡分級,自适應調整啟播 buffer
- 設定啟播 buffer 最大調整區間為[0,850ms]
- 不同網絡分級映射到不同的啟播 buffer 區間
- 随着網絡分級的變差,啟播 buffer 檔位遞增速率也加快
- 同一網絡分級的不同 vv,根據重試和卡頓次數,在該網絡分級的啟播 buffer 區間中進行微調
- 随着卡頓次數的增加,啟播 buffer 在對應檔位區間内的微調幅度逐步下降
- 對于同一次 app 啟動周期内,發生多次直播 vv 的情況,需要考慮最近一次直播播放 session 中的卡頓和重試情況,且卡頓和重試的影響權重随着時間衰減
- QoS 收益:卡頓負向降低了 20%
基于網絡質量的個性化延遲策略
基于數據統計發現:網絡分級 1 ~ 4 的 vv 占比為 5.54%,但卡頓指标卻貢獻了 47.83%,再結合本需求場景設備間延遲差并不是核心指标,因此可通過個性化延遲來優化卡頓。
- 方案設計基本原理
- 基于網絡分級,自适應調整延遲
- 不同網絡分級映射不同的 gopCache 下限
- 随着網絡分級的變差,延遲逐漸增大
- QoS 收益:卡頓負向降低了 30%
客戶端管控 CDN 卡頓優化策略
在需求推進過程中發現兩個奇怪的現象:
- 在網絡質量足夠好的場景下進行線下測試,發現低延遲更容易觸發 CDN 的丢幀策略(優化卡頓的策略),從而導緻渲染卡頓上漲(和 CDN 溝通後,CDN 側不願意透露太多的丢幀策略細節,根因無法求證)
- 在 AB 實驗過程中,某一家 CDN 廠商上線了過激的丢幀策略,引起了線上大量反饋,從用戶反饋看,基本都是反饋剛進入直播間的卡頓,推測用戶對啟播階段的丢幀卡頓,更敏感
結合以上兩個現象,基本可以判斷低延遲情況下,CDN 在啟播階段更容易丢幀,且啟播丢幀會嚴重影響 QoE 體驗,因此管控 CDN 丢幀策略,對 QoS(視頻渲染卡頓)以及 QoE 都是有正向優化效果的,管控規則如下:
參數名描述規則protected_period拉流 session 丢幀保護期:請求開始的前 n 毫秒不能丢幀protected_period=0:表示整個拉流過程中都不能丢幀;當 value>0 時,比如 protected_period=5000:表示拉流 session 的前 5000ms 不能丢幀,5000ms 是以系統時鐘(本地時間)緯度來衡量gop_keep_duration發生丢幀的 gop 保留時長下限:時長是視頻流緯度的 duration當 value>0 時,比如 gop_keep_duration =2000ms,表示丢幀後,對應 gop 必須保留發送到用戶的的視頻流總時長不低于 2000ms
最終效果驗收
- QoS 收益:FLV 低延遲渲染卡頓負向降低約 30%
- QoE 指标收益
- 核心業務指标:直播人均看播時長、看播滲透、留存等顯著正向
- 營收相關指标:電商人均支付訂單數、付費滲透、充值等顯著正向
- Qos 指标
- 端到端延遲:3.24s
- 卡頓:增加 13%
- 帶寬成本收益
由于低延遲降低了 gopCache,延遲下降到 3s,相對于 7s 高延遲 FLV,在啟播時會少下載 4s 的數據,尤其抖音直播預覽流占比達到 70%,因此低延遲 FLV 可以節省不必要的帶寬成本,成本收益為 10%
關于延遲的思考思考一:觀衆對互動延遲的感知是否存在拐點,延遲降到一定程度,用戶感知不到?我們從三個典型的互動場景來思考:
- 觀衆評論,主播看到評論進行口播回複互動:觀衆對話框輸入評論平均耗時至少 2s 以上,再降低互動延遲是否有收益?
- 觀衆打賞送禮,主播進行口播感謝互動:假設觀衆打賞耗時平均 1s 左右,此時打賞後互動延遲 3s 口播感謝,此時的延遲水平是否已經滿足觀衆對主播感謝響應度的需求?
- 直播帶貨場景:無論“上鍊接”口播與鍊接實際彈窗是否一緻,還是秒拍場景,核心的延遲指标都是設備間延遲差指标會影響體驗,是否實際的端到端延遲其實觀衆并沒有互動延遲敏感?
思考二:在傳統标準直播 http-flv 場景下,是否可以依然基于本文中介紹的方法,繼續下探更低延遲,比如 1s?個人判斷是可以做到的,但面臨的挑戰也更多,需要更精細的播控策略來平衡延遲與播放流暢性,比如:
,
- 在 tcp/quic 等傳輸協議場景,啟播時 CDN 側都存在帶寬(最佳的發送速率)探測的算法邏輯,基于實際發送數據探測結合 ACK 等反饋信息來增加發送速率,那麼這裡就存在一個問題——繼續降低 gopCache,滿足延遲下降到 1s 的同時,也導緻 CDN 用于發送探測的數據量會變少,不足以探測到網絡鍊路實際的帶寬,這樣會導緻 gopCache 階段平均發送速率會降低,抗網絡抖動能力會急劇下降,同時也會影響首幀,因此為進一步下探延遲,需要播放端和 CDN 相互配合優化啟播發包速率,這樣才能保證流暢性不負向過多
- 更低延遲的場景對延遲的要求也極高,也更容易發生卡頓,但凡發生一次卡頓,延遲就很容易成倍增加,最終導緻延遲降不下來,進一步下探延遲也需要配合精細的追幀或者丢幀策略