# 透過 WebRTC 與 Websocket 實作簡易的視訊服務
_分享者:LiangC_
_分享日期:2023.10.13_
_分享地點:Appworks School 10 sharing
目錄如下:
[TOC]
## WebRTC 介紹
**WebRTC(Web Real-Time Communication)** 它本身既代表 API,也是多個 Protocol 的綜合實踐,主要目標是讓網頁或移動端應用程式無須安裝額外插件或軟體,就能建立即時、雙向、安全的點對點(Peer to Peer)連線,藉此提供更有效率的通訊選擇,常應用於視訊、音訊、檔案傳輸服務。
以瀏覽器而言,目前大多都有實作 WebRTC API,支援度已經很高了:

_(圖片來源:[Can I Use](https://caniuse.com/?search=WebRTC))_

_(圖片來源:[Practical WebRTC: A Complete WebRTC Bootcamp for Beginners](https://learning.oreilly.com/videos/practical-webrtc-a/9781801810012/))_
### 延伸問題一:WebRTC 只能用於網頁服務嗎?
並非如此。
雖然它核心設計的確是要讓網頁應用能夠輕鬆地實現即時通訊,但它的核心技術和 Protocol 也可以在其他環境中使用,以下是一些範例:
- 移動端應用: 通過在移動端應用整合 WebRTC,開發人員可以在 Android 和 iOS 等移動平台上建立即時音視訊和資料通訊的應用。
- 桌面應用: 可以在桌面應用中整合 WebRTC,例如:通過 Electron 或其他框架來建立跨平台的桌面應用。
- IoT (物聯網) 和嵌入式系統: 在 IoT 和嵌入式系統中,WebRTC 可以用於實時音視訊通訊和資料交換,例如在智慧家庭、安全監控和遙控機器人等領域。
### 延伸問題二:哪些是 WebRTC 的知名服務?
WebRTC 已經被應用在各種常見的應用程式中,以實現更有效率的即時通訊,特別是在視訊和音訊聊天的領域。
- Google Meet: WebRTC 就是由 Google 所倡導和開源出的專案,最知名的應用就是 Google Meet 的即時通訊服務。
- Facebook Messenger: Facebook 已將 WebRTC 整合到其 Messenger 服務中,以提供視訊聊天和群組視訊聊天功能。此外,Facebook Live 和 VR Chat 也利用 WebRTC 進行視訊通訊。
- Discord:Discord 最初是遊戲玩家的社交平台,也有利用 WebRTC 進行其實時通訊功能。
基本上,現今大多有用到即時通訊的功能,都會透過 WebRTC 處理。
### 延伸問題三:為什麼深入學習 WebRTC 是困難的?
- **涵蓋多種 Protocal**:WebRTC 涵蓋了多種 Protocol 每種 Protocol 演進長達 20 年以上,且還在持續演進中,因此若要深入細節,其中的複雜性是非常高的。
- **技術複雜性高**:WebRTC 的實踐所需要的知識能力包含前端技術、後端技術、網路層技術、多媒體傳輸技術等等,若要深入理解,會需要既廣又深的技術能力。
- **實作應用情境的調整困難**:由於 WebRTC 涉及的技術範圍廣,有些屬於較難控的網路層,要應對多種錯誤情境的調適,假定要對效能有極高的要求或情境特殊的處理,都會較為困難。
綜合以上,本次分享會專注談論架構概念以及實作簡單版本的視訊服務,並不會深究每個 Protocol 的細節或網路層的細節。

_(圖片來源:[Practical WebRTC: A Complete WebRTC Bootcamp for Beginners](https://learning.oreilly.com/videos/practical-webrtc-a/9781801810012/))_

_(圖片來源:[WebRTC for the Curious](https://webrtcforthecurious.com/docs/01-what-why-and-how/))_
## WebRTC 四大概念
### Signaling
#### 簡介
當創建最初創建兩端 WebRTC Agent 應用程式時,想要連線的兩端,對彼此是一無所知,此時就需要有 Signaling 的過程,實作上會透過 Signaling Server 讓兩端能夠彼此交換某些必要訊息,像是媒體類型、傳輸協議等等,藉此讓彼此能建構出點對點的雙向即時連線。
簡單理解:兩端要先互相知道要怎麼傳遞、傳遞哪些格式,才能進行傳遞和接收。
#### SDP Protocol
在 Signaling 概念中,是透過 SDP(Session Description Protocol) protocol 去實踐。
這個 Protocal 其實並非單為了 WebRTC 而設立,在此之前就已經存在,這個 Session Description Protocal 顧名思義會描述傳遞內容的所有信息,內容會以 `Key=Value` 的形式存在,其中 Key 代表各種意義的縮寫:
- v - Version, should be equal to 0.
- o - Origin, contains a unique ID useful for renegotiations.
- s - Session Name, should be equal to -.
- t - Timing, should be equal to 0 0.
- m - Media Description (m=<media> <port> <proto> <fmt> ...), described in detail below.
- a - Attribute, a free text field. This is the most common line in WebRTC.
- c - Connection Data, should be equal to IN IP4 0.0.0.0.
一份 SDP 中可包含多個 Media Description,而一個 Media Description 通常代表一個 Media Stream。
例如:一個影片有兩個 Video Stream 外加三個 Audio Stream,那就需要五個 Media Description 描述之。
實際上的 SDP 可能是長這樣:
```
v=0
m=audio 4000 RTP/AVP 111
a=rtpmap:111 OPUS/48000/2
m=video 4000 RTP/AVP 96
a=rtpmap:96 VP8/90000
a=my-sdp-value
......more
```
這裡定義兩個 Media Description
- audio 帶著 fmt 111,並指定 codec 為 OPUS。
- video 帶著 fmt 96,codec 為 VP8,並帶著第二個屬性值為 my-sdp-value。
#### 交換 SDP 步驟
大方向來看,實際要建立 P2P 連線前,會跑交換 SDP 的步驟如下:
- Client A 創建 SDP Offer
- Client A 傳遞 SDP Offer 給 Server,Server 傳遞給 Client B
- Client B 接收 SDP Offer
- Client B 創建 SDP Answer
- Client B 傳遞 SDP Answer 給 Server,Server 傳遞給 Client A
- Client A 接收到 SDP Answer


_(圖片來源:[Practical WebRTC: A Complete WebRTC Bootcamp for Beginners](https://learning.oreilly.com/videos/practical-webrtc-a/9781801810012/))_
### Connecting
#### 簡介
P2P 點對點的建立並非只要交換 SDP 就會開啟,還需要「連接 Connecting」彼此。而若要連結,會需要知道彼此的位置,近一步說算是彼此的 IP 和相關資訊,當知道彼此的位置相關資訊後,就有機會連接彼此,然而這是很理想的說法,實際情況上,還會牽涉到 NAT(Network Address Translation,網絡地址轉換)的複雜運作。
#### NAT(Network Address Translation)
NAT 是一種網絡技術,它允許私有(內部)網絡地址被轉換為公共(外部)IP 地址,反之亦然。這種技術主要用於節省 IP 地址的數量,並提供網絡的安全性。
具體來說,每台電腦在網路上都會有個 IP 位置,而 IP 是由位元數字組成,會有數量限制,例如:IPv4 使用32 位元(4位元組)位址,因此位址空間中只有約四十億(4,294,967,296,232)個位址,不過,一些位址是為特殊用途所保留的,所以實際上會更少。雖然後來有更長位元的 IPv6 可以應用,但一樣有天被用完,這時候 NAT 就有用處了。
NAT 可以讓一個區域的電腦共用 1 個 IP,所以也多了所謂的內網、外網。除了提供共用 IP 外,NAT 同時也提供了基本安全性,不同 NAT 會有不同的安全性連線規則,讓連線更安全。
1. Full Cone NAT
- 說明:內部主機 A 的所有請求都會被映射到同一個外部地址和端口,並且任何外部主機,不論其身份,均可通過該映射地址向 A 發送數據。這種方式非常自由,但安全性較低。
- 簡例:內部主機 A 私有位置 `192.168.1.2:8080`,通過 NAT 映射到 `203.0.113.1:8080`。現在,任何外部主機都可通過 `203.0.113.1:8080` 向 A 發送數據。
2. Address-Restricted Cone NAT
- 說明:內部主機 A 的所有請求都會被映射到同一個外部地址和端口,但只有那些已經被內部主機 A 發送過訊息的外部主機 IP,才能透過該映射地址向 A 發送數據。
- 簡例:內部主機 A 私有位置 `192.168.1.2:8080`,通過 NAT 映射到 `203.0.113.1:8080`。現在,A 曾經聯繫過外部主機 C `303.0.113.1`,如此一來,`303.0.113.1` 的任何端口(例如 `303.0.113.1:3000`、`303.0.113.1:4000`...)都能透過 `203.0.113.1:8080` 向 A 發送數據。
3. Port-Restricted Cone NAT
- 說明:內部主機 A 的所有請求都會被映射到同一個外部地址和端口,但只有那些已經被內部主機 A 發送過訊息的外部主機的 IP + Port,才能透過該映射地址向 A 發送數據。這種 NAT 相比上一種多了端口的限制。
- 簡例:內部主機 A 私有位置 `192.168.1.2:8080`,通過 NAT 映射到 `203.0.113.1:8080`。現在,A 曾經聯繫過外部主機 C `303.0.113.1:3000`,如此一來,只有 `303.0.113.1:3000` 能透過 `203.0.113.1:8080` 向 A 發送數據。
4. Symmetric NAT
- 說明:在對稱型 NAT 中,來自內部主機 A 的每個請求(即使是目的 IP 和端口完全相同的請求)都可能被映射到不同的外部地址和端口。這種 NAT 的特點是,它會根據內部主機的目的地址和端口以及源地址和端口來分配外部地址和端口。這使得**Symmetric NAT 在 P2P 連接中很難直接使用,因為外部主機無法預先知道應該用哪個地址和端口來接收或發送數據**。
- 簡例:內部主機 A 私有位置 `192.168.1.2:8080`,當它嘗試連接到外部主機 B `203.0.113.1:8080` 時,NAT可能會分配外部地址和端口 `198.51.100.1:6000`。但是,如果稍後內部主機 A 從相同的端口嘗試連接到另一個外部主機 C `203.0.113.1:8081`,NAT 可能會分配不同的外部地址和端口,例如 `198.51.100.1:6001`。在這種情況下,**即使是對同一外部主機的不同連接也可能得到不同的映射地址和端口**。

_([連結](https://info.support.huawei.com/info-finder/encyclopedia/zh/NAT.html))_
#### NAT 穿透 (NAT Traversal)
由於 NAT 會修改通信中的 IP 地址或端口,直接通信變得困難。NAT 穿透 (NAT Traversal) 技術旨在解決這個問題,使得位於不同類型的 NAT 環境,依然能夠實踐端點通信。
簡而言之,需要有方式知道彼此的位置,才能夠通信。
- STUN(Session Traversal Utilities for NAT):STUN協議能幫助裝置發現自己的公共 IP 地址和端口,以及 NAT 的類型。它可以讓裝置知道自己該如何被外部訪問。
- TURN(Traversal Using Relays around NAT):當直接通信無法實現時,TURN 協議提供了一個中繼服務來轉發數據,此時就不算是 P2P 連線,而是藉由中心 Server 串接。
#### ICE Protocol
ICE(Interactive Connectivity Establishment)是一種協議,它結合了 STUN 和 TURN 技術來找到最佳的通信路徑,讓 WebRTC 運行時,可以是直接的 P2P 連接,也可以是通過 TURN 服務器的連接,端看當時的連線狀況而定。
- 情況一:共用網絡中

- 情況二:需要 STUN

- 情況三:需要 TURE

_(圖片來源:[Practical WebRTC: A Complete WebRTC Bootcamp for Beginners](https://learning.oreilly.com/videos/practical-webrtc-a/9781801810012/))_
### Communicating
#### 簡介
在 WebRTC 中,通信是通過不同的協議和技術來實現的,主要分為「媒體通信」和「數據通信」兩個方面。
#### RTP/RTCP for transport media
RTP (Real-Time Transport Protocol):
- RTP 是一個專為實時傳輸音頻和視頻數據而設計的協議。它提供了時間戳和序列號,以支持數據的同步和順序傳輸。
通過 RTP,接收端能夠正確地重新組合來自發送端的媒體數據,並且能夠處理網絡抖動和包丟失。
RTCP (Real-Time Transport Control Protocol):
- RTCP 是與 RTP 一起使用的協議,用於提供傳輸的反饋信息,例如包丟失率、抖動和網絡延遲等。
RTCP 允許發送端和接收端了解網絡狀況,並相應地調整傳輸參數,例如改變碼率或使用不同的編碼。
通過 RTP 和 RTCP 的結合,WebRTC 能夠提供高效、同步並且有反饋的媒體傳輸服務,以確保音頻和視頻通信的質量和效率。

_(圖片來源:[Practical WebRTC: A Complete WebRTC Bootcamp for Beginners](https://learning.oreilly.com/videos/practical-webrtc-a/9781801810012/))_
#### SCTP for other data
SCTP (Stream Control Transmission Protocol) 是一個多路復用的傳輸協議,它允許在一個單一的連接中同時傳輸多個獨立的數據流。在 WebRTC 中,SCTP 通常被用於以下方面:
- 數據通道(Data Channels):
WebRTC 的數據通道允許在參與者之間直接傳輸數據,例如文字消息、文件或其他任何類型的二進制數據。
SCTP 提供了可靠和不可靠的傳輸選項,以及按序和未按序的傳輸,使得開發人員能夠根據應用需求選擇最適合的傳輸模式。
- 多路復用和流控制:
SCTP 的多路復用功能允許多個數據流在一個連接中共享,每個數據流都有自己的序列號,以保證數據的順序和完整性。
SCTP 也提供了流控制和擁塞控制機制,以確保網絡資源的高效利用和數據傳輸的可靠性。
通過 SCTP,WebRTC 可以提供高效、可靠並且可定制的數據通信服務,以滿足不同的應用需求和網絡環境。

_(圖片來源:[Practical WebRTC: A Complete WebRTC Bootcamp for Beginners](https://learning.oreilly.com/videos/practical-webrtc-a/9781801810012/))_
### Securing
#### 簡介
由於 WebRTC 通常用於傳輸敏感的通信數據,例如視頻和音頻流,因此需要確保這些數據在傳輸過程中不會被未經授權的第三方訪問或篡改。WebRTC 使用了多種標準協議來保護通信的安全。
#### SRTP Protocol
SRTP(Secure Real-Time Transport) Protocol 是 RTP (Real-Time Transport Protocol) 的安全版本,用於保護實時媒體流的傳輸。SRTP 提供了加密、消息完整性檢查和重播保護,以確保媒體數據在傳輸過程中的安全和完整。
主要是與**媒體傳輸有關(Media Communication)**。
SRTP 用於保護視頻和音頻數據流的傳輸,而 RTCP (Real-Time Transport Control Protocol) 用於傳輸控制信息,如報告包丟失率、抖動等,來協助管理實時媒體連接。SRTP 也可以用於保護 RTCP 消息。
#### DTLS Protocol
DTLS(Datagram Transport Layer Security) 是 TLS (Transport Layer Security) 的數據包版本,用於保護基於數據包的通信。DTLS 提供了與 TLS 相同級別的安全保護,但是適用於不可靠的傳輸協議,如 UDP。
主要是與**媒體外的傳輸有關(Data Communication)**。
DTLS 在 WebRTC 中主要用於保護 SCTP (Stream Control Transmission Protocol) 通信。SCTP 是一種用於傳輸數據的協議,它支持數據流的多路復用和可靠傳輸。在 WebRTC 中,SCTP 通常用於傳輸非媒體數據,例如文字消息或其他應用數據。
## WebRTC 實作架構
上面提到的比較是四大概念,而在實作上,通常會專注於 Signaling Server, STUN Server, TUNE Server 的流程。

_(圖片來源:[Practical WebRTC: A Complete WebRTC Bootcamp for Beginners](https://learning.oreilly.com/videos/practical-webrtc-a/9781801810012/))_
#### Signaling Server
Signaling Server 是 WebRTC 架構中的重要部分,負責協助 WebRTC 的節點(Peers)之間進行初始連接。
通過 Signaling Server,節點可以交換彼此的媒體元數據信息(如音頻、視頻的編碼/解碼能力)、網絡信息(如 IP 地址和端口)以及任何其他需要的信息以便建立連接。
Signaling Server 可以使用任何通信協議,如 WebSocket, HTTP 等,來完成這些交換。而通常會使用 WebSocket,因為 Client / Server 兩端可以主動傳輸資訊。
p.s 本次實作,最主要就會實作 Signaling Server
#### STUN Server
STUN(Session Traversal Utilities for NAT)服務器是用於幫助節點發現其公共 IP 地址和端口的。
當一個節點位於 NAT(網絡地址轉換)後面時,它可能不知道自己的公共 IP 地址和端口。
STUN 服務器可以幫助它發現這些信息,從而允許它將這些信息通過信令服務器分享給其他節點,以便建立連接。
p.s 本次實作,只會拿別人架好的 STUN Server 來用
#### TUNE Server
由於 NAT 和防火牆的限制,直接的節點到節點連接並不總是可能的。在這些情況下,TURN(Traversal Using Relays around NAT)服務器可以提供幫助。
TURN 服務器充當中繼,允許節點將媒體數據發送到 TURN 服務器,然後 TURN 服務器將數據轉發到另一個節點。這樣,即使節點之間無法直接通信,它們也可以通過 TURN 服務器通信。
p.s 本次實作,只會拿別人架好的 TUNE Server 來用
#### 綜合理解 Signaling + STUN Server

_(圖片來源:[初探 WebRTC — 手把手建立線上視訊 (2)](https://medium.com/@jedy05097952/%E5%88%9D%E6%8E%A2-webrtc-%E6%89%8B%E6%8A%8A%E6%89%8B%E5%BB%BA%E7%AB%8B%E7%B7%9A%E4%B8%8A%E8%A6%96%E8%A8%8A-2-8ec7202345b1))_
## WebRTC APIs
#### getUserMedia:
用來處理音視串流採集。 (採集聲音或影像)。
#### RTCPeerConnection
用來建立兩個瀏覽器之間的直接通訊。 (建立與管理 p2p 連線)
#### RTCDataChannel
負責用來傳送資料。(操作那條 p2p 連線)
## Websocket 介紹
WebSocket 是一種網路通訊協定,它允許用戶端和服務端之間建立持久的連接,並且能夠實現全雙工通信。
與傳統的 HTTP 協定不同,WebSocket 在連接建立後能夠持續交換數據,而不是每次需要通信時都重新建立連接。這種特性使 WebSocket 非常適用於實時應用,例如:聊天應用、股票交易應用等。
## 視訊服務中 Websocket 與 WebRTC 的角色
#### WebSocket
Signaling Server :WebSocket 主要用於信令的傳輸,它能夠幫助參與者之間交換必要的信息,例如 SDP(會話描述協定)和 ICE 候選人,以便建立和維護 P2P 連接。
#### WebRTC
媒體和數據通信:一旦信令過程完成,WebRTC 就負責視頻和音頻的傳輸,以及其他數據的傳輸(如果需要)。
結合 WebSocket 和 WebRTC,可以在視訊服務中實現高效的信令傳輸和高質量的媒體通信。例如,可以通過 WebSocket 傳輸信令來協商連接的參數,然後通過 WebRTC 建立 P2P 連接來傳輸視頻和音頻數據。
## 實作簡易視訊服務
https://github.com/PacktPublishing/Practical-WebRTC-A-Complete-WebRTC-Bootcamp-for-Beginners/tree/main/Video-Chat-main
---
## References
- [ChatGPT4](https://chatgptui.org/)
- [WebRTC For The Curious](https://webrtcforthecurious.com/)
- [Practical WebRTC: A Complete WebRTC Bootcamp for Beginners](https://learning.oreilly.com/videos/practical-webrtc-a/9781801810012/)
- [WebRTC samples Munge SDP](https://webrtc.github.io/samples/src/content/peerconnection/munge-sdp/)
- [深入理解 WebRTC](https://yuanchieh.page/posts/2021/2021-05-30-%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90-webrtc/)
- [初探 WebRTC — 手把手建立線上視訊 (2)](https://medium.com/@jedy05097952/%E5%88%9D%E6%8E%A2-webrtc-%E6%89%8B%E6%8A%8A%E6%89%8B%E5%BB%BA%E7%AB%8B%E7%B7%9A%E4%B8%8A%E8%A6%96%E8%A8%8A-2-8ec7202345b1)