- +1
基于WebRTC的開源低延時播放器實踐
編者按: 隨著互聯網的發展、流量咨詢費用的下降,直播互動越來越多的呈現在大眾面前。直播帶貨、游戲主播,亦或者是大型網課,在直播中良好的網絡環境與低延時是優質交互體驗的關鍵。在這個各家云服務廠商標準不統一的年代,如何讓低延時直播更加便捷穩定呢?本次LiveVideoStackCon 2022音視頻技術大會上海站邀請到了畢偉老師為我們介紹網易云信的解決方案。
文/畢偉
整理/LiveVideoStack

大家下午好!我是網易云信資深音視頻引擎研發工程師畢偉,今天為大家介紹云信開源低延時播放器的相關內容。云信開源播放器基于WebRTC二次開發,并且現在已經將代碼上傳到GitHub上,感興趣的各位可以關注一下。

接下來我會從直播行業背景、低延時直播現狀、低延時播放器框架、關鍵指標優化和未來展望5個方面逐步介紹。
一、直播行業背景

近幾年直播發展非常迅速,已經滲透到各行各業。舉兩個非常典型的例子,一個是電商直播,另一個是在線教育。
電商直播中,存在主播直播和粉絲互動的環節,觀眾會通過下部的評論問主播相關的問題。如果延時很大,問完問題5到10秒才能聽到主播的回答,會帶來很差的交流體驗,導致用戶沒有及時的收到反饋而直接退出直播間,成交轉化率也較低。
因為疫情的原因,在線課堂十分火熱,尤其是一個老師對應很多學生的大班課。老師在上課中也會和學生進行互動,高延時也會降低互動體驗,影響課堂質量。

這兩個典型場景的主要訴求都是低延時。現在市面上主流的仍然是標準CDN直播,即主播通過RTMP協議推流到CDN,CDN再進行分發,最后觀看者通過HTTP-FLV、HLS、RTMP等協議進行拉流。整個方案基于TCP進行傳輸。因為TCP重傳效率低,ACK反饋延遲導致數據積壓,所以TCP方案的延時基本上在3到10秒。雖然HTTP-FLV/RTMP可以做到3秒左右,但是HLS因為切片的原因,會延長到10秒。綜上所述,TCP方案并不適合用于低延時直播。

現在各大云廠商陸續推出了低延時直播的服務,主要是改造下行鏈路。通過把下行鏈路的RTMP轉換成RTP,再進行UDP傳輸。整個直播過程包含主播端的采集、編碼和發送、CDN分發、播放端接收、解碼和渲染,主播端的延時相對較低,CDN內部走專網專線所以延時也是可控的。整個延時主要是下行TCP網絡相對不太可控造成的,需要播放器加大緩沖區對抗網絡抖動。正因如此,TCP方案端到端網絡延時較大。事實上,改造下行網絡帶來的收益是最大化的。只需要將下行改為UDP傳輸,整個端到端延時就可以降低至1秒左右。現在市面上基于UDP的方案也有很多,例如QUIC、SRT、WebRTC等。目前WebRTC方案非常火熱,大多數瀏覽器都支持,生態也很不錯,所以云信也選擇WebRTC作為低延時直播的基礎。

云信也推出了自己的低延時直播服務。這張圖是云信整個低延時直播的系統流程圖。上行采用的是RTMP推流,通過改造下行鏈路,中間建立一張低延時傳輸網WE-CAN,主播推流到源站,源站再轉推到WE-CAN進行分發。拉流端在邊緣節點進行拉流。從云信傳統的CDN直播轉入到云信的低延時直播十分簡便,只需要再重新申請一個低延時拉流的域名即可。
二、低延時直播現狀

傳統CDN直播能快速發展,和一些優秀的開源項目密不可分,例如FFMPEG、OBS、 VLC。目前的低延時直播仍然存在以下幾個問題。首先各大云廠商采用的都是私有協議,沒有標準化。另外,在使用這些協議時需要強綁定對應的SDK。在接入多家云廠商的服務時需要接入多個SDK。多個SDK對現階段移動端APP的包大小十分不友好,不利于低延時直播的大規模推廣。為此,云信推出一個開源的低延時播放器,開放信令交互,可以用一套SDK對接多家低延時云服務廠商。
三、低延時播放器框架

這是云信低延時播放器的框架。云信低延時播放器是一個傳輸層的SDK,最底層是WebRTC。因為我們意在打造一個通用版的SDK,所以我們將WebRTC全量包入,通過PeerConnection層接入,里面是一些主要模塊,例如JitterBuffer、NetEQ、RTP/RTCP、Transport等。中間是RtdEngine層,主要作用是對WebRTC進行封裝,包含API、引擎創建、信令建連、 媒體數據的接收回調等。最上層是FFMPEG插件。直播已近發展了數些年,各廠商都有一些存量的播放器,市面上大多數播放器都是基于FFMPEG開發,為了降低用戶SDK接入門檻,云信將API封裝成FFMPEG插件,擴展了輸入流格式——ff_rtd_demuxer,對應的云信拉流地址協議頭是“nertc://”。在FFMPEG插件里注冊協議頭,拉流地址替換以后就可以接入云信的低延時鏈路。如果要接入其他云廠商,只需要替換拉流協議頭,同時將協議頭添加到插件中即可,播放器代碼不需要任何的改動。

下面介紹云信低延時播放器的交互流程。通過采用標準SDP+ICE的交互方式,以達到通用SDK的目的。客戶端創建Offer SDP,通過HTTP POST到服務器,服務器響應Answer SDP,信令交互完成后進行ICE,ICE建連成功后服務器會發送媒體數據給播放器。

SDK的底層有一個Transport模塊,建連成功后會收到服務器發送來的音視頻數據,音視頻數據包會分開傳送。視頻的數據包會送到JitterBuffer,音頻數據包會送到NetEQ。視頻的RTP包會在JitterBuffer中進行排序,組幀、重傳等操作,之后會回調到RtdEngine。整個SDK內部不對視頻進行解碼,而是交由上層播放器做。視頻數據組幀完成后回調時,為了不破壞原有的結構,云信模擬了一個解碼線程,繼承了WebRTC原來的VideoDecoder基類,模擬從JitterBuffer取數據的過程。取到的視頻幀放在RtdEngine中,播放器通過插件從RtdEngine讀取。音頻在NetEQ中會被解碼,之后回調PCM數據。同樣,我們也在RtdEngine中模擬一個playout 線程,讀取PCM數據到RtdEngine中,供播放器讀取。大家可以注意到,我們只對音頻做了解碼,視頻沒有做。由于延時和緩沖區大小相關。播放器上層有一個緩沖區,JitterBuffer和NetEQ中也有緩沖區,多個緩沖區會對延時的控制帶來難度,尤其是播放器上層的延時。我們希望將播放器上層的緩存區降為0,所有數據都在JitterBuffer和NetEQ中管理。這里音頻解碼是為了復用NetEQ中音頻加減速的能力,更好地控制延時。

上面是傳統CDN直播播放器的結構。通過FFMPEG從CDN中拉流,放到緩沖區中,然后進行解碼、音畫同步和渲染等。緩沖區一般設置為3到5秒。如果接入云信的低延時SDK,只要把云信的SDK編到FFMPEG中,作為FFMPEG的第三方插件,后續的整個流程不需要任何的改動,只需要把緩沖區降為0。所有的緩沖區都是由SDK中的JitterBuffer接管。拉流時只需要使用對應的低延時拉流地址,就可以接入到整個低延時拉流鏈路上。由此可見SDK的接入十分簡便,同時可以復用原有FFMPEG拉流流程。原有播放器的業務不需要進行任何的改動。

下面具體介紹一下播放器的SDK接入。云信通過作為FFMPEG的插件,擴展AVInputformat格式,實現了如下接口rtd_probe、 rtd_read_header、 rtd_read_packet、 rtd_read_close等。在rtd_probe中添加nertc://的拉流協議頭,FFEMPEG可以根據其中的分數探測最終的協議。如果需要接入其他低延時廠商的服務,就可以在rtd_probe添加對應廠商的協議頭。使用對應的拉流協議頭就可以走進云信的低延時模塊中。但僅僅走進模塊還不夠,后續還需要去和云廠商對接,了解其信令交互,自己進行一些對接上的調整即可。

我們提供了一個插件的源碼,稱之為rtd_dec.c。只需要把rtd_dec.c拷貝到FFMPEG的libavformat文件夾下,修改對應的腳本Makefile即可。另外,需要將生成的AVInputFormat類型ff_rtd_demuxer注冊到FFMPEG中,使其能夠認識。在allformats.c中添加AVInputFormat格式,FFMPEG重新編譯。除此之外還有另外一種格式,即不編譯FFMPEG ,直接調用FFMPEG接口av_register_input_format()。這種方法僅對于低版本的FFMPEG支持,對于高版本的不太支持。所以我們統一采用allformats.c中添加libavformat格式,FFMPEG重新編譯的方法。

還有一部分播放器是非FFMPEG播放器。云信也提供了一套API。具體操作可以參考rtd_dec.c插件調用API的流程。
四、關鍵指標優化

下面來介紹關于直播指標的一些優化。分別是首幀優化、延遲優化和抗性優化。
1、首幀優化

首幀分為以下幾個過程。用戶點擊播放之后進行建連,隨后收到數據,再進行解碼渲染。云信有一張WE-CAN傳輸網,在全球的主流國家和重點省市都進行了布點,大多數地區的用戶都可以就近接入。同一地區的用戶會盡量調度到同一個機房,減少回源。現階段低延時拉流還是復用RTMP的上行,RTMP推流到CDN,再進行回源拉流。如果命中率較低,多次回源非常耗時,會大大影響首幀。

直播和RTC存在一些區別,直播在接入時沒法請求關鍵幀等,如果服務器不緩存GOP,在訂閱流時,服務器因為沒有關鍵幀可以發,需要等待下一個關鍵幀到來才行。這會對首幀帶來很大的影響。如果服務器緩存前一個GOP,訂閱流時能立即發送數據。
以上都是服務器的優化。因為云信是一個通用的播放器,媒體建連會采用標準的ICE。ICE中存在DTLS,對于直播來說大部分場景不需要進行加密,可以關閉DTLS 減少建連耗時。
建連完成之后就可以收媒體數據包。網絡中可能存在一些丟包的情況。檢測丟包一般會通過序列號是否連續進行判斷。但是當第一個關鍵幀最前面幾個包丟掉,往往很難檢測出來,或者能檢測出丟包,但是不能判斷前面丟了幾個包,就不能確定如何重傳。關鍵幀組幀不成功,會導致整個GOP都難以進行解碼。有些用戶的推流GOP很大,首個關鍵幀組幀失敗會導致首幀時間非常長,這對用戶體驗影響很大。
有兩個方法解決上述問題。第一個方法是拉流時服務器通過信令告知第一個序列號是多少,將拿到的序列號和收到的第一個包序列號進行比較,就能知道中間有沒有包丟失,丟了幾個包。就可以在收到包時立即進行重傳。第二種方法,收到第一個RTP包,不管前面有沒有丟包,直接往前重傳10~20個包。
最后一個優化方式是首幀快速出幀。組幀完成以后出幀有一定的等待時間,為了快速出幀,將前面幾幀等待時間設置為0,使得快速接觸到視頻包進行解碼渲染。
通過以上幾步的優化,整個首幀可以控制在200ms以內。
2、抗性優化

抗性優化第一個方面是NACK。WebRTC原生的重傳效率較低,重傳間隔在100ms左右,對于低延時直播來說,整個端到端延時也只有幾百毫秒,因此這樣的重傳效率是不可接受的。我們對重傳的間隔進行了優化,會根據實際的RTT進行重傳。另外,對于重傳的優先級,服務器會響應不同幀之間的優先級。
第二個方面是JitterBuffer、NetEQ。在整個播放過程中會實時監控網絡質量,例如丟包率、RTT、Jitter等。有了丟包率就可以算出需要多少次重傳才可以將這個包重傳回來,根據重傳次數和RTT,大致能估算出需要多少JitterBuffer來應對該次網絡抖動,實時感知和調整。
第三種方式是添加冗余包。目前云信實現了標準RED。一開始我們打算做RSFEC,但RSFEC需要和服務器進行配合,對于我們的通用播放器不太適合。之后可能會把整個RSFEC鏈路流程建立好,具體實現通過插件的方式對接不同的云廠商。
3、延時優化

在起播階段,服務器會發送GOPCache中的數據,導致起播階段延時較大。整個播放過程中延時最高的時候就是在起播階段。播放器通過加速播放來追趕延時,加速速度過快不僅會影響我們的感官體驗,一些低端的機器還會因為解碼速度不夠導致無法加速,長時間處于高延時的狀態,這樣就違背了我們的低延時理念。為此云信采用了服務器丟幀的策略。假如在訂閱流的時候是P幀,服務器發送緩存數據幀到某個P幀時,服務器收到了下一個關鍵幀,這個時候服務器會直接從當前P幀跳躍到下個關鍵幀,P幀和關鍵幀之間一段數據全部丟掉,重編關鍵幀及其后面幀的時間戳,保證時間戳連續。由于時間戳連續,所以播放器感知不到跳幀,只是起播階段畫面有一個小跳躍。通過上述的方法可以在起播階段快速追趕上延時。
4、功能升級

WebRTC一開始并不是用來進行直播,它對直播有一些限制,比如音頻只支持OPUS。現在低延時直播很多都是復用了RTMP上行,RTMP推流音頻采用AAC。如果播放器不支持AAC,服務器就需要進行轉碼,例如AAC轉OPUS。轉碼不僅會帶來音質的損失,還會帶來延時。所以我們在開源播放器中支持了AAC。
另外WebRTC不支持44.1K采樣。云信也進行了44.1K采樣的支持。
WebRTC不支持H265。現在分辨率越來越高,H265的壓縮效率比H264高一些。云信也完成了對H265的支持。
WebRTC不支持多Slice。在播放Slice流時WebRTC在組幀時會出現幀完整性判斷錯誤的情況,導致花屏現象的出現。云信也對多Slice進行了支持。

這是GitHub上開源播放器的DEMO。我們進行了一個測試。左邊是OBS推流,利用OBS將其配置成低延時的模式,右邊是拉流延時的對比。jitterBuffer配置成200ms,端到端延時在600ms左右。具體的延時可以根據自己的業務需求進行jitterBuffer調控,jitterBuffer下調一點,延時也會降低一點,反之亦然。

除了開源播放器,云信也有一個閉源的播放器。雖然閉源播放器也是基于WebRTC開發,但是因為不需要考慮通用,所以并沒有使用整個WebRTC,只抽取其中的部分模塊,例如JitterBuffer、NetEQ、Transport、NACK等模塊。再進行相應的封裝,包體積在iOS單架構增加550k,Android單架構增加1M。
信令協議方面,開源播放器使用的HTTP,HTTP在弱網環境下經常連接不上。我們采用KCP協議,增加冗余的方式,提升建連成功率。
首幀方面,我們簡化了信令流程,提升建連速度。
弱網抗性中,得益于閉源包,會存在很多私有協議,QoS策略較為豐富。可以支持FEC、或者反饋支持不同分級的重傳,可以抗住100ms+50%的丟包。
閉源播放器和RTC可以進行融合,支持連麥互動。
五、未來計劃

5月份云信開源了windows端,之后我們將實現移動端的支持。移動端目前正在內測,內測結束后就會發布到GitHub上。未來我們也會持續優化各項播放指標,以及推行播放器標準化。也歡迎大家一起在開源播放器上開發,提供寶貴的意見。另外,云信正在構建一個低延時推流工具,未來也會開源,現階段的方案是做成OBS插件,以提供全鏈路的解決方案。
謝謝大家!我的分享就到這里。
本文為澎湃號作者或機構在澎湃新聞上傳并發布,僅代表該作者或機構觀點,不代表澎湃新聞的觀點或立場,澎湃新聞僅提供信息發布平臺。申請澎湃號請用電腦訪問http://renzheng.thepaper.cn。





- 報料熱線: 021-962866
- 報料郵箱: news@thepaper.cn
互聯網新聞信息服務許可證:31120170006
增值電信業務經營許可證:滬B2-2017116
? 2014-2025 上海東方報業有限公司