Web前端WebRTC攻略(四) 媒體協商與SDP簡析

語言: CN / TW / HK

1 媒體協商

在音視 頻通訊場景中,由於兩端之間所支援的音影片編解碼、傳輸協議、傳輸的速率,都需要進行彼此通知對方。

我們把一個 1 對 1 的音影片通訊,比喻成雙方互送快遞包裹的過程。

首先這裡有很多問題,雙方要彼此告知對方後,才能寄送包裹。
比如:

  • 我不知道包裹要寄給誰?(我要和誰建立通訊)

  • 對方能否使用我的包裹?(我的媒體格式對方是否支援)

  • 對方在哪裡,地址是什麼?(對方所處網路的位置在哪)

  • 走那條路線寄送最快?(走哪種網路傳輸最效率)

實際場景中,我們要打電話互相告訴對方一些資訊。而在音影片通訊中,也需要這個“打電話”步驟,形式上一般是通過建立“信令通道”來傳送信令。對於 Web 前端來說最常見以 WebSocket 來作為信令通道,通過它來交換信令並進行協商。真正的媒體資料,則是通過 RTCPeerConnection 進行傳輸。

比如包含什麼媒體流/軌,或者是我的編碼是否被對方的解碼器所支援等等這些問題,則通過 SDP 作為載體告訴給對方。

1.1 什麼是媒體協商?

在沒有建立 WebRTC 連線傳輸資料前,首先需要讓本地端和遠端確認彼此共同支援的媒體能力。如:音影片編解碼器、使用的傳輸協議、IP 埠和傳輸速率等等。而這些資訊需要通過前文所說的 SDP 來互換,這個過程稱之為媒體協商。

1.2 媒體協商的流程

這裡以在兩個前端瀏覽器建立通訊來進行說明,我們暫且稱“發起端”和“應答端”。

  1. 首先雙方連線信令通道,(一般由業務決定如何實現),並能交換信令。

  2. 發起端呼叫  RTCPeerConnection.cr eateOffer   建立一個 offer ,並呼叫  setLocalDescription  設定本地的 SDP。

  3. 然後通過信令伺服器 將含有 SDP 的 offer 設定給應答端。

  4. 應答端拿到此 offer 以後呼叫  setRemoteDescription  將此 SDP 資訊儲存。

  5. 應答端呼叫  RTCPeerConnection.createAnswer  建立一個 answer,並呼叫  setLocalDescription  設定本地的 SDP。

  6. 通過信令伺服器將含有 SDP 的  answer  傳送給發起端。

  7. 發起端呼叫  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 剖析的示例結構與說明

https://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

  • https://webrtchacks.com/ 

緊追技術前沿,深挖專業領域

掃碼關注我們吧!