實時音視頻通話作為高效便捷的溝通手段在許多場景下得到應用。隨著5G商用元年的真正到來,實時音視頻通話將會得到更加蓬勃的發展。本次LiveVideoStackCon 2020線上峰會我們邀請到了網易云信資深音視頻服務端開發工程師魯林俊,他將結合網易云信流媒體服務搭建的實戰經驗,進行一些深入的分享。
文 / 魯林俊
整理 / LiveVideoStack
?
大家好,我叫魯林俊,很高興參加LiveVideoStackCon 2020線上峰會,本次我分享的主題是網易云信流媒體服務端架構設計與實現。

本次內容主要分為三個部分:一是實時音視頻為基礎的流媒體服務端設計;二是錄制服務方案設計;三是視頻會議傳輸質量控制。
實時音視頻為基礎的流媒體服務端設計
1.1 分發架構
在設計以實時音視頻為基礎的流媒體服務器之前需要解決的一個問題是:轉發方案的選取。討論比較多的方案有三種:

一是Mesh方案,即通話各端兩兩進行媒體通道的建立,并交換數據,實現媒體通話。從服務器角度看,這種方案比較簡單,服務器只要實現一些信令和打洞相關的能力等就可以實現通話,但這種方案的缺陷是通話能否成功建立依賴于打洞的成功率。

二是SFU彈性轉發方案,下行轉發的單位是每個用戶的單個流。

三是MCU方案,媒體服務器會進行媒體處理,將混合好的音頻和視頻進行重新編碼并轉發給下行用戶。

網易云信搭建音視頻服務器時選取的是一個混合轉發方案,它是基于SFU為主的媒體轉發方案,輔助MCU進行特定場景轉發。特定場景比如用戶為觀眾端,可以以一條MCU的流轉播給觀眾端。
這種方案的優勢在于:一是基于SFU的設計,服務器邏輯輕、性能好。二是SFU彈性轉發設計,可以配合發布訂閱的邏輯,做到可選的下行轉發。三是可以配合MCU,做到下行寬帶的節省以及跨通話系統間的互通簡化。
1.2 傳輸通道和協議

協議通道的設計中有兩個協議通道:非可靠的UDP通道和可靠的KCP通道。

非可靠的UDP通道主要用于傳輸媒體,可靠的KCP通道主要用于登入、登出、網絡狀態同步、傳輸控制等。
1.3 小程序網關和WebRTC網關

除此之外,傳輸層是基于我們自己的私有協議。

做PaaS服務僅僅覆蓋三端是不夠的,要盡可能覆蓋更多的平臺,比如基于web的開發、基于小程序的開發。由于基于私有協議比較困難,我們搭建了WebRTC網關和小程序網關。
WebRTC網關基于WebRTC標準的實現,接收RTP/RTCP的流,進行協議的轉封裝,并推送到中轉分發服務器的骨干節點上面,最終推送到私有用戶上,這就實現了私有端和web端的互通,小程序的網關同理。這兩個網關的搭建足夠滿足純粹的實時音視頻場景,但要做純粹的實時音視頻,PaaS服務是無法滿足用戶的需求的。
1.4 流媒體處理輔助系統

當一個擁有幾十萬粉絲的用戶進行一個簡單的聊天時,想要獲得聊天內容又想將聊天內容直播給粉絲看,此外,也想和粉絲聊天并將聊天內容給其他粉絲看。這就是在基于純粹的實時音視頻的基礎上去獲得錄制、直播、互動直播的功能。

為了滿足用戶的場景需求,在基于實時音視頻為主要核心系統的基礎上,搭建了兩個輔助的媒體處理系統:直播系統和錄制點播系統。
圖中左邊展示的是實時通話系統,實時通話內容把媒體數據推給互動直播服務器進行媒體數據協議封裝,封裝成私有協議或者RTMP協議,并推送到CDN和我們自建的直播源站,這樣用戶就可以基于標準協議從CDN或者直播源站上進行拉流,這也正是圖中右側所展示的直播系統。
直播系統中還有一個單項的直播功能,主播支持RTMP協議或者私有協議并推送到直播源站,用戶從直播源站拉流觀看即可。另外,錄制功能同樣是將媒體內容推送到錄制服務器,錄制服務器進行相應的錄制后上傳到NOS存儲上,最后到達點播源站,用戶通過CDN回源到點播源站,并進行錄制內容的點播。以上就是在實現純粹的實時音視頻通話基礎上,我們相應擴展了其他媒體處理能力,使用戶使用場景最大化。
1.5 中心控制系統

因為會面臨會話如何發起、節點如何就近接入、通話過程中如何對通話進行管理等問題,所以我們搭建了三個中心控制服務器。
第一個是會議接入控制中心,它的主要職能是提供IM通道,用戶基于IM消息通知服務器發起通話。
第二個是會話調度中心,它的職能是為用戶創建房間、加入房間調度一個最佳節點。
第三個是房間管理中心,它負責整個房間信息生命周期的管理,并提供RESTful Api,為用戶提供房間管理,比如查詢目前通話的房間內容等,都可以通過房間管理中心進行相應的處理。
舉個例子,當用戶發起一通通話,用戶A可以基于IM消息發一個創建會議的消息,會議接入控制中心會將此消息推送給用戶B。同時會議接入控制中心,從房間管理中心、會議調度中心獲取相應的信息后,通過IM通道將結果反饋給用戶A,用戶A再將這些信息反饋給用戶B。用戶A或者用戶B獲取信息后推送給中轉分發服務器集群,實現整個會議接入點流程。
以上的內容主要介紹了網易云信如何基于用戶的需求打造音視頻的PaaS服務。
錄制服務方案設計

以下部分我將介紹了錄制服務的搭建,很多人認為云端錄制比較容易,但是由于2B業務的用戶場景的多樣化,使得錄制服務會面臨很多挑戰。
首先是錄制服務方案如何選取。如果采用實時錄制,全量通話進行MCU處理,性能無法滿足。
如果采用離線處理,會遇到一些用戶需求問題,比如用戶要馬上看到文件,但錄制還未開始。
另外,有些用戶想要有錄制的功能,但是媒體數據他們自己加密了,我們的服務器沒法進行解密,所以也無法進行錄制。以上都是一些客觀存在的問題,為了應對各種用戶場景,我們設計了一套融合錄制方案。
2.1 融合錄制方案

這張圖向大家展示了融合錄制方案的內容。對于即時點播需求很高的用戶,我們提供了實時MCU服務器,實時通話時會把通話內容轉給MCU服務器進行數據的混合編碼,以H264單幀的方式投遞到MP4/FLV協議封裝服務器上,并將封裝后的MP4/FLV數據上傳到云存儲,這樣用戶就可以進行相應的點播。
另外,對于錄制功能有要求但對即時點播要求不高的客戶,需要選擇離線處理的方案,網絡碼流Dump服務器實時地將需要錄制的會話Dump下來,并轉成私有Dump文件,離線MCU處理器將私有Dump文件進行調度處理,最終上傳到MP4/FLV協議封裝服務器上,用戶就可以進行相應的點播操作。以上就是實時錄制方案和離線錄制方案。
針對于用戶想要將媒體數據加密并且保留錄制功能的需求,我們開發了錄制SDK。用戶可以基于錄制SDK開發用戶自建錄制服務器,這套錄制方案可以解決大多數用戶的錄制場景。
2.2 離線錄制實現

這部分細致介紹一下離線錄制方案,用戶基于RESTful Api向房間管理中心發送錄制請求,房間管理中心基于調度中心就近調度到一個實時網絡碼流Dump服務器,同時將錄制請求和錄制參數(用戶錄制如何布局、是否進行音頻能量的選取等)下發到選中的網絡碼流Dump服務器。網絡碼流Dump服務器收到請求通知后會和中轉分發服務器建立拉流鏈路并獲取媒體數據,之后進行私有協議文件的封裝,這相當于進行一個離線處理,將實時數據封裝到離線文件里,然后經過離線MCU服務器進行離線文件處理并錄制,再將錄制好的碼流投遞到文件封裝上傳服務再到存儲點播服務器,這樣從錄制的發起到上傳、存儲的離線錄制就完成了。
其中私有協議文件格式設計非常重要,離線處理要處理好音頻和視頻的同步以及畫面中所有人的音頻和視頻的同步,就需要建立一個合適的同步機制以適配私有協議文件。
2.3 實時音視頻錄制與白板錄制同步回放機制

教育場景下,如何進行實時音視頻錄制和白板錄制同步回放?
由于白板通訊基于TCP,實時音視頻基于UDP,兩者相互獨立。用戶基于白板SDK進行白板數據的傳輸,基于音視頻SDK進行音視頻通話,這就要解決如何進行跨系統之間的錄制文件的同步回放問題。
首先,白板服務器集群和音視頻服務器集群要基于NTP同步服務器進行時間同步操作,即做到離散服務器之間的系統時間一致。
其次,需要制定一個合理的同步方案,即在白板錄制文件和MP4文件里增加同步字段(NTP時間)。每一個白板數據和視頻幀都增加NTP時間,也就是基于NTP時間進行相應的同步。但要解決NTP存放的問題,對于白板錄制而言,因為白板錄制文件是私有錄制文件,只需要在TAG-HEADER字段里每個隔一個字段存放NTP這個時間的字段即可。
對于實時音視頻錄制而言,MP4或者FLV要基于H246一幀插入一個NAL-SEI,NAL-SEI的payload type要設置為5,在用戶自定義數據里同樣插入一個NTP字段。MP4播放時間是基于MP4player的,無法控制其播放進度,所以整體的同步方案是基于白板播放時,實時的用位于同步時間軸上下的兩個NTP進行校準,進行白板的加速播放或者慢播放,這樣就可以做到音視頻錄制文件和白板錄制文件同步回放的效果。
視頻會議傳輸質量控制

對于視頻會議傳輸質量控制要從三個模塊分析:一是第一公里接入;二是多流發布訂閱機制;三是傳輸層上下行QoS策略。
3.1 第一公里接入

第一公里接入主要采取兩種方法:一是邊緣加速代理和傳輸層路由策略結合。二是進行網絡探測和智能選路。
3.1.1 邊緣加速代理和傳輸層路由策略結合

第一公里接入模塊的具體操作是,首先在基于現有的中轉分發服務器集群覆蓋的場景下,無法做到覆蓋所有的地域、運營商,一些偏遠地域或者運營商還是依賴于其他的云服務器廠商,并利用他們的節點進行就近接入。
就近接入就是在云廠商的云主機上部署我們的代理服務器,代理服務器監管傳輸層的數據和PaaS傳輸層的協議,并獲取下一跳地址,也就是用戶就近把數據發送到第一跳加速節點上,加速節點進程接管傳輸層,由傳輸層的頭部獲取下一跳地址,再把數據拋給下一跳加速節點上,然后推送到中轉分發服務器集群,并最終推送到實際的接收端。
3.1.2 網絡探測和智能選路

網絡探測和智能選路方法的具體操作是:當用戶發起接入時,會調度給它一組就近接入的節點。節點的選取是在會話開始前和開始過程中都進行網絡探測,并按一定頻率的機制去發送探測數據包。當節點接收探測數據包時會進行接收信息反饋,基于這些信息反饋將這次探測結果的丟包率、RTT、jitter、BW指標計算出來,基于這些指標進行評分,最終從調度基礎的就近接入節點選取最佳的接入節點。
3.2 多流發布訂閱機制

多流發布訂閱機制可以解決兩個問題:一是用戶可以根據自己的意愿或者能力進行下行接收;二是媒體處理服務器在進行下行QoS控制時會基于探測到的網絡真實的帶寬,幫助用戶智能的選取可以接受的碼流。所以基于發布訂閱機制可以做到兩件事情:一是滿足用戶需求;二是做好傳輸質量。
具體實現是在媒體服務器上有兩個模塊:一是媒體處理模塊,二是Pub/Sub管理器。用戶發布流時會基于可靠信道,發布一條想要Pub流的信令給發布訂閱管理器,發布訂閱管理器會將所有用戶的Pub列表廣播到所有接收端,由所有的接收端根據需要通知發布訂閱管理器訂閱哪一條流,然后發布訂閱管理器會將所有消息同步到媒體線程并進行下行轉發的管理,這樣就實現了發布訂閱功能。

發布訂閱機制發布的內容是:以stream為發布單位,以編碼能力為基本內容。其中編碼能力包括:codec、分辨率、幀率、碼率。
訂閱分為兩個部分:客戶端訂閱和服務器訂閱。客戶端訂閱以stream為訂閱單位,并攜帶訂閱優先級,也就是流在下行接收中的重要性會反饋在訂閱優先級上。另外,當所有的客戶發布訂閱消息后是交由服務器訂閱,它匯聚所有端的訂閱消息,向發布源端發送訂閱消息,同時將訂閱碼率反饋給源端。
右圖顯示的是多流的發布機制是彈性碼率大小流機制,上行發布的大小流并不是固定的分辨率,而是一個可伸展的碼率空間,小流的碼率范圍和大流的碼率范圍都是很大的,這樣的設計是以彈性的碼率針對上行的帶寬,并動態的調整碼率,以進行最佳的上行發布,針對下行所有的接收端來調整碼率,做到最大程度提高用戶體驗。
3.3 傳輸層上下行QoS策略
3.3.1 傳輸層上行QoS策略

對于上行QoS服務器策略主要設計了四種:一是FEC/RED;二是NACK重傳請求;三是PLI/FIR;四是接受信息反饋。
在這里我區分了FEC/RED,因為使用RED是為了增強音頻的保障性。對于視頻,使用矩陣運算的方式生成額外的冗余包去對抗丟包。NACK重傳請求是服務器作為接收端在上行傳授過程中,如果數據有丟失的話會主動作為接收端發送重傳請求進行對抗丟包。
PLI/FIR主要是首幀問題,在偏大量的丟包場景下,也會進行關鍵幀請求去替代NACK請求。
接受信息反饋是記錄上行接受信息,并反饋給源端,源端基于接收信息計算帶寬、網絡指標等進行一個上行的把控。

FEC/RED和NACK重傳請求這兩種設計都是比較普通的對抗丟包的手段。
FEC/RED機制是基于預測丟包,提前產生冗余,對抗丟包。它的優勢是低時延;劣勢是抗丟包效果依賴于丟包預測準確性。NACK/RTX機制是如果丟包已經發生,則基于測量的RTT做重傳請求的控制。它的優勢是不用預測,低時延恢復率高,產生額外流量小;劣勢是產生時延,高時延場景恢復效果差,設計不好容易產生NACK風暴。

針對前兩個設計對抗丟包的特點,網易云信分三個步驟來進行傳輸質量控制:一是建立網絡狀態的觀測器,評估網絡相關指標。二是ARQ手段先行,FEC手段做兜底,也就是盡量利用ARQ對抗丟包,再利用FEC兜底,這樣可以減少帶寬的浪費,做到較好的抗丟包效果,圖中的式子是FEC需要做兜底的丟包率。三是基于接受端反饋以及模塊自檢的策略調整,這一模塊會統計NACK成功率、NACK響應時長和FEC恢復率。

具體做法是:ARQ和FEC并不是割裂的兩個模塊,它們的統籌由抗丟包綜合控制器進行管控,抗丟包綜合控制器最核心的地方是FEC兜底的丟包率的計算公式,它的計算來源于網絡觀測器基于對它的觀測,計算出來的網絡的指標,去生成公式。而且基于服務器端FEC模塊數據統計反饋、服務器端ARQ請求響應模塊數據統計反饋和擁塞控制模塊數據反饋統籌的告知抗丟包綜合控制器。
此外,ARQ模塊和FEC模塊產生的,流量也會統籌的告知抗丟包綜合控制器,最終由抗丟包綜合控制器進行公式的參數調整,最終做到在不影響網絡質量的場景下做到最大的丟包場景。
3.3.2 傳輸層下行QoS策略

下行QoS服務器策略在復用了上行QoS服務器策略的基礎上增加了一些其他的QoS手段,主要有四個模塊:一是設計出下行接收端可彈性接收流組合的方案;二是準確的探測出用戶真實的下行寬帶;三是制定合理的寬帶分配方案;四是進行流量的平滑發送以及擁塞控制。

這張圖展示了四個模塊相互作用的關系。用戶在上行發布了兩天流,要做到下行的最佳體驗,實際接收到的流要匹配用戶的真實帶寬。如果上行發布的都是大流,而用戶的帶寬不足,無法支撐所有大流的支撐,可能就會將某些大流切成小流。
智能訂閱
總體就是首先是發布訂閱管理模塊,基于多流的發布訂閱管理,進行下行的一個可智能選取的方案。其次是帶寬分配模塊,探測出用戶真實的帶寬之后告知帶寬分配器,再結合用戶實際訂閱以及上行流的碼率等數據后,幫助用戶選取最佳的接受組合。最后是總體把控擁塞控制模塊,它的工作是進行下行流量的平滑,另外,它基于其他的設計能夠避免讓網絡產生擁塞,最終讓下行產生最佳的效果。
下行帶寬探測

接下來我將介紹以上四個模塊是如何具體操作的。第一個模塊是發布訂閱模塊。第二個模塊是帶寬探測模塊,它是基于google的BBR音視頻場景下的優化,主要有六點:一是probe_RTT階段的隱藏弱化;二是上行網絡丟包帶寬補償;三是上行網絡RTT突變以及高jitter場景優化;四是下行鏈路抖動自己丟包的優化;五是padding流量的優化;六是快速上探機制的實現。右圖展示了我們優化后的BBR在弱網下的探測效果,基本做了探測準確度為95%以上。
帶寬分配策略

探測出帶寬后如何結合地域關系、上行的實際碼率做下行帶寬的分配。假如下行用戶實際帶寬有2M,訂閱了A、B、C的大流,A、B、C的大流的最大碼率和最小碼率分別是2M、800k,1M、700k,1.6M、1M。那么下行用戶實際帶寬2M是不可以接收所有的大流的。

針對以上問題,帶寬的分配策略為:首先基于現有大小流進行選擇性接收;其次綜合所有下行接收端的帶寬以及預分配結果,反饋到發送端,進行上行流的碼率的壓制。
擁塞控制

擁塞控制模塊主要有四個模塊:一是平滑發送;二是基于流級別的優先級策略以及可選擇性發送策略;三是擁塞避免;四是擁塞緩解。

基于流級別的優先級策略以及可選擇性發送策略中優先級是在實際發送包后制定的包的優先級:重傳包>音頻包>視頻包>被切掉的流>padding包。
可選性發送策略是在實際轉發中基于上行流SVC的碼流,我們制定了SVC時域分層選取:在實際下行轉發時會實時評估各個層總體的碼流,在實際分發過程中會基于當前近程發送隊列的擁塞程度去實時選取應該分發的層。

擁塞緩解的具體工作為:首先下調SVC分層選取,如果擁塞嚴重就切小流,然后基于包級別的優先級發送。其次是如果實際網絡發生擁塞,需要改造BBR的發送周期,即減少1.0倍發送周期。另外,如果數據超發,源端的碼率波動比較大,需要代替網絡主動丟包。
下圖是具體的丟包策略:綠色條柱是應用程序發送隊列的堆積情況,基于堆積的安全閾值和堆積的Trendline這兩個去判斷當前是否需要主動丟包。

上圖是擁塞控制總圖,首先是擁塞避免從BBR獲取匹配的發送數據,當避免不了的時候就需要進行流優先級控制以及SVC分層選取控制,并進行擁塞緩解,最后數據真實發送給用戶時要進行平滑發送。