最近幾年,實時音視頻領域越來越熱,今年的疫情更是“火上澆油”了一把。網易智企旗下產品網易雲信在實時音視頻領域深耕多年,積累了不少實踐經驗。在本文里,筆者將以烹飪為比喻,深入淺出地將網易雲信如何從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 就好比是有了廚具/原材料,而實時音視頻引擎是給客戶的那頓大餐。
有了廚具/原材料,第一步是什么呢?“學會廚具使用方法”— WebRTC 的源碼工程化。
WebRTC 官網和其他第三方渠道已有不少資料介紹如何使用 Google 提供的工具編譯出 WebRTC 的生成物,本文不再詳細贅述。
會用廚具之后,是不是就能做出一頓好吃的飯菜了呢?
現實往往是這樣的:用着很牛的廚具和材料,做着難以下咽的料理…
所以要以合理的步驟來做一頓飯菜,這飯菜才適合下咽。
基於 WebRTC 網易雲信如何構建音視頻能力
在網易雲信的實踐中,我們選擇了怎樣的步驟呢?因為基於 WebRTC 建立通話的基礎是通過設置 SDP 來完成的,所以我們選擇了通過信令傳遞 SDP 信息,然后設置 SDP 信息給 PeerConnection 來完成建聯。整個多人音視頻能力中核心的是發布、訂閱、響應訂閱等媒體功能,其他的功能都是圍繞着這些核心功能來做的。而核心功能是采用如下流程來完成的:
舉例:
發布音視頻:把自己的 SDP 信息給媒體服務器(上圖中的媒體服務器是 SFU 服務器),媒體服務器把自己對應的 SDP 信息返回來。這樣就具備了 Local SDP 和 Remote SDP,就可以完成一次設置並建聯了。
訂閱和被訂閱也是類似的過程,通過發送自己的 SDP 給服務器,拿到遠端的 SDP 信息,然后建立/更新聯接。
以上是一個基本的建聯過程。拿烹飪來說,是不是飯菜做熟了就很好吃了呢?其實還有很多需要提升的:把飯菜做得更好吃/根據不同人的口味做不同的飯菜。這個提升的過程,就是各種優化。
網易雲信優化實踐
網易雲信的優化實踐有很多,下面介紹其中的幾種優化。
優化一:Simulcast
所謂 Simulcast,就是在一路視頻里提供多個分辨率的視頻流,訂閱方靈活根據需要訂閱想要的視頻流。典型的就是在會議場景的應用,如下圖:
如果沒有 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 的硬件編解碼功能不夠完整,為了能用起來,我們在整條路徑中做了不少事情。如下圖:
Android 端主要是硬件的碎片化引起,iOS 端主要是偶發的崩潰引起。碎片化靠下發白名單來解決(只對認證過的硬件啟用),偶發崩潰靠收集線上信息來限制特定版本/特定機型來解決。兩個移動端都有偶發失敗的問題,所以設計了一個失敗時的回退機制,以免視頻卡住的現象發生。最后再補完 simulcast 邏輯,就完成了這個硬件編解碼的支持。
以上的優化,基本上是大部分場景都可以適用的,但也有些優化要看具體場景確定。這就好比不同的人口味不一樣,有人喜歡辣,有人喜歡原味,做不到一套方法搞定所有的食客,於是我們做了定制化的優化來進行適應。
優化三:Audio profile
Audio 的優化做了很多,這其中挑了一個 Audio profile 的優化來講。語音場景里,需要的編碼碼率不太高,而娛樂場景里(比如播放伴音歌曲的),對碼率要求就高很多了,不然會丟失音質。碼率要求高了對網絡要求也會高,所以為了應對不同的場景,audio 的采樣數/聲道數都是不一樣的。音頻硬件又是五花八門,能力不統一,如果采集上來的數據不合適,就需要做重采樣支持。同時 codec 的傾向也做了 speech 和 music 的區分,以適應不同的需要。WebRTC 原先的設計里,基本只考慮了語音,跟娛樂場景相關的部分都需要優化支持。同時,為了能夠兼容更多的音頻處理/更差性能的機器,我們在優化過程中,將播放/采集線程進行了分離,相當於硬件要求降低了一半。
優化四:傳輸策略優化
傳輸策略要照顧實時性/清晰度/流暢度三個維度,理想中的優化當然是三個都做得更好,可惜這三個維度是互為掣肘的。如下圖所示:
這三個點里,一個點加強了,其他點會被影響。舉個例子:實時性要求很高,那緩存時間就得降低,這時候如果出現網絡抖動,很可能會卡頓,流暢性就受影響。所以想要同一個策略滿足不同的需求不太現實。在項目實踐中,我們根據不同的場景,設置不同的策略,來滿足不同傾向的需求。
通信場景一般對實時性要求高。舉個例子,你跟別人語音聊天,隔了一秒鍾才聽見對面的聲音,那么兩個人的聊天很容易“打架”,互相搶着發言。如果是多人語音聊天,那這個現象就更加嚴重了。娛樂直播場景對清晰度要求很高,但卻可以接受較高的延時。所以我們在實踐過程中給予了不同的策略支持,就好比做不同口味的飯菜來滿足不同人的口味。
以上就是網易雲信在構建音視頻引擎過程中的一些實踐經驗,在此分享給大家,希望能給有興趣的同學參考。