文 / 施維
整理 / LiveVideoStack
視訊回放
https://www2.tutormeetplus.com/v2/render/playback?mode=playback&token=a1564111ef934005b4b1acf2105128e31. 為什麼選擇SRT?
毋庸置疑,現今存量最大的直播協定是RTMP,但随着新技術的不斷發展與使用場景的不斷拓展,繼續使用RTMP會令人感到有些力不從心。RTMP協定的缺陷主要有以下四個方面:
RTMP協定缺陷

首先,RTMP協定太老,且最後一次更新是在2012年;同時HEVC/H.265/AV1等視訊格式都沒有官方定義,以至于需要國内CDN廠商自行定義。
RTMP連接配接過程較長,由于RTMP基于TCP(TCP存在三次握手),除此之外,其本身又存在c0/s0到c2/s2的三次握手,再加上connection,createstream,play/publish,總地來說RTMP完成一次建連需要進行9次會話,用于PC端勉強能夠接受,對于移動端網絡品質的要求則很高。
RTMP的擁塞控制完全依賴傳輸層,即完全依賴于TCP傳輸層的擁塞控制算法來進行擁塞管理,幾乎沒有什麼優化;RTMP本身基于TCP傳輸,無法提供帶寬自适應的算法。
在此背景下,衆多廠商開始着手提供一些新的直播協定供行業參考。如QUIC、SRT等。本次我們将重點講述SRT的特點與應用。
SRT協定的特點
Haivision聯手Wowza在UDT的基礎上針對音視訊實時性提出了SRT協定。SRT是基于UDT的協定(UDT協定是基于UDP的傳輸協定,在IETF已經送出了4個版本),具有非常良好的丢包重傳機制,丢包重傳的控制消息非常豐富,同時支援ACK、ACKACK、NACK。
我們都知道音視訊對于時間這一點非常在意,而SRT基于時間的封包發送,使其具有良好的防止流量突發的能力。SRT對上層提供了豐富的擁塞控制統計資訊,包括RTT、丢包率、inflight、send/receive bitrate等。利用這些豐富的資訊,我們可以實作帶寬預測,并根據帶寬的變化在編碼層去做自适應動态編碼與擁塞控制。
2. SRT協定原理分析
2.1 SRT基本思想
上圖可以涵蓋SRT的基本思想:對比編碼後的視音頻碼流(左側綠色折線“Source”)與經過公網傳輸後的碼流(紅色折線“NetworkTransmission”),可以看到編碼後的源視音頻碼流具有固定的幀間隔與一定特性的可變比特率,但經過公網傳輸後的碼流,其幀間隔變得不固定且碼率特性也被完全改變,解碼這樣的信号是一項十分艱巨的挑戰,甚至根本無法解碼。
而如果使用加入糾錯的SRT協定進行公共網際網路傳輸,盡管編碼後的視音頻碼流經過公網傳輸幀間隔變得不固定,但由于SRT協定封裝中包含精準的時間戳,解碼接收端可以通過該時間戳重制固定的幀間隔。更重要的是,通過規定延時量,同時劃定了send buffer(發送端緩沖區)與receive buffer(接收端緩沖區),來自接收端的回報信号(可以了解為後向糾錯)通過一系列的設定、糾錯、流量控制,使編碼後的視音頻碼流擁有與原碼流幾乎一樣的碼率特性。
Encoder編碼器處理完成的資料會被輸入send buffer,send buffer會對資料進行時間校驗,也就是按照一定的時間順序編碼并通過internet發送至receivebuffer,receive buffer按照封包上的時間戳一點點處理,確定生成的資料與源碼流基本一緻。
整個SRT協定的思想基于編碼,具有抗丢包、抗擁塞、抗抖動等特性。
2.2 SRT封包基礎
互動過程
SRT的封包基礎也就是其互動過程依次為以上五個步驟:握手(Handshake)、重要資訊(Capability)、媒體(Media)、控制資訊(Control)與關閉(Shutdown)。與RTMP的九次握手不同,SRT的建連過程僅需兩個RTT。也就是Handshake Request與Capability Announce。Caller與Listener之間的進行的Handshake Request是一個簡化版的握手,用以提高效率;握手之後Caller與Listener間進行重要資訊的交換,整個SRT的第一項關鍵步驟就是Caller與Listener在這裡交換了延時量與緩沖區的大小;随後Caller與Listener之間開始媒體資料的傳輸,同時也傳輸了為恢複幀間隔而封裝的精準時間戳;SRT的第二項關鍵步驟是Listener向Caller同步控制資訊,用以對抗公網中的抖動、丢包等一系列突發狀況;最後,待至媒體資料傳輸完畢之後關閉傳輸。
資料封包
SRT的封包格式較為簡單,分為資料封包與控制封包。上圖展示了資料封包的資料結構,觀察結構我們可以發現上方兩層為UDP部分,而在這之下是UDT部分。如果初始化為0,則認為其是資料封包。FF表示封包的序列, 0b10是分片的第一個封包,0b00是分片的中間封包,0b01是分片的最後一個封包,0b11表示單個封包并沒有分片。KK表示是否加密,R表示是否屬于重傳封包,Timestamp表示時間戳,Destination Socket ID是SRT自定義的一個socket id。由該資料結構我們可以看出:SRT的資料封包擁有精準的32位時間戳,package sequence number絕對夠用,且結構非常簡單。
下圖展示的則是控制封包的資料結構,右側表格展示了控制封包的正常類型,其中值得重點關注的有ACK、NACK、ACKACK等。
控制封包
2.3 SRT丢包重傳
2.3.1 Send/Receive Buffer
SRT在接收和發送端都有receive buffer與send buffer,send Buffer嚴格按照時間戳間隔來發送,定時器預設10毫秒。
2.3.2 ACK
丢包重傳最常見的便是ACK機制。以上圖為例,假設發送端緩沖區發送五個資料包:1、2、3、4、5給接收端緩沖區,接收端緩沖區成功接收到這些資料包之後會向發送端緩沖區發送ACK——肯定應答已表示資料包被成功接收,發送端接收到ACK——肯定應答之後回收空間,删除1、2、3、4、5這五個資料包并準備發送資料包6。
send buffer完全按照時間戳間隔處理資料,在确定的間隔(與ACKs,ACKACKs 和 Round Trip Time相關),接收方發送ACK給發送方,使得發送方把收到ack的packet從sender buffer中移除,其在buffer中的空間點将被回收。接收端的receivebuffer中存在Latency Window也就是延遲視窗,其作用為按照時間戳一點點上送資料。并嚴格按照時間戳檢測,檢測周期預設為10毫秒。
2.3.3 ACK/ACKACK/RTT
接收端在收到資料包後會向發送端回報表示成功接收的ACK,例如上圖左側,接收端在收到第十一個資料包後向發送端回報ACK(11),而發送端在收到來自接收端的ACK(11)之後會向對端再發送一個ACKACK用以表示收到ACK(11)。這一過程最大的意義在于可讓接收端計算出RTT,ACK發送的時間與對應ACKACK收到的時間之差就是RTT——Round Trip Time(RTT)是時間的度量,表示封包一個來回的耗時。SRT不能測量單方向的耗時,是以隻能用RTT/2來表示單方向耗時。一個ACK(從接收方)會觸發ACKACK(從發送方)的發送,幾乎不帶其他延時。RTT可評估目前網絡品質,RTT高表示整個網絡的延遲很大,RTT低則說明網絡延遲較低。RTT由接收端計算而出,計算得出的RTT會通過ACK發送至發送端,發送端就可獲知目前網絡的品質如何。帶寬情況是不斷變化的,是以RTT也是一個随網絡環境不斷變化的實時動态值。
2.3.4 ACK資訊
ACK封包包含了豐富的關鍵資訊。其中Last Acknowledge Packet Sequence Number表示目前收到第幾個包,RTT資訊便于發送端評估網絡的品質,RTT的變化表示網絡變化情況。Available Buffer Size表示接收端緩存可用率,SRT是可以用作檔案傳輸的,Available Buffer Size對檔案傳輸的擁塞控制非常有用。當檔案傳輸過快時接收端的記憶體緩存無法成功接收,此時發送端除了考慮網絡還需要考慮接收端的性能與緩存是否有足夠的空間與能力在短時間内接收龐大的檔案。Packets Receiving Rate表示每秒鐘的收包率,這裡統計的是包的個數;而ReceivingRate表示接收包的比特率。
總而言之,接收端以10毫秒為周期向發送端發送ACK,其中包括網絡RTT資訊、接收端緩存資訊、接收端比特率等關鍵資料,其中以上三個資料至關重要,直接反映出發送端到接收端之間的網絡環境狀态。
2.3.5 NACK
正常情況下QUIC或TCP僅提供ACK方式,也就是接收端向發送端回報哪些包成功接收;而WebRTC的RTP或RTCP常用選擇NACK,也就是接收端向發送端回報哪些包沒有成功接收。NACK回傳的是接收端沒收到的資料包的清單。
SRT同時支援ACK與NACK,這樣設定的原因在我看來是帶寬搶占的強勢。例如,接收端向發送端發送ACK表示該資料包已經成功接收,不排除該ACK封包本身丢失,導緻發送端以為資料封包丢失而要逾時重發,實際接收端對該資料包已經成功接收了。
還有一種情況是:NACK的周期性發送可能會造成發送端多發封包,例如發送端成功發送5号與6号資料包,卻一直未收到來自接收端的ACK消息,當達到重發的時間時發送端再次發送5号與6号資料包,在此之後發送端收到了來自接收端的NACK消息,表示接收端未成功接收5号資料包與6号資料包;于是發送端第三次發送5号資料包與6号資料包。一個周期下來,發送端發了兩次資料包。從協定原理角度分析,我們發現 SRT在丢包過程中對帶寬的消耗比QUIC與其他協定要高。 一旦出現丢包,SRT的重傳要多于其他協定,SRT以此來搶占帶寬進而達到音視訊的同步效果。
2.4 SRT基于時間發送
按時間發送是一個标準的音視訊傳輸特性。我們知道編碼器發送是以編碼器的速度向外發送資料,但有時編碼器會太樂觀,完全按照編碼輸出向外發送會導緻輸出超過預期過高的比特率。在這種情況下SRT Packet就不會足夠快地輸出,因為SRT會最終被過低的錯誤配置影響到。
2.5 可配置比特率
SRT中包含三個配置選項:INPUTBW表示編碼器輸入帶寬,MAXBW表示最大帶寬,以及OVERHEAD(%)表示過載率,配置原則如上圖所示:
如果不配置INPUTBW與OVERHEAD(%)而僅配置MAXBW,則目前編碼器輸出的比特率是<mbw>也就是MAXBW;
如果不配置MAXBW與INPUTBW而僅配置OVERHEAD(%),則目前編碼器輸出的比特率是<smpinpbw>(1080+<oh>)/100,預設為25%;
第三種情況是不配置MAXBW而配置OVERHEAD(%)與INPUTBW,最大輸出比特率便為<ibw>(100+<oh>)/100。
SRT最大的特點便是可配置。在有配置的情況下按照配置來做,在無配置的情況下按實際測量的比特率來做。正常情況下我們不選擇進行配置,尤其是針對網際網路而言,因為單一配置無法保證能夠在不同時段應對不同境況的網絡。通常我們選擇使用實際測量出的編碼比特率計算:<smpinpbw>*(1080+<oh>)/100。
2.6 SRT簡單擁塞控制——簡單,太簡單
接下來我們讨論一下SRT的流控。我們知道在丢包重傳機制下,如果封包在網絡傳輸中丢失,則發送端會重新發送。例如在某網絡環境下發送端與接收端之間的帶寬僅有1M,現在由于背景流量與噪聲等影響,原來1M的帶寬減少100k變成了900k,此時就會出現10%的丢包;發送端未收到來自接收端的ACK或者收到NACK認為出現丢包,于是嘗試重傳這10%的資料;但實際上發送端與接收端之間的帶寬就剩下900k了,而加上丢包重傳的發送量是1.1M,帶寬變窄發送的流量不降反增,就會導緻網絡情況越來越糟糕,最後造成網絡擁塞卡頓頻繁,最後網絡崩潰。SRT單純地丢包重傳不能解決網絡擁塞的問題,出現網絡擁塞的最好解決方案是限流,降低帶寬流量壓力。
SRT的擁塞控制過于簡單,僅在congctrl.cpp中實作。其包括以下幾個變量:
M_iFlowWindowSize表示接收方的緩存大小,m_dCWndSize等于1秒内發送的bytes資料 / (RTT + 10),sendbufer表示發送方未發送buffer大小。其中這裡的1秒内發送的bytes資料,具體是指一個RTT内發送的資料。總結算法如下:m_iFlowWindowSize用以衡量接收方緩存是否耗盡,同時監測發送方每RTT發送資料size是否大于發送buffer大小。接收方緩存一般在傳輸檔案時起作用。
在我看來,SRT在擁塞控制方面做得還遠遠不夠。
2.7 SRT協定總結
SRT在快速連接配接方面有明顯優勢,兩次握手成功即可建連;SRT的丢包重傳政策出色,ACK、ACKACK、NACK等提供了豐富的控制消息,還有RTT、Receive比特率等。但是同時我們經過測試也發現SRT在丢包時,發送資料的帶寬占用率還是有些大,丢包率越高發送帶寬占用越大。
SRT按照時間發送音視訊資料,根據實際的編碼比特率來發送音視訊資料;但SRT的擁塞控制過于簡單,隻針對接收方緩存是否有能力接收與編碼比特率是否發送過快。
3. SRT在SRS4.0中的方案用
3.1 SRT在SRS4.0中的方案應用
3.1.1 最後一公裡——SRT推流
我們推薦從編碼器到推流至邊緣節點的部分使用SRT。其目的主要有兩個:提高源流品質與基于SRT自适應比特率編碼,發送端和接收端配合進而解決最後一公裡的推流問題。是自己對srt的了解。SRS支援 SRT的接收端推流,邊緣SRS在接收到來自推流端的SRT推流之後會将其轉為RTMP并分發給中央節點,而後所有的邊緣節點都可以進行RTMP拉流。
3.1.2 SRT位址格式
作為一個傳輸協定,SRT的一個弊端在于給出一個未定義的位址,我們不清楚這究竟是推流位址還是拉流位址,那麼如何進行比對?
為友善SRT編碼器推流,SRS4.0支援編碼器的簡單配置。如伺服器IP、伺服器Port以及streamid。根據SRT的官方文檔,SRT通過StreamID進行辨別,簡配位址格式如上圖所示,帶有vhost虛拟主機配置的位址格式如下圖所示,其中m=publish/request表示推/拉流位址。顯而易見的是,對比RTMP,SRT位址的可讀性并不好,位址長而冗雜。
3.1.3 SRT各種網絡情況下的測試
測試各種網絡情況下的SRT我們不難發現,丢包率增加導緻帶寬消耗增加,網絡狀況不良或發生擁塞時,發送端會發送更多的資料,這便會導緻網絡狀況愈發惡化,丢包率變得更高,并以此惡性循環;除此之外,RTT增加也會導緻延時增加,一樣會導緻丢包率增加,帶寬消耗更大。
這裡我們提出的解決方案是預測網絡帶寬——通過目前的send bitrate、RTT、inflight等資料預測網絡帶寬;同時動态調整編碼比特率,根據預測的帶寬動态調整編碼比特率1來适應實時的帶寬,避免發生擁塞并提高視訊流暢度。
3.1.4 GCC算法自适應編碼架構
上圖展示的就是谷歌擁塞控制算法GCC的架構圖。如圖所示:發送端将封包發給接收端,接收端由幾個部分組成,其中計算接收封包Delay,也就是計算基于D(i,j) = (Rj-Sj) - (Ri-Si) 的變化的導數,得到m(ti)。除此之外,接收端設定的卡曼濾波算法會計算出一個門限值,通過該卡曼濾波的計算與比對,決定是增加碼率還是降低碼率,最終得出下一次網絡帶寬的預估值(Ar),并将資料傳回給發送方。
3.2 自适應碼率的SRT推流
3.2.1基于SRT自适應碼率編碼
基于SRT自适應碼率編碼的關鍵參數如上圖左側所示:rtt_min表示1s内的RTT最小值,send_bitrate_max表示1s内最大的發送bitrate,正常情況我們大概200~300毫秒統計一次;inflight表示已經發送出去但還未接收到ACK的封包的個數,這種情況可能意味着封包還在傳輸鍊路的途中;BDP(bandwidth-delay product) BDP = send_bitrate_max*rtt_min表示一個RTT内發送的最大位元組數。如果BDP大于(1.2 x inflight)表示網絡狀況良好,可以增加編碼碼率;如果BDP小于(0.8 x inflight)則意味着網絡狀況不佳需要減少編碼碼率,其他情況則維持現有編碼碼率不變。這樣便能較為有效地避免網絡擁塞的情況發生。
3.2.2 基于SRT自适應碼率編碼——執行個體
我們以測試執行個體來驗證效果:通過Internet推流,來自于美國的SRT編碼器的資料推至杭州的節點,建立SRS4.0。該測試開源位址如圖中所示,使用FFmpeg配置編碼碼率為1000kbps,傳輸過程中根據實際出口帶寬動态調整編碼碼率。由上圖右側圖線1我們可以看到自适應碼率最高可達到1400kbps,有良好的自适應效果;實際測試感受來看,視訊播放平滑無明顯示卡頓,即便偶爾出現帶寬抖動也能夠迅速恢複。
4. SRT與QUIC
接下來我們對比SRT與QUIC,總結二者特點。
4.1 SRT1.4的優缺點
SRT1.4的優缺點可以簡單概括為以下内容:SRT的優點在于基于音視訊按照時間戳進行收發,可有效保證音視訊,同時ACK/ACKACK/NACK多種丢包糾正機制可有效降低延時與丢包率。SRT對上層提供豐富的傳輸層資料資訊如RTT、lost packet rate、receive rate等。當然,SRT的缺點也不容忽視,如SRT的擁塞控制過于簡單,需要在傳輸層合入BBR算法,原生SRT不支援連接配接遷移等。
基于以上特點,我認為SRT更加适合編碼器到最近節點的傳輸,也就是通過SRT探測出的RTT等相關資訊實作自适應碼率編碼;除此之外,SRT也适合網絡節點固定、網絡情況固定的環境,合理配置lantency、send/recv buffer、ohead rate等SRT參數可達到事半功倍的效果。
4.2 QUIC的優缺點
QUIC的優點是連接配接快,同時具有可插拔的擁塞控制,包括CUBIC、BBR;另外在丢包重傳方面,QUIC擁有更多的ACK block,最大可達256個,并且對于RTT的計算更加準确(QUIC中存在獨立的Packet number,包括重傳包在内的Packet number也都不相同,非常有利于RTT的精确計算);最後還有QUIC支援連接配接遷移。
當然,QUIC同樣存在缺點:第一,封包頭大在發送封包中所占比例較高。第二,丢包重傳隻有ACK原生;第三,QUIC不支援丢包,一旦出現丢包,若沒有在timeout前恢複就會斷開連接配接。
基于以上優缺點,我認為QUIC更适合運用在網絡丢包率較高的環境,因為QUIC具有0RTT快速連接配接能力、丢包重傳中ACK回複的block較大并且在擁塞控制方面表現非常優秀。除此之外QUIC也适合用于長距離傳輸當中,因為網絡傳輸RTT較高,QUIC在連接配接斷開後重連是0RTT,傳輸資料更加高效。
4.3mediago服務:rtmp over quic
Mediago具有支援QUIC協定來傳輸RTMP直播流的特性,如RTMP over TCP推拉流、RTMP over QUIC推拉流以及對FLV的支援。伺服器之間則支援基于TCP伺服器間RTMP回源與基于QUIC伺服器間RTMP回源,上圖中有測試連結,感興趣的朋友可以自己嘗試一下。
————————————————
版權聲明:本文為CSDN部落客「LiveVideoStack_」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。
原文連結:
https://blog.csdn.net/vn9PLgZvnPs1522s82g/article/details/104707689「視訊雲技術」你最值得關注的音視訊技術公衆号,每周推送來自阿裡雲一線的實踐技術文章,在這裡與音視訊領域一流工程師交流切磋。