跳至主要內容
Skip to content

WebRTC 實戰 (3) —— SDP 交換與媒體協商

有了「信令伺服器」這個報馬仔,現在兩台電腦終於可以說話了。但它們要說什麼呢?

WebRTC 的成功連線,依賴於一場精密的 「媒體協商 (Media Negotiation)」。這個過程就像是兩個第一次見面的外交官,在交換各自的通訊規格書。這本規格書,就是 SDP (Session Description Protocol)


一、 核心主角:RTCPeerConnection

RTCPeerConnection 是 WebRTC API 的核心。它負責媒體協商、ICE 連線、加密、壅塞控制與資料傳輸。

連線建立的 5 個經典步驟

  1. A 建立 Offer:A 呼叫 createOffer() 生成自己的 SDP,並透過 setLocalDescription() 給自己存檔。
  2. A 傳送 Offer:透過「信令伺服器」把這份 SDP 傳給 B。
  3. B 接收 Offer:B 收到後,呼叫 setRemoteDescription() 把 A 的資訊記下來。
  4. B 建立 Answer:B 呼叫 createAnswer() 生成回應的 SDP,並透過 setLocalDescription() 自己存檔。
  5. B 傳送 Answer:透過「信令伺服器」把自己的 SDP 回傳給 A。最後 A 呼叫 setRemoteDescription()

二、 揭開 SDP 的面紗:它到底寫了什麼?

SDP 其實是一串看似亂碼的純文字資訊。它記錄了:

  • 媒體類型:我有攝影機、麥克風、資料通道。
  • 編碼格式:我支援 VP8, VP9, H.264。
  • 連線資訊:網路候選位址。
  • 安全性:加密的金鑰指紋。

三、 實作:手寫連線握手

將我們前兩篇學過的內容串聯起來:

javascript
const pc = new RTCPeerConnection({
  iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] 
});

// 1. 加入本地軌道
stream.getTracks().forEach(track => pc.addTrack(track, stream));

// 2. 處理遠端軌道
pc.ontrack = (event) => {
  const [remoteStream] = event.streams;
  document.querySelector('#remoteVideo').srcObject = remoteStream;
};

// 3. 發起連線 (Offerer)
async function makeCall() {
  const offer = await pc.createOffer();
  await pc.setLocalDescription(offer);
  signaling.send({
    type: "offer",
    from: "User_A",
    to: "User_B",
    payload: pc.localDescription,
  });
}

// 4. 回應連線 (Answerer)
signaling.onMessage = async (msg) => {
  if (msg.type === 'offer') {
    await pc.setRemoteDescription(msg.payload);
    const answer = await pc.createAnswer();
    await pc.setLocalDescription(answer);
    signaling.send({
      type: "answer",
      from: "User_B",
      to: msg.from,
      payload: pc.localDescription,
    });
  } else if (msg.type === 'answer') {
    await pc.setRemoteDescription(msg.payload);
  }
};

範例使用整個 pc.localDescription,而不是只傳 sdp 字串,接收端才能同時取得 typesdp

同時發起 Offer:Glare

真實產品不能假設永遠只有一方發起協商。雙方同時新增 track 或 DataChannel 時,可能同時產生 Offer,造成 Glare。正式實作應採用 Perfect Negotiation 模式,依 signalingState 與 polite/impolite 角色決定接受、忽略或 rollback Offer。


總結

今天我們攻克了 WebRTC 最核心的邏輯:RTCPeerConnection 的管理職責、Offer/Answer 的 5 步握手流程,以及 SDP 作為「媒體合約」的重要性。

下一篇,我們將進入網路穿透的最終戰:ICE Candidate 與 NAT 穿越。


進階挑戰

試著把範例改成監聽 negotiationneeded,並研究 Perfect Negotiation 如何處理雙方同時發起 Offer 的情況。


延伸閱讀與資源

← 上一章:信令伺服器與連線中心 | 返回專題首頁 | 下一章:ICE 候補者與 NAT 穿越