建構 WebRTC 應用程式所需的後端服務

什麼是信號?

訊號是協調溝通的過程。為了讓 WebRTC 應用程式設定呼叫,其用戶端必須交換下列資訊:

  • 用於開啟或關閉通訊的工作階段控制訊息
  • 錯誤訊息
  • 媒體中繼資料,例如轉碼器、轉碼器設定、頻寬和媒體類型
  • 用於建立安全連線的金鑰資料
  • 外部界看到的網路資料,例如主機的 IP 位址和通訊埠

這個信號程序需要讓用戶端能來回傳遞訊息。WebRTC API 並未實作該機制。您必須自行建構。本文稍後會介紹幾種建立信號服務的方法。不過,首先您需要一些背景資訊,

為什麼 WebRTC 未定義信號?

為了避免備援機制並盡可能提高與既有技術的相容性,WebRTC 標準並未指定訊號方法和通訊協定。這種做法請參考 JavaScript 工作階段建立通訊協定 (JSEP)

此外,JSEP 的架構還能避免瀏覽器儲存狀態,也就是做為信號狀態機器運作。舉例來說,如果系統在每次重新載入網頁時指出資料遺失,就會造成問題。而是可以將信號狀態儲存在伺服器中。

JSEP 架構圖
JSEP 架構

JSEP 要求優惠答案的同儕之間交換上述媒體中繼資料。優惠和答案會以工作階段說明通訊協定 (SDP) 格式傳達,如下所示:

v=0
o=- 7614219274584779017 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS
m=audio 1 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:1 IN IP4 0.0.0.0
a=ice-ufrag:W2TGCZw2NZHuwlnf
a=ice-pwd:xdQEccP40E+P0L5qTyzDgfmW
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=mid:audio
a=rtcp-mux
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:9c1AHz27dZ9xPI91YNfSlI67/EMkjHHIHORiClQe
a=rtpmap:111 opus/48000/2
…

想知道這個 SDP 鵝卵石頭星的意義嗎?請參閱網際網路工程任務組 (IETF) 範例

請記住,WebRTC 設計讓您可以修改 SDP 文字中的值,先調整優惠或答案,將其設為本機或遠端說明。舉例來說,appr.tc 中的 preferAudioCodec() 函式可用來設定預設轉碼器和位元率。利用 JavaScript 操控 SDP 有點困難,也討論了是否應將日後推出的 WebRTC 版本改為應使用 JSON,然而維持 SDP 的一些優點

RTCPeerConnection API 和信號:優惠、解答和候選人

RTCPeerConnection 是 WebRTC 應用程式用來建立對等點連線,以及傳輸音訊和視訊的 API。

如要初始化這項程序,RTCPeerConnection 有兩個工作:

  • 確認當地媒體狀況,例如解析度和轉碼器功能。這是商品和答案機制使用的中繼資料,
  • 取得應用程式主機的潛在網路位址,也稱為「候選項目」

確認這項本機資料後,資料必須透過遠端對等端的訊號機制交換。

假設Alice 想要打電話給夏威夷。以下是合作方案的完整細節:

  1. Alice 建立 RTCPeerConnection 物件。
  2. 小艾使用 RTCPeerConnection createOffer() 方法建立優惠 (SDP 工作階段說明)。
  3. 莉莉撥打了優惠電話給setLocalDescription()
  4. Alice 將方案串連起來,並使用信號機制將優惠傳送給夏威夷。
  5. 夏娃透過 Alice 的優惠致電「setRemoteDescription()」,讓RTCPeerConnection瞭解小艾的設定。
  6. 夏娃呼叫 createAnswer(),而針對此結果傳送成功回呼,並傳送本機工作階段說明 - Eve 的回答。
  7. 夏娃呼叫 setLocalDescription(),將答案設為本地描述。
  8. 夏娃接著運用信號機制,將經過嚴格篩選的答案傳送給 Alice。
  9. 小艾使用 setRemoteDescription() 將夏娃的答案設為遠端工作階段的說明。

愛麗和夏娃也需要交換網路資訊。「尋找候選項目」運算式是指使用 ICE 架構尋找網路介面和通訊埠的程序。

  1. 小艾使用 onicecandidate 處理常式建立 RTCPeerConnection 物件。
  2. 當網路候選項目可供使用時,就會呼叫處理常式。
  3. 在處理常式中,Alice 會透過其信號管道,將經過字串的候選資料傳送給夏威夷。
  4. 當夏娃收到 Alice 的候選訊息時,她會呼叫 addIceCandidate(),將候選項目新增至遠端對等點說明。

JSEP 支援 ICE 候選試行法,可讓呼叫端在初次報價後逐步為受呼叫端提供候選人,也能讓受呼叫端在通話時開始採取行動及設定連線,不必等待所有應試者抵達。

使用程式碼 WebRTC 發出信號

下列程式碼片段是 W3C 程式碼範例,摘要說明完整的信號程序。程式碼會假設存在部分信號機制 SignalingChannel。稍後會詳細說明信號。

// handles JSON.stringify/parse
const signaling = new SignalingChannel();
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);

// Send any ice candidates to the other peer.
pc.onicecandidate = ({candidate}) => signaling.send({candidate});

// Let the "negotiationneeded" event trigger offer generation.
pc.onnegotiationneeded = async () => {
  try {
    await pc.setLocalDescription(await pc.createOffer());
    // send the offer to the other peer
    signaling.send({desc: pc.localDescription});
  } catch (err) {
    console.error(err);
  }
};

// After remote track media arrives, show it in remote video element.
pc.ontrack = (event) => {
  // Don't set srcObject again if it is already set.
  if (remoteView.srcObject) return;
  remoteView.srcObject = event.streams[0];
};

// Call start() to initiate.
async function start() {
  try {
    // Get local stream, show it in self-view, and add it to be sent.
    const stream =
      await navigator.mediaDevices.getUserMedia(constraints);
    stream.getTracks().forEach((track) =>
      pc.addTrack(track, stream));
    selfView.srcObject = stream;
  } catch (err) {
    console.error(err);
  }
}

signaling.onmessage = async ({desc, candidate}) => {
  try {
    if (desc) {
      // If you get an offer, you need to reply with an answer.
      if (desc.type === 'offer') {
        await pc.setRemoteDescription(desc);
        const stream =
          await navigator.mediaDevices.getUserMedia(constraints);
        stream.getTracks().forEach((track) =>
          pc.addTrack(track, stream));
        await pc.setLocalDescription(await pc.createAnswer());
        signaling.send({desc: pc.localDescription});
      } else if (desc.type === 'answer') {
        await pc.setRemoteDescription(desc);
      } else {
        console.log('Unsupported SDP type.');
      }
    } else if (candidate) {
      await pc.addIceCandidate(candidate);
    }
  } catch (err) {
    console.error(err);
  }
};

如要瞭解優惠/答案和候選交易交換程序的實際運作情形,請參閱 simpl.info RTCPeerConnection,並查看控制台記錄中的單頁視訊通訊範例。如需更多詳情,請前往 Google Chrome 的 about://webrtc-internals 頁面或 Opera 中的 opera://webrtc-internals 頁面,下載 WebRTC 信號和統計資料的完整傾印檔案。

同業探索

正如剛才提到的「要怎麼找人聊聊呢?」

如果是通話,您有電話號碼和目錄。如要進行線上視訊通訊和通訊,您需要身分識別和在家狀態管理系統,以及為使用者提供啟動工作階段的方法。WebRTC 應用程式需要某種方式,讓用戶端向彼此發出要發起或加入通話的通知。

WebRTC 並未定義同業探索機制,因此請勿在這裡看到這些選項。整個流程非常簡單,只要以電子郵件傳送網址或訊息傳送網址即可。對於 Talkytawk.toBrowser Meeting 等視訊通訊應用程式,您可以透過分享自訂連結來邀請使用者加入通話。開發人員 Chris Ball 打造了有趣的「無伺服器 Webrtc」serverless-webrtc實驗,讓 WebRTC 呼叫參與者得以透過偏好的任何訊息服務 (例如 IM、電子郵件或愛犬海盜) 交換中繼資料。

如何建構信號服務?

換句話說,WebRTC 標準並未定義訊號通訊協定和機制。無論您選擇哪一種,都需要透過中介伺服器在用戶端之間交換信號訊息和應用程式資料。可惜,網頁應用程式不能單憑網路大聲大喊「與好友聯絡!」

謝天謝地的發送訊息雖然較小,且大多會在通話開始時傳送。在針對視訊通訊工作階段使用 appr.tc 進行測試時,信號服務總共處理了約 30 到 45 則訊息,總訊息大小約為 10 KB。

WebRTC 信號服務在頻寬方面相對較低,因此不會耗用過多的處理或記憶體,因為這類服務只需要轉發訊息並保留少量工作階段狀態資料 (例如已連線的用戶端)。

從伺服器將訊息推送至用戶端

信號的訊息服務需為雙向:用戶端對伺服器,以及伺服器對用戶端。雙向通訊是根據 HTTP 用戶端/伺服器要求/回應模型進行,但許多駭客攻擊 (例如長期輪詢) 都經過多年開發,以便將資料從網路伺服器上執行的服務,推送到在瀏覽器中執行的網頁應用程式。

不久前,EventSource API廣泛導入。這會啟用伺服器傳送事件,也就是透過 HTTP 從網路伺服器傳送至瀏覽器用戶端的資料。EventSource 是專為單向傳訊而設計,但可與 XHR 搭配使用,建構交換信號訊息的服務。信號服務會透過 EventSource 將呼叫端推送至受呼叫端,以便透過 XHR 要求傳遞呼叫端的訊息。

WebSocket 是比較自然的解決方案,專為全雙工用戶端通訊而設計,可同時往兩個方向傳輸的訊息。使用純 WebSocket 或伺服器傳送事件 (EventSource) 建立的信號服務一項優點,在於這些 API 的後端可以在各種常見網路架構中實作,適用於 PHP、Python 和 Ruby 等語言的網站代管套件。

除了 Opera Mini 以外,所有新式瀏覽器也都支援 WebSocket,更重要的是,所有支援 WebRTC 的瀏覽器在電腦和行動裝置上都能支援 WebSocket。所有連線都應使用 TLS,確保郵件無法在未加密的情況下遭到攔截,以及減少 Proxy 週遊問題。(如要進一步瞭解 WebSocket 和 Proxy 週遊,請參閱 Ilya Grigorik 的「高效能瀏覽器網路」中的 WebRTC 章節)。

另一種處理信號也可能是讓 WebRTC 用戶端透過 Ajax 重複輪詢訊息伺服器,但這會導致大量重複的網路要求,這對於行動裝置來說尤其嚴重。即使建立工作階段後,同業仍必須輪詢訊息,以因應其他同業異動或工作階段終止的情況。WebRTC Book 應用程式範例會使用這個選項,搭配某些輪詢頻率最佳化設定。

比例尺信號

雖然信號服務針對每個用戶端耗用的頻寬和 CPU 相對較少,但某個熱門應用程式的信號伺服器可能必須處理來自不同位置高度並行的大量訊息。流量較高的 WebRTC 應用程式,需要訊號伺服器才能處理可觀的負載。本文不會詳細說明,但您可以採取以下幾種做法,進行大量與高成效的訊息傳遞作業,包括:

(開發人員 Phil Leggetter 的《即時網路技術指南》提供了訊息傳遞服務和程式庫的完整清單。

在節點上使用 Socket.io 建立信號服務

以下程式碼適用於簡易網頁應用程式,其所使用的信號服務在 Node 上使用 Socket.io 建構的信號服務。Socket.io 的設計讓您可以輕鬆建構交換訊息的服務,而 Socket.io 由於內建聊天室概念,因此特別適合 WebRTC 信號。本範例的規模並非為實際工作環境等級的信號服務,而對少數使用者而言很容易理解。

Socket.io 使用 WebSocket 搭配遞補功能:AJAX 長時間輪詢、AJAX 多部分串流、永久 iframe 和 JSONP 輪詢。該 API 已移植到各種後端,但或許最接近在此範例中所用的節點版本。

這個範例中沒有 WebRTC。其只是示範如何在網頁應用程式中建立信號。請查看控制台記錄,瞭解客戶加入聊天室及交換訊息時發生的情況。這個 WebRTC 程式碼研究室提供逐步操作說明,說明如何將這項功能整合至完整的 WebRTC 視訊通訊應用程式。

以下是 index.html 用戶端:

<!DOCTYPE html>
<html>
  <head>
    <title>WebRTC client</title>
  </head>
  <body>
    <script src='/socket.io/socket.io.js'></script>
    <script src='js/main.js'></script>
  </body>
</html>

以下是用戶端中參照的 JavaScript 檔案 main.js

const isInitiator;

room = prompt('Enter room name:');

const socket = io.connect();

if (room !== '') {
  console.log('Joining room ' + room);
  socket.emit('create or join', room);
}

socket.on('full', (room) => {
  console.log('Room ' + room + ' is full');
});

socket.on('empty', (room) => {
  isInitiator = true;
  console.log('Room ' + room + ' is empty');
});

socket.on('join', (room) => {
  console.log('Making request to join room ' + room);
  console.log('You are the initiator!');
});

socket.on('log', (array) => {
  console.log.apply(console, array);
});

以下是完整的伺服器應用程式:

const static = require('node-static');
const http = require('http');
const file = new(static.Server)();
const app = http.createServer(function (req, res) {
  file.serve(req, res);
}).listen(2013);

const io = require('socket.io').listen(app);

io.sockets.on('connection', (socket) => {

  // Convenience function to log server messages to the client
  function log(){
    const array = ['>>> Message from server: '];
    for (const i = 0; i < arguments.length; i++) {
      array.push(arguments[i]);
    }
      socket.emit('log', array);
  }

  socket.on('message', (message) => {
    log('Got message:', message);
    // For a real app, would be room only (not broadcast)
    socket.broadcast.emit('message', message);
  });

  socket.on('create or join', (room) => {
    const numClients = io.sockets.clients(room).length;

    log('Room ' + room + ' has ' + numClients + ' client(s)');
    log('Request to create or join room ' + room);

    if (numClients === 0){
      socket.join(room);
      socket.emit('created', room);
    } else if (numClients === 1) {
      io.sockets.in(room).emit('join', room);
      socket.join(room);
      socket.emit('joined', room);
    } else { // max two clients
      socket.emit('full', room);
    }
    socket.emit('emit(): client ' + socket.id +
      ' joined room ' + room);
    socket.broadcast.emit('broadcast(): client ' + socket.id +
      ' joined room ' + room);

  });

});

(您不必熟悉節點靜態概念。您只需在本範例中使用)。

如要在 localhost 上執行這個應用程式,您必須安裝 Node、Socket.IO 和 node-static。您可以從 Node.js 下載節點 (安裝程序簡單快速。)如要安裝 Socket.IO 和節點靜態,請在應用程式目錄中的終端機執行 Node Package Manager:

npm install socket.io
npm install node-static

如要啟動伺服器,請在應用程式目錄中透過終端機執行下列指令:

node server.js

在瀏覽器中開啟 localhost:2013。在任何瀏覽器中開啟新分頁或視窗,然後再次開啟 localhost:2013。如要瞭解發生的情況,請查看控制台。在 Chrome 和 Opera 中,您可以透過 Google Chrome 開發人員工具使用 Ctrl+Shift+J (在 Mac 上則是 Command+Option+J) 存取控制台。

無論您選擇哪種信號方法,後端和用戶端應用程式至少都需要提供類似本例的服務。

訊號錯誤

  • 在呼叫 setLocalDescription() 後,RTCPeerConnection 才會開始收集候選人。這項資訊請參閱 JSEP IETF 草稿
  • 不妨使用 Trickle ICE。只要在候選人抵達時立即呼叫 addIceCandidate()

現成訊號伺服器

如果您不想自行推送,目前有多個 WebRTC 訊號伺服器可供使用,這些伺服器使用的是 Socket.IO (跟上述範例一樣),並與 WebRTC 用戶端 JavaScript 程式庫整合:

如果您不想編寫任何程式碼,歡迎向 vLineOpenTokAsterisk 等公司提供完整的商業 WebRTC 平台。

針對記錄,Ericsson 在 WebRTC 早期階段使用 PHP 在 Apache 中建構了訊號伺服器。這部分已過時,但如果您考慮採取類似做法,也很值得查看程式碼。

訊號安全

「安全性是沒有任何改變的藝術。」

薩爾曼拉什迪

所有 WebRTC 元件都必須使用加密功能。

不過,WebRTC 標準並不定義信號機制,因此訊息傳遞方式由您決定。如果攻擊者設法入侵訊號,可以停止工作階段、重新導向連線,以及記錄、變更或植入內容。

保護訊號時,最重要的因素是使用安全通訊協定 (例如 HTTPS 和 WSS,例如 TLS),確保郵件在未加密的情況下不會遭到攔截。此外,請小心不要以同一個訊號伺服器的其他呼叫端存取廣播訊息,

訊號後:使用 ICE 因應網路位址轉譯 (NAT) 和防火牆

針對中繼資料信號,WebRTC 應用程式會使用中介伺服器,但針對工作階段建立後的實際媒體和資料串流,RTCPeerConnection 會嘗試直接或點對點連線用戶端。

在簡明的情況下,每個 WebRTC 端點都有一個專屬位址,可與其他對等互連項目交換,以便直接通訊。

簡單的點對點連線
沒有 NAT 和防火牆的世界

事實上,大多數裝置都位於 NAT 的一或多個層後方,有些裝置的防毒軟體會封鎖特定通訊埠和通訊協定,且多數裝置位於 Proxy 和企業防火牆的背後。防火牆和 NAT 實際上可能由同一部裝置 (例如家用 WIFI 路由器) 導入。

NAT 和防火牆後方的對等互連
真實世界

WebRTC 應用程式可以使用 ICE 架構克服真實世界網路的複雜問題。如要讓應用程式執行這項操作,請依照本文所述,將 ICE 伺服器網址傳遞至 RTCPeerConnection

ICE 致力找出促進同事交流的最佳途徑。它會同時嘗試各種可能性,然後選擇最有效率的選項。ICE 會先使用從裝置作業系統和網路卡取得的主機位址來建立連線。如果失敗 (這會用於 NATs 後方的裝置),ICE 會使用 STUN 伺服器取得外部位址,如果失敗,則會透過 TURN 轉發伺服器轉送流量。

換句話說,STUN 伺服器會取得外部網路位址,而在直接 (點對點) 連線失敗時,會使用 TURN 伺服器轉發流量。

每個 TURN 伺服器都支援 STUN。TURN 伺服器是具備額外內建轉發功能的 STUN 伺服器。ICE 也因應網路位址轉譯 (NAT) 設定的複雜性。事實上,網路位址轉譯 (NAT) 打孔可能除了需要公開 IP:通訊埠位址外,

STUN 和/或 TURN 伺服器的網址是由 (選擇性) 由 WebRTC 應用程式指定 (在 iceServers 設定物件中,這是 RTCPeerConnection 建構函式的第一個引數)。如果是 appr.tc,值如下所示:

{
  'iceServers': [
    {
      'urls': 'stun:stun.l.google.com:19302'
    },
    {
      'urls': 'turn:192.158.29.39:3478?transport=udp',
      'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
      'username': '28224511:1379330808'
    },
    {
      'urls': 'turn:192.158.29.39:3478?transport=tcp',
      'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
      'username': '28224511:1379330808'
    }
  ]
}

RTCPeerConnection取得這些資訊後,ICE 的魔法就會自動生成。RTCPeerConnection 採用 ICE 架構找出同業的最佳路徑,並視需要使用 STUN 和 TURN 伺服器。

週日

NAT 會提供具有 IP 位址的裝置,以便在私人區域網路中使用,但這個位址不能在外部使用。如果沒有公開位址,WebRTC 對等互連就無法進行通訊。為瞭解決這個問題,WebRTC 會使用 STUN

STUN 伺服器位於公開的網際網路中,而且執行一項簡單的工作。檢查傳入要求的 IP:port 位址 (來自在 NAT 後方執行的應用程式),然後將該位址傳回做為回應。也就是說,應用程式會使用 STUN 伺服器從公開的角度探索其 IP:port。這項程序可讓 WebRTC 對等互連取得自行存取的公開位址,然後再透過信號機制將該位址傳送至其他對等互連,以便設定直接連結。(實際上,不同的 NAT 運作方式不同,可能有多個 NAT 層,但原則依然相同)。

STUN 伺服器不必太多或費心,因此相對低規格的 STUN 伺服器可以處理大量要求。

大多數 WebRTC 呼叫都根據 Webrtcstats.com 成功使用 STUN - 86% 建立連線,但對於防火牆後方的對等端和複雜的 NAT 設定而言,這可能會比較少。

使用 STUN 伺服器的點對點連線
使用 STUN 伺服器取得公開 IP:通訊埠位址

RTCPeerConnection 會嘗試透過 UDP 設定對等點之間的直接通訊。如果失敗,RTCPeerConnection 會下達 TCP。如果失敗,TURN 伺服器可做為備用伺服器,在端點之間轉發資料。

我想重申一下,使用 TURN 轉發音訊、影片和資料串流,而不是通訊資料!

TURN 伺服器具有公開位址,因此即使對等點位於防火牆或 Proxy 後方,對等端也能與其連線。TURN 伺服器在概念上來說就是轉送串流,這個工作的概念非常簡單。不過,與 STUN 伺服器不同的是,這類伺服器本身會佔用大量頻寬。換句話說,TURN 伺服器必須提高效率。

使用 STUN 伺服器的點對點連線
整個蒙地:STUN、TURN 和信號

下圖顯示「TURN」功能的實際運作情形。由於 Pure STUN 失敗,因此每個同儕使用 TURN 伺服器。

正在部署 STUN 和 TURN 伺服器

為了進行測試,Google 執行了 appr.tc 所用的公開 STUN 伺服器 stun.l.google.com:19302。如果是正式環境的 STUN/TURN 服務,請使用 rfc5766 輪轉伺服器。您可以在 GitHub 取得 STUN 和 TURN 伺服器的原始碼,同樣可以在其中找到多個伺服器安裝相關資訊的連結。您也可以用 Amazon Web Services 的 VM 映像檔

替代的 TURN 伺服器可做為原始碼使用,也適用於 AWS。以下操作說明說明如何在 Compute Engine 上設定復原。

  1. 視需要對 tcp=443、udp/tcp=3478 開啟防火牆。
  2. 建立四個執行個體,每個公開 IP 一個執行個體:標準 Ubuntu 12.06 映像檔。
  3. 調整本機防火牆設定 (允許 ANY)。
  4. 安裝工具: shell sudo apt-get install make sudo apt-get install gcc
  5. creytiv.com/re.html 安裝 libre。
  6. creytiv.com/restund.html 擷取保留資料並解壓縮。/
  7. wget hancke.name/restund-auth.patch,並透過 patch -p1 < restund-auth.patch 提出申請。
  8. 執行 makesudo make install 來校正和還原。
  9. 根據需求調整 restund.conf (取代 IP 位址並確認其包含相同的共用密鑰),然後將副本複製到 /etc
  10. restund/etc/restund 複製到 /etc/init.d/
  11. 設定備援功能:
    1. 設定 LD_LIBRARY_PATH
    2. restund.conf 複製到 /etc/restund.conf
    3. 設定 restund.conf 以使用正確的 10。IP 位址
  12. 執行休息一下
  13. 使用遠端機器的前景用戶端進行測試:./client IP:port

超越一對一:多方 WebRTC

建議您同時參閱 Justin Uberti 針對存取 TURN 服務的 REST API 提議的 IETF 標準。

我們很容易想像媒體串流的使用情境,不再提供簡單的一對一通話服務。例如,一群同事進行視訊會議,或是舉辦公開活動時邀請一位演講者和數百或數百萬名觀眾進行視訊會議。

WebRTC 應用程式可以使用多個 RTCPeerConnection,讓每個端點都能連接至網格設定中的其他端點。這也是應用程式 (例如 talky.io) 採用的做法,非常適合只有少數同業使用。除此之外,處理和頻寬使用量也已成為過度使用的問題,對行動用戶端而言更是如此。

網格:小型 N 路通話
完整網狀拓撲:所有人都能連線至所有人

或者,WebRTC 應用程式可以選擇使用一個端點,將串流分配到星號設定中其他所有端點。您也可以在伺服器上執行 WebRTC 端點,並建構自己的重新分配機制 (webrtc.org 提供範例用戶端應用程式)。

自 Chrome 31 和 Opera 18 起,你可以使用 RTCPeerConnection 中的 MediaStream 做為另一個的輸入值。這會啟用更靈活的架構,因為這項服務可讓網頁應用程式選擇其他連線的對等點,處理呼叫轉送。如要瞭解實際運作情形,請參閱「WebRTC 範例連線轉送」和「WebRTC 樣本多個對等互連連線」。

多點控制單元

如果端點數量很多,最好的做法是使用多點控制單元 (MCU)。這個伺服器可做為橋樑,在大量參與者之間分配媒體。在視訊會議中,MCU 可因應不同的解析度、轉碼器和畫面更新率,還可處理轉碼;執行選擇性串流轉送,以及混音或錄製音訊和視訊。使用多方通話時,需要考慮一些問題,特別是如何顯示多個視訊輸入來源及混合來自多個來源的音訊。雲端平台 (例如 vLine) 也會嘗試最佳化流量轉送。

您可以購買完整的 MCU 硬體套件,也可以自行建立套件。

Cisco MCU5300 的後視圖
Cisco MCU 的背面

目前提供多個開放原始碼 MCU 軟體選項。舉例來說,Licode (先前稱為 Lynckia) 會針對 WebRTC 產生開放原始碼 MCU。OpenTok 有 Mantis

超越瀏覽器:VoIP、電話和簡訊

WebRTC 標準化特性,讓您可以在瀏覽器執行的 WebRTC 應用程式,以及在其他通訊平台 (例如電話或視訊會議系統) 的裝置或平台之間建立通訊。

SIP 是 IP 網路語音傳遞技術和視訊會議系統使用的信號通訊協定。如要啟用 WebRTC 網頁應用程式和 SIP 用戶端 (例如視訊會議系統) 之間的通訊功能,WebRTC 需要 Proxy 伺服器來調解訊號。訊號必須通過閘道,不過一旦建立通訊,SRTP 流量 (視訊和音訊) 便可直接傳入點對點。

公開交換電話網路 (PSTN) 是所有「純舊」類比電話的電路切換網路。對於 WebRTC 網頁應用程式和電話之間的呼叫,流量必須通過 PSTN 閘道。同樣地,WebRTC 網頁應用程式需要使用中介 XMPP 伺服器與 Jingle 端點 (例如 IM 用戶端) 進行通訊。Jingle 是 Google 開發的 Jingle 做為 XMPP 的擴充功能,用來啟用訊息傳遞服務的語音和視訊功能。目前的 WebRTC 實作是以 C++ libjingle 程式庫為基礎,Jingle 最初是針對 Talk 開發的一種實作。

許多應用程式、程式庫和平台都會使用 WebRTC 的功能與外界通訊:

  • sipML5:開放原始碼 JavaScript SIP 用戶端
  • jsSIP:JavaScript SIP 程式庫
  • Phono:建構為外掛程式的開放原始碼 JavaScript 手機 API
  • Zingaya:可嵌入的手機小工具
  • Twilio:語音和訊息功能
  • Uberconference:會議

sipML5 開發人員也已建構 webrtc2sip 閘道。Tethr 和 Tropo 已用 OpenBTS 細胞示範災難復原架構,以使用 WebRTC 進行功能型手機和電腦之間的通訊。那是沒有電信業者的電話通訊功能!

瞭解詳情

WebRTC 程式碼研究室提供逐步操作說明,協助您使用在節點上執行的 Socket.io 訊號服務,建構視訊和文字即時通訊應用程式。

2013 年的 Google I/O WebRTC 簡報,WebRTC 技術主管 Justin Uberti

Chris Wilson 的 SFHTML5 簡報 - WebRTC 應用程式簡介

HTML5 即時網頁中的 350 頁書籍 WebRTC: API 和 RTCWEB 通訊協定,有詳盡的資料和信號路徑相關細節,以及許多詳細的網路拓撲圖表。

WebRTC 和 Signaling: What Years Has Taught Us (WebRTC 和 Signaling):TokBox 的網誌文章,說明為何不表達規格的重要性

Ben Strong 的建構 WebRTC 應用程式實務指南」提供了大量關於 WebRTC 拓撲和基礎架構的資訊。

Ilya Grigorik 高效能瀏覽器網路中的 WebRTC 章節,深入探討 WebRTC 架構、用途和效能。