在與同行交流過程當中,發現不少同行對 WebRTC 改動太多,致使沒法升級 WebRTC 版本。而 WebRTC 開源社區的快速迭代,讓他們感到欣喜又焦慮:開源社區的迭代效果,是否是超過了他們對 WebRTC 的優化效果?咱們針對特定場景優化 WebRTC 時,怎麼緊跟 WebRTC 開源社區通用的優化?git
做者:阿里雲智能技術專家 熊金水github
簡言之,把 WebRTC 做爲 Framework 使用,而不是 Library,即:WebRTC 倉庫輕量化,核心模塊插件化。web
詳細的,WebRTC 做爲 Framework 串聯核心模塊;核心模塊既能夠以插件形式使用咱們的實現,也能夠 Fallback 到 WebRTC 的默認實現。目的是減小 WebRTC 衝突的可能性,提升升級 WebRTC 的敏捷性。算法
目標:一年升級一次 WebRTC,一次花費一我的月。架構
WebRTC 的核心模塊,包括:ide
WebRTC 在長期的演進中,API 已經具有了做爲 Framework 的大部分能力。紅色的核心模塊,已經基本能夠插件化,以下面的 API:
函數
light-rtc 做爲 WebRTC 倉庫,咱們須要保留兩個 Remote,一個是 Alibaba,一個是 Google。升級 WebRTC 時,咱們從 Google 上 Pull 最新代碼, 解決衝突,而後 Push 到 Alibaba。性能
對插件化的模塊,咱們須要放到單獨的倉庫 lrtc-plugin 裏,這樣有兩個好處:優化
對 lrtc-plugin 依賴的第三方庫,也應該以單獨的倉庫存在,並保留兩個 Remote,好比 Opus,這樣,即便修改了 Opus 源碼,仍然能夠像升級 light-rtc 同樣,方便的單獨升級 Opus 版本。阿里雲
音頻編解碼器、視頻編解碼器,是咱們最常優化的部分之一:
這部分插件化是相對簡單的,只須要實現本身的[Video|Audio][Encoder|Decoder]Factory
便可。以 Simulcast爲例,在本身實現的 VideoEncoderFactory 裏,先用 WebRTC 原始的 VideoEncoderFactory,建立多個 Encoder 對象,而後封裝到一個 Simulcast Encoder 裏。
很惋惜,ADM(Audio Device Module)沒有提供檢測設備插拔的功能,須要增長 Callback 接口。
另外,雖然 WebRTC 支持樣本數量的監控,可是當前只用於打印日誌,若是想在此基礎上作更多事情(如:發現採集樣本爲 0 時,重啓採集),則單獨作一個 AudioSampleMoniter 的類,比較有利於擴展。
ADM 是一個適配難點,相信是困擾 RTC 同行的共同難題。不一樣操做系統、不一樣機型,均可能有不同的問題。例如:
這些修改大部分屬於 Bugfix,參考「Bugfix」章節。
APM(Audio Processing Module)多是 light-rtc 相對難處理的部分。
APM 與 NetEQ 一塊兒,多是 WebRTC 核心模塊中,開源價值最大的部分。在我對 APM 有限的認知裏,對 APM 常見的優化可能有:
下圖是 WebRTC APM 內部模塊的數據流程圖:
從圖中能夠看出,APM 其實也爲插件化作了準備,可是隻在近端信號的尾部、遠端信號的頭部。從 APM 構造函數上也能夠看出來:
濾波/均衡,能夠方便的實現一個 CustomProcessing 的 render_pre_processor。
其餘的優化,遵循輕量化/插件化的理念,沒有現成的插件接口,咱們能夠創造新的插件接口,如嘯叫抑制,以及 AECM 優化的部分算法。
但 APM 仍然會有不少沒辦法插件化的,只能修改 light-rtc 倉庫,如 AECM Double Talk 優化等。
AM(Audio Mixer)的插件化,能夠在不修改 light-rtc 的基礎上,玩出不少花樣:
FEC(Forward Error Correction),常見的修改:
CC(Congestion Control),包含兩個方面,一個是 CC 算法自己,一個是 CC 關聯模塊。
算法自己,能夠用不一樣的算法實現,如 WebRTC 默認的 goog_cc,也能夠是 BBR,甚至是知足 WebRTC::NetworkControllerFactoryInterface 接口的外部插件。
關聯模塊:
Android、iOS、Mac,WebRTC 都提供了默認的實現,雖然有少許 Bug,可是基本知足需求。
Windows 平臺,早期 WebRTC 提供了 D3D 的實現,最新版已經剔除,咱們能夠在 lrtc-plugin 倉庫實現本身的 D3D,或者其餘的渲染,如 QT OpenGL。
WebRTC 並無提供視頻前處理(如:美顏)、後處理(如:超分辨率)的接口,可是咱們徹底能夠像 rtc::BitrateAllocationStrategy 同樣,創造 VideoProcessInterface 接口, 並在 lrtc-plugin 倉庫裏實現。
讓 VideoProcessInterface 同時繼承 Sink 和 Source 接口,能夠方便的把多個對象串聯起來。
其餘核心模塊,如 JitterBuffer、ICE 等,目前接觸的主要是 Bugfix,尚未發現本身定製重寫的必要。
Bugfix,每每只能修改 light-rtc 倉庫。一方面,是儘可能把 Bugfix 內聚成函數,減小對已有代碼的修改;另外一方面,儘可能把 Bugfix 貢獻到開源社區(Issue Tracker),既爲開源社區作了貢獻,也完全避免了升級的衝突。
貢獻到開源社區,每每比想象的要複雜,但也更能鍛鍊人。在特定場景,每每只用了 WebRTC 一部分能力,如視頻 JitterBuffer,一個 Bugfix 可能只考慮到了 H264,貢獻到開源社區時,則須要同時兼顧 VP8/VP9,甚至是未來的 AV1。在這個過程當中,Google 工程師會在 Code Review 中與你親密切磋,實際上是很是好的鍛鍊機會,進一步提升對 WebRTC 的認識。
WebRTC m74 源碼
RSFEC:
CC
「視頻雲技術」你最值得關注的音視頻技術公衆號,每週推送來自阿里雲一線的實踐技術文章,在這裏與音視頻領域一流工程師交流切磋。