天天看點

light-rtc: 理念與實踐

在與同行交流過程中,發現很多同行對 WebRTC 改動太多,導緻無法更新 WebRTC 版本。而 WebRTC 開源社群的快速疊代,讓他們感到欣喜又焦慮:開源社群的疊代效果,是不是超過了他們對 WebRTC 的優化效果?我們針對特定場景優化 WebRTC 時,怎麼緊跟 WebRTC 開源社群通用的優化?

理念

簡言之,把 WebRTC 作為 Framework 使用,而不是 Library,即:WebRTC 倉庫輕量化,核心子產品插件化。

詳細的,WebRTC 作為 Framework 串聯核心子產品;核心子產品既可以以插件形式使用我們的實作,也可以 Fallback 到 WebRTC 的預設實作。目的是減少 WebRTC 沖突的可能性,提高更新 WebRTC 的靈活性。

目标:一年更新一次 WebRTC,一次花費一個人月。

架構

子產品拆解

light-rtc: 理念與實踐

WebRTC 的核心子產品,包括:

音頻

  • ADM 采集、APM、ACM 編碼;
  • NetEQ 與解碼、AM、ADM 渲染;

視訊

  • 采集、編碼;
  • JB、解碼、渲染;

通用

  • RTP 打包與解包、FEC 生成與恢複、CC 與 Pacer、ICE、SDP 信令等。

WebRTC 在長期的演進中,API 已經具備了作為 Framework 的大部分能力。紅色的核心子產品,已經基本可以插件化,如下面的 API:

light-rtc: 理念與實踐

倉庫管理

light-rtc: 理念與實踐

light-rtc 作為 WebRTC 倉庫,我們需要保留兩個 Remote,一個是 Alibaba,一個是 Google。更新 WebRTC 時,我們從 Google 上 Pull 最新代碼, 解決沖突,然後 Push 到 Alibaba。

對插件化的子產品,我們需要放到單獨的倉庫 lrtc-plugin 裡,這樣有兩個好處:

  1. 對 light-rtc 倉庫改動少,減少與 Google 沖突的可能性;
  2. 更重要的,讓每個開發同學,在每次改動前,更主動、更有意識的思考,放到哪個倉庫更合适,否則容易慣性思維,直接改動 light-rtc。

對 lrtc-plugin 依賴的第三方庫,也應該以單獨的倉庫存在,并保留兩個 Remote,比如 Opus,這樣,即使修改了 Opus 源碼,仍然可以像更新 light-rtc 一樣,友善的單獨更新 Opus 版本。

子產品

Codec

音頻編解碼器、視訊編解碼器,是我們最常優化的部分之一:

  • 新的編碼工(AV1/SCC/ROI 等)優化視訊品質和帶寬;
  • 分辨率自适應,使不同能力(編碼能力、發送帶寬等)的發送端,發送不同分辨率的碼流;
  • Simulcast,為不同能力(解碼能力、顯示能力、接收帶寬等)的接收端,提供不同分辨率碼流;
  • SVC,提供時域/空域分層;
  • 新的視訊解碼實作,規避 Mac 硬解卡死等問題;
  • 新的音頻編碼器,适配商用接收端;

……

light-rtc: 理念與實踐

這部分插件化是相對簡單的,隻需要實作自己的 [Video|Audio][Encoder|Decoder]Factory 即可。以 Simulcast為例,在自己實作的 VideoEncoderFactory 裡,先用 WebRTC 原始的 VideoEncoderFactory,建立多個 Encoder 對象,然後封裝到一個 Simulcast Encoder 裡。

ADM

很可惜,ADM(Audio Device Module)沒有提供檢測裝置插拔的功能,需要增加 Callback 接口。

另外,雖然 WebRTC 支援樣本數量的監控,但是目前隻用于列印日志,如果想在此基礎上做更多事情(如:發現采集樣本為 0 時,重新開機采集),則單獨做一個 AudioSampleMoniter 的類,比較有利于擴充。

light-rtc: 理念與實踐

ADM 是一個适配難點,相信是困擾 RTC 同行的共同難題。不同作業系統、不同機型,都可能有不一樣的問題。例如:

  • Mac 3.5mm 耳機插拔時,偶爾崩潰;
  • Mac 擷取的裝置 ID 在插拔後發生變化,不能做持久化;
  • 聯想 X1 電腦,多次插拔後,整個 Audio 背景服務失效;
  • 某些 Windows 機型采集不到聲音;
  • 某些手機采音權限問題;

這些修改大部分屬于 Bugfix,參考“Bugfix”章節。

APM

APM(Audio Processing Module)可能是 light-rtc 相對難處理的部分。

APM 與 NetEQ 一起,可能是 WebRTC 核心子產品中,開源價值最大的部分。在我對 APM 有限的認知裡,對 APM 常見的優化可能有:

  • 混音後的遠端信号,做濾波/均衡處理。這是業界不少音頻算法的必要條件;
  • 利用 Android 手機特性,優化 AECM,尤其是 Double Talk 時的效果;
  • 嘯叫檢測與抑制;
  • 利用機型特性,優化 AGC,提高語音音量;

下圖是 WebRTC APM 内部子產品的資料流程圖:

light-rtc: 理念與實踐

從圖中可以看出,APM 其實也為插件化做了準備,但是隻在近端信号的尾部、遠端信号的頭部。從 APM 構造函數上也可以看出來:

light-rtc: 理念與實踐

濾波/均衡,可以友善的實作一個 CustomProcessing 的 render_pre_processor。

其他的優化,遵循輕量化/插件化的理念,沒有現成的插件接口,我們可以創造新的插件接口,如嘯叫抑制,以及 AECM 優化的部分算法。

但 APM 仍然會有很多沒辦法插件化的,隻能修改 light-rtc 倉庫,如 AECM Double Talk 優化等。

AM

AM(Audio Mixer)的插件化,可以在不修改 light-rtc 的基礎上,玩出很多花樣:

  • 播放本地檔案;
  • 借助語音檢測算法,優化語音排序,進而選出更準确的語音做混音;
  • Mono 變成 Stereo,借助 HRTF,可以在多方同時說話時提高說話人辨識度和可懂度;
  • 對 RTP 方案的回放,倍速回放時變速不變調;
light-rtc: 理念與實踐

FEC

FEC(Forward Error Correction),常見的修改:

  • 調參,如備援度、MaxFrames、Table 類型,包括固定參數和動态自适應調參兩類,已有的插件接口 WebRTC::FecControllerFactoryInterface 即可滿足;
  • RSFEC,需要創造新的插件接口;
  • Opus Inband FEC。WebRTC 動态配置的 Opus FEC 參數,不能很好的解決弱網時聲音卡頓問題。這時,一個辦法是把 Opus 獨立成倉庫,直接修改 Opus 編碼器。
light-rtc: 理念與實踐

CC

CC(Congestion Control),包含兩個方面,一個是 CC 算法本身,一個是 CC 關聯子產品。

算法本身,可以用不同的算法實作,如 WebRTC 預設的 goog_cc,也可以是 BBR,甚至是滿足 WebRTC::NetworkControllerFactoryInterface 接口的外部插件。

關聯子產品:

  • 帶寬配置設定:不同場景可能不一樣,如視訊會議裡,需要“保音頻、保螢幕”。可以通過 rtc::BitrateAllocationStrategy 實作插件化。
light-rtc: 理念與實踐
  • Pacer 調優:對于螢幕内容,I幀往往非常大,WebRTC 的 2.5 倍的發送帶寬,會導緻巨大的首幀時間。具體解法見仁見智。

VideoRender

Android、iOS、Mac,WebRTC 都提供了預設的實作,雖然有少量 Bug,但是基本滿足需求。

Windows 平台,早期 WebRTC 提供了 D3D 的實作,最新版已經剔除,我們可以在 lrtc-plugin 倉庫實作自己的 D3D,或者其他的渲染,如 QT OpenGL。

VideoProcess

WebRTC 并沒有提供視訊前處理(如:美顔)、後處理(如:超分辨率)的接口,但是我們完全可以像 rtc::BitrateAllocationStrategy 一樣,創造 VideoProcessInterface 接口, 并在 lrtc-plugin 倉庫裡實作。

light-rtc: 理念與實踐

讓 VideoProcessInterface 同時繼承 Sink 和 Source 接口,可以友善的把多個對象串聯起來。

其他 & Bugfix

其他核心子產品,如 JitterBuffer、ICE 等,目前接觸的主要是 Bugfix,還沒有發現自己定制重寫的必要。

Bugfix,往往隻能修改 light-rtc 倉庫。一方面,是盡量把 Bugfix 内聚成函數,減少對已有代碼的修改;另一方面,盡量把 Bugfix 貢獻到開源社群(Issue Tracker),既為開源社群做了貢獻,也徹底避免了更新的沖突。

貢獻到開源社群,往往比想象的要複雜,但也更能鍛煉人。在特定場景,往往隻用了 WebRTC 一部分能力,如視訊 JitterBuffer,一個 Bugfix 可能隻考慮到了 H264,貢獻到開源社群時,則需要同時兼顧 VP8/VP9,甚至是将來的 AV1。在這個過程中,Google 工程師會在 Code Review 中與你親密切磋,其實是非常好的鍛煉機會,進一步提高對 WebRTC 的認識。

參考

  • WebRTC RSFEC 詳解和剖析;
  • ARTP 技術探秘之:WebRTC 中支援 RS FEC。

繼續閱讀