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

王下邀月熊發表於2018-10-26

本文節選自 Live CheatSheet | 直播技術理論基礎與實踐概論很多內容非作者原創,而是對 Live Links 中列舉出的多篇文章的盤點總結,更多直播相關內容可以前往 xCompass 互動式檢索或 MushiChat 檢視程式碼。

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

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

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

  • 偽實時:視訊消費延遲超過 3 秒,單向觀看實時,通用架構是 CDN + RTMP + HLS,譬如很多的直播平臺

  • 準實時: 視訊消費延遲 1 ~ 3 秒,能進行雙方互動但互動有障礙;可以通過 TCP/UDP + FLV 已經實現了這類技術,譬如 YY 直播等

  • 真實時:視訊消費延遲 < 1 秒,平均 500 毫秒,譬如 QQ、微信、Skype 和 WebRTC 等

編解碼

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

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

image

視訊封裝格式

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

image

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 幀來說,還多了後一張影象的預測,所以它的壓縮率更高。

image

考慮到不同幀傳輸的無序性,我們還需要引入 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。

image

在實時視訊當中最好不要加入 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 支援性廣 延時巨高 10s 以上
RTMP 延時性好,靈活 量大的話,負載較高 1s 以上
HTTP-FLV 延時性好,遊戲直播常用 只能在手機 APP 播放 2s 以上

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 編碼。

image

.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 controls autoplay>
  <source
    src="http://devimages.apple.com/iphone/samples/bipbop/masterplaylist.m3u8"
    type="application/vnd.apple.mpegurl"
  />
  <p class="warning">Your browser does not support HTML5 video.</p>
</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 傳遞資料。兩者都可以起到流的劃分作用。流的內容也主要分為:視訊,音訊,相關協議包等。

image

HTTP-FLV

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

image

每個 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 開發者來進行相關的操作和處理。所以,它本身不會造成過度的複雜性。

相關文章