天天看點

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

簡介: NetEQ 是 WebRTC 音視訊核心技術之一,對于提高 VoIP 品質有明顯的效果,本文将從更為宏觀的視角,用通俗白話介紹 WebRTC 中音頻 NetEQ 的相關概念背景和架構原理,以及相關的優化實踐。

作者| 良逸  

審校| 泰一

為什麼要 “白話” NetEQ?

随便搜尋一下,我們就能在網上找到很多關于 WebRTC 中音頻 NetEQ 的文章,比如下面的幾篇文章都是非常不錯的學習資料和參考。特别是西安電子科技大學 2013 年吳江銳的碩士論文《WebRTC 語音引擎中 NetEQ 技術的研究》,非常詳盡地介紹了 NetEQ 實作細節,也被引用到了很多很多的文章中。

《WebRTC 語音引擎中 NetEQ 技術的研究》

NetEQ 算法

WebRTC 中音頻相關的 NetEQ

這些文章大部分從比較 “學術” 的或 “算法” 的角度,對 NetEQ 的細節做了非常透徹的分析,是以這裡我想從更宏觀一些的角度,說一下我個人的了解。白話更容易被大家接受,争取一個數學公式都不用,一行代碼都不上就把思路說清楚,有了解不對的地方,還請大家不吝賜教。

丢包、抖動和優化的了解

在音視訊實時通信領域,特别是移動辦公(4G),疫情下的居家辦公和線上課堂 (WIFI),網絡環境成了影響音視訊品質最關鍵的因素,在差的網絡品質面前,再好的音視訊算法都顯得有些杯水車薪。網絡品質差的表現主要有延時、亂序、丢包、抖動,誰能處理和平衡好這幾類問題,誰就能獲得更好的音視訊體驗。由于網絡的基礎延時是鍊路的選擇決定的,需優化鍊路排程層來解決;而亂序在大部分網絡條件下并不是很多,而且亂序的程度也不是很嚴重,是以接下來我們主要會讨論丢包和抖動。

抖動是資料在網絡上的傳輸忽快忽慢,丢包是資料包經過網絡傳輸,因為各種原因被丢掉了,經過幾次重傳後被成功收到是恢複包,重傳也失敗的或者恢複包過時的,都會形成真正的丢包,需要丢包恢複 PLC 算法來無中生有的産生一些假資料來補償。丢包和抖動從時間次元上又是統一的,等一會來了的是抖動,遲到很久才來的是重傳包,等一輩子也不來的就是 “真丢包”,我們的目标就是要盡量降低資料包變成 “真丢包” 的機率。

優化,直覺來講就是某個資料名額,經過一頓猛如虎的操作之後,從 xxx 提升到了 xxx。但我覺得,評判優化好壞不能僅僅停留在這個次元,優化是要 “知己知彼”,己是自己的産品需求,彼是現有算法的能力,己彼合一才是最好的優化,不管算法是簡單還是複雜,隻要能完美的比對自己的産品需求,就是最好的算法,“能捉到老鼠的就是好貓”。

NetEQ 及相關子產品

NetEQ 的出處

《GIPS NetEQ 原始文檔》,這是由 GIPS 公司提供的最原始的 NetEQ 的說明文檔(中文翻譯),裡面介紹了什麼是 NetEQ 以及對其性能的簡單說明。NetEQ 本質上就是一個音頻的 JitterBuffer(抖動緩沖器),名字起的非常貼切,Network Equalizer(網絡均衡器)。大家都知道 Audio Equalizer 是用來均衡聲音的效果器,而這裡的 NetEQ 是用來均衡網絡抖動的效果器。而且 GIPS 還給這個名字注冊了商标,是以很多地方看到的是 NetEQ (TM) 。

上面的官方文檔中,有一條很重要資訊,“最小化抖動緩沖帶來的延時影響”,這說明 NetEQ 的設計目标之一就是:“追求極低延時”。這個資訊很關鍵,為我們後續的優化提供了重要線索。   

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結
解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結
解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結
解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

NetEQ 在音視訊通訊 QoS 流程中的位置

音視訊通訊對于普通使用者來說,隻要網絡是通的,WIFI 和 4G 都可以,一個呼叫過去,看到人且聽到聲音,就 OK 了,很簡單的事情,但對于底層的實作卻沒有看起來那麼簡單。單 WebRTC 開源引擎的相關代碼檔案數量就有 20 萬個左右,代碼行數不知道有沒有人具體算過,應該也是千萬數量級的了。不知道多少碼農為此掉光了頭發 :)。

下面這張圖,是對實際上更複雜的音視訊通訊流程的抽象和簡化。左邊是發送 (推流) 側:經過采集、編碼、封裝、發送;中間經過網絡傳輸;右邊是接收 (拉流) 側:接收、解包、解碼、播放;這裡重點展現了 QoS(Quality of Service,服務品質)的幾個大的功能,以及跟推拉流資料主要流程的關系。可以看到 QoS 功能分散在音視訊通訊流程中的各個位置,導緻要了解整個流程之後才能對 QoS 有比較全面的了解。圖上看起來左邊發送側的 QoS 功能要多一些,這是因為 QoS 的目的就是要解決通訊過程中的使用者體驗問題,要解決問題,最好就是找到問題的源頭,能從源頭解決的,都是比較好的解決方式。但總有一部分問題是不能從源頭來解決的,比如在多人會議的場景,一個人的收流側網絡壞了,不能影響其它人的開會體驗,不能出現 “一顆老鼠屎壞掉一鍋粥” 的情況,不能污染源頭。是以收流也要做 QoS 的功能,目前收流側的必備功能就是 JitterBuffer,包括視訊的和音頻的,本文重點分析音頻的 JitterBuffer -- NetEQ。

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

NetEQ 原理及相關子產品的關系

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

上面這張圖是對 NetEQ 及其相關子產品工作流程的抽象,主要包含 4 個部分,NetEQ 的輸入、NetEQ 的輸出、音頻重傳 Nack 請求子產品、音視訊同步子產品。為什麼要把 Nack 請求子產品和音視訊同步子產品也放進 NetEQ 的分析中?因為這兩個子產品都直接跟 NetEQ 有依賴,互相影響。圖裡面的虛線,辨別每個子產品依賴的其它子產品的資訊,以及這些資訊的來源。接下來介紹一下整個流程。

1. 首先是 NetEQ 的輸入部分:

底層 Socket 收到一個 UDP 包後,觸發從 UDP 包到 RTP 包的解析,經過對 SSRC 和 PayloadType 的比對,找到對應的音頻流接收的 Channel,然後從 

InsertPacketInternal

 輸入到 NetEQ 的接收子產品中。

收到的音頻 RTP 包很可能會帶有 RED 備援包(redundance),按照 RFC2198 的标準或者一些私有的封裝格式,對其進行解包,還原出原始包,重複的原始包将會被忽略掉。解出來的原始 RTP 資料包會被按一定的算法插入到 packet buffer 緩存裡面去。之後會将收到的每一個原始包的序列号,通過 

UpdateLastReceivedPacket

 函數更新到 Nack 重傳請求子產品,Nack 子產品會通過 RTP 收包或定時器觸發兩種模式,調用 

GetNackList

 函數來生成重傳請求,以 NACK RTCP 包的格式發送給推流側。

同時,解完的每一個原始包,得到了時間軸上唯一的一個接收時刻,包和包之間的接收時間差也能算出來了,這個接收時間差除以每個包的打包時長就是 NetEQ 内部用來做抖動估計的 IAT(interarrival time),比如,兩個包時間差是 120ms,而打包時長是 20ms,則目前包的 IAT 值就是 120/20=6。之後每個包的 IAT 值經過核心的網絡抖動估計子產品(DelayManager)處理之後,得到最終的目标水位(TargetLevel),到此 NetEQ 的輸入處理部分就結束了。

2. 其次是 NetEQ 的輸出部分:

輸出是由音頻硬體播放裝置的播放線程定時觸發的,播放裝置會每 10ms 通過 

GetAudioInternal

接口從 NetEQ 裡面取 10ms 長度的資料來播放。

進入 

GetAudioInternal

 的函數之後,第一步要決策如何應對目前資料請求,這個任務交給操作決策子產品來完成,決策子產品根據之前的和目前的資料和操作的狀态,給出最終的操作類型判斷。NetEQ 裡面定義了幾種操作類型:正常、加速、減速、融合、拉伸(丢包補償)、靜音,這幾種操作的意義,後面再詳細的說。有了決策的操作類型,再從輸入部分的包緩存(packet buffer)裡面取出一個 RTP 包,送給抽象的解碼器,抽象的解碼器通過 

DecodeLoop

 函數層層調用到真正的解碼器進行解碼,并把解碼後的 PCM 音頻資料放到 

DecodedBuffer

 裡面去。然後就是開始執行不同的操作了,NetEQ 裡面為每一種操作都實作了不同的音頻數字信号處理算法(DSP),除了 “正常” 操作會直接使用 

DecodedBuffer

 裡的解碼資料,其它操作都會結合解碼的資料進行二次 DSP 處理,處理結果會先被放到算法緩存(Algorithm Buffer)裡面去,然後再插入到 Sync Buffer 裡面。Sync Buffer 是一個循環 buffer,設計的比較巧妙,存放了已經播放過的資料、解碼後未播放的資料,剛剛從算法緩存裡插入的資料放在 Sync Buffer 的末尾,如上圖所示。最後就是從 Sync Buffer 取出最早解碼後的資料,送出去給外部的混音子產品,混音之後再送到音頻硬體來播放。

另外,從圖上可以看出決策子產品(BufferLevelFilter)會結合目前包緩存 packet buffer 裡緩存的時長,和 Sync Buffer 裡緩存的資料時長,經過算法過濾後得到音頻目前的緩存水位。音視訊同步子產品會使用目前音頻緩存水位,和視訊目前緩存水位,結合最新 RTP 包的時間戳和音視訊的 SR 包獲得的時間戳,計算出音視訊的不同步程度,再通過 

SetMinimumPlayoutDelay

 最終設定到 NetEQ 裡面的最小目标水位,來控制 TargetLevel,實作音視訊同步。

NetEQ 内部子產品

NetEQ 抖動估計子產品(DelayManager)

1. 平穩抖動估計部分:

将每個包的 IAT 值,按照一定的比例(取多少比例是由下面的遺忘因子部分的計算決定的),累加到下面的 IAT 統計的直方圖裡面,最後計算從左往右累加值的 0.95 位置,此位置的 IAT 值作為最後的抖動 IAT 估計值。例如下圖,假定目标水位 TargetLevel 是 9,意味着目标緩存資料時長将會是 180ms(假定打包時長 20ms)。 

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

2. 平穩抖動遺忘因子計算:

遺忘因子是用來控制目前包的 IAT 值取多少比例累加到上面的直方圖裡面去的系數,計算過程用了一個看起來比較複雜的公式,經過分析,其本質就是下面的黃色曲線,意思是開始的時候遺忘因子小,會取更多的目前包的 IAT 值來累加,随着時間推移,遺忘因子逐漸變大,會取更少的目前包 IAT 值來累加。這個過程搞的有點複雜,從工程角度看完全可以簡化成直線之類的,因為測試下來 5s 左右的時間,基本就收斂到目标值 0.9993 了,其實這個 0.9993 才是影響抖動估計的最主要的因素,很多優化也是直接修改這個系數來調節估計的靈敏度。 

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

3. 峰值抖動估計:

DelayManager 中有一個峰值檢測器 PeakDetector 用來識别峰值,如果頻繁檢測到峰值,會進入峰值抖動的估計狀态,取最大的峰值作為最終估計結果,而且一旦進入這個狀态會一直維持 20s 時間,不管目前抖動是否已經恢複正常了。下面是一個示意圖。

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

NetEQ 操作決策子產品(DecisionLogic)

決策子產品的簡化後的基本判定邏輯,如下圖所示,比較簡潔不用解釋。這裡解釋一下下面這幾個操作類型的意義:

ComfortNoise:是用來産生舒适噪聲的,比單純的靜音包聽起來會更舒服的靜音狀态;

Expand(PLC):丢包補償,最重要的無中生有算法子產品,解決 “真丢包” 時沒資料的問題,造假專業戶 ;

Merge:如果上一次是 Expand 造假出來的資料,那為了聽起來更舒服一些,會跟正常資料包做一次融合算法;

Accelerate:變聲不變調的加速播放算法;

PreemptiveExpand:變聲不變調的減速播放算法;

Normal:正常的解碼播放,不額外引入假資料;

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結
解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

NetEQ 相關子產品優化點

NetEQ 抗抖動優化

1. 由于 NetEQ 的設計目标是 “極低延時”,不能很好的比對,視訊會議,線上課堂,直播連麥等非極低延時場景,需要對其敏感度進行調整,主要調整抖動估計子產品相關的靈敏度;

2. 直播場景,由于對于延時敏感度可以到秒級以上,是以需要啟用 StreamMode 的功能(新版本中好像去掉了),而且也需要對其中參數進行适配;

3. 服務于極低延時目标,原始的包緩存 packetbuffer 太小,容易造成 flush,需要按業務需要調大一些;

4. 還有一些業務會根據自己的業務場景主動識别網絡狀況,然後直接設定最小 TargetLevel,簡單粗暴的控制 NetEQ 的水位。 

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

NetEQ 抗丢包優化:

1. 原始的 WebRTC 的 Nack 丢包請求的觸發機制是用包觸發的,在弱網下會惡化重傳效果,可以改為定時觸發來解決;

2. 丢包場景會有重傳,但如果 buffer 太小,重傳也會被丢棄,是以為了提高重傳效率,增加 ARQ 延時預留功能,可明顯降低拉伸率;

3. 比較算法級的優化是對丢包補償 PLC 算法的優化,調整現有 NetEQ 的拉伸機制,優化聽感效果;

4. 開啟 Opus 的 Dtx 功能之後,在丢包場景會導緻音頻 Buffer 變大,需要單獨優化 Dtx 相關處理邏輯。

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

下面是 ARQ 延時預留功能開啟後的效果對比,平均拉伸率降低 50%,延時也會相應增加: 

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

音視訊同步優化: 

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結
解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

1,原始的 WebRTC 的 P2P 音視訊同步算法是沒有問題的,但是目前架構上面一般都有媒體轉發伺服器(SFU),而伺服器的 SR 包生成算法可能會由于某些限制或者錯誤會不完全正确,導緻無法正常同步,為規避 SR 包生成錯誤,需要優化音視訊同步子產品的計算方式,使用水位為主要參考來同步,即在接收端保證音視訊的緩存時間是差不多大小的。下面是優化效果的對比: 

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結
解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結
解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結
解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

2,還有一種音視訊同步的問題,其實不是音視訊同步機制導緻的,而是裝置性能有問題,不能及時處理視訊的解碼和渲染,導緻視訊資料累積,進而形成的音視訊不同步。這種問題可以通過對比不同步時長的趨勢,跟視訊解碼和渲染時長的趨勢,兩者比對度會很高,如下圖所示: 

解讀 WebRTC 音頻 NetEQ 及優化實踐為什麼要 “白話” NetEQ?丢包、抖動和優化的了解NetEQ 及相關子產品NetEQ 内部子產品NetEQ 相關子產品優化點總結

總結

NetEQ 作為音頻接收側的核心功能,基本上包含了各個方面,是以很多很多音視訊通訊的技術實作裡都會有它的蹤迹,乘着 WebRTC 開源快 10 年的東風,NetEQ 也變的非常普及,希望這篇白話文章能幫大家更好的了解 NetEQ。

作者最後的話:需求不停歇,優化無止境!

「視訊雲技術」你最值得關注的音視訊技術公衆号,每周推送來自阿裡雲一線的實踐技術文章,在這裡與音視訊領域一流工程師交流切磋。
原文連結:

https://developer.aliyun.com/article/782756?

版權聲明: 本文内容由阿裡雲實名注冊使用者自發貢獻,版權歸原作者所有,阿裡雲開發者社群不擁有其著作權,亦不承擔相應法律責任。具體規則請檢視《阿裡雲開發者社群使用者服務協定》和《阿裡雲開發者社群知識産權保護指引》。如果您發現本社群中有涉嫌抄襲的内容,填寫侵權投訴表單進行舉報,一經查實,本社群将立刻删除涉嫌侵權内容。

繼續閱讀