技術乾貨 | 基於標準 WebRTC 低延遲直播的開源實踐

網易雲信 發表於 2022-01-14
導讀:2020年,新冠疫情爆發並席捲全球,對包括中國在內的全球經濟造成了巨大的衝擊,同時深刻影響了社會生活。在這一背景下,以消費市場上轟轟烈烈的直播電商為引爆點,直播行業再次掀起熱潮。在中國企業數字化轉型的浪潮中發展了十年之久的企業直播服務市場,也順勢進入高速發展階段。

圖片

文|洪順迪 網易雲信流媒體 Server 端研發工程師

1 典型的直播架構

圖片

在典型的直播架構中,左邊是推流客戶端,協議上才採用 RTMP 上行;右邊是拉流客戶端,支援不同的拉流協議拉流,比較常見的是:RTMP、FLV、HLS

1.1 現有架構的優點

這套框架很好的利用了 CDN 廠商或者說雲廠商的能力。儘管拉流協議沒有統一,rtmp/flv/hls 等拉流協議作為比較成熟的流媒體協議,經過多年的發展,得到了各 CDN 廠商廣泛支援。在雲端能力的支援下,服務端併發能力和拉流端加速能力大大增加了,直播行業蓬勃發展。

2 低延遲直播的現狀

圖片

在直播領域中卡頓和延遲就像是天平的兩端。延遲做的越短,則卡頓越高;延遲越長,卡頓就越少。

一般場景下都是客戶端用更大的 buffer 時長,犧牲延時來滿足流暢性。隨著行業的發展,某一些應用場景對延時時間的要求越來越苛刻,比如體育比賽直播,教育場景下老師與學生間的互動等,這些場景下常見的直播流媒體協議的缺點就體現出來了。

一般 rtmp 協議直播延時在 3-10s,如果經過層層 CDN 的快取和轉發,超過10秒也是常有的事,flv 和 hls 協議的延時更高。就拉流端來說,延遲的很大一部分源自網路傳輸:rtmp 在傳輸媒體前的 tcp 3次握手和 c0/c1/c2 握手協議,無端引入了好幾個 RTT 的延遲;由於 rtmp/flv/hls 的傳輸層都是基於 tcp 協議,在網路不穩定的情況下,受限於 tcp 協議的擁塞控制不能充分利用網路頻寬,客戶端為了保持流暢性,只能加大快取時間,因此更進一步加大了延遲。\
 

在認識到現有流媒體直播協議的侷限性後,各大友商也紛紛推出了自己的低延時直播,較好的起到了對抗弱網和加快首屏的作用。但目前大都基於私有的信令協議和私有的 UDP 流媒體傳輸協議,各大雲廠商無法互相相容,這就限制了低延遲直播的大規模發展。

3 基於標準 WebRTC 的低延遲直播的開源實踐

網易雲信一直在探索如何做一個開放的低延時直播方案, 將來各家雲廠商也能夠比較方便的實現,就像現有的 rtmp/hls 協議一樣,推動整個直播行業低延遲化。要實現這種方案需要做以下兩件事情。

  1. 開放的信令協議: 信令協議需要滿足絕大多數廠商的媒體協商需求,同時又能儘可能的簡潔。
  2. 開放的媒體協議: 媒體傳輸協議需要滿足在各大廠商間能夠通用,在這之上的 QoS 能力也需要開放,不能是私有的。

依據上面的要求我們選擇了 RTC 領域成熟的解決方案——WebRTC。下圖是我們現在的實踐架構。

圖片

上圖中 WE-CAN 是網易雲信的全球加速 RTC 大網,媒體在 Server 間的網路傳輸依賴 WE-CAN。

邊緣媒體伺服器從 CDN 拉流到 WE-CAN 大網邊緣節點,再從 WE-CAN 大網邊緣節點傳送給客戶端。

3.1 開源的信令協議實現

信令協議上採用 HTTP+SDP 的方式,即客戶端 POST 一個 SDP Offer。 

{
    ...
    "pull_stream": "nertc://your.domain.com/live/testname"
    "sdp": "v=0\r\no=4611731400430051336 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\n......",
    "type": "offer"
}

然後媒體伺服器經過協商返回 SDP Answer。

{
    ...
    "code": 200
    "sdp": "v=0\r\no=4611731400430051336 10000 1 IN IP4 0.0.0.0\r\ns=-\r\nt=0 0\r\na=ice-lite\r\n......",
    "type": "answer"
    ...
}

3.2 標準的 WebRTC 媒體協議

客戶端拿到 SDP Answer 後,就是標準的 WebRTC 媒體互動流程:ICE、 DTLS 加密連線,接收 RTP 流媒體。

下面是一個基本的 Web 端的拉流程式碼 Demo:

self.pc = new RTCPeerConnection(null);

self.pc.addTransceiver("audio", {direction: "recvonly"});
self.pc.addTransceiver("video", {direction: "recvonly"});

var offer = await self.pc.createOffer();
await self.pc.setLocalDescription(offer);

var session = await new Promise(function(resolve, reject) {
    var data = {
        pull_stream: streamId, 
        type: "offer", 
        sdp: offer.sdp
    };
    
    $.ajax({
        type: "POST", url: apiUrl, data: JSON.stringify(data),
        contentType:'application/json', dataType: 'json'
    }).done(function(data) {
        resolve(data);
    });
});

await self.pc.setRemoteDescription(
    new RTCSessionDescription({type: 'answer', sdp: session.sdp})
);

3.3 開源的 Native 媒體播放器

為了讓 Native 客戶端能夠更方便的接入 WebRTC,我們同樣開源了一個整合了標準 WebRTC 的低延遲直播播放器:We-Can-Player,只要輸入流地址,就能實現接收 WebRTC 流播放。

3.4 客戶端的架構:

圖片

 

只要廠商實現了類似的協議,用這個播放器稍作修改就可以拉到 WebRTC 的流。從架構上可以看出媒體伺服器和拉流客戶端之間的互動大都是基於標準的 WebRTC,沒有私有的 RTP 擴充套件和私有的 QoS 協議, CDN 廠商甚至可以沒有自己的 RTC 大網,只需在 CDN 邊緣節點實現標準的 WebRTC 閘道器+一個簡單的 HTTP Server 就可以擁有同樣的能力。

為了優化直播體驗,我們還在 Server 端做了大量的優化。

4 優化直播體驗

4.1 首屏優化

4.1.1 GOP 快取首屏優化

直播領域有兩大指標:首屏和流暢性。 假設使用者推流端的 GOP 的是5秒,在某些情況下,拉流端要等接近5秒才能收到第一個 I 幀,首屏才能渲染。這對直播來說是不可接受的。

解決方案是在媒體伺服器裡做 Gop 快取,快取最近1-2個 Gop 的媒體包在 Server 端,當客戶端和媒體器媒體連線成功以後,先傳送 Gop 快取裡面的媒體包,再傳送當前的媒體資料。客戶端收到媒體包後,需要根據一定的策略對齊音視訊包,再加速追幀。

在具體的實踐過程中,要注意 Gop 快取大小、客戶端的 Jitter buffer 大小的配合、Gop 快取裡音視訊的對齊、不同的推流端不同的 Gop 長度的適配等情況。

4.1.2 Pacer 平滑傳送

如果推流端設定的 Gop 比較大,當拉流客戶端媒體連線成功後,會一股腦的給客戶端傳送全部的 Gop 裡資料,可能造成客戶端緩衝溢位以及其他問題。這時候就需要 Server 的 Pacer 平滑傳送發揮作用了。

在具體的實踐過程中,要注意 Pacer 的追幀速率與客戶端追幀速率的配合。

4.2 延遲優化

4.2.1 WE-CAN 大網

前文提到了直播行業之所以能蓬勃發展,在技術方面 CDN 廠商的雲端能力起到了很大的推動作用。CDN 加快了邊緣節點的回源速度,邊緣節點又加快了拉流終端的接入速度。

從上面的架構圖可以看到,為了加快回源速度,回源媒體服務的選擇會盡可能的接近 CDN 的區域中心節點;為了優化客戶端的接入效能,拉流媒體伺服器也要儘可能的接近拉流客戶端,因此媒體 如何迅速地從回源媒體服務傳輸給拉流媒體服務就至關重要。

而 WE-CAN 就承當了這個職責, 他是雲信內部開發的一套高效全球傳輸大網,能加速全球任何兩個媒體伺服器之間的網路傳輸。從某種意義上來說,他起到了推動 CDN 加速傳輸的作用,不過 CDN 的原理是層層 cache,WE-CAN 靠的是路徑優化。

4.2.2 全 SFU 架構的媒體伺服器

設想兩個主播的互動,如果我們加入 MCU 的話必然會引入快取,導致首屏和延遲都加大,所以 RTC 大網內部都是基於 SFU 架構做的佈局。

4.2.3 全鏈路延時監控

如何全鏈路的監控拉流測引入的延遲? 媒體流在 WE-CAN 大網裡經過層層轉發,如果任何一段路由引入不必要的延遲,就會影響最終的低延遲效果。我們的做法是在 RTP 頭裡加上一個 extension,記錄 RTP 包到達每個機器的毫秒級的 NTP 時間後,在轉發給客戶端的最後一個媒體伺服器上彙報每跳路由的時間消耗以及邊緣伺服器與客戶端之間的 RTT 時間,在最終發給客戶端的客戶端 RTP 中再剝離這個 extension。儘管各機器的 NTP 時間沒有絕對對齊,但依賴 WE-CAN 大網的全域性 NTP 時間同步功能,差距能夠控制在 1ms,這個精度足夠在工程實踐中發揮監控作用。

5 效果和後續工作

第一階段在網路 QoS 方面暫時只支援 ARQ 和 Opus 的 inband-FEC 能力。由於 WebRTC 原生支援基於 XOR 的 FEC 能力,在抗連續丟包方面很弱,所以暫時沒有開啟 FEC,但較 RTMP 有了巨大的改進。實現了在 50% 丟包條件下,控制在2秒左右的延遲,200~400ms的首屏。

我們後面的計劃包括:加入更多的 WebRTC 標準 Qos 能力(包括 FEC 在內);推流側的 WebRTC 改造能力等,具體的開源內容可以持續關注【智企技術+】公眾號,後續我們會持續更新開源相關內容及開源地址。

技術乾貨 | 基於標準 WebRTC 低延遲直播的開源實踐

作者介紹

洪順迪 ,網易雲信流媒體 Server 端研發工程師,負責網易雲信流媒體 Server 端的開發工作。