跳至主要内容

[Media] 影音傳輸-傳輸方式與通訊協定

以下內容完全為整理自 30 天之即時網路影音開發攻略(小白本) by 我是小馬克 @ iThome 的筆記,無原創內容。

影音資料的傳輸

方法一:將檔案直接透過網路丟給對方

imgur

  • 透過 AirDrop 直接把檔案丟到別人的電腦
  • 先上傳到雲端空間,產生連結後給他人下載
  • 缺點:全部下載完才能開始聽或看影片

方法二:以串流的方式傳送給對方

imgur

  • 將資料切成一段一段傳出去,使用者可以一邊下載一邊觀看
  • 不會花費使用者的儲存空間,串流的檔案會儲存在使用者的緩衝記憶體中,播完後即捨棄
  • 傳統的影音檔由表頭和表身組成,通常需要在所有資料都傳輸完成後,才可以根據表頭知道這個影音的編碼為何,解碼完後才可以開始觀看。
  • 串流的影音則需要先透過伺服器轉成「流容器」,流容器的一個檔案中包含多塊的表頭和表身,每次傳輸的資料都同時包含了表頭和表身,因此可以一邊傳送檔案一邊觀看影音。

imgur

方法三:即時影音傳輸(直播、視訊通話)

基本的原理和串流傳輸相同,但同時需要使用「推流傳輸協議」,例如 RTMP(Real Time Messaging Protocol —即時訊息協定),影音錄製這端會一小段一小段的上傳,使用者也是一小段一小段的取得。

imgur

常見的網路傳輸協定(Communications Protocol)

imgur

**通訊協定(Communications Protocol)**簡單來說就是溝通的雙方約好要「如何進行溝通」的規定。

特點整理

協議傳輸層選擇聲音編碼影像編碼延遲性
RTSPRTP、TCP、UDPRTP 可支援的都行RTP 可支援的東行
RTMPTCPAAC、MP3H.26X 系列
HLSTCP (因為它是用 HTTP )AAC、MP3H.26X 系列
HTTP-FLVTCP (因為它是用 HTTP )AAC、MP3H.26X 系列
MEPG-DASHTCP (因為它是用 HTTP )沒啥限制,不過 AAC 用比較多H.26X、VPX 系列

支援度

協議支援度 web html5支援度 ios支援度 mac支援度 android
RTSP不支援,需使用套件。不支援,需使用套件。不支援,需使用套件。不支援,需使用套件。
RTMPhtml5 不支援,需使用套件。不支援,需使用套件。不支援,需使用套件。不支援,需使用套件。
HLS支援支援支援支援
HTTP-FLV支援 (flv.js)不支援,需使用套件。不支援,需使用套件。不支援,需使用套件。
MPEG-DASH支援 (dash.js)不支援,需使用套件。不支援,需使用套件。不支援,需使用套件。

30-18 之影音傳輸協議總整理 by 我是小馬克 @ iThome

TCP/IP 通訊協定

TCP/IP 是一組協定套組,主要是為了讓電腦可以在網路上進行端點和端點間的溝通,TCP/IP 總共可以分成四個層級,每個層級又有各自的協定來完成某些事情。更詳細的說明可以參考 [[網際網路] TCP/IP 階層模型基礎](/Users/pjchen/Projects/Notes/source/_posts/Internet-MIS-IS/[Internet] TCP_IP 階層模型基礎.md) @ 筆記

imgur

TCP/UDP 協定:一般檔案傳輸

屬於傳輸層的協定,更詳細的說明可以參考 [[網際網路] TCP/IP 階層模型基礎](/Users/pjchen/Projects/Notes/source/_posts/Internet-MIS-IS/[Internet] TCP_IP 階層模型基礎.md) @ 筆記

RTP/RTCP 協定:傳輸串流媒體

因為在 UDP 協定中只定義了來源端和目的端的 port,但是並沒有定義需要使用的解碼方式,因此出現了即時傳輸協定(RTP, Real-time Transport Protocol)

RTP 和 TCP/UDP 協定一樣屬於傳輸層,其重點在於端點到端點間的串流媒體傳輸,定義了傳輸串流媒體的封包標準(參數標準),它本身就可以算是一種流容器,但只適用於無損編碼,目前廣泛用於網路電視和網路會議。

RTP 通常是搭配 TCP/UDP 使用,封包會像是這樣子:

RTP 表頭 + UDP/TCP 表頭 + 表身(就是資料)

詳細的封包組成在這 30-12 之 RTP/RTCP 傳輸協議 @ iThome by 我是小馬克

因此會有(目前 RTP 多是搭配 UDP 使用):

  • RTP over UDP:效率較好但品質較差
  • RTP over TCP:效率較差但品質較好

其中在 RTP 的標頭中會包含:

bitfielddescribe
2V (Version)用來說明使用的 RTP 版本 (default 為 2)。
1P (Padding)為 1 的話,就會在最後面的 payload 後面加填充位置。
1X (Extension)為 1 的話,就代表存在 header 的擴展。
4CC (CSRC count)用來記錄 CSRC 的數量。(csrc 後面會說)。
1M (Marker)配置文件定義。
7PT (payload type)就是說明你要傳輸的語音視頻的編碼是啥 (ex. H.264, PCM)。
16Sequence Number每發送一個封包就 + 1 ,接受端可以用它來判斷封包順序。
32Timestamp時間戳,用來記錄採樣第一個 bit 資料(音視頻)的時間。
32SSRC (Synchronization source)記錄封包的發送方,它只是隨機的從 md5 隨機演算法中選取,然後在同一個視頻會議中,不會有相同的 ssrc 值。
(0~15) X 32CSRC (Contributing source)記錄這所有參於方的來源之 ssrc。
  • 同步來源(SSRC, Synchronization source):也就是建立媒體的來源,即使同一個 IP 位址但不同的輸入裝置(例如麥克風),仍然會有不同的 SSRC 值
  • CSRC (Contributing source):存放了組成這個 RTP 流的所有 SSRC,也就是由多個輸入裝置(麥克風、攝影機)所組成

imgur

因為 RTP 本身並不保證串流中間有沒有封包遺失,而只是負責傳送,因此為了確保 RTP 的**服務品質(Qos, Quality of Service)**而有了 RTCP (RTP Control Protocol)

其中的標頭如下:

bitfielddescribe
2VersionRTP 的版本號,預設為 2 。
3P (padding)在最後的位置增加空間,大部份都是給加密使用的地方。
8RC接受方報告的數量。
16Packet Type用來判斷這個封包是那一種 RTCP 類型。

Packet Type 又可以分為:

codetypedescribe
200SR(Sender Report)發送方的報告
201RR(Receiver Report)接受方的報告
202SDES(Source Description Items)來源端
203BYE結束
204APP(Application)特定應用

在 RTCP 協議中:

  • 「接收方」每收到一個 RTP 封包時就會產生 RR 報告(包含 SSRC 和流失率)
  • 「發送方」每傳出一個 RTP 封包時則會發出 SR 讓接收方知道發送方的資訊。
  • 標頭中的 SDES(Source Description Items) 則會給出會議參與者的描述,包含參與者的規範名稱(CNAME, Canonical NAME),也就是機器的別名,與會者只需要使用別名就可以找到發送者。

RTSP 協定:操作串流媒體

**即時串流協定(RTSP, Real Time Streaming Protocol)是設計來讓客戶端(Client)與伺服器端(Server)針對串流媒體進行溝通,以此控制串流媒體伺服器的協定,像是快轉或暫停影片,在 RTSP 中定義了控制串流媒體的方法和參數,當伺服器接收到這些動作後,就會以此傳輸影片給使用者。目前很多東西仍不支援這種協定,它多用在隨選視訊(VOD, video on demand)**和視訊會議。

RTSP 用於伺服器和客戶端間的溝通實例可以回到原本的文章 30-13 之 RTSP 傳輸協議 觀看。

RTSP 只處理串流的控制,並不會去管用什麼方式傳輸,但一般來說會使用 RTP over UDP 或 UDP 來傳輸。

RTMP 協定:Adobe 專為 flash 設計

**即時訊息協定(RTMP, Real-Time Messaging Protocol)**是 Adobe 所開發,設計來讓 Flash 與媒體串流伺服器進行溝通。

HLS 協定:透過 HTTP 傳輸串流媒體

HLS (HTTP Live Streaming) 由蘋果公司提出,在此之前大部分的媒體串流傳輸都是由 Adobe 的 RTMP 所掌控,其最重要的功能是讓 client 和 server 可以透過 HTTP 進行媒體串流的傳輸,在這個協定中會將媒體切成許多的小檔案,client 則透過一個一個發 http 請求去下載。

HTTP Live Streaming Overview @ Apple Developer

協定內容

在 HLS 協定中,會將影音轉成兩種檔案:

  • .m3u8:這是一個索引檔,裡面記錄了一段影音,被分割成哪些檔案存放
  • .ts:這是實際的影音檔,而且也是流容器,因此可以一邊播放一邊下載

imgur

傳輸方式

若 client 想要聽這一段聲音,他會先向 server 發送 .m3u8 的檔案請求,如此 Server 會回傳 .m3u8 的檔案,client 則會遵循 HLS 協定去取得 .m3u8 中所定義的 .ts 檔。

imgur

.m3u8 檔案的內容會像這樣:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:5
#ID3-EQUIV-TDTG:2016-11-26T02:40:23
#EXT-X-MEDIA-SEQUENCE:376
#EXT-X-TWITCH-ELAPSED-SYSTEM-SECS:1511.137
#EXT-X-TWITCH-ELAPSED-SECS:1508.980
#EXT-X-TWITCH-TOTAL-SECS:1535.137
#EXTINF:4.000,
index-0000000377-6zCW.ts
#EXTINF:4.000,
index-0000000378-vHZS.ts
#EXTINF:4.000,
index-0000000379-Gkgv.ts
#EXTINF:4.000,
index-0000000380-PNoG.ts
#EXTINF:4.000,
index-0000000381-h58g.ts
#EXTINF:4.000,
index-0000000382-W88t.ts

其中比較重要的是 EXTINF 的部分,這裡表示總共有 6 支 .ts 檔,每個 .ts 檔有 4 秒,因此這部影音一共有 24 秒。

HLS 的缺點:延遲問題

HLS 有比較嚴重的延遲問題,如果是點播已存在的影音檔案沒有太大的問題,但若是即時通訊與直播的話,直撥主講話後可能要 10 秒後聽眾才聽得到,但相對的畫面不會卡頓。

調整片段的數量與長度

每個 .ts 檔的長度是可以調整的,如果把每個片段都切成很小的長度,如此延遲的時間會少非常多,但伺服器的負擔卻會加重,非常不建議使用。因此要做直播或很在意延遲的話,應直接放棄 HLS

支援的編碼格式:H.264, AAC, MP3

HLS 支援影像編碼為 H.264、聲音編碼為 AACMP3

HTTP-FLV 協定:減少 HLS 延遲的情況

由於 HLS 有比較嚴重的延遲問題,HTTP-FLV 則試著用 HTTP 完成低延遲的媒體串流傳輸,它在 HTML5 的支援度佳,且延遲性較 HLS 優,是目前直播主流用的通訊協定。透過 HTTP-FLV 協定,直播主這端會用任何形式(例如 RMTP)將影音傳送到 server,server 會將此影音轉成 FLV 容器,而 client 則透過 HTTP 來請求這個影音,server 則使用「HTTP 流式傳輸」的方式將影音一段一段丟給 client。

目前支援的影像編碼包含 H.264、聲音編碼包含 AAC, MP3,使用的則是 .flv 流容器。

imgur

HTTP 流式傳輸

在 HTTP 流式傳輸的情況下,當 client 發送 HTTP 請求後,server 會先回傳許多的 TCP 小封包,當判斷是最後一包時,就會回傳 HTTP response,裡面包含有 TCP 中最後一段資料。這種做法會在 HTTP 的 response header 中加上,如此 HTTP response 就會變成一段一段:

Transfer-Encoding: chunked

Node.js 的 http 本身如果不執行 res.end() 這一段,它就會自動的幫你在 response header 中加 chunked。

MPEG-DASH 協定:HLS 的替代版

keywords: .mpd, .ts, .mp4

由於 HLS 是由蘋果所主導,並不算國際通用協定,一切必須聽從蘋果的指示,因此在許多大廠的合作下即產生了「動態自適應流(DASH, Dynamic Adaptive Streaming over HTTP)」。它的作法和概念與 HLS 幾乎一樣,都是將影音切成許多小檔後,請 client 發 http 一個一個下載,它支持任何的編碼格式,例如, H.26XVPX。目前主要由 Youtube 和 Facebook 使用。

DASH 會產生副檔名為 .mpd 的索引檔,裡面記錄了這段影音一共由哪些小檔案所組成,client 則根據這個檔案來得知要抓取哪些檔案。DASH 可以將原本的影音檔切成多段 .ts.mp4 的流容器,並且支援動態碼率,因此可以根據使用者的狀態提供不同解析度的影音(例如 1080p, 720p)。

imgur

mpd 索引檔

這是一份類似 XML 的檔案,裡面會包含這些資訊:

  • Period:一部影音可以有多個 Period,用來表示不同的場景或曲目,或用來穿插廣告,這中間描述該 Period 的時間。
  • AdaptationSet:用來說明這個媒體流的資訊。
  • ContentComponent:說明此媒體留屬於影片(video)或聲音(audio
  • Representation:用來表示不同的螢幕大小或碼率,DASH 可以根據使用的狀態抓取不同解析度的影音,例如,1080p720p
  • SegmentBase:實際的檔案

.mpd 的內容會像這樣

<MPD xmlns="urn:mpeg:DASH:schema:MPD:2011" mediaPresentationDuration="PT0H3M1.63S" minBufferTime="PT1.5S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" type="static">
<Period duration="PT0H3M1.63S" start="PT0S">
<AdaptationSet>
<ContentComponent contentType="video" id="1" />
<Representation bandwidth="4190760" codecs="avc1.640028" height="1080" id="1" mimeType="video/mp4" width="1920">
<BaseURL>car-20120827-89.mp4</BaseURL>
<SegmentBase indexRange="674-1149">
<Initialization range="0-673" />
</SegmentBase>
</Representation>
</AdaptationSet>

<AdaptationSet>
<ContentComponent contentType="audio" id="2" />
<Representation bandwidth="127236" codecs="mp4a.40.2" id="6" mimeType="audio/mp4" numChannels="2" sampleRate="44100">
<BaseURL>car-20120827-8c.mp4</BaseURL>
<SegmentBase indexRange="592-851">
<Initialization range="0-591" />
</SegmentBase>
</Representation>
</AdaptationSet>
</Period>
</MPD>

參考資源