摘要: 在上週落幕帷幕的多媒體領域技術盛會——LiveVideoStackCon音視頻技術大會上,阿里雲的高級技術專家李剛進行了《下一代低延時的直播CDN》技術分享。主講人李剛,多年關注在CDN這個領域,早期主要研究和cache服務器緩存以及流媒體相關的技術, 專一CDN文件分發、圖片與大文件下載等業務。算法
在上週落幕帷幕的多媒體領域技術盛會——LiveVideoStackCon音視頻技術大會上,阿里雲的高級技術專家李剛進行了《下一代低延時的直播CDN》技術分享。主講人李剛,多年關注在CDN這個領域,早期主要研究和cache服務器緩存以及流媒體相關的技術, 專一CDN文件分發、圖片與大文件下載等業務。從2015年開始負責全面構建阿里雲CDN直播系統,對流式長鏈接的分發有很深入的理解。今天主要分享內容是阿里雲自研低延時直播系統在構建時,遇到的一些技術難點與實踐。瀏覽器
分享從當下直播技術回顧、低延時直播技術思考、低延時直播技術實現、展望四個部分展開,本文爲演講原文,但願對直播CDN相關從業者有必定的幫助。緩存
1、直播場景回顧
下圖列舉了當下存在的一些常見的直播場景。安全
秀場直播是國內最先出現的直播形式,在各個直播平臺上是比較常見的。
遊戲直播,像鬥魚、虎牙、戰旗等直播平臺都是比較典型的遊戲直播平臺,遊戲直播對碼率要求比較高,觀看人數也多,因此它也是流量貢獻最大的直播形式。
移動直播是最近一兩年比較火的直播形式,比較明顯的特色就是推流和播放比較容易, 經過手機APP就能夠進行直播,因此手機直播通常也是推流數最多的直播形式。
活動賽事直播,像今年夏天的世界盃,這類直播通常對交互要求不高,因此通常都是HLS播放形式,延遲相對其餘都會多一些。
答題直播是今年年初左右出現的新型直播形式,每場直播的時間不長,突發流量比較高。
這些直播場景,在國內主要用HTTP-FLV和RTMP這種傳輸形式,這兩種傳播形式通常延時在3-5秒,固然這也會受視頻自己GOP影響, 移動直播通常是1-2秒時間間隔,因此控制在3-5秒是比較容易的。可是遊戲直播關鍵幀延時通常在8-10秒,因此遊戲直播的延時更大一些。而活動賽事直播通常不會強調互動性,對流暢度比較高,因此會通常選用HLS,延時在10秒以上。服務器
2、低延時直播需求
3~5秒延時對於多數常見的直播形式通常問題不大, 可是對於某些場景效果會不好。網絡
對於連麥場景影響是最明顯的, 連麥超過1秒,對話可能就沒辦法維持下去了。如今通常直播平臺的連麥直播需求都會藉助第三方的連麥服務,而後再推給直播CDN廠商。socket
在答題直播場景下, 通常都要求在一段時間內用戶提交答案,若是有各別用戶延遲比較大,這樣對用戶是不公平的。雖然直播平臺仍然使用FLV的傳輸形式完成答題直播,可是基本都會採用SEI插幀等方法來解決時間同步問題, 須要平臺的端和直播CDN作一些配合來完成。ide
除了連麥、答題場景以外,像在線課堂、在線拍賣等場景由於涉及到實時性的互動,對延時的要求也比較高。優化
從對業務的支持層面來看, 僅僅有RTMP、FLV這種3~5秒延時以上的直播形式已經不夠了, 須要對更低延遲的直播業務進行支持。從技術的角度來看,國內經常使用的FLV、RTMP這種直播手段,自己是Adobe本身的標準, 並且很快會中止對flash的維護, 另外一方面WebRTC技術的興起,Chrome、Safari等瀏覽器也都進行了支持,所以也須要對新的技術有一些調研和準備。阿里雲
基於對於這些問題的思考, 阿里雲CDN也開展了對低延時直播技術的研發。
3、短延時直播VS實時音視頻通訊
簡單介紹下實時音視頻通訊和短延時直播的區別:
使用WebRTC主要用於解決實時音視頻通話的需求,必然對延遲要求很是嚴格, 一個會議室中參與的多方能夠進行視頻通話, 每一個參與者能夠看到其餘參與者,也能聽到其餘參與者說話。每一個參與者既有推流,又有播放,數據是雙向的。因此參與人數不會太多,通常不能超過20個。
短延時直播仍然是直播業務類型, 只是延時比較低, 短延時直播的業務模型相對簡單, 數據單向傳輸,一個主播推流,參與的播放者人數沒有限制,上百萬均可以。
4、技術選型的思考
在作短延時直播項目的時候,咱們在技術選型上作了一些思考。
首先,是必需要兼容已有直播業務和技術棧,由於阿里雲直播CDN系統已經有了不少客戶,短延時直播須要從現有直播的業務上慢慢衍生, 可讓客戶在短延時和常規直播手段進行切換, 這也是處於業務穩定性的考慮。
第二,對於直播來說, 秒開是一個很重要的指標,咱們後面詳細展開。固然卡頓也是重要的指標,由於WebRTC在移動端擁塞控制和重傳方面有一些處理,因此卡頓率方面不會比TCP差。
第三,對齊到WebRTC會是最終的結果, 畢竟用戶可以使用H5就能夠直接推流或者觀看直播, 更方便客戶的接入和使用。但因爲完整的支持WebRTC要解決加解密、打洞、音頻格式等問題, 因此前期考慮只使用WebRTC中的一部分技術,完整支持WebRTC會是二期的工做。
5、TCP的可能性
已有的業務,不管是圖片、大小文件、點播、直播,這些都是在TCP通訊基礎上實現的,因此短延時直播在開展的時候咱們就思考了TCP的可能性。
咱們對於短延時的目標定義爲從端到端800毫秒之內,一場直播的延遲來自於推流端延遲、CDN產生的延遲、播放端延遲這三個方面,不少客戶會關注CDN產生的延遲,咱們也對數據進行過統計,CDN從入到出所產生的總延時,全網平均不到100毫秒,晚高峯平均也不超過200毫秒。而從經驗角度來看,播放端的延遲會比較嚴重,主要是兩方面,一方面是開播時候卡前一個關鍵幀所帶來的延遲,另外一方面若是CDN服務器到播放端有抖動,累積的延遲會愈來愈多。
以前有一個彩票直播業務的客戶, 由於客戶擔憂用戶懷疑刮獎的時效性, 因此對延時要求就很是苛刻, 客戶的端進行延遲優化, 延遲也能夠作到1秒內。
因此,一開始咱們有了這樣一個結論,網絡正常的狀況下,使用現有的RTMP、FLV進行分發,延遲也能夠作到1秒之內。
可是現實狀況是網絡是不可能出現不丟包的狀況。當網絡抖動出現丟包的時候,TCP是ACK確認機制的,也就是發送方發送一包以後,必定要等過對方迴應,纔會繼續發。若是說網絡一旦出現丟包,就會在一個RTO以後重傳,RTO的值和RTT有關,而且RTO的最小值是200ms。若是想保證流暢性,你的播放端必定要至少能容忍200ms以上的抖動,但播放端的jitbuffer太多又沒法知足低延時的要求。
這裏對一下比WebRTC中RTP傳輸使用的NACK機制,NACK的丟包反饋更加及時,若是網絡是偶然性抖動居多的時候, NACK機制效果更加好。這裏咱們也作了一個統計,全網平均RTT小於15ms,若是CDN節點覆蓋足夠好的狀況下,延遲理論上會很低。以1.5Mbps碼率的音視頻流舉例,每秒鐘100個包,包和包之間就是10ms的間隔。若是當第二個丟包出現的時候,第三個包對方接收到了,就能夠立刻知道第二個包是丟掉了,就能夠馬上返回一個NACK,進行重傳。在這種極限狀況下,重傳間隔就是25ms,相比以前TCP的200ms是一個質的提高,想知足絕大部分播放延遲在800ms之內纔有可能。
另外,使用TCP的話,無效傳輸無法避免,。TCP是採用socket buffer進行通訊,數據也是從應用層先進入socket buffer再分發。對於RTMP或FLV的分發來講,假如某一幀的數據的一部分已經進入了socket緩衝區, 那麼也必須將這一幀剩餘的數據發送出去, 若是剩餘的數據不發出去的話, 播放端會出現解析錯誤, 斷開鏈接, 這個體驗會不好。
而在網絡在出現波動的時候, 有可能這socket buffer裏面的數據好久以後才能傳送到對方, 而在短延時直播的場景下, 這些socket buffer裏面和應用層過久的數據再發送給播放端已經沒有意義,也就是說會產生不少無效的傳輸。
6、自研短延時直播方案
基於這些考慮,咱們最終採用瞭如下的方案。WebRTC是當下短延時流媒體的傳輸比較熱門的技術, 因此在實現短延時直播的同時會考慮使用WebRTC相關的一些技術。原有的RTMP, FLV, HLS這些使用TCP,新增阿里自研私有ARTP短延時方案,最終會支持WebRTC,ARTP和WebRTC使用UDP傳輸。
在研發以前,咱們會對各項部署作一些思考。
1.端口問題
WebRTC的默認工做方式SFU服務器會爲每一個參與者須要爲其餘每一個參與者分配一個端口, 必定程度上來講是經過不一樣的端口來區分參與者。而CDN從安全的角度來考慮, 不會採起這種方式, 因此從一開始就認定在短延時直播這個場景下,咱們會使用固定端口的方式來提供服務。下圖是最終的方案,流媒體服務器會開幾個端口分別支持不一樣播放形式的訪問,容許用戶的端進行的靈活控制。
這裏講一下播放秒開的問題, 若是採用標準的WebRTC方式,那麼須要通過下圖這樣幾個環節。
這樣下來對於直播秒開的體驗來講就會不好,因此在實現低延時直播方案時針對這個問題須要進行優化處理, 去掉一些沒必要要的環節。
CDN服務器自己是有公網IP和端口的, 播放端沒有獨立的公網IP和端口,若是是像WebRTC這麼實現的話, 服務器把數據直接傳給播放端,那麼必然涉及到打洞探測的問題,因此若是想要達到秒開效果的話,就不能使用WebRTC的這種方式, 須要讓播放端先給服務器發送請求, 讓本身所在的NAT網關創建起映射以後,服務器再把數據吐給客戶端時就OK了。
上圖就是最終的時序圖,使用的是比較簡單的應答模式。沒有了TCP的三次握手環節,因此秒開效果必定比FLV、RTMP更好。同時,客戶端直接發起播放請求,請求包長度儘可能控制在一個UDP包內,不要出現一個請求兩個包的狀況。
國內直播平臺大部分仍是使用h264和AAC,因此咱們也是首先支持這兩種格式,其餘音視頻格式像HEVC等也是咱們後續要支持的格式。
3.RTP報文
PT字段是載荷類型,sequence number是包序列號,發送端切片的時候,寫好序列號,接收端依據這個序列號進行數據的還原。並且在重傳發生的時候,還依靠這個序列號進行NACK的反饋。時間戳對流媒體傳輸很是重要,播放器依賴它進行解碼和同步。SSRC用來識別不一樣的身份,同一個IP和端口被NAT從新分配的時候, SSRC識別出這是一個不一樣的鏈接。
前面講過使用TCP傳輸的時候,網絡抖動出現堆積時,須要丟幀,可是必定是丟完整的幀,不能丟片斷。那爲何RTP場景下爲何沒有這個問題?以H264爲例,RTP在封裝的時候,若是NAL單元小於MTU,那麼咱們認爲一個RTP包能夠完整封裝一個NAL單元的,若是出現丟幀,那麼咱們認爲缺乏的是一個完整的NAL單元,對後面NAL單元解析是沒有問題的,不會出現數據錯亂。
若是一個NAL單元大於一個MTU的時候,假設一個NAL單元須要三個RTP包封裝,無論丟到哪個仍是所有丟掉,接收端均可以標識出這個NAL單元,不會影響其餘NAL單元的解析。
4.平滑發送機制
如今採用的混合擁塞算法,基於丟包率和基於延遲進行碼率控制。標準的作法是,當播放卡頓時,會讓發送端降碼率。
從兩個方面來看,當推流端上行出現抖動的時候,服務器會反饋數據包,把碼率自動降下來。當播放端出現下行抖動的時候,一種是輸出轉碼流,另外一種是讓主播推兩路流上來,讓播放卡頓的用戶換到低碼率。
5.播放端上的優化
第一階段是開播階段,得到GOP數據的時候,若是端不作處理的話,必定會有一個延遲。因此在這個階段,播放端必定進行快進的操做,縮短延遲。第二階段是當網絡出現抖動的時候,會慢慢放大buffer的長度,來必定程度上適應抖動,提升流暢度。第三階段,當網絡恢復的時候,咱們能夠適當快進,減少buffer,把進度趕回來。也就是說這個buffer大小是動態變化的。
6.RTC內部打包機制
H264和AAC數據會在內部先進行切片,放到平滑發送隊列再發送給對端,同時重傳包也會進入平滑發送隊列, 而且會放到平滑發送隊列的隊首位置。
7.FEC冗餘傳輸
FEC是靠冗餘傳輸,來提升容錯率。關鍵幀10%冗餘率, 非關鍵幀5%,根據丟包判斷出網絡情況,動態調整冗餘度。
8.UDP傳輸注意事項
UDP無鏈接,也就沒有TCP的鏈接斷開時的揮手確認鏈接關閉的機制。那麼對於主播來講,若是出現斷開,而後短期再重推的話就會遇到問題,由於CDN會認爲前一個推流鏈接還在,新的推流鏈接推的是同名流,會拒絕掉新的鏈接,主播也會反饋沒法推流。對於播放來講,雖然沒有同名流問題,可是若是播放端再也不觀看,CDN服務器會仍然將數據發送給指定的IP和端口,這就產生了不少無效的傳輸。最終會反映到流量和計費日誌上。因此採用RTCP報文的方式,對於播放和推流鏈接的斷開進行通知,節省資源消耗, 流搶佔等問題。
9.探活策略
除了對於正常關閉進行主動通知以外, 還須要對超時狀況進行處理。即使是TCP傳輸的時候也有相似的問題,推流端發送了FIN結束報文,可是服務器未必收到,因此必定要有超時的機制來進行管理。咱們採用數據及時反饋的機制,在下行播放端要求週期性的返回心跳,上行要求推流端在8或10秒內必定要有一些真實數據傳輸,不然咱們就會斷開。
這幅時序圖更細緻的展開了一下實現的邏輯,播放端和服務器。
Tengine是阿里開源的服務器軟件, 阿里雲CDN的文件、點播、直播功能都是在其基礎上進行開發,而在短延時直播功能的實現咱們也是把開源的WebRTC的庫進行了一些改造。選擇Tengine來作主要緣由也是由於對其很是的熟悉,並且在其基礎上也積累了不少配套的技術,包括配置下發管理、日誌收集、業務處理等。
最後,咱們來看下實際的數據狀況。
目前短延時直播功能是在一些地區進行了部署和驗證,還沒到全網鋪開的階段。
秒開數據比原來FLV訪問提高很大, UDP交互省去了三次握手環節。錯誤率和延遲都有了較大的提高。這裏目前只對比了下行,從已經灰度的一些節點來看,上行卡頓數據要優於原有RTMP的推流。
7、後續展望
完整的支持WebRTC必定是目標, 畢竟直接經過瀏覽器就能夠完成推流和播放對於用戶的接入來講實在太方便, 對於CDN來說控制接入必定是一個必須作的事情。
對於CDN要作的另外一個事情就是優化傳輸,其實不管對於文件加速仍是流媒體加速,傳輸永遠都是最重要的,CDN這個分發網絡自己就是爲了優化傳輸而存在。
從實踐來看,UDP傳輸比原來的TCP傳輸對資源消耗要多,並且重傳、封包、FEC冗餘計算等都會額外增長計算量,在多進程模式下可能還會遇到內存資源的過多消耗。