視頻 QoE 的平衡之道—揭祕網易雲信 NERTC 視頻質量控制系統

語言: CN / TW / HK
本文根據網易雲信資深引擎工程師戚繼躍在《MCtalk Live#4:視頻 QoE 的平衡之道》線上直播分享整理,文末有直播視頻回顧以及 QA 整理。

導讀

互聯網發展迅猛,實時通信(Real Time Communication,簡稱 RTC)需求與日俱增。如何在各種複雜網絡服務質量 (Quality of Serverice,簡稱 QoS)下,以及參差不齊的硬件終端上取得最佳的視頻體驗質量 (Quality of Experience,簡稱 QoE) ,是 RTC 技術的重要一環。
 
本文從視頻質量控制系統 (Video Quality Controller,簡稱 VQC)模塊出發,介紹網易雲信 NERTC 在提升視頻 QoE 方面做的一些工作。
 

VQC 在視頻 QoE 中的作用

 
視頻的 QoE 主要包含視頻的清晰度、視頻流暢度、視頻延時三個方面的指標,整體上由網絡 QoS、視頻處理算法、VQC 共同決定:
 
  • 網絡 QoS:提供儘可能充分的可使用帶寬
  • 視頻處理算法:在一定的碼率下,輸出儘可能好的視頻質量
  • VQC:
    • 對 QoS 負責,控制碼率,保證流暢度和延時
    • 對視頻算法負責,保證性能,平衡清晰度和流暢度
 
 
VQC 通過對視頻 QoS 狀態、視頻算法狀態的監控,輸出控制信號,達到場景化的最佳 QoE 表現,包括平衡清晰度、流暢度、延時這幾個指標。今天,我們主要分享網易雲信 NERTC 上的 VQC 實現以及 QoE 調優的相關工作。
 

網易雲信 VQC 實現

 
網易雲信的 VQC 模塊部分參考了 WebRTC 的模塊設計,整體結構如圖中所示,主要包含四個監控模塊和一個策略模塊。輸入的參數通過監控模塊後得到當前的各種狀態結果,然後由 VQC 策略模塊決定最終輸出的控制信號,控制視頻 pipeline 的工作。下面,我們具體介紹每個模塊。
 
 

QualityScaller

 
QualityScaller 模塊的作用是監測當前的編碼質量,主要對清晰度和編碼器穩定性負責。
 
 
該模塊輸入根據編碼器類型和編碼算法類型而確定的 QP 閾值、當前輸出編碼幀的 QP 值、當前丟幀的統計數據,輸出視頻質量好壞的結果。
 
其中 QpSmoother 模塊使用指數加權累加的方式來確定 QP 的統計值,如下:
 
 
我們詳細看一下這個公式的組成,公式中:
 
  • sample 為當前幀的 QP
  • 輸出 y 為 QP 統計值
  • alpha 是根據編碼器 QP 變化特性總結的一組係數值,根據上限和下限使用不同的係數值。比如我們測試下來針對 OpenH264 編碼器,QP 上限係數值可以使用 0.9995, QP 下限係數值可以使用 0.9999。通過這種差異性的上下限係數,達到視頻質量變差時(QP 增加)反應迅速,視頻質量變好時(QP 減小)反應稍微遲鈍的效果。
 
最終統計的上下限 QP 統計值,與輸入的 QP 閾值比較判斷,決定當前畫質的好壞。輸入的 QP 閾值也是根據編碼器不同而不同的,比如在 OpenH264 上我們測試下來使用閾值下限為 24,上限為 37;硬件 iOS 設備上硬件編碼則使用其他值,Android 上硬件編碼則又不同,這都需要根據設備的大量驗證來獲取。
 
MovingAverage 為一個滑動窗口函數,取這個窗口內的丟幀比例,超過一定閾值認為是質量變差。
 
最終內部週期性查詢模塊會收集 QpSmoother 和 MovingAverage 的統計結果,輸出兩個結果(不輸出不計入結果):
  1. 視頻質量好
  • QpSmoother 的 QP 統計值下限小於等於 QP 下限閾值
  • MovingAverage 統計的丟包率超過閾值
  1. 視頻質量差
  • QpSmoother 的 QP 統計值上限大於 QP 上限閾值
 

OveruseFrameDetector

 
OveruseFrameDetector 模塊主要作用是監測當前的性能能否支撐當下幀率的運行,對視頻的流暢度負責。
 
 
該模塊輸入當前的目標幀率、分辨率、CPU Usage 閾值,採集和發送視頻幀時間,輸出當前性能好或者壞的結果。
 
ProcessingUsage 模塊通過輸入的視頻幀採集和發送的時間,統計整個視頻發送鏈路即視頻採集到發送的時長,用這個時長做一些平滑運算後得到一個統計值,用這個統計值和當前幀率下幀間隔的理論時長做比較,統計時長是否超過理論值,並記錄次數。然後週期性的收集次數,超過一定次數則輸出性能差 CPU bad 的結果,低於一定次數則輸出性能好 CPU good 的結果。
 
在該模塊中,需要防止一些假的 CPU good 或者 bad 結果,比如:
  • 樣本數量少時(比如幀率低),週期性收集數據的時間沒有變,這就容易導致結果誤差
  • 新的幀率分辨率剛開始工作時,各個環節的處理時間還沒有問題,也需要特殊處理
 

RateAllocator

 
RateAllocator 模塊負責決定當前碼率的使用,在大小流場景下充當大小流使用的策略模塊。
 
該模塊有幾個關鍵性作用:
 
  1. 遠端有多個用户,其中有用户訂閲了小流也有用户訂閲了大流,該模塊會決定有限的碼率按照什麼比例分配比較合適
  2. 同樣的場景,在碼率十分不足的情況下,該模塊會決策大小流合併成一條流使用,提升畫質
  3. 在下行的帶寬受限情況下,該模塊會決策發送端有沒有必要降低帶寬發送
 

MediaOptimization

 
MediaOptimization 模塊主要負責監測和修正實時的碼率和幀率,防止碼率超發導致網絡擁堵,因為擁堵後網絡會進一步惡化,導致畫質、流暢度、延時全面的降低。
 
該模塊控制實時碼率主要通過內部的 FrameDropper 模塊,其使用漏斗算法決策當前是否碼率超發,是否需要丟幀來穩定碼率。
 
在每一幀編碼之前,將該幀的目標碼率作為輸入放入漏斗中,編碼之後將當前幀的實際碼率作為漏斗的輸出,然後去查看漏斗是否滿了,如果滿了就丟棄下一個編碼幀來控制碼率。漏斗的容量大小和可以容忍的延時相關,需要進行場景化定義。
 
丟幀與否的結果也會輸出給 QpScaller 模塊,作為評價編碼質量的依據的一方面。
 
 

VQC 決策模塊

 
VQC 決策模塊根據 VQC 內部前述所有模塊的結果,結合用户的場景設置,決策當下的視頻策略。
 
 
其內部包含兩個狀態機以及一個決策模塊。
 
兩個狀態機相互獨立,互不影響:
 
  • 視頻質量狀態機
  • 性能情況狀態機
 
一個決策模塊,我們具體説明其中的一些重要功能:
 
  • 根據用户設置的場景以及期望視頻參數,設置各種內部調整的閾值
  • 根據狀態機的結果,決策提高或者降低視頻的參數 (分辨率、幀率),以及提高或者降低的策略
  • 根據其他信息,決策當前幀編碼的其他參數,比如 simulcast 雙流場景下大流或者小流是否編碼
  • 根據其他信息,決定算法是否需要調整,比如編碼算法,後處理算法等
 

通過 VQC 進行視頻 QoE 調優

 
VQC 通過對視頻質量的全鏈路監控和調節來保證良好的視頻 QoE ,下面介紹下雲信 RTC 這邊在通過 VQC 調優 QoE 方面的一些工作。
 

正確判斷編碼質量

 
表徵編碼質量的參數有很多:PSNR、SSIM、QP、VMAF 等,因為硬件編碼器的特殊性以及參數獲取計算成本的考慮,選用了 QP 作為評判標準。
 
如果選擇使用 QP 作為正確反應編碼質量的指標,需要考慮如下幾點:
 
  • 常規的 Slice QP 在 H264/265 編碼中,一般編碼器中只能反應前面幾個編碼宏塊的質量。在軟件編碼上可以使用更優的 average QP 來作為視頻幀的 QP,這樣判斷軟件編碼質量效果更優。
  • 不同編碼算法的 QP 閾值是不同的,比如我們在 OpenH264 上可以使用 (24,37)作為 QP 好壞判斷的上下限,但是在不同的編碼器和不同的編碼算法上就需要調整,比如我們的 NE264、NE265、NEVC 編碼算法都需要做對應的適配調整。
  • 不同硬件加速平台上編碼器的 QP 的閾值是不同的,比如 iOS 系統、Android 系統,甚至 Android 不同的芯片平台也需要做對應的適配。
  • 不同編碼算法,不同硬件平台,QP 質量變化的曲線不同,為了提取特徵,需要調節統計方法的統計係數。
 

正確判斷性能問題

 
為了防止性能問題導致的視頻 QoE 降低,我們需要能準確的甄別出性能問題並作出正確有效的調整。當前我們的 VQC 中,使用視頻幀處理時間來表徵性能狀態,想要正確甄別性能狀態,需要考慮以下幾個方面:
 
  • 能判斷編碼和前處理的整個流程的性能
  • 一些硬件有 pipeline 延時需要考慮
  • 如果幀間隔不均勻,會導致誤判定性能問題,需要識別出這種特徵
 
為了進行有效的調整,我們主要需要考慮以下幾個方面內容:
 
  • 根據測試中性能消耗的優先級來調整,比如我們測試下來部分模塊的優先級是:前處理 > 編碼算法 > 幀率調整 > 分辨率調整
  • 如果做了相應的調整,統計的性能狀態還是沒有變化,我們需要有相應的處理手段,反饋調整內容和結果給狀態機,讓狀態機報告給決策模塊進行下一步決策
  • 如果性能狀態變化過大,需要拉大調整步長
 

最優化調整

 
有效的調整就是是調整後視頻 QoE 提升明顯,我們主要可以通過以下幾個方面進行調整:
 
  • 分辨率調整
  • 幀率調整
  • Simulcast 流的調整
  • 前處理的一些算法開關
  • Codec 調整
 
VQC 是如何進行最優化調整的呢,如下:
 
  • 支持用户可配置多種場景和策略
    • 通信模式,直播模式
    • 用户高可定製化:特殊場景模式,分辨率不變模式,幀率不變模式,最小幀率最小碼率等設置
  • 內部自適應調整,根據大量測試試驗確定某個具體場景下的參數組合,調整步長以及最佳路徑,比如如下視頻分辨率和幀率調整步長和路徑
 
 

結語

 
本文主要介紹了網易雲信 RTC 中視頻質量控制系統 VQC 的設計,以及在 QoE 調優方面的一些工作。沒有一種策略是完美無缺的,魚和熊掌不可兼得。我們在 QoE 調優中做的工作就是在一定的條件下,通過一些列手段平衡清晰度、流暢度、延時這些指標,趨利避害。通過互相配合的策略以及大量的數據測試驗證,尋找出最優的策略。
 

QA 整理

 
以下內容,根據線上直播羣內 QA 記錄整理:
 
  1. @一葦以航 提問:
Q: 請問 ratecontroller 的時候,一般都是 SFU 轉發模式,這個時候的 simulcast 是從服務端考慮所有訂閲端反饋給發送者去調整大小流的碼率嗎?
A:我們服務端做了各種場景下的策略,默認是走可配置的 TopN 策略,部分頭部觀眾儘量使用高清高流暢的大流,少量網絡質量不好的用户使用小流,服務端會根據下行所有觀眾的網絡情況,算出一個合適的反饋碼率
Q: 恩,我的問題不是問服務端的 SFU 轉發策略,而是發送端在大小流的碼率調整策略,你們談 ratecontrol 這個模塊的時候説到了一點,發送端收到一個 cc 的帶寬反饋,同時發送端提供了 simulcast,你們好像還能夠考慮到不同的接收端的網絡狀態,進行大小流的碼率調整 , 是有這個能力嗎?
A: 我們有下行的 cc,服務器會根據下行 cc 輸出的估計帶寬,然後綜合出一個合適的帶寬反饋給發送端。Simulcast 是端上根據總的碼率,在我們模塊裏面做決策,是發大流還是小流,還是雙流。服務端也會根據每個端的情況,決定給下行發送大流還是小流。
 
Q:美顏跟超分會帶來多大的延遲?
A: 關於美顏跟超分會帶來多大的延遲的問題:小於幀間隔,不會 delay 我們 pipeline,我們做了動態適配,如果大於幀間隔,會動態關閉掉,對整個流水線的延時小於一個幀間隔,如果 30 fps 就是小於 33ms。
 
Q: 一般做這一塊的都是基於 WebRTC 去做的,好像中途要切換 codec 的話,要麼就重新創建 peerconnection 重新協商,你們支持是因為自研添加的嗎,還是 WebRTC 本身支持呀?
A: 我們有部分參考了 WebRTC,codec 切換這塊不需要重新協商,我們做了頻道內的能力協商,是私有協議,不需要像 WebRTC 那樣做 sdp 交換,我們有自己的能力協商協議,然後音視頻引擎內部做切換。
 
Q:還有一個問題,你們在 RTC 會議房間裏如何處理關鍵幀請求,每一個新加入的用户如果都發關鍵幀請求,會導致房間的流量很大,但是不發的話等到下一個 GOP 會很久,你們採用了什麼樣的策略去均衡?
A: 1. 一般邏輯是每個新加入的用户都會有 intra request 發出來,然後接收端有一個 key frame 發送間隔的控制。這樣不會有太多 key frame,也不會導致出圖很慢。
2. 當然我們為快速出圖做了些優化,提前服務器 intrarequest, 保存近期的 key frame 等操作。
這些都是我們實際調整的一些細節,需要根據自己的場景去適配,我們也是分場景的。直播和通信策略就不一樣。
 
  1. @galen 提問:
Q: 請教下怎麼檢測卡頓呢, 一般檢測卡頓幀間隔時間有講究嗎?
A:卡頓我們會統計 200ms 卡頓和 500ms 卡頓,檢測實際渲染的幀率間隔,超過 200ms 或者 500ms,統計小卡頓或者大卡頓。

作者介紹

 
戚繼躍,網易雲信資深引擎工程師,長期從事音視頻相關開發工作,對 WebRTC 引擎,音視頻會議系統,視頻編解碼等有深入研究。目前主要負責網易雲信 NERTC 引擎的視頻體驗。
 
視頻回顧地址:https://mctalk.yunxin.163.com/details-live/13