[Media] 影音傳輸-傳輸方式與通訊協定
以下內容完全為整理自 30 天之即時網路影音開發攻略(小白本) by 我是小馬克 @ iThome 的筆記,無原創內容。
影音資料的傳輸
方法一:將檔案直接透過網路丟給對方
- 透過 AirDrop 直接把檔案丟到別人的電腦
- 先上傳到雲端空間,產生連結後給他人下載
- 缺點:全部下載完才能開始聽或看影片
方法二:以串流的方式傳送給對方
- 將資料切成一段一段傳出去,使用者可以一邊下載一邊觀看
- 不會花費使用者的儲存空間,串流的檔案會儲存在使用者的緩衝記憶體中,播完後即捨棄
- 傳統的影音檔由表頭和表身組成,通常需要在所有資料都傳輸完成後,才可以根據表頭知道這個影音的編碼為何,解碼完後才可以開始觀看。
- 串流的影音則需要先透過伺服器轉成「流容器」,流容器的一個檔案中包含多塊的表頭和表身,每次傳輸的資料都同時包含了表頭和表身,因此可以一邊傳送檔案一邊觀看影音。
方法三:即時影音傳輸(直播、視訊通話)
基本的原理和串流傳輸相同,但同時需要使用「推流傳輸協議」,例如 RTMP(Real Time Messaging Protocol —即時訊息協定),影音錄製這端會一小段一小段的上傳,使用者也是一小段一小段的取得。
常見的網路傳輸協定(Communications Protocol)
**通訊協定(Communications Protocol)**簡單來說就是溝通的雙方約好要「如何進行溝通」的規定。
特點整理
協議 | 傳輸層選擇 | 聲音編碼 | 影像編碼 | 延遲性 |
---|---|---|---|---|
RTSP | RTP、TCP、UDP | RTP 可支援的都行 | RTP 可支援的東行 | 低 |
RTMP | TCP | AAC、MP3 | H.26X 系列 | 低 |
HLS | TCP (因為它是用 HTTP ) | AAC、MP3 | H.26X 系列 | 高 |
HTTP-FLV | TCP (因為它是用 HTTP ) | AAC、MP3 | H.26X 系列 | 低 |
MEPG-DASH | TCP (因為它是用 HTTP ) | 沒啥限制,不過 AAC 用比較多 | H.26X、VPX 系列 | 高 |
支援度
協議 | 支援度 web html5 | 支援度 ios | 支援度 mac | 支援度 android |
---|---|---|---|---|
RTSP | 不支援,需使用套件。 | 不支援,需使用套件。 | 不支援,需使用套件。 | 不支援,需使用套件。 |
RTMP | html5 不支援,需使用套件。 | 不支援,需使用套件。 | 不支援,需使用套件。 | 不支援,需使用套件。 |
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) @ 筆記
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 的標頭中會包含:
bit | field | describe |
---|---|---|
2 | V (Version) | 用來說明使用的 RTP 版本 (default 為 2)。 |
1 | P (Padding) | 為 1 的話,就會在最後面的 payload 後面加填充位置。 |
1 | X (Extension) | 為 1 的話,就代表存在 header 的擴展。 |
4 | CC (CSRC count) | 用來記錄 CSRC 的數量。(csrc 後面會說)。 |
1 | M (Marker) | 配置文件定義。 |
7 | PT (payload type) | 就是說明你要傳輸的語音視頻的編碼是啥 (ex. H.264, PCM)。 |
16 | Sequence Number | 每發送一個封包就 + 1 ,接受端可以用它來判斷封包順序。 |
32 | Timestamp | 時間戳,用來記錄採樣第一個 bit 資料(音視頻)的時間。 |
32 | SSRC (Synchronization source) | 記錄封包的發送方,它只是隨機的從 md5 隨機演算法中選取,然後在同一個視頻會議中,不會有相同的 ssrc 值。 |
(0~15) X 32 | CSRC (Contributing source) | 記錄這所有參於方的來源之 ssrc。 |
同步來源(SSRC, Synchronization source)
:也就是建立媒體的來源,即使同一個 IP 位址但不同的輸入裝置(例如麥克風),仍然會有不同的 SSRC 值CSRC (Contributing source)
:存放了組成這個 RTP 流的所有 SSRC,也就是由多個輸入裝置(麥克風、攝影機)所組成
因為 RTP 本身並不保證串流中間有沒有封包遺失,而只是負責傳送,因此為了確保 RTP 的**服務品質(Qos, Quality of Service)**而有了 RTCP (RTP Control Protocol)。
其中的標頭如下:
bit | field | describe |
---|---|---|
2 | Version | RTP 的版本號,預設為 2 。 |
3 | P (padding) | 在最後的位置增加空間,大部份都是給加密使用的地方。 |
8 | RC | 接受方報告的數量。 |
16 | Packet Type | 用來判斷這個封包是那一種 RTCP 類型。 |
Packet Type 又可以分為:
code | type | describe |
---|---|---|
200 | SR(Sender Report) | 發送方的報告 |
201 | RR(Receiver Report) | 接受方的報告 |
202 | SDES(Source Description Items) | 來源端 |
203 | BYE | 結束 |
204 | APP(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
:這是實際的影音檔,而且也是流容器,因此可以一邊播放一邊下載
傳輸方式
若 client 想要聽這一段聲音,他會先向 server 發送 .m3u8
的檔案請求,如此 Server 會回傳 .m3u8
的檔案,client 則會遵循 HLS 協定去取得 .m3u8
中所定義的 .ts
檔。
.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
、聲音編碼為 AAC
和 MP3
。
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
流容器。
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。