1. 程式人生 > >關於直播的技術細節都在這裡

關於直播的技術細節都在這裡

(2016-05-26 17:59:34)

加速會注:本文由 著名直播平臺都在使用的雲端計算公司 UCloud 流媒體研發團隊撰寫!


網路視訊直播存在已有很長一段時間,隨著移動上下行頻寬提升及資費的下調,視訊直播被賦予了更多娛樂和社交的屬性,人們享受隨時隨地進行直播和觀看,主播不滿足於單向的直播,觀眾則更渴望互動,直播的開啟時間和延遲變成了影響產品功能發展重要指標。那麼,問題來了:如何實現低延遲、秒開的直播?

先來看看視訊直播的5個關鍵的流程:錄製->編碼->網路傳輸->解碼->播放,每個環節對於直播的延遲都會產生不同程度的影響。這裡重點分析移動裝置的情況。受限於技術的成熟度、硬體環境等,我們針對移動場景簡單總結出直播延遲優化的4個點:網路、協議、編解碼、移動終端

,並將分四大塊來一一解密UCloud直播雲實現低延遲、秒開的技術細節。

一、UCloud直播雲實現接入網路優化的技術細節:

1)全域性負載均衡-就近接入

實現就近接入的技術比較廣為人知,就是CDN即Content Delivery Network (內容分發網路)。CDN包含兩大核心技術:負載均衡和分發網路,隨著10多年的演進,對負載均衡和分發的實現方式已多種多樣,分發網路的構建策略通常是經過日積月累的總結出一套最合適的分發路由,並且也不是一成不變,需時刻關注調整,動態運營。這裡重點介紹下CDN的負載均衡技術。

負載均衡是如何實現讓使用者就進訪問的呢?比較普遍的實現方式:通過使用者使用的DNS伺服器來判斷客戶端所在的網路位置,從而返回對應的服務IP。如下圖示例:


1>使用者向配置的DNS伺服器1.1.1.0(通常是運營商指定,也稱local DNS,後面簡稱Ldns)發起的查詢;

2> Ldns 上沒有該域名的記錄,則往頂級即Root NS上發起查詢;

3>Root NS返回告知Ldns該域名的權威解析記錄在UCloud NS上;

4>Ldns 向UCloud NS發起查詢;

5>UCloud NS 向UCloud GSLB服務發起查詢,GSLB發現 Ldns1.1.1.0是屬於廣東電信;

6>返回廣東電信的就近節節點IP1.1.1.2

7>返回1.1.1.2給Ldns;

8>返回給使用者1.1.1.2

,使用者到1.1.1.2上去獲取直播內容。

鏈路很長,但是每個Ldns上都會對查詢過的域名做合理的快取,下一個廣東電信的使用者再來查詢的時候就可以直接返回1.1.1.2。架構並不複雜,關鍵點是如何知道Ldns是位於廣東電信,這就涉及一個IP地址庫。有開源地址庫,也有商業地址庫,可以按需求採購即可,一般一年1萬左右。這裡不難看出來,排程的準確度是完全依賴使用者配置的Ldns,而這些Ldns大多數是省級別的,即GLSB只知道使用者是廣東電信,但是常常分不出來是廣東廣州電信,還是廣東深圳電信。 HTTPDNS就是實現更精準的排程一種方式:


1>使用者1.1.1.1通過HTTP協議直接向UCloud NS請求直播域名www.ucloud.cn

2>UCloud NS發現使用者IP1.1.1.1屬於廣東深圳電信;

3>返回廣東深圳電信節點1.1.1.11給UCloud NS;

4>返回給使用者。

HTTPDNS的好處顯而易見:一可精準獲得使用者端的IP,有效避免使用者配錯Ldns(有時是網路中心配錯DNS)的情況,可更精準定位使用者所在網路位置。二可避免DNS解析劫持。

2)BGP中轉架構-最短傳輸路徑

BGP即Border Gateway Protocol (邊界閘道器協議),業內簡稱BGP。為什麼BGP中轉架構對直播加速和分發如此重要?不得不提國內複雜的網路狀況,較廣為人知的是“南電信北聯通”的寬頻使用者分佈。那一個簡單的問題,電信主播發起了直播,聯通的使用者想看怎麼辦呢? 從結構上講,肯定是有有限個電信聯通兩個運營商的交匯點,相當於資訊橋樑。 這就會帶來兩個問題:1、路程要繞遠,網路延遲高且不穩定;2、高峰期擁堵,導致直播流卡頓。

BGP的技術原理往簡單的說就是允許同一IP在不同網路中廣播不同的路由資訊,效果就是同一個IP,當電信使用者來訪問時走電信網內的路由,聯通使用者來訪問時走的聯通的路由。所以BGP技術對跨運營商的訪問帶來了巨大的便利,特別是直播場景。不同於傳統的檔案快取場景,一個圖片哪怕第一次是跨了遙遠的距離從源站獲取後,本地網路進行快取,後面的訪問都走本地網路。直播加速是流式的,並且當要做到低延遲的時候,中間的快取要儘可能少。 BGP相當於給跨網的使用者就近搭建了一坐橋樑,不必繞遠路,延時和穩定性都大大提高了。


技術原理部分介紹完了,那麼多直播延遲影響有多少改善呢?首先這裡的就近,不一定是物理距離近,不考慮瞬時負載情況下,更多是指測速延時最優的機房。在國內一般而言相同的接入運營商(電信、聯通、移動)並且地理位置最近的情況網路延遲最優,小於15ms。跨省同運營商的網路延遲25~50ms,跨運營商情況更復雜一些,在50~100ms。總結起來,直播當中每個包的延時可以縮短100ms,由於網路的疊加效果,反射到上層是秒級的延遲縮減。

二、直播應用層協議及傳輸層協議的選擇以及對直播體驗影響的分析 

直播協議的選擇

國內常見公開的直播協議有幾個:RTMP、HLS、HDL(HTTP-FLV)、RTP,我們來逐一介紹。

RTMP協議:

是Adobe的專利協議,現在大部分國外的CDN已不支援。在國內流行度很高。原因有幾個方面:

1、開源軟體和開源庫的支援穩定完整。如鬥魚主播常用的OBS軟體,開源的librtmp庫,服務端有nginx-rtmp外掛。

2、播放端安裝率高。只要瀏覽器支援FlashPlayer就能非常簡易的播放RTMP的直播,協議詳解可以Google瞭解。相對其他協議而言,RTMP協議初次建立連線的時候握手過程過於複雜(底層基於TCP,這裡說的是RTMP協議本身的互動),視不同的網路狀況會帶來給首開帶來100ms以上的延遲。基於RTMP的直播一般內容延遲在2~5秒。


HTTP-FLV協議:

即使用HTTP協議流式的傳輸媒體內容。相對於RTMP,HTTP更簡單和廣為人知,而且不擔心被Adobe的專利綁架。內容延遲同樣可以做到2~5秒,開啟速度更快,因為HTTP本身沒有複雜的狀態互動。所以從延遲角度來看,HTTP-FLV要優於RTMP。

HLS 協議:

即Http Live Streaming,是由蘋果提出基於HTTP的流媒體傳輸協議。HLS有一個非常大的優點:HTML5可以直接開啟播放;這個意味著可以把一個直播連結通過微信等轉發分享,不需要安裝任何獨立的APP,有瀏覽器即可,所以流行度很高。社交直播APP,HLS可以說是剛需,下來我們分析下其原理 。

基於HLS的直播流URL是一個m3u8的檔案,裡面包含了最近若干個小視訊TS(一種視訊封裝格式,這裡就不擴充套件介紹)檔案,如 http://www.ucloud.cn/helloworld.m3u8 是一個直播留連結,其內容如下:


假設列表裡面的包含5個TS檔案,每個TS檔案包含5秒的視訊內容,那麼整體的延遲就是25秒。當然可以縮短列表的長度和單個TS檔案的大小來降低延遲,極致來說可以縮減列表長度為1,1秒內容的m3u8檔案,但是極易受網路波動影響造成卡頓。

通過公網的驗證,目前按同城網路可以做到比較好的效果是5~7秒的延遲,也是綜合流暢度和內容延遲的結果。那麼HTML5是否可以有更低延遲直接開啟的直播流技術呢? 我們在最後會探討這個問題。

RTP協議:

即Real-time Transport Protocol,用於Internet上針對多媒體資料流的一種傳輸層協議。

實際應用場景下經常需要RTCP(RTP Control Protocol)配合來使用,可以簡單理解為RTCP傳輸互動控制的信令,RTP傳輸實際的媒體資料。

RTP在視訊監控、視訊會議、IP電話上有廣泛的應用,因為視訊會議、IP電話的一個重要的使用體驗:內容實時性強。

對比與上述3種或實際是2種協議,RTP和它們有一個重要的區別就是預設是使用UDP協議來傳輸資料,而RTMP和HTTP是基於TCP協議傳輸。為什麼UDP 能做到如此實時的效果呢?關於TCP和UDP差別的分析文章一搜一大把,這裡不在贅述,簡單概括:

UDP:單個數據報,不用建立連線,簡單,不可靠,會丟包,會亂序;

TCP:流式,需要建立連線,複雜,可靠 ,有序。

實時音視訊流的場景不需要可靠保障,因此也不需要有重傳的機制,實時的看到影象聲音,網路抖動時丟了一些內容,畫面模糊和花屏,完全不重要。TCP為了重傳會造成延遲與不同步,如某一截內容因為重傳,導致1秒以後才到,那麼整個對話就延遲了1秒,隨著網路抖動,延遲還會增加成2秒、3秒,如果客戶端播放是不加以處理將嚴重影響直播的體驗。

總結一下:在直播協議的選擇中,如果選擇是RTMP或HTTP-FLV則意味著有2~5秒的內容延遲,但是就開啟延遲開,HTTP-FLV 要優於RTMP。HLS則有5~7秒的內容延遲。選擇RTP進行直播則可以做到1秒內的直播延遲。但就目前所瞭解,各大CDN廠商沒有支援基於RTP直播的,所以目前國內主流還是RTMP或HTTP-FLV。

是否有除了HLS外更低延遲的方案?

HLS的優點點是顯而易見的:移動端無需安裝APP使用相容HTML5的瀏覽器開啟即可觀看,所有主流的移動端瀏覽器基本都支援HTML5,在直播的傳播和體驗上有巨大的優勢。

而看起來唯一的缺點:內容延遲高(這裡也有很多HLS限制沒有提到,比如必須是H264+AAC編碼,也可認為是“缺點”之一)。如果能得到解決,那將會是直播技術非常大的一個進步。或者換個說法,有沒有更低延遲可直接用連結傳播的直播方案?不侷限於HLS本身。

對於瀏覽器直接的視訊互動,Google一直在推WebRTC,目前已有不少成型的產品出現,可以瀏覽器開啟即實時對話、直播。但來看看如下的瀏覽器覆蓋圖:


非常遺憾的說,在直至iOS 9.3上的Safari仍然不能支援WebRTC。繼續我們的探索,那Websocket支援度如何呢?


除了老而不化的Opera Mini外,所有的瀏覽器都支援WebSocket。這似乎是個好訊息。梳理一下HTML5 WebSocket直播需要解決的問題:

1、後端相容

2、傳輸

3、解碼播放

對於#1似乎不是特別大問題,對於做過RTMP轉HLS、RTP來說是基本功。#2對於瀏覽器來說使用HTTP來傳輸是比較好的選項。對於#3 這裡推薦一個開源的JS解碼專案jsmpeg: https://github.com/phoboslab/jsmpeg,裡面已有一個用於直播的stream-server.js的NodeJS伺服器。

從測試結果看,該專案的程式碼相對較薄,還沒達到工業級的成熟度,需要大規模應用估計需要自填不少坑,有興趣的同學可以學習研究。

以上就是直播雲:直播應用層協議及傳輸層協議的選擇以及對直播體驗影響的分析 。關於接入網路優化、內容快取與傳輸策略優化、終端優化,請參閱接下來發布的其他部分。

三、在傳輸直播流媒體過程中的內容快取與傳輸策略優化細節原理

基礎知識:I幀、B幀、P幀

I幀表示關鍵幀。你可以理解為這一幀畫面的完整保留;解碼時只需要本幀資料就可以完成。(因為包含完整畫面)

P幀表示這一幀跟之前的一個關鍵幀(或P幀)的差別。解碼時需要用之前快取的畫面疊加上本幀定義的差別,生成最終畫面。(也就是差別幀,P幀沒有完整畫面資料,只有與前一幀的畫面差別的資料)

B幀是雙向差別幀。B幀記錄的是本幀與前後幀的差別(具體比較複雜,有4種情況)。換言之,要解碼B幀,不僅要取得之前的快取畫面,還要解碼之後的畫面,通過前後畫面的與本幀資料的疊加取得最終的畫面。

B幀壓縮率高,但是編解碼時會比較耗費CPU,而且在直播中可能會增加直播延時,因此在移動端上一般不使用B幀。


關鍵幀快取策略

一個典型的視訊幀序列為IBBPBBPBBP……

對於直播而言,為了減少直播的延時,通常在編碼時不使用B幀。P幀B幀對於I幀都有直接或者間接的依賴關係,所以播放器要解碼一個視訊幀序列,並進行播放,必須首先解碼出I幀,其後續的B幀和P幀才能進行解碼,這樣服務端如何進行關鍵幀的快取,則對直播的延時以及其他方面有非常大的影響。

比較好的策略是服務端自動判斷關鍵幀的間隔,按業務需求快取幀序列,保證在快取中儲存至少兩個或者以上的關鍵幀,以應對低延時、防卡頓、智慧丟包等需求。

延遲與卡頓的折中

直播的延時與卡頓是分析直播業務質量時,非常關注的兩項指標。互動直播的場景對延時非常敏感,新聞體育類直播則更加關注播放的流暢度。

然而,這兩項指標從理論上來說,是一對矛盾的關係——需要更低的延時,則表明伺服器端和播放端的緩衝區都必須更短,來自網路的異常抖動容易引起卡頓;業務可以接受較高的延時時,服務端和播放端都可以有較長的緩衝區,以應對來自網路的抖動,提供更流暢的直播體驗。

當然,對於網路條件非常好的使用者,這兩項是可以同時保證的,這裡主要是針對網路條件不是那麼好的使用者,如何解決延時與卡頓的問題。

這裡通常有兩種技術來平衡和優化這兩個指標。

一是服務端提供靈活的配置策略,對於延時要求更敏感的,則在服務端在保證關鍵幀的情況下,對每個連線維持一個較小的緩衝佇列;對於卡頓要求更高的直播,則適當增加緩衝佇列的長度,保證播放的流暢。

二是服務端對所有連線的網路情況進行智慧檢測,當網路狀況良好時,服務端會縮小該連線的緩衝佇列的大小,降低延遲;而當網路狀況較差時,特別是檢測到抖動較為明顯時,服務端對該連線增加緩衝佇列長度,優先保證播放的流暢性。


丟包策略

什麼時候需要丟包呢?

對於一個網路連線很好,延時也比較小的連線,丟包策略永遠沒有用武之地的。而網路連線比較差的使用者,因為下載速度比較慢或者抖動比較大,這個使用者的延時就會越來越高。

另外一種情況是,如果直播流關鍵幀間隔比較長,那麼在保證首包是關鍵幀的情況下,觀看這個節目的觀眾,延遲有可能會達到一個關鍵幀序列的長度。上述兩種情況,都需要啟用丟包策略,來調整播放的延時。

關於丟包,需要解決兩個問題:

一是正確判斷何時需要進行丟包;

二是如何丟包以使得對觀眾的播放體驗影響最小。較好的做法是後端週期監控所有連線的緩衝佇列的長度,這樣佇列長度與時間形成一個離散的函式關係,後端通過自研演算法來分析這個離散函式,判斷是否需要丟包。

一般的丟幀策略,就是直接丟棄一個完整的視訊幀序列,這種策略看似簡單,但對使用者播放的影響體驗非常大。而應該是後臺採用逐步丟幀的策略,每個視訊幀序列,丟最後的一到兩幀,使得使用者的感知最小,平滑的逐步縮小延時的效果。

四、客戶端的優化

解析優化

參見之前介紹的DNS過程,如下圖:


基於可控和容災的需要,移動端程式碼一般不會hardcode 推流、播放的伺服器IP地址,而選用域名代替。在IP出現宕機或網路中斷的情況下,還可以通過變更DNS來實現問題IP的剔除。而域名的解析時間需要幾十毫秒至幾秒不等,對於新生成熱度不高的域名,一般的平均解析延遲在300ms,按上圖的各個環節只要有一個通路網路產生波動或者是裝置高負載,會增加至秒級。幾十毫秒的情況是ISP NS這一層在熱度足夠高的情況下會對域名的解析進行快取。如下圖:


按我們上面分析的情況,本省延遲大概是15ms左右,那麼域名解析最低也可以做到15ms左右。但由於直播場景的特殊性,推流和播放使用的域名使用的熱度較難達到ISP NS快取的標準,所以經常需要走回Root NS進行查詢的路徑。

那客戶端解析優化的原理就出來了:本機快取域名的解析結果,對域名進行預解析,每次需要直播推流和播放的時候不再需要再進行DNS過程。此處節省幾十到幾百毫秒的開啟延遲。

播放優化

直播播放器的相關技術點有:直播延時、首屏時間(指從開始播放到第一次看到畫面的時間)、音視訊同步、軟解碼、硬解碼。參考如下播放流程:


播放步驟描述:

根據協議型別(如RTMP、RTP、RTSP、HTTP等),與伺服器建立連線並接收資料;

解析二進位制資料,從中找到相關流資訊;

根據不同的封裝格式(如FLV、TS)解複用(demux)

分別得到已編碼的H.264視訊資料和AAC音訊資料;

使用硬解碼(對應系統的API)或軟解碼(FFMpeg)來解壓音視訊資料;

經過解碼後得到原始的視訊資料(YUV)和音訊資料(AAC);

因為音訊和視訊解碼是分開的,所以我們得把它們同步起來,否則會出現音視訊不同步的現象,比如別人說話會跟口型對不上;

最後把同步的音訊資料送到耳機或外放,視訊資料送到螢幕上顯示。

瞭解了播放器的播放流程後,我們可以優化以下幾點:

首屏時間優化

從步驟2入手,通過預設解碼器型別,省去探測檔案型別時間;

從步驟5入手,縮小視訊資料探測範圍,同時也意味著減少了需要下載的資料量,特別是在網路不好的時候,減少下載的資料量能為啟動播放節省大量的時間,當檢測到I幀資料後就立馬返回並進入解碼環節。

延時優化

視訊緩衝區或叫視訊快取策略,該策略原理是當網路卡頓時增加使用者等待時間來快取一定量的視訊資料,達到後續平滑觀看的效果,該技術能有效減少卡頓次數,但是會帶來直播上的內容延時,所以該技術主要運用於點播,直播方面已去掉該策略,以此儘可能去掉或縮小內容從網路到螢幕展示過程中的時間;(有利於減少延時)。

下載資料探測池技術,當用戶下載速度不足發生了卡頓,然後網路突然又順暢了,伺服器上之前滯留的資料會加速發下來,這時為了減少之前卡頓造成的延時,播放器會加速播放探測池的視訊資料並丟棄當前加速部分的音訊資料,以此來保證當前觀看內容延時穩定。

推流優化


推流步驟說明:很容易看出推流跟播放其實是逆向的,具體流程就不多說了。

優化一:適當的Qos(Quality of Service,服務質量)策略。

推流端會根據當前上行網路情況控制音視訊資料發包和編碼,在網路較差的情況下,音視訊資料傳送不出去,造成資料滯留在本地,這時,會停掉編碼器防止傳送資料進一步滯留,同時會根據網路情況選擇合適的策略控制音視訊傳送。

比如網路很差的情況下,推流端會優先發送音訊資料,保證使用者能聽到聲音,並在一定間隔內發關鍵幀資料,保證使用者在一定時間間隔之後能看到一些畫面的變化。

優化二:合理的關鍵幀配置。

合理控制關鍵幀傳送間隔(建議2秒或1秒一個),這樣可以減少後端處理過程,為後端的緩衝區設定更小創造條件。

軟硬編解選擇

網上有不少關於選擇軟解還是硬解的分析文章,這裡也介紹一些經驗,但根本問題是,沒有一個通用方案能最優適配所有作業系統和機型。

推流編碼:推薦Andorid4.3(API18)或以上使用硬編,以下版本使用軟編;iOS使用全硬編方案;

播放解碼:Andorid、iOS播放器都使用軟解碼方案,經過我們和大量客戶的測試以及總結,雖然犧牲了功耗,但是在部分細節方面表現會較優,且可控性強,相容性也強,出錯情況少,推薦使用。

附軟硬編解碼優缺點對比:


雲端機型及網路適配

上面分析了很多針對視訊編解碼的引數,但實際情況最好的編解碼效果是需要根據機型的適配的,由於iOS的裝置型別較少,可以做到每個機型針對性的測試和調優,但是對於Android就非常難做到逐款機型針對性調優,並且每年都會出產不少的新機器,如果程式碼中寫死了配置或判斷邏輯將非常不利於維護和迭代。

所以我們就誕生了一個想法,這些判斷邏輯或配置是否可以放在雲上呢?  這樣就產生了雲端機型與網路適配的技術。


終端在推流、播放前會獲取通過協議上報當前的機型配置、網路情況、IP資訊。雲端會返回一個已最適合的編解碼策略配置:走軟編還是硬編、各項引數的配置,就近推流服務的IP,就近播放服務的IP。 終端獲取一次即可,不需要每次推流、播放前都去獲取一次。

這樣,在我們不斷的迭代和完善機型編解碼適配庫的同時,所有使用該技術的直播APP都將收益。

總結

分析很多直播後端、終端的關於低延遲、秒開的優化技術,在UCloud直播雲上都已有了相關的實踐,都是一些較“靜態”的技術。實際提供穩定、低延遲、流暢的直播服務,是日常中非常大量細緻的監控、演算法和動態運營的結果,並不是實現了某些的技術點,就能坐享一套穩定的直播服務,只能說是完成了萬里長城的第一道磚。