本文由 著名直播平臺都在使用的雲計算公司 UCloud 流媒體研發團隊撰寫!html
網絡視頻直播存在已有很長一段時間,隨着移動上下行帶寬提高及資費的下調,視頻直播被賦予了更多娛樂和社交的屬性,人們享受隨時隨地進行直播和觀看,主播不知足於單向的直播,觀衆則更渴望互動,直播的打開時間和延遲變成了影響產品功能發展重要指標。那麼,問題來了: 如何實現低延遲、秒開的直播?html5
先來看看視頻直播的5個關鍵的流程:錄製->編碼->網絡傳輸->解碼->播放,每一個環節對於直播的延遲都會產生不一樣程度的影響。這裏重點分析移動設備的狀況。受限於技術的成熟度、硬件環境等,咱們針對移動場景簡單總結出直播延遲優化的4個點:網絡、協議、編解碼、移動終端,並將分四大塊來一一解密UCloud直播雲實現低延遲、秒開的技術細節。android
實現就近接入的技術比較廣爲人知,就是CDN即Content Delivery Network (內容分發網絡)。CDN包含兩大核心技術:負載均衡和分發網絡,隨着10多年的演進,對負載均衡和分發的實現方式已多種多樣,分發網絡的構建策略一般是通過日積月累的總結出一套最合適的分發路由,而且也不是一成不變,需時刻關注調整,動態運營。這裏重點介紹下CDN的負載均衡技術。ios
負載均衡是如何實現讓用戶就進訪問的呢?比較廣泛的實現方式:經過用戶使用的DNS服務器來判斷客戶端所在的網絡位置,從而返回對應的服務IP。以下圖示例:nginx
廣東電信用戶IP:1.1.1.1 須要看一個直播http://www.ucloud.cn/helloworld.flv ,實現就近訪問的過程是:git
1>用戶向配置的DNS服務器1.1.1.0(一般是運營商指定,也稱local DNS,後面簡稱Ldns)發起www.ucloud.cn 的查詢;github
2> Ldns 上沒有該域名的記錄,則往頂級即Root NS上發起查詢;算法
3>Root NS返回告知Ldns該域名的權威解析記錄在UCloud NS上;docker
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解析劫持。
BGP即Border Gateway Protocol (邊界網關協議),業內簡稱BGP。爲何BGP中轉架構對直播加速和分發如此重要?不得不提國內複雜的網絡情況,較廣爲人知的是「南電信北聯通」的寬帶用戶分佈。那一個簡單的問題,電信主播發起了直播,聯通的用戶想看怎麼辦呢? 從結構上講,確定是有有限個電信聯通兩個運營商的交匯點,至關於信息橋樑。 這就會帶來兩個問題:一、路程要繞遠,網絡延遲高且不穩定;二、高峯期擁堵,致使直播流卡頓。
BGP的技術原理往簡單的說就是容許同一IP在不一樣網絡中廣播不一樣的路由信息,效果就是同一個IP,當電信用戶來訪問時走電信網內的路由,聯通用戶來訪問時走的聯通的路由。因此BGP技術對跨運營商的訪問帶來了巨大的便利,特別是直播場景。不一樣於傳統的文件緩存場景,一個圖片哪怕第一次是跨了遙遠的距離從源站獲取後,本地網絡進行緩存,後面的訪問都走本地網絡。直播加速是流式的,而且當要作到低延遲的時候,中間的緩存要儘量少。 BGP至關於給跨網的用戶就近搭建了一坐橋樑,沒必要繞遠路,延時和穩定性都大大提升了。
技術原理部分介紹完了,那麼多直播延遲影響有多少改善呢?首先這裏的就近,不必定是物理距離近,不考慮瞬時負載狀況下,更可能是指測速延時最優的機房。在國內通常而言相同的接入運營商(電信、聯通、移動)而且地理位置最近的狀況網絡延遲最優,小於15ms。跨省同運營商的網絡延遲25~50ms,跨運營商狀況更復雜一些,在50~100ms。總結起來,直播當中每一個包的延時能夠縮短100ms,因爲網絡的疊加效果,反射到上層是秒級的延遲縮減。
國內常見公開的直播協議有幾個:RTMP、HLS、HDL(HTTP-FLV)、RTP,咱們來逐一介紹。
RTMP協議:
是Adobe的專利協議,如今大部分國外的CDN已不支持。在國內流行度很高。緣由有幾個方面:
一、開源軟件和開源庫的支持穩定完整。如鬥魚主播經常使用的OBS軟件,開源的librtmp庫,服務端有nginx-rtmp插件。
二、播放端安裝率高。只要瀏覽器支持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的優勢點是顯而易見的:移動端無需安裝APP使用兼容HTML5的瀏覽器打開便可觀看,全部主流的移動端瀏覽器基本都支持HTML5,在直播的傳播和體驗上有巨大的優點。
而看起來惟一的缺點:內容延遲高(這裏也有不少HLS限制沒有提到,好比必須是H264 AAC編碼,也可認爲是「缺點」之一)。若是能獲得解決,那將會是直播技術很是大的一個進步。或者換個說法,有沒有更低延遲可直接用連接傳播的直播方案?不侷限於HLS自己。
對於瀏覽器直接的視頻互動,Google一直在推WebRTC,目前已有很多成型的產品出現,能夠瀏覽器打開即實時對話、直播。但來看看以下的瀏覽器覆蓋圖:
很是遺憾的說,在直至iOS 9.3上的Safari仍然不能支持WebRTC。繼續咱們的探索,那Websocket支持度如何呢?
除了老而不化的Opera Mini外,全部的瀏覽器都支持WebSocket。這彷佛是個好消息。梳理一下HTML5 WebSocket直播須要解決的問題:
一、後端兼容
二、傳輸
三、解碼播放
對於#1彷佛不是特別大問題,對於作過RTMP轉HLS、RTP來講是基本功。#2對於瀏覽器來講使用HTTP來傳輸是比較好的選項。對於#3 這裏推薦一個開源的JS解碼項目jsmpeg: https://github.com/phoboslab/jsmpeg,裏面已有一個用於直播的stream-server.js的NodeJS服務器。
從測試結果看,該項目的代碼相對較薄,還沒達到工業級的成熟度,須要大規模應用估計須要自填很多坑,有興趣的同窗能夠學習研究。
以上就是直播雲:直播應用層協議及傳輸層協議的選擇以及對直播體驗影響的分析 。關於接入網絡優化、內容緩存與傳輸策略優化、終端優化,請參閱接下來發布的其餘部分。
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直播雲上都已有了相關的實踐,都是一些較「靜態」的技術。實際提供穩定、低延遲、流暢的直播服務,是平常中很是大量細緻的監控、算法和動態運營的結果,並非實現了某些的技術點,就能坐享一套穩定的直播服務,只能說是完成了萬里長城的第一道磚。