­

從 0 到 1 構建實時音影片引擎

最近幾年,實時音影片領域越來越熱,今年的疫情更是「火上澆油」了一把。網易智企旗下產品網易雲信在實時音影片領域深耕多年,積累了不少實踐經驗。在本文里,筆者將以烹飪為比喻,深入淺出地將網易雲信如何從0到1構建實時音影片引擎的過程分享給讀者。

跟業界很多引擎的實現方案一樣,網易雲信也是基於 WebRTC 構建的實時音影片引擎。本文會從介紹 WebRTC 提供了什麼開始,一步步引入工程化/產品化/優化實踐等內容,完整呈現引擎的整個構建過程。

WebRTC 是什麼

首先,WebRTC 是什麼?

WebRTC 全稱 Web Real-Time Communication。原本是用於支援網頁瀏覽器開發實時音影片用的一套 API,它提供了統一的交互協議:SDP,同時提供了影片會議的核心技術,包括音頻引擎、影片引擎、傳輸控制三大塊,並且還支援跨平台:Windows / Mac / Linux / Android / iOS。

WebRTC 本來就是給瀏覽器用的,沒有 native 程式碼可以參考。但是,在 2011 年它被 Google 開源了,源碼被應用於各種 native 開發,並被業內廣泛借鑒,大有一統天下的趨勢。

WebRTC 提供了什麼?

有了 WebRTC,是不是就等於有了實時音影片引擎呢?並不是,以烹飪來做比喻的話,有了 WebRTC 就好比是有了廚具/原材料,而實時音影片引擎是給客戶的那頓大餐。

圖1.png

有了廚具/原材料,第一步是什麼呢?「學會廚具使用方法」— WebRTC 的源碼工程化。

WebRTC 官網和其他第三方渠道已有不少資料介紹如何使用 Google 提供的工具編譯出 WebRTC 的生成物,本文不再詳細贅述。

會用廚具之後,是不是就能做出一頓好吃的飯菜了呢?

現實往往是這樣的:用著很牛的廚具和材料,做著難以下咽的料理…

圖2.png

所以要以合理的步驟來做一頓飯菜,這飯菜才適合下咽。

基於 WebRTC 網易雲信如何構建音影片能力

在網易雲信的實踐中,我們選擇了怎樣的步驟呢?因為基於 WebRTC 建立通話的基礎是通過設置 SDP 來完成的,所以我們選擇了通過信令傳遞 SDP 資訊,然後設置 SDP 資訊給 PeerConnection 來完成建聯。整個多人音影片能力中核心的是發布、訂閱、響應訂閱等媒體功能,其他的功能都是圍繞著這些核心功能來做的。而核心功能是採用如下流程來完成的:

圖3.png

舉例:

發布音影片:把自己的 SDP 資訊給媒體伺服器(上圖中的媒體伺服器是 SFU 伺服器),媒體伺服器把自己對應的 SDP 資訊返回來。這樣就具備了 Local SDP 和 Remote SDP,就可以完成一次設置並建聯了。

訂閱和被訂閱也是類似的過程,通過發送自己的 SDP 給伺服器,拿到遠端的 SDP 資訊,然後建立/更新聯接。

以上是一個基本的建聯過程。拿烹飪來說,是不是飯菜做熟了就很好吃了呢?其實還有很多需要提升的:把飯菜做得更好吃/根據不同人的口味做不同的飯菜。這個提升的過程,就是各種優化。

網易雲信優化實踐

網易雲信的優化實踐有很多,下面介紹其中的幾種優化。

優化一:Simulcast

所謂 Simulcast,就是在一路影片里提供多個解析度的影片流,訂閱方靈活根據需要訂閱想要的影片流。典型的就是在會議場景的應用,如下圖:

圖4.png

如果沒有 Simulcast 功能,假定需要 720P 的影片,在這個場景里,發送方需要發送/壓碼一路 720P 影片,接收/解碼4路 720P 影片,頻寬和性能壓力非常大。如果增加了 Simulcast 能力,同時能夠發送 720P/180P 的影片。在這個場景里,發送方通常只要發送/壓碼 180P 影片,接收/解碼1路 720P 影片,接收/解碼3路 180P 影片。頻寬要求和性能要求降到了原先的1/4左右,而效果是完全一樣的。

WebRTC 的 Simulcast 功能,並不是由 WebRTC 團隊完成的,而是一個第三方開發團隊開發,並 merge 到 WebRTC 里去的。要開啟它,需要開啟一個實驗室介面,然後在 Video quality control 里更改相應的源碼才能正常運行。配合上層的信令,就能做到靈活訂閱了。

優化二:影片硬體編解碼

通常,影片硬體編解碼會比軟體編解碼性能開銷更低。無論在日常使用還是上高清解析度(比如 1080P)都有很重要的作用。WebRTC 的硬體編解碼功能不夠完整,為了能用起來,我們在整條路徑中做了不少事情。如下圖:

圖5.png

Android 端主要是硬體的碎片化引起,iOS 端主要是偶發的崩潰引起。碎片化靠下發白名單來解決(只對認證過的硬體啟用),偶發崩潰靠收集線上資訊來限制特定版本/特定機型來解決。兩個移動端都有偶發失敗的問題,所以設計了一個失敗時的回退機制,以免影片卡住的現象發生。最後再補完 simulcast 邏輯,就完成了這個硬體編解碼的支援。

以上的優化,基本上是大部分場景都可以適用的,但也有些優化要看具體場景確定。這就好比不同的人口味不一樣,有人喜歡辣,有人喜歡原味,做不到一套方法搞定所有的食客,於是我們做了訂製化的優化來進行適應。

優化三:Audio profile

Audio 的優化做了很多,這其中挑了一個 Audio profile 的優化來講。語音場景里,需要的編碼碼率不太高,而娛樂場景里(比如播放伴音歌曲的),對碼率要求就高很多了,不然會丟失音質。碼率要求高了對網路要求也會高,所以為了應對不同的場景,audio 的取樣數/聲道數都是不一樣的。音頻硬體又是五花八門,能力不統一,如果採集上來的數據不合適,就需要做重取樣支援。同時 codec 的傾向也做了 speech 和 music 的區分,以適應不同的需要。WebRTC 原先的設計里,基本只考慮了語音,跟娛樂場景相關的部分都需要優化支援。同時,為了能夠兼容更多的音頻處理/更差性能的機器,我們在優化過程中,將播放/採集執行緒進行了分離,相當於硬體要求降低了一半。

優化四:傳輸策略優化

傳輸策略要照顧實時性/清晰度/流暢度三個維度,理想中的優化當然是三個都做得更好,可惜這三個維度是互為掣肘的。如下圖所示:

圖6.png

這三個點裡,一個點加強了,其他點會被影響。舉個例子:實時性要求很高,那快取時間就得降低,這時候如果出現網路抖動,很可能會卡頓,流暢性就受影響。所以想要同一個策略滿足不同的需求不太現實。在項目實踐中,我們根據不同的場景,設置不同的策略,來滿足不同傾向的需求。

圖7.png

通訊場景一般對實時性要求高。舉個例子,你跟別人語音聊天,隔了一秒鐘才聽見對面的聲音,那麼兩個人的聊天很容易「打架」,互相搶著發言。如果是多人語音聊天,那這個現象就更加嚴重了。娛樂直播場景對清晰度要求很高,但卻可以接受較高的延時。所以我們在實踐過程中給予了不同的策略支援,就好比做不同口味的飯菜來滿足不同人的口味。

以上就是網易雲信在構建音影片引擎過程中的一些實踐經驗,在此分享給大家,希望能給有興趣的同學參考。