Web前端WebRTC攻略(四) 媒體協商與SDP簡析
1 媒體協商
在音視 頻通訊場景中,由於兩端之間所支援的音視訊編解碼、傳輸協議、傳輸的速率,都需要進行彼此通知對方。
我們把一個 1 對 1 的音視訊通訊,比喻成雙方互送快遞包裹的過程。
首先這裡有很多問題,雙方要彼此告知對方後,才能寄送包裹。
比如:
-
我不知道包裹要寄給誰?(我要和誰建立通訊)
-
對方能否使用我的包裹?(我的媒體格式對方是否支援)
-
對方在哪裡,地址是什麼?(對方所處網路的位置在哪)
-
走那條路線寄送最快?(走哪種網路傳輸最效率)
實際場景中,我們要打電話互相告訴對方一些資訊。而在音視訊通訊中,也需要這個“打電話”步驟,形式上一般是通過建立“信令通道”來傳送信令。對於 Web 前端來說最常見以 WebSocket 來作為信令通道,通過它來交換信令並進行協商。真正的媒體資料,則是通過 RTCPeerConnection 進行傳輸。
比如包含什麼媒體流/軌,或者是我的編碼是否被對方的解碼器所支援等等這些問題,則通過 SDP 作為載體告訴給對方。
1.1 什麼是媒體協商?
在沒有建立 WebRTC 連線傳輸資料前,首先需要讓本地端和遠端確認彼此共同支援的媒體能力。如:音視訊編解碼器、使用的傳輸協議、IP 埠和傳輸速率等等。而這些資訊需要通過前文所說的 SDP 來互換,這個過程稱之為媒體協商。
1.2 媒體協商的流程
這裡以在兩個前端瀏覽器建立通訊來進行說明,我們暫且稱“發起端”和“應答端”。
-
首先雙方連線信令通道,(一般由業務決定如何實現),並能交換信令。
-
發起端呼叫 RTCPeerConnection.cr eateOffer 建立一個 offer ,並呼叫 setLocalDescription 設定本地的 SDP。
-
然後通過信令伺服器 將含有 SDP 的 offer 設定給應答端。
-
應答端拿到此 offer 以後呼叫 setRemoteDescription 將此 SDP 資訊儲存。
-
應答端呼叫 RTCPeerConnection.createAnswer 建立一個 answer,並呼叫 setLocalDescription 設定本地的 SDP。
-
通過信令伺服器將含有 SDP 的 answer 傳送給發起端。
-
發起端呼叫 setRemoteDescription 將此 SDP 資訊儲存。
簡單概括就是: 發起端和應答端通過 creatOffer 和 createAnswer 建立 offer/answerSDP ,然後通過信令服務互換,最後呼叫 setLocalDescription/setRemoteDescription 進行設定本地和遠端的 SDP 以完成協商。
在雙方都建立 RTCPeerConnection 之後,它們就可以開始進行媒體協商了。
1.3 媒體協商的前端程式碼實現
1.3.1 呼叫方建立&傳送 Offer
//local
var pc_local = new RTCPeerConnection(otps1);
pc_local.createOffer((offer)=>{
pc_local.setLocalDescription(offer);
singalChannel.send(offer)
}, handleError);
1.3.2 應答方收到 Offer
//remote
var pc_remote = new RTCPeerConnection(otps2);
signalChannel.on('message', (message)=>{
if(message.type === 'offer'){
pc_remote.setRemoteDescription( new RTCSessionDescription(message) )
}
})
1.3.3 應答方建立&傳送 Answer
//remote
pc_remote.createAnswer((answer)=>{
pc_remote.setLocalDescription(answer);
singalChannel.send(answer);
}, handleError );
1.3.4 呼叫方收到 Answer
//local
signalChannel.on('message',(message)=>{
if(message.type==='answer'){
pc_local.setRemoteDescription( new RTCSessionDescription(message) )
}
})
2 SDP
2.1 什麼是SDP?
SDP 全稱 SessionDescription Protocal,直譯就是通用會話描述協議。
光看直面意思可能不太好理解,其實就是 描述雙方的會話資訊,以及各端所具備能力 的通用協議。
在 WebRTC 中 SDP 所 描述的資訊主要有:
1. 各端所支援音視訊編解碼器
2. 編解碼所設定的引數
3. 所使用的的傳輸協議
4. ICE 連線候選項等
2.2 標準 SDP 規範
要注意的是 SDP 並不是 WebRTC 獨有規範,關於標準的 SDP 規範可以查閱: IETFRFC4556規範 。 標準 SDP 規範主要包括 SDP 描述格式 和 SDP 結構 ,而 SDP 結構由 會話描述 和 媒體資訊描述 兩個部分組成。
2.3 SDP 的格式
SDP 是由多個 <type>=<value> 這樣的表示式組成的。
v=0
o=- 7017624586836067756 2 IN IP4 127.0.0.1
s=-
t=0 0...
-
type 只能為一個字元,代表屬性。
-
value 為結構化文字,UTF-8 編碼,代表屬性值。
-
= 兩邊不能有空格。
SDPLine 沒有統一的 Schema 描述,也就是沒有一個固定的規則能解析所有 Line,SDPGrammer 只是描述了 SDP 相關的屬性,具體每個屬性的表達需要根據屬性定義 IETFRFC4556 。 而 SDP 的結構有一個會話描述和零至多個媒體資訊描述組成。
2.3.1 會話描述
常見屬性:
v= SDP 協議版本
v=0
o= 會話發起者描述
o=<username> <sess-id> <sess-version> <nettype> <addrtype> <address>
username:使用者名稱
sess-id:會話id,在整個會話中是唯一的,建議使用NTP時間戳。
sess-version:會話版本,每次會話資料修改後,該版本值會遞增。
nettype:網路型別,一般為“IN”。
addrtype:地址型別,一般為IP4。
address:IP地址。
s= 會話名
s=<sessionname>
不關注時可為-
t= 會話活動時間
t=<start-time><stop-time>
start-time:會話開始時間
stop-time:結束時間
均為NTP時間,單位是秒,均為0時表示持久會話。
c= 連線資訊
c=<nettype><addrtype><connection-address>
nettype:網路型別
addrtype:地址型別
connection-address:連線地址
2.3.2 媒體描述
會話級別描述完成後,後面就是零到多個媒體級別描述,比如:
常見屬性:
m= 媒體描述
m=<media><port> <transport> <fmt-list>
media:媒體型別(audio / video)
port:埠號
transport:傳輸協議 RTP/AVP(RTP/SAVP)或 UDP
fmt-list:媒體格式,表述 RTP 的資料負載型別(PayloadType)的列表,可以包含多個。分別代表音訊和視訊的編碼格式,後面會跟著 rtpmap、rtcp-fb、fmtp 這些屬性來做進一步的詳細的描述。
RTP型別參考:RTPPayload
a= 附加描述
有以下兩種格式:
a=<type> a=<type>:<value>
SDP 解析時,每個 SDPLine 都是以 key=... 形式,解析出 key 是 a 後,可能有兩種方式,可參考 RFC4566:
在 m= 之前,為會話附加描述;
在 m= 之後,為媒體附加描述。
其中可以關注 rtpmap 和 fmtp。
a= rtpmap RTP引數對映表
a=rtpmap:<playload-type><encoding-name>/<sample-rate>/<encodingparameters可選>
playload-type:資料負載型別
encoding-name:編碼名稱
sample-rate:取樣率
encodingparameters:編碼引數
a=fmtp 格式引數
a=fmtp:<playload-type><specific-parameters>
playload-type:資料負載型別
specific-parameters:編碼引數
2.4 SDP 剖析的示例結構與說明
http://webrtchacks.com/sdp-anatomy/ 這個站點給我們展示了一個詳細的 SDP 例子。左側為 SDP 文字,可以明顯看出 SDP 的格式與結構,右側則對每一行描述進行了說明。如果你不想看冗長的規範文件,這個例子是一個不錯的學習材料。
2.5 WebRTC 的 SDP 總結
在 WebRTC 中的 SDP 相對於標準 SDP 規範中有點不一樣,它對於 SDP 劃分了更多部分,詳情可以看下圖:
WebRTC 按功能將 SDP 劃分成了五部分,即會話元資料、網路描述、流描述、安全描述以及服務質量描述。WebRTCSDP 中的會話元資料(SessionMetadata)其實就是 SDP 標準規範中的會話層描述;流描述、網路描述與 SDP 標準規範中的媒體層描述是一致的;而安全描述與服務質量描述都是新增的一些屬性描述。SDP 作為 WebRTC 的核心部分,是你深入學習 WebRTC 前所要必須掌握的基礎內容。
3 參考文章
-
SDP: Session Description Protocol
-
http://webrtchacks.com/
緊追技術前沿,深挖專業領域
掃碼關注我們吧!
- 基於 qiankun 的微前端實踐
- 基於 qiankun 的微前端實踐
- 動態監聽DOM元素高度變化
- 解決前端常見問題:競態條件
- Scroll,你玩明白了嘛?
- 深入理解 Promise 之手把手教你寫一版
- 文件解析和DOMContentLoaded觸發時機
- 【TypeScript】never 和 unknown 的優雅之道
- 【音視訊掃盲】可分級視訊編碼
- 基於 Yarn 的 Monorepo 實踐
- WebSocket 基礎與應用系列(二)—— Engine.IO 原理了解
- Node.js 流原始碼解讀之可讀流
- Dark Mode 實踐踩坑記錄
- 帶你深入瞭解 useState
- Nohost 實現原理 —— 遠端辦公下的開發測試協同提效方案
- Jest React Testing Library 單測總結
- OpenGL 圖形渲染流程入門
- 又過年了,盤一盤近一年閱讀量最高的十篇文章
- 視訊中的 I 幀,P 幀,B 幀
- “和 loading 介面說 ByeBye”—— Remix 顛覆式預載入解析