前言
在處理影視頻網路通信的程序中,我們經常會遇到如下幾個問題,今天就圍繞如下幾個問題講講我個人的優化心得.
- 為什么 TCP 傳輸的延時比 UDP 大 ?
- 直播的延時往往在 1s 以上,根本原因在哪里 ?
- RTC 實時通信的延時要求在 400ms 以內,是怎么做到的 ?
舉個栗子
我們就以網上購物,一份快遞從發貨到送達這一程序的耗時優化為例子:

在快遞站入庫和逗留的時間太長 ?—— 比如,每個快遞件入庫半天堆積 1 天再才轉派發,看看,有哪些可能的因素會影響快遞從商家 A 傳遞到消費者 B 的手中的時間 ?如上圖所示:
- 快遞數量不均勻,有時候特別多(堆積如山),有時候特別少(零零散散),各節點的資源利用率未能充分發揮出來
- 中途發生快遞丟失了,需要重新補發一份(整體時間基本上要翻倍)
- 運輸的路線太堵,導致在路上耗費太多時間
有什么思路,一一解決上述的延時因素,以提高快遞的送達速度呢 ?
- 提高每個快遞站的吞吐量,減少每個中轉站的快取,加速快遞的流轉 ?
- 快件的攬件、傳輸與派送,從 “天” 的粒度拆分到更細的粒度,比如小時粒度,以追求資源的調度更動態和平滑一點 ?
- 每個快件同時發 2 份 ?丟了一個還可以派送另一個 ?—— 當然,負面影響是帶來運力資源的增加
- 動態選擇合適的中轉運輸路線,哪里不堵走哪里 ?—— 運輸路線動態規劃避開擁堵,這是一門藝術,
從上面的探索可以看出,優化延時,我們關注的點主要是:減少中間環節的快取,最大化提高資源的利用率,通過冗余對抗丟失,動態地規劃傳輸路徑,如果你能理解這幾個抽象的點,那么恭喜,下面你就不難理解如何降低音視頻的網路傳輸延時了,
分析原因
為什么 TCP 傳輸的延時比 UDP 大 ?
因為 TCP 保證了 “可靠傳輸”,當資料發生丟失后,一定會進行重傳,重傳帶來延時(類似快遞丟失補發),并且非常影響后續資料的持續及時發送:
- 因為 TCP 有個 “快取佇列”(類似于快遞站),它不會來一個資料就立馬發送出去,而是先快取起來,通過一個 “滑動視窗” 來控制發送頻率(類似快遞站的派送人力),在上一波資料發送完畢得到 ACK 確認后,再發送下一波資料(類似一箱快遞的派送結束后再投入下一箱);而 UDP 則沒有該機制,閉著眼睛發(需要搶占整個地區更多的快遞員)
- 因為 TCP 是一個 “君子”,一旦發現有丟資料或者網路不好,則主動去 “退讓”,減少自己的 “滑動視窗” 大小(讓出快遞人力給地區其他公司),導致自己的資料發得更慢了
直播的延時往往在 1s 以上,根本原因在哪里 ?
- 直播底層的傳輸協議(RTMP)默認使用了 TCP ,引入了 TCP 上述延時大的特性
- 由于 TCP 不丟資料的特性,會導致播放端一旦因為網路原因卡住多少秒,在播放器不追幀的情況下,后續恢復播放后就有多少秒的延時(因為這些因為網路卡住沒有及時發送過來的資料不會憑空消失)
- 為了實作播放秒開,通常直播的流媒體服務器,會快取最近的 GOP,在播放器不追幀的情況下,會帶來一個固定的延時(取決于推流端配置的 GOP 大小)

- 如果播放端使用的 HLS 延時,那就更大了,取決于服務端 HLS 切片的最小間隔(官方推薦 10s)

RTC 實時通信的延時要求在 400ms 以內,是怎么做到的 ?
關于這一點,需要知道如下幾個關鍵詞:UDP、FEC、擁塞控制、資料量調節、jitter buffer、服務的端調度和級聯
-
底層使用 UDP 代替 TCP —— 相比于 TCP 滑動視窗 “君子退讓” 的特性,UDP 可以不講武德,最大化地發送資料,提高吞吐量(提高帶寬利用率)
-
底層使用 UDP 協議,如何解決丟包重傳的問題呢 ?
音視頻傳輸,為了滿足低延時,首先是 “允許” 丟部分不重要的資料的,針對丟失的資料,在接收和播放端會做一些兼容性處理,如:PLC(音頻包丟失的智能補償)、視頻跳過 GOP 尾部的 B/P 幀等
在 UDP 之上,使用 FEC 冗余(類似多發一份快遞,但更高級),可以在不重傳的情況下,在接收端把丟失的資料 “恢復” 回來,相關細節參考這篇文章有詳細科普: 《談談網路通信中的 FEC 基礎》
當然,在 UDP 之上,依然也有使用重傳來兜底的,因為 FEC 冗余會帶來對帶寬的資源消耗變大,因此在 RTT 網路延時較小的場合,重傳依然是一個不錯的選擇,關于重傳的更多細節可以參考我的這篇文章: 《認識網路通信中的 ACK、NACK 和 REX》
-
底層使用 UDP 不講武德地發送資料,不會讓網路爆掉么 ?
當然會,因此,我們可以在 UDP 之上,加一些控制流量的機制,讓整體地發送更加平滑,詳細細節可以參考我的這篇文章: 《認識網路通信中的流量整形》
但是,如果要發送的資料量(類似快遞的數量)本身就爆掉了(高于當前網路所能承載的能力),無論怎么在傳輸端加平滑,都解決不了擁堵的問題的,因此,RTC 最最核心的降低延時的方法之一就是:帶寬探測及配套的資料量調節手段
-
有哪些帶寬探測及配套的資料量調節手段 ?
帶寬探測,就是動態地預估當前的網路帶寬,如何做到實時地對帶寬進行準確地預測,是一門值得深挖和長期研究的藝術,本文就不展開講了,可以搜索了解 BBR、GCC 等關鍵詞
資料量調節:當探測到網路帶寬不足時,可以調節資料量以防止擁塞帶來的延時,通常可調節的內容包括:音視頻的幀率/碼率、FEC 的冗余比例、大小流等
-
那既然 UDP 也有重傳,自然也會存在網路抖動的情況下,接收和播放端被動產生被動的 buffer 資料,RTC 是如何消除掉這些被動 buffer 的呢 ?
核心原理:動態 jitter buffer + TSM 時域壓擴(變速不變調)演算法
接收端的 buffer,往往是用來抵抗網路抖動的,固定的 buffer 則帶來的是固定的延時(如:必須緩沖到 500ms 的資料再輸出播放),而動態的 jitter buffer 則會根據網路好壞動態調節 buffer 大小
TSM 時域壓擴(變速不變調):則是一種不影響用戶聽感體驗的音頻播放追幀策略,類似可以做到 0.9/1.1 倍數播放,用于加快或者減慢 buffer 資料的消耗達到追幀或者降速的作用,演算法科普文章可參考: 《TSM時域壓擴(變速不變調)演算法總結》
-
有了一系列客戶端層面的延時優化,最后就剩下整體服務端流轉發網路的調度和級聯了,這也是一門值得深挖和長期研究的方向,這里也不長篇大論了,用一張圖大致表達一下:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/296690.html
標籤:其他
