一文盤點直播技術中的編解碼、直播協議、網絡傳輸與簡單實現

Live CheatSheet | 直播技術理論基礎與實踐概論

音視頻直播的基本流程都是採集 → 編碼推流 → 網絡分發 → 解碼 → 播放這五大環節,其中又會涉及平臺硬件、編解碼、網絡傳輸、服務併發、數字信號處理、在線學習等多方面技術。從交互模式上,又可以泛分為單對單模式與會議模式兩大類;從實時性要求上,直播又可以分為偽實時、準實時與真實時三個等級:

  • 偽實時:視頻消費延遲超過 3 秒,單向觀看實時,通用架構是 CDN + RTMP + HLS,譬如很多的直播平臺
  • 準實時: 視頻消費延遲 1 ~ 3 秒,能進行雙方互動但互動有障礙;可以通過 TCP/UDP + FLV 已經實現了這類技術,譬如 YY 直播等
  • 真實時:視頻消費延遲 < 1 秒,平均 500 毫秒,譬如 QQ、微信、Skype 和 WebRTC 等

編解碼

視頻封裝格式就是我們通常所說的 .mp4,.flv,.ogv,.webm 等,它其實就是一個盒子,用來將實際的視頻流以一定的順序放入,確保播放的有序和完整性。視頻壓縮格式(視頻編碼)就是指能夠對數字視頻進行壓縮或者解壓縮(視頻解碼)的程序或者設備。通常這種壓縮屬於有損數據壓縮。

視頻壓縮格式和視頻格式具體的區別就是,它是將原始的視頻碼流變為可用的數字編碼。首先,由原始數碼設備提供相關的數字信號流,然後經由視頻壓縮算法,大幅度的減少流的大小,然後交給視頻盒子,打上相應的 dts,pts 字段,最終生成可用的視頻文件。視頻編碼也可以指通過過特定的壓縮技術,將某個視頻格式轉換成另一種視頻格式。

一文盤點直播技術中的編解碼、直播協議、網絡傳輸與簡單實現

歡迎工作一到五年的Java工程師朋友們加入Java程序員開發: 854393687

群內提供免費的Java架構學習資料(裡面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!

視頻封裝格式

常見的視頻封裝格式(簡稱:視頻格式)包括了 AVI,MPEG,VOB 等,即相當於一種儲存視頻信息的容器,由相應的公司開發出來的。

一文盤點直播技術中的編解碼、直播協議、網絡傳輸與簡單實現

AVI

AVI 格式(後綴為.AVI):它的英文全稱為 Audio Video Interleaved,即音頻視頻交錯格式。它於 1992 年被 Microsoft 公司推出。

這種視頻格式的優點是圖像質量好。由於無損 AVI 可以保存 alpha 通道,經常被我們使用。缺點太多,體積過於龐大,而且更加糟糕的是壓縮標準不統一,最普遍的現象就是高版本 Windows 媒體播放器播放不了採用早期編碼編輯的 AVI 格式視頻,而低版本 Windows 媒體播放器又播放不了採用最新編碼編輯的 AVI 格式視頻,所以我們在進行一些 AVI 格式的視頻播放時常會出現由於視頻編碼問題而造成的視頻不能播放或即使能夠播放,但存在不能調節播放進度和播放時只有聲音沒有圖像等一些莫名其妙的問題。

DV-AVI

DV-AVI 格式(後綴為.AVI):DV 的英文全稱是 Digital Video Format,是由索尼、松下、JVC 等多家廠商聯合提出的一種家用數字視頻格式。

數字攝像機就是使用這種格式記錄視頻數據的。它可以通過電腦的 IEEE 1394 端口傳輸視頻數據到電腦,也可以將電腦中編輯好的的視頻數據回錄到數碼攝像機中。這種視頻格式的文件擴展名也是 avi。電視臺採用錄像帶記錄模擬信號,通過 EDIUS 由 IEEE 1394 端口採集卡從錄像帶中採集出來的視頻就是這種格式。

MOV

QuickTime File Format 格式(後綴為.MOV):美國 Apple 公司開發的一種視頻格式,默認的播放器是蘋果的 QuickTime。

具有較高的壓縮比率和較完美的視頻清晰度等特點,並可以保存 alpha 通道。大家可能注意到了,每次安裝 EDIUS,我們都要安裝蘋果公司推出的 QuickTime。安裝其目的就是為了支持 JPG 格式圖像和 MOV 視頻格式導入。

MPEG

MPEG 格式(文件後綴可以是 .MPG .MPEG .MPE .DAT .VOB .ASF .3GP .MP4 等):它的英文全稱為 Moving Picture Experts Group,即運動圖像專家組格式,該專家組建於 1988 年,專門負責為 CD 建立視頻和音頻標準,而成員都是為視頻、音頻及系統領域的技術專家。

MPEG 文件格式是運動圖像壓縮算法的國際標準。MPEG 格式目前有三個壓縮標準,分別是 MPEG-1、MPEG-2、和 MPEG-4。MPEG-1、MPEG-2 目前已經使用較少,著重介紹 MPEG-4,其制定於 1998 年,MPEG-4 是為了播放流式媒體的高質量視頻而專門設計的,以求使用最少的數據獲得最佳的圖像質量。目前 MPEG-4 最有吸引力的地方在於它能夠保存接近於 DVD 畫質的小體積視頻文件。你可能一定注意到了,怎麼沒有 MPEG-3 編碼,因為這個項目原本目標是為高分辨率電視(HDTV)設計,隨後發現 MPEG-2 已足夠 HDTV 應用,故 MPEG-3 的研發便中止。

WMV

WMV 格式(後綴為.WMV .ASF):它的英文全稱為 Windows Media Video,也是微軟推出的一種採用獨立編碼方式並且可以直接在網上實時觀看視頻節目的文件壓縮格式。

WMV 格式的主要優點包括:本地或網絡回放,豐富的流間關係以及擴展性等。WMV 格式需要在網站上播放,需要安裝 Windows Media Player(簡稱 WMP),很不方便,現在已經幾乎沒有網站採用了。

Real Video

Real Video 格式(後綴為.RM .RMVB):Real Networks 公司所制定的音頻視頻壓縮規範稱為 Real Media。

用戶可以使用 RealPlayer 根據不同的網絡傳輸速率制定出不同的壓縮比率,從而實現在低速率的網絡上進行影像數據實時傳送和播放。RMVB 格式:這是一種由 RM 視頻格式升級延伸出的新視頻格式,當然性能上有很大的提升。RMVB 視頻也是有著較明顯的優勢,一部大小為 700MB 左右的 DVD 影片,如果將其轉錄成同樣品質的 RMVB 格式,其個頭最多也就 400MB 左右。大家可能注意到了,以前在網絡上下載電影和視頻的時候,經常接觸到 RMVB 格式,但是隨著時代的發展這種格式被越來越多的更優秀的格式替代,著名的人人影視字幕組在 2013 年已經宣佈不再壓制 RMVB 格式視頻。

FLV

Flash Video 格式(後綴為.FLV):由 Adobe Flash 延伸出來的的一種流行網絡視頻封裝格式。隨著視頻網站的豐富,這個格式已經非常普及。

MKV

Matroska 格式(後綴為.MKV):是一種新的多媒體封裝格式,這個封裝格式可把多種不同編碼的視頻及 16 條或以上不同格式的音頻和語言不同的字幕封裝到一個 Matroska Media 檔內。它也是其中一種開放源代碼的多媒體封裝格式。Matroska 同時還可以提供非常好的交互功能,而且比 MPEG 的方便、強大。

視頻編解碼

視頻實際上就是一幀一幀的圖片,拼接起來進行播放;標準的圖像格式使用 RGB 三字節描述像素顏色值,會佔用較大的存儲空間與帶寬。視頻編解碼器會根據前後圖像的變化做運動檢測,通過各種壓縮把變化的結果發送到對方。

實時視頻編碼器需要考慮兩個因素:編碼計算量和碼率帶寬,實時視頻會運行在移動端上,需要保證實時性就需要編碼足夠快,碼率儘量小。基於這個原因現階段一般認為 H.264 是最佳的實時視頻編碼器,而且各個移動平臺也支持它的硬編碼技術;譬如 1080P 進行過 H.264 編碼後帶寬也就在 200KB/S ~ 300KB/S 左右。

編碼基礎

總的來說,常用的編碼方式分為三種:

  • 變換編碼:消除圖像的幀內冗餘。涉及到圖像學裡面的兩個概念:空域和頻域。空域就是我們物理的圖片,頻域就是將物理圖片根據其顏色值等映射為數字大小。而變換編碼的目的是利用頻域實現去相關和能量集中。常用的正交變換有離散傅里葉變換,離散餘弦變換等等。
  • 運動估計和運動補償:消除幀間冗餘。視頻壓縮還存在時間上的關聯性。例如,針對一些視頻變化,背景圖不變而只是圖片中部分物體的移動,針對這種方式,可以只對相鄰視頻幀中變化的部分進行編碼。
  • 熵編碼:提高壓縮效率,熵編碼主要是針對碼節長度優化實現的。原理是針對信源中出現概率大的符號賦予短碼,對於概率小的符號賦予長碼,然後總的來說實現平均碼長的最小值。編碼方式(可變字長編碼)有:霍夫曼編碼、算術編碼、遊程編碼等。

I,B,P 實際上是從運動補償中引出來的,這裡為了後面的方便先介紹一下。

  • I 幀(I-frame): 學名叫做: Intra-coded picture。也可以叫做獨立幀。該幀是編碼器隨機挑選的參考圖像,換句話說,一個 I 幀本身就是一個靜態圖像。它是作為 B,P 幀的參考點。對於它的壓縮,只能使用熵 和 變化編碼 這兩種方式進行幀內壓縮。所以,它的運動學補償基本沒有。
  • P 幀(P‑frame): 又叫做 Predicted picture--前向預測幀。即,他會根據前面一張圖像,來進行圖片間的動態壓縮,它的壓縮率和 I 幀比起來要高一些。
  • B 幀(B‑frame): 又叫做 Bi-predictive picture-- 雙向預測。它比 P 幀來說,還多了後一張圖像的預測,所以它的壓縮率更高。
一文盤點直播技術中的編解碼、直播協議、網絡傳輸與簡單實現

考慮到不同幀傳輸的無序性,我們還需要引入 PTS 與 DTS 來進行控制,使用 DTS 來解碼,PTS 來進行播放。

  • PTS(presentation time stamps): 顯示時間戳,顯示器從接受到解碼到顯示的時間。
  • DTS(decoder timestamps): 解碼時間戳。也表示該 sample 在整個流中的順序

H.26X

H.26X 系列由 ITU 國際電傳視訊聯盟主導包括, H.261、H.262、H.263、H.264、H.265 等:

  1. H.261:主要在老的視頻會議和視頻電話產品中使用。
  2. H.263:主要用在視頻會議、視頻電話和網絡視頻上。
  3. H.264:H.264/MPEG-4 第十部分,或稱 AVC(Advanced Video Coding,高級視頻編碼),是一種視頻壓縮標準,一種被廣泛使用的高精度視頻的錄製、壓縮和發佈格式。
  4. H.265:高效率視頻編碼(High Efficiency Video Coding,簡稱 HEVC)是一種視頻壓縮標準,H.264/MPEG-4 AVC 的繼任者。HEVC 被認為不僅提升圖像質量,同時也能達到 H.264/MPEG-4 AVC 兩倍之壓縮率(等同於同樣畫面質量下比特率減少了 50%),可支持 4K 分辨率甚至到超高畫質電視,最高分辨率可達到 8192×4320(8K 分辨率),這是目前發展的趨勢。直至 2013 年,Potplayer 添加了對於 H.265 視頻的解碼,尚未有大眾化編碼軟件出現。

H.264 是由 ITU 和 MPEG 兩個組織共同提出的標準,整個編碼器包括幀內預測編碼、幀間預測編碼、運動估計、熵編碼等過程,支持分層編碼技術(SVC)。單幀 720P 分辨率一般 PC 上的平均編碼延遲 10 毫秒左右,碼率範圍 1200 ~ 2400kpbs,同等視頻質量壓縮率是 MPEG4 的 2 倍,H.264 也提供 VBR、ABR、CBR、CQ 等多種編碼模式,各個移動平臺兼容性好。

H.264 為了防止丟包和減小帶寬還引入一種雙向預測編碼的 B 幀,B 幀以前面的 I 或 P 幀和後面的 P 幀為參考幀。H.264 為了防止中間 P 幀丟失視頻圖像會一直錯誤它引入分組序列(GOP)編碼,也就是隔一段時間發一個全量 I 幀,上一個 I 幀與下一個 I 幀之間為一個分組 GOP。

一文盤點直播技術中的編解碼、直播協議、網絡傳輸與簡單實現

在實時視頻當中最好不要加入 B 幀,因為 B 幀是雙向預測,需要根據後面的視頻幀來編碼,這會增大編解碼延遲。

MPGA 系列

MPEG 系列由 ISO 國際標準組織機構下屬的 MPEG 運動圖象專家組開發視頻編碼方面主要有:

  1. MPEG-1 第二部分(MPEG-1 第二部分主要使用在 VCD 上,有些在線視頻也使用這種格式。該編解碼器的質量大致上和原有的 VHS 錄像帶相當。)
  2. MPEG-2 第二部分(MPEG-2 第二部分等同於 H.262,使用在 DVD、SVCD 和大多數數字視頻廣播系統和有線分佈系統(cable distribution systems)中。)
  3. MPEG-4 第二部分(MPEG-4 第二部分標準可以使用在網絡傳輸、廣播和媒體存儲上。比起 MPEG-2 和第一版的 H.263,它的壓縮性能有所提高。)
  4. MPEG-4 第十部分(MPEG-4 第十部分技術上和 ITU-T H.264 是相同的標準,有時候也被叫做“AVC”)最後這兩個編碼組織合作,誕生了 H.264/AVC 標準。ITU-T 給這個標準命名為 H.264,而 ISO/IEC 稱它為 MPEG-4 高級視頻編碼(Advanced Video Coding,AVC)。

音頻編碼器

實時音視頻除了視頻編碼器以外還需要音頻編碼器,音頻編碼器只需要考慮編碼延遲和丟包容忍度,所以一般的 MP3、AAC、OGG 都不太適合作為實時音頻編碼器。從現在市場上來使用來看,Skype 研發的 Opus 已經成為實時音頻主流的編碼器。Opus 優點眾多,編碼計算量小、編碼延遲 20ms、窄帶編碼-silk、寬帶編碼器 CELT、自帶網絡自適應編碼等。

同視頻編碼類似,將原始的音頻流按照一定的標準進行編碼,上傳,解碼,同時在播放器裡播放,當然音頻也有許多編碼標準,例如 PCM 編碼,WMA 編碼,AAC 編碼等等。

直播協議

常用的直播協議包括了 HLS, RTMP 與 HTTP-FLV 這三種,其對比如下:

一文盤點直播技術中的編解碼、直播協議、網絡傳輸與簡單實現

HLS

HLS, HTTP Live Streaming 是 Apple 提出的直播流協議,其將整個流分成一個個小的塊,並基於 HTTP 的文件來下載;HLS 由兩部分構成,一個是 .m3u8 文件,一個是 .ts 視頻文件;每一個 .m3u8 文件,分別對應若干個 ts 文件,這些 ts 文件才是真正存放視頻的數據,m3u8 文件只是存放了一些 ts 文件的配置信息和相關路徑,當視頻播放時,.m3u8 是動態改變的,video 標籤會解析這個文件,並找到對應的 ts 文件來播放,所以一般為了加快速度,.m3u8 放在 web 服務器上,ts 文件放在 CDN 上。 HLS 協議視頻支持 H.264 格式的編碼,支持的音頻編碼方式是 AAC 編碼。

一文盤點直播技術中的編解碼、直播協議、網絡傳輸與簡單實現

.m3u8 文件,其實就是以 UTF-8 編碼的 m3u 文件,這個文件本身不能播放,只是存放了播放信息的文本文件:

#EXTM3U m3u文件頭
#EXT-X-MEDIA-SEQUENCE 第一個TS分片的序列號
#EXT-X-TARGETDURATION 每個分片TS的最大的時長
#EXT-X-ALLOW-CACHE 是否允許cache
#EXT-X-ENDLIST m3u8文件結束符
#EXTINF 指定每個媒體段(ts)的持續時間(秒),僅對其後面的URI有效
mystream-12.ts

HLS 協議的使用也非常便捷,將 m3u8 直接寫入到 src 中然後交與瀏覽器解析,也可以使用 fetch 來手動解析並且獲取相關文件:

<video>
<source> class="lazy" data-original="http://devimages.apple.com/iphone/samples/bipbop/masterplaylist.m3u8"
type="application/vnd.apple.mpegurl"
/>

Your browser does not support HTML5 video.


/<source>/<video>

HLS 詳細版的內容比上面的簡版多了一個 playlist,也可以叫做 master。在 master 中,會根據網絡段實現設置好不同的 m3u8 文件,比如,3G/4G/wifi 網速等。比如,一個 master 文件中為:

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2855600,CODECS="avc1.4d001f,mp4a.40.2",RESOLUTION=960x540

live/medium.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=5605600,CODECS="avc1.640028,mp4a.40.2",RESOLUTION=1280x720
live/high.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1755600,CODECS="avc1.42001f,mp4a.40.2",RESOLUTION=640x360
live/low.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=545600,CODECS="avc1.42001e,mp4a.40.2",RESOLUTION=416x234
live/cellular.m3u8

以 high.m3u8 文件為例,其內容會包含:

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:26
#EXTINF:9.901,
http://media.example.com/wifi/segment26.ts
#EXTINF:9.901,
http://media.example.com/wifi/segment27.ts
#EXTINF:9.501,
http://media.example.com/wifi/segment28.ts

該二級 m3u8 文件也可以稱為 media 文件,其有三種類型:

  • live playlist: 動態列表。顧名思義,該列表是動態變化的,裡面的 ts 文件會實時更新,並且過期的 ts 索引會被刪除。默認,情況下都是使用動態列表。
  • event playlist: 靜態列表。它和動態列表主要區別就是,原來的 ts 文件索引不會被刪除,該列表是不斷更新,而且文件大小會逐漸增大。它會在文件中,直接添加 #EXT-X-PLAYLIST-TYPE:EVENT 作為標識。
  • VOD playlist: 全量列表。它就是將所有的 ts 文件都列在 list 當中。如果,使用該列表,就和播放一整個視頻沒有啥區別了。它是使用 #EXT-X-ENDLIST 表示文件結尾。

顯而易見,HLS 的延時包含了 TCP 握手、m3u8 文件下載與解析、ts 文件下載與解析等多個步驟,可以縮短列表的長度和單個 ts 文件的大小來降低延遲,極致來說可以縮減列表長度為 1,並且 ts 的時長為 1s,但是這樣會造成請求次數增加,增大服務器壓力,當網速慢時回造成更多的緩衝,所以蘋果官方推薦的 ts 時長時 10s,所以這樣就會大改有 30s 的延遲。

RTMP

RTMP,Real-Time Messaging Protocol 是由 Adobe 推出的音視頻流傳遞協議;它通過一種自定義的協議,來完成對指定直播流的播放和相關的操作。在 Web 上可以通過 MSE(MediaSource Extensions)來接入 RTMP,基本思路是根據 WebSocket 直接建立長連接進行數據的交流和監聽。RTMP 協議根據不同的套層,也可以分為:

  • 純 RTMP: 直接通過 TCP 連接,端口為 1935
  • RTMPS: RTMP + TLS/SSL,用於安全性的交流。
  • RTMPE: RTMP + encryption。在 RTMP 原始協議上使用,Adobe 自身的加密方法
  • RTMPT: RTMP + HTTP。使用 HTTP 的方式來包裹 RTMP 流,這樣能直接通過防火牆。不過,延遲性比較大。
  • RTMFP: RMPT + UDP。該協議常常用於 P2P 的場景中,針對延時有變態的要求。

RTMP 內部是藉由 TCP 長連接協議傳輸相關數據,所以,它的延時性非常低。並且,該協議靈活性非常好(所以,也很複雜),它可以根據 message stream ID 傳輸數據,也可以根據 chunk stream ID 傳遞數據。兩者都可以起到流的劃分作用。流的內容也主要分為:視頻,音頻,相關協議包等。

一文盤點直播技術中的編解碼、直播協議、網絡傳輸與簡單實現

HTTP-FLV

RTMP 是直接將流的傳輸架在 RTMP 協議之上,而 HTTP-FLV 是在 RTMP 和客戶端之間套了一層轉碼的過程,即:

一文盤點直播技術中的編解碼、直播協議、網絡傳輸與簡單實現

每個 FLV 文件是通過 HTTP 的方式獲取的,所以,它通過抓包得出的協議頭需要使用 chunked 編碼:

Content-Type:video/x-flv
Expires:Fri, 10 Feb 2017 05:24:03 GMT
Pragma:no-cache
Transfer-Encoding:chunked

網絡傳輸

單對單模式主要是怎麼通過路由路徑優化手段達到兩點之間最優,這方面 SKYPE 首先提出基於 P2P 的 Real-time Network 模型。而 單對多模式是一個分發樹模型,各個客戶端節點需要就近接入離自己最近的服務器,然後在服務器與服務器構建一個實時通信網絡。

基礎

推流

所謂推流,就是將我們已經編碼好的音視頻數據發往視頻流服務器中。實時音視頻系統都是一個客戶端到其他一個或者多個客戶端的通信行為,這就意味著需要將客戶端編碼後的音視頻數據傳輸到其他實時音視頻系統都是一個客戶端到其他一個或者多個客戶端的通信行為,這就意味著需要將客戶端編碼後的音視頻數據傳輸到其他客戶端上,一般做法是先將數據實時上傳到服務器上,服務器再進行轉發到其他客戶端,客戶端這個上傳音視頻數據行為稱為推流。

我們可以通過 Nginx 的 RTMP 擴展方便地搭建推流服務器:

rtmp {
server {
listen 1935; #監聽的端口
chunk_size 4000;
application hls { #rtmp推流請求路徑
live on;
hls on;
hls_path /usr/local/var/www/hls;
hls_fragment 5s;
}
}
}

推流會受到客戶端網絡的影響,例如:wifi 信號衰減、4G 弱網、擁擠的寬帶網絡等。為了應對這個問題,實時音視頻系統會設計一個基於擁塞控制和 QOS 策略的推流模塊。

WebRTC

WebRTC 是一個開源項目,旨在使得瀏覽器能為實時通信(RTC)提供簡單的 JavaScript 接口。說的簡單明瞭一點就是讓瀏覽器提供 JS 的即時通信接口。這個接口所創立的信道並不是像 WebSocket 一樣,打通一個瀏覽器與 WebSocket 服務器之間的通信,而是通過一系列的信令,建立一個瀏覽器與瀏覽器之間(peer-to-peer)的信道,這個信道可以發送任何數據,而不需要經過服務器。並且 WebRTC 通過實現 MediaStream,通過瀏覽器調用設備的攝像頭、話筒,使得瀏覽器之間可以傳遞音頻和視頻。WebRTC 有三個重要的部分:MediaStream、RTCPeerConnection、RTCDataChannel:

  • MediaStream:通過設備的攝像頭及話筒獲得視頻、音頻的同步流
  • PeerConnection: 用於構建點對點之間穩定、高效的流傳輸的組件
  • DataChannel:能夠使得瀏覽器之間(點對點)簡歷一個高吞吐量、低延時的信道,用於傳輸任何數據

實時網絡傳輸優化

TCP 與 UDP

在大規模實時多媒體傳輸網絡中,TCP 和 RTMP 都不佔優勢。TCP 是個擁塞公平傳輸的協議,它的擁塞控制都是為了保證網絡的公平性而不是快速到達,我們知道,TCP 層只有順序到對應的報文才會提示應用層讀數據,如果中間有報文亂序或者丟包都會在 TCP 做等待,所以 TCP 的發送窗口緩衝和重發機制在網絡不穩定的情況下會造成延遲不可控,而且傳輸鏈路層級越多延遲會越大。

在實時傳輸中使用 UDP 更加合理,UDP 避免了 TCP 繁重的三次握手、四次揮手和各種繁雜的傳輸特性,只需要在 UDP 上做一層簡單的鏈路 QoS 監測和報文重發機制,實時性會比 TCP 好,這一點從 RTP 和 DDCP 協議可以證明這一點,我們正式參考了這兩個協議來設計自己的通信協議。

UDP 不可避免地存在抖動、亂序、丟包問題,視頻必須按照嚴格是時間戳來播放,否則的就會出現視頻動作加快或者放慢的現象,如果我們按照接收到視頻數據就立即播放,那麼這種加快和放慢的現象會非常頻繁和明顯。也就是說網絡抖動會嚴重影響視頻播放的質量,一般為了解決這個問題會設計一個視頻播放緩衝區,通過緩衝接收到的視頻幀,再按視頻幀內部的時間戳來播放既可。

UDP 除了小範圍的抖動以外,還是出現大範圍的亂序現象,就是後發的報文先於先發的報文到達接收方。亂序會造成視頻幀順序錯亂,一般解決的這個問題會在視頻播放緩衝區裡做一個先後排序功能讓先發送的報文先進行播放。

UDP 在傳輸過程還會出現丟包,丟失的原因有多種,例如:網絡出口不足、中間網絡路由擁堵、socket 收發緩衝區太小、硬件問題、傳輸損耗問題等等。在基於 UDP 視頻傳輸過程中,丟包是非常頻繁發生的事情,丟包會造成視頻解碼器丟幀,從而引起視頻播放卡頓。這也是大部分視頻直播用 TCP 和 RTMP 的原因,因為 TCP 底層有自己的重傳機制,可以保證在網絡正常的情況下視頻在傳輸過程不丟。基於 UDP 丟包補償方式一般有以下幾種:

  • 報文冗餘,報文冗餘很好理解,就是一個報文在發送的時候發送 2 次或者多次。這個做的好處是簡單而且延遲小,壞處就是需要額外 N 倍(N 取決於發送的次數)的帶寬。
  • FEC, Forward Error Correction,即向前糾錯算法,常用的算法有糾刪碼技術(EC),在分佈式存儲系統中比較常見。最簡單的就是 A B 兩個報文進行 XOR(與或操作)得到 C,同時把這三個報文發往接收端,如果接收端只收到 AC,通過 A 和 C 的 XOR 操作就可以得到 B 操作。
  • 丟包重傳,丟包重傳有兩種方式,一種是 push 方式,一種是 pull 方式。Push 方式是發送方沒有收到接收方的收包確認進行週期性重傳,TCP 用的是 push 方式。pull 方式是接收方發現報文丟失後發送一個重傳請求給發送方,讓發送方重傳丟失的報文。丟包重傳是按需重傳,比較適合視頻傳輸的應用場景,不會增加太對額外的帶寬,但一旦丟包會引來至少一個 RTT 的延遲。

擁塞控制

要評估一個網絡通信質量的好壞和延遲一個重要的因素就是 Round-Trip Time(網絡往返延遲),也就是 RTT。評估兩端之間的 RTT 方法很簡單,大致如下:

  • 發送端方一個帶本地時間戳 T1 的 ping 報文到接收端;
  • 接收端收到 ping 報文,以 ping 中的時間戳 T1 構建一個攜帶 T1 的 pong 報文發往發送端;
  • 發送端接收到接收端發了的 pong 時,獲取本地的時間戳 T2,用 T2 – T1 就是本次評測的 RTT。

因為客戶端有可能在弱網環境下進行推流,音視頻數據如果某一時刻發多了,就會引起網絡擁塞或者延遲,如果發少了,可能視頻的清晰不好。在實時音視頻傳輸過程會設計一個自動適應本地網絡變化的擁塞控制算法,像 QUIC 中的 BBR、webRTC 中 GCC 和通用的 RUDP。思路是通過 UDP 協議反饋的丟包和網絡延遲(RTT)來計算當前網絡的變化和最大瞬時吞吐量,根據這幾個值調整上層的視頻編碼器的碼率、視頻分辨率等,從而達到適應當前網絡狀態的目的。

QoS 策略

客戶端推流除了需要考慮網絡上傳能力以外,還需要考慮客戶端的計算能力。如果在 5 年前的安卓機上去編碼一個分辨率為 640P 的高清視頻流,那這個過程必然會產生延遲甚至無法工作。為此需要針對各個終端的計算能力設計一個 QoS 策略,不同計算能力的終端採用不同的視頻編碼器、分辨率、音頻處理算法等,這個 QoS 策略會配合擁塞控制做一個狀態不可逆的查找過程,直到找到最合適的 QoS 策略位置

媒體處理技術

回聲消除

在實時音視頻系統中,回聲消除是一個難點,儘管 webRTC 提供了開源的回聲消除模塊,但在移動端和一些特殊的場景表現不佳。專業的實時音視頻系統會進行回聲消除的優化。回聲消除的原理描述很簡單,就是將揚聲器播放的聲音波形和麥克風錄製的波形進行抵消,達到消除回聲的作用。因為回聲的回錄時間不確定,所以很難確定什麼時間點進行對應聲音數據的抵消。在專業的回聲消除模塊裡面通常會設計一個逼近函數,通過不斷對輸出和輸入聲音波形進行在線學習逼近,確定回聲消除的時間差值點。

簡單 Web 實驗

本部分的代碼實驗參考 MushiChat。

Media Source Extension

MSE 全稱就是 Media Source Extensions。它是一套處理視頻流技術的簡稱,裡面包括了一系列 API:Media Source,Source Buffer 等。在沒有 MSE 出現之前,前端對 video 的操作,僅僅侷限在對視頻文件的操作,而並不能對視頻流做任何相關的操作。現在 MSE 提供了一系列的接口,使開發者可以直接提供 media stream。

const vidElement = document.querySelector('video'); 

if (window.MediaSource) {
const mediaSource = new MediaSource();
vidElement.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen);
} else {
console.log('The Media Source Extensions API is not supported.');
}
function sourceOpen(e) {
URL.revokeObjectURL(vidElement.src);
const mime = 'video/webm; codecs="opus, vp9"';
const mediaSource = e.target;
const sourceBuffer = mediaSource.addSourceBuffer(mime);
const videoUrl = 'droid.webm';
fetch(videoUrl)
.then(function(response) {
return response.arrayBuffer();
})
.then(function(arrayBuffer) {
sourceBuffer.addEventListener('updateend', function(e) {
if (!sourceBuffer.updating && mediaSource.readyState === 'open') {
mediaSource.endOfStream();
}
});
sourceBuffer.appendBuffer(arrayBuffer);
});
}

其中 MediaSource 只是一系列視頻流的管理工具,它可以將音視頻流完整的暴露給 Web 開發者來進行相關的操作和處理。所以,它本身不會造成過度的複雜性。

歡迎工作一到五年的Java工程師朋友們加入Java程序員開發: 854393687

群內提供免費的Java架構學習資料(裡面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!


分享到:


相關文章: