開始使用 WebRTC

WebRTC 是長期戰爭中的新前線,保護開放且不受干擾的網路。

JavaScript 發明家 Brendan Eich

無需外掛程式即可進行即時通訊

想像一下,手機、電視和電腦都能透過通用平台進行通訊。想像一下,您可以在網頁應用程式中新增視訊通訊和點對點資料分享功能,這是 WebRTC 的願景。

想試試嗎?WebRTC 適用於電腦版和行動版 Google Chrome、Safari、Firefox 和 Opera。我們建議您從 appr.tc 的簡易視訊通訊應用程式著手:

  1. 在瀏覽器中開啟 appr.tc
  2. 按一下「加入」加入聊天室,讓應用程式使用網路攝影機。
  3. 在新分頁中開啟網頁末端顯示的網址,最好還是在其他電腦上開啟。

快速入門

沒有時間閱讀這篇文章或只想寫程式嗎?

您也可以直接跳至 WebRTC 程式碼研究室。這份逐步指南會說明如何建構完整的視訊通訊應用程式,包括簡易訊號伺服器。

WebRTC 歷史記錄非常短

網路環境最後一個挑戰之一,就是能透過語音和視訊進行人類通訊:即時通訊或 RTC (簡稱 RTC)。在網頁應用程式中,RTC 應該就像在文字輸入中輸入文字一樣自然。如果沒有 AI,創新和開發新互動方式的能力將受到限制。

RTC 一直以來都是企業和複雜的公司,他們需要昂貴的音訊和視訊技術才能取得授權或自行開發。將 RTC 技術與現有內容、資料和服務整合既困難又耗時,尤其是在網路上。

Gmail 視訊通訊在 2008 年大受歡迎;2011 年,Google 推出了採用 Talk (跟 Gmail 一樣) 的 Hangouts 功能。Google 購買 GIPS,這家公司開發了 RTC 所需的許多元件,例如轉碼器和回音消除技術。Google 將由 GIPS 開發的技術開放原始碼,並與網際網路工程任務組 (IETF) 和全球資訊網協會 (World Wide Web Consortium,W3C) 的相關標準機構參與,以確保業界達成共識。Ericsson 在 2011 年 5 月建構了 WebRTC

WebRTC 採用開放標準,進行即時無外掛程式的即時視訊、音訊和資料通訊。真正的需求:

  • 許多網路服務都使用 RTC,但還需要下載、原生應用程式或外掛程式。包括 Skype、Facebook 和 Hangouts。
  • 外掛程式的下載作業複雜、容易出錯且令人不悅。
  • 外掛程式難以部署、偵錯、疑難排解、測試與維護,而且可能需要授權及整合複雜昂貴的技術。一開始很難說服使用者安裝外掛程式!

WebRTC 專案的指導原則在於 API 的 API 應為開放原始碼、免費、標準化、內建於網路瀏覽器,且效率超越現有技術。

我們現在在哪裡?

WebRTC 常用於許多應用程式,例如 Google Meet。WebRTC 也已經與 WebKitGTK+ 和 Qt 原生應用程式整合。

WebRTC 實作以下三個 API: - MediaStream (也稱為 getUserMedia) - RTCPeerConnection - RTCDataChannel

定義 API 時,有兩種規格:

Chrome、Safari、Firefox、Edge 和 Opera 皆支援行動裝置和電腦上的這三個 API。

getUserMedia:如需示範和程式碼,請參閱 WebRTC 範例,或試試 Chris Wilson 的幾個重要範例,這些範例將 getUserMedia 做為網路音訊的輸入內容。

RTCPeerConnection:如需簡易示範和功能完整的視訊通訊應用程式,請參閱 WebRTC 範例對等互連連線appr.tc。這個應用程式會使用 adapter.js;這個 JavaScript 填充是由 Google 在 WebRTC 社群的協助下維護的 JavaScript 填充,能夠抽離瀏覽器的差異和規格變更。

RTCDataChannel:如要查看實際運作情形,請參閱「WebRTC 範例」,查看其中一個 Data-channel 示範。

WebRTC 程式碼研究室將說明如何使用全部三個 API 建構簡單的應用程式,以便進行視訊通訊和檔案共用。

您的第一個 WebRTC

WebRTC 應用程式需要執行以下作業:

  • 取得串流音訊、影片或其他資料。
  • 取得網路資訊 (例如 IP 位址和通訊埠) 並與其他 WebRTC 用戶端 (稱為「對等互連」) 交換,藉此啟用連線,甚至透過 NAT 和防火牆。
  • 協調訊號通訊以回報錯誤及啟動或關閉工作階段。
  • 交換媒體和用戶端功能相關資訊,例如解析度和轉碼器。
  • 傳達串流音訊、影片或資料。

為了取得及通訊串流資料,WebRTC 會實作下列 API:

  • MediaStream 可存取資料串流,例如透過使用者的攝影機和麥克風。
  • RTCPeerConnection 支援音訊或視訊通話,並提供加密和頻寬管理設備。
  • RTCDataChannel 支援點對點對一般資料進行通訊。

(我們稍後會針對網路與信號各方面進行詳細討論)。

MediaStream API (又稱為 getUserMedia API)

MediaStream API 代表已同步的媒體串流。舉例來說,從攝影機和麥克風輸入擷取的串流會同步處理視訊與音軌。(請勿將 MediaStreamTrack<track> 元素混為一談,後者是完全不同的元素)。

理解 MediaStream API 最簡單的方法是從外部檢視:

  1. 透過瀏覽器前往 WebRTC 範例getUserMedia
  2. 開啟控制台。
  3. 檢查全域範圍內的 stream 變數。

每個 MediaStream 都有一個輸入內容 (可能是 getUserMedia() 產生的 MediaStream),以及輸出內容 (可傳遞至影片元素或 RTCPeerConnection)。

getUserMedia() 方法會採用 MediaStreamConstraints 物件參數,並傳回可解析為 MediaStream 物件的 Promise

每個 MediaStream 都有 label,例如 'Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ'getAudioTracks()getVideoTracks() 方法會傳回 MediaStreamTrack 陣列。

getUserMedia 範例來說,stream.getAudioTracks() 會傳回空陣列 (因為沒有音訊),且假設已連接有效的網路攝影機,stream.getVideoTracks() 會傳回一個 MediaStreamTrack 陣列,代表從網路攝影機拍攝的串流。每個 MediaStreamTrack 都有種類 ('video''audio')、label (類似 'FaceTime HD Camera (Built-in)'),代表音訊或影片的一或多個聲道。在這種情況下,只有一個視訊軌不會聽到聲音,但很容易想像的應用情況有很多,例如可透過前置鏡頭串流播放的即時通訊應用程式、後置鏡頭、麥克風,以及分享畫面的應用程式。

設定 srcObject 屬性即可將 MediaStream 附加至影片元素。這項設定先前會將 src 屬性設為使用 URL.createObjectURL() 建立的物件網址,但是已淘汰

getUserMedia 也可用來做為 Web Audio API 的輸入節點

// Cope with browser differences.
let audioContext;
if (typeof AudioContext === 'function') {
  audioContext = new AudioContext();
} else if (typeof webkitAudioContext === 'function') {
  audioContext = new webkitAudioContext(); // eslint-disable-line new-cap
} else {
  console.log('Sorry! Web Audio not supported.');
}

// Create a filter node.
var filterNode = audioContext.createBiquadFilter();
// See https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#BiquadFilterNode-section
filterNode.type = 'highpass';
// Cutoff frequency. For highpass, audio is attenuated below this frequency.
filterNode.frequency.value = 10000;

// Create a gain node to change audio volume.
var gainNode = audioContext.createGain();
// Default is 1 (no change). Less than 1 means audio is attenuated
// and vice versa.
gainNode.gain.value = 0.5;

navigator.mediaDevices.getUserMedia({audio: true}, (stream) => {
  // Create an AudioNode from the stream.
  const mediaStreamSource =
    audioContext.createMediaStreamSource(stream);
  mediaStreamSource.connect(filterNode);
  filterNode.connect(gainNode);
  // Connect the gain node to the destination. For example, play the sound.
  gainNode.connect(audioContext.destination);
});

以 Chromium 為基礎的應用程式和擴充功能也可以整合 getUserMedia。在資訊清單新增 audioCapture 和/或 videoCapture 權限後,系統只會在安裝時要求及授予一次權限。在那之後,系統不會要求使用者授予相機或麥克風存取權。

getUserMedia()」只需授予一次權限。不久後,瀏覽器的資訊列會顯示「允許」按鈕。getUserMedia() 的 HTTP 存取權已歸類為強大的功能,因此 Chrome 已於 2015 年底淘汰這項 HTTP 存取權。

該目的可能會為任何串流資料來源啟用 MediaStream,而不只是相機或麥克風。如此一來,就能從儲存的資料或任意資料來源 (例如感應器或其他輸入來源) 進行串流。

getUserMedia() 必須與其他 JavaScript API 和程式庫搭配使用,才真正發揮效用。

  • Webcam Toy 為自動攝影應用程式,可利用 WebGL 添加奇怪的特效,造成可分享或儲存在本機的相片。
  • FaceKat 是一款使用 headtrackr.js 打造的臉部追蹤遊戲。
  • ASCII 相機會使用 Canvas API 產生 ASCII 圖片。
idevelop.ro/ascii-camera 產生的 ASCII 圖像
gUM ASCII 圖片!

限制

您可以使用限制條件來設定 getUserMedia() 的影片解析度值。這也適用於其他限制條件,例如顯示比例、面向模式 (前置或後置鏡頭)、影格速率、高度和寬度,以及 applyConstraints() 方法。

如需範例,請參閱「WebRTC 範例 getUserMedia:選取解析度」。

如果設定不允許的限制值,系統就會提供 DOMExceptionOverconstrainedError (舉例來說,如果無法要求的解析度)。如要查看實際運作情形,請參閱 WebRTC 範例 getUserMedia:選取解析度示範模式。

螢幕畫面和分頁擷取

Chrome 應用程式也能透過 chrome.tabCapturechrome.desktopCapture API,分享單一瀏覽器分頁或整個桌面的即時影像。(如需示範和詳細資訊,請參閱「使用 WebRTC 分享螢幕畫面」一文)。雖然這篇文章只有幾年發布,但內容仍然有趣)。

您也可以透過實驗性的 chromeMediaSource 限制,在 Chrome 中使用螢幕畫面擷取做為 MediaStream 來源。請注意,螢幕畫面擷取需要使用 HTTPS。建議您僅在透過指令列標記啟用擷取功能 (如這篇文章所述) 的情況下使用,因此才應用於開發。

信號:工作階段控制設定、網路和媒體資訊

WebRTC 會使用 RTCPeerConnection 在瀏覽器之間傳遞串流資料 (也稱為對等項目),但還需要一個機制來協調通訊及傳送控制訊息,這個流程也稱為「信號」。WebRTC「不」指定訊號方法和通訊協定。信號並不屬於 RTCPeerConnection API。

WebRTC 應用程式開發人員可以改用他們偏好的任何訊息通訊協定 (例如 SIP 或 XMPP),以及任何適當的雙雙 (雙向) 通訊管道。appr.tc 範例使用 XHR 和 Channel API 做為信號機制。程式碼研究室會使用在 Node 伺服器上執行的 Socket.io

信號可用於交換三種資訊:

  • 工作階段控制訊息:初始化或關閉通訊及回報錯誤。
  • 網路設定:至外部,您的電腦 IP 位址和通訊埠為何?
  • 媒體功能:瀏覽器和要與哪個瀏覽器進行通訊時可以處理哪些轉碼器和解析度?

必須先順利完成透過訊號交換資訊交換作業,才能開始點對點串流模式。

例如,假設小艾想和小包溝通。以下是 W3C WebRTC 規格的程式碼範例,這是顯示信號程序的實際運作情形。程式碼會假設存在在 createSignalingChannel() 方法中建立的部分信號機制。另請注意,在 Chrome 和 Opera 中,RTCPeerConnection 目前加上前置字串。

// 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);
  }
};

// Once 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);
  }
};

首先,小莉和 Bob 會交換網路資訊。(尋找候選項目運算式是指使用 ICE 架構尋找網路介面和通訊埠的程序)。

  1. Alice 會建立含有 onicecandidate 處理常式的 RTCPeerConnection 物件,該處理常式會在網路候選項目可供使用時執行。
  2. Alice 會透過所使用的任何訊號管道 (例如 WebSocket 或其他機制),將序列化的候選資料傳送給 Bob。
  3. 當志明收到 Alice 的候選訊息時,他會呼叫 addIceCandidate,將候選項目加入遠端對等點說明。

WebRTC 用戶端 (在本範例中稱為對等點,或稱 Alice 和 Bob) 也需要確定並交換本機和遠端的音訊及視訊媒體資訊,例如解析度和轉碼器功能。只要使用工作階段說明通訊協定 (SDP) 交換「產品」和「答案」,即可交換媒體設定資訊的行為:

  1. 小艾會執行 RTCPeerConnection createOffer() 方法。傳回的結果會傳遞 RTCSessionDescription - Alice 的本機工作階段說明。
  2. 在回呼中,Alice 會使用 setLocalDescription() 設定本機說明,然後透過信號管道將此工作階段說明傳送給 Bob。請注意,在呼叫 setLocalDescription() 後,RTCPeerConnection 才會開始收集候選內容。以上資訊請參閱 JSEP IETF 草稿
  3. 白先生使用 setRemoteDescription() 將說明設為遠端說明。
  4. Bob 執行 RTCPeerConnection createAnswer() 方法,並傳遞他從 Alice 取得的遠端說明,以便產生能與她相容的本機工作階段。createAnswer() 回呼會傳遞 RTCSessionDescription。Bob 將這個值設為本地商家簡介,並傳送給 Alice。
  5. 當 Alice 取得小明的工作階段說明時,會使用 setRemoteDescription 將其設為遠端說明。
  6. 重要通知!

RTCSessionDescription 物件是符合工作階段說明通訊協定的 blob,也就是 SDP。已序列化的 SDP 物件如下所示:

v=0
o=- 3883943731 1 IN IP4 127.0.0.1
s=
t=0 0
a=group:BUNDLE audio video
m=audio 1 RTP/SAVPF 103 104 0 8 106 105 13 126

// ...

a=ssrc:2223794119 label:H4fjnMzxy3dPIgQ7HxuCTLb4wLLLeRHnFxh810

網路與媒體資訊的收購與交易平台可以同時完成,但都必須先完成這兩個程序,才能在同業之間串流播放音訊和視訊。

前述的優惠/答案架構稱為「JavaScript 工作階段建立通訊協定」(簡稱 JSEP)。以下的 Ericsson 示範影片中說明瞭首次實作 WebRTC 時的信號和串流程序,有一段非常感謝的動畫。

JSEP 架構圖
JSEP 架構

信號程序順利完成後,即可在呼叫端和受呼叫端之間,直接透過點對點傳送資料。如果傳送失敗,則會透過中介轉發伺服器進行串流 (詳情請參閱稍後說明)。串流是指 RTCPeerConnection 的工作。

RTCPeerConnection

RTCPeerConnection 是 WebRTC 元件,能處理對等點之間的串流資料穩定且有效率的通訊。

以下是顯示 RTCPeerConnection 角色的 WebRTC 架構圖表。如你所知,綠色零件很複雜!

WebRTC 架構圖
WebRTC 架構 (來自 webrtc.org)

從 JavaScript 的角度來看,這張圖的重點是讓 RTCPeerConnection 能夠保護網頁開發人員免於遭受潛伏的眾多複雜問題。WebRTC 使用的轉碼器和通訊協定會執行大量工作,以實現即時通訊,即使網路不穩定也不例外:

  • 封包遺失隱藏功能
  • 取消回音
  • 頻寬調整
  • 動態時基誤差緩衝
  • 自動增益控制
  • 雜訊抑制和抑制
  • 圖片清理

先前的 W3C 程式碼顯示從信號的角度來看,簡化 WebRTC 範例。以下提供兩個運作中 WebRTC 應用程式的逐步操作說明。第一個是示範 RTCPeerConnection 的簡單範例,第二個則是完全運作的視訊通訊用戶端。

RTCPeerConnection 不使用伺服器

以下程式碼是取自 WebRTC 範例對等互連連線,此連線具備本機「和」遠端 RTCPeerConnection (以及本機和遠端影片) 的網頁。這並不算是非常有用的東西 (呼叫端和受呼叫者位於相同頁面),但會更清楚地顯示 RTCPeerConnection API 的運作方式,因為網頁上的 RTCPeerConnection 物件可以直接交換資料和訊息,不必使用中介信號機制。

在這個範例中,pc1 代表本機對等點 (呼叫端),pc2 則代表遠端對等點 (受呼叫者)。

來電者

  1. 建立新的 RTCPeerConnection 並新增 getUserMedia() 中的串流: ```js // 伺服器是選用設定檔,(稍後請參閱 TURN 和 STUN 討論內容)。 pc1 = new RTCPeerConnection(servers); // ... localStream.getTracks().forEach((track) => { pc1.addTrack(track, localStream);) });
  1. 建立優惠,並將其設為 pc1 的本地說明,且設為 pc2 的遠端說明。呼叫端和受呼叫者都位於同一個頁面,因此不必使用信號就能直接在程式碼中完成這項操作: js pc1.setLocalDescription(desc).then(() => { onSetLocalSuccess(pc1); }, onSetSessionDescriptionError ); trace('pc2 setRemoteDescription start'); pc2.setRemoteDescription(desc).then(() => { onSetRemoteSuccess(pc2); }, onSetSessionDescriptionError );

受呼叫者

  1. 建立 pc2,然後在新增 pc1 的串流時,在影片元素中顯示該串流: js pc2 = new RTCPeerConnection(servers); pc2.ontrack = gotRemoteStream; //... function gotRemoteStream(e){ vid2.srcObject = e.stream; }

RTCPeerConnection API 加上伺服器

不過在現實世界中,WebRTC 需要伺服器,所以可能實現以下目標:

  • 使用者會發現彼此,並交換真實資訊,例如姓名。
  • WebRTC 用戶端應用程式 (對等點) 交換網路資訊。
  • 同類應用程式交換的媒體資料,例如影片格式和解析度。
  • WebRTC 用戶端應用程式週遊於 NAT 閘道和防火牆。

也就是說,WebRTC 需要四種類型的伺服器端功能:

  • 探索及通訊
  • 訊號
  • NAT/防火牆週遊
  • 轉發伺服器 (以免點對點通訊失敗)

網路位址轉譯 (NAT) 遍歷、點對點網路,以及針對使用者探索和信號建構伺服器應用程式的需求,不在本文的討論範圍內。簡單來說,ICE 架構會使用 STUN 通訊協定及其擴充功能 TURN,讓 RTCPeerConnection 能因應 NAT 週遊和其他網路差異。

ICE 是一種架構,可用於與同事 (例如兩個視訊通訊用戶端) 建立連結。ICE 一開始會嘗試「直接」透過 UDP 與對等節點連線,藉此縮短延遲時間。在這個程序中,STUN 伺服器有一項工作:讓 NAT 背後的對等互連得以找出其公開位址和通訊埠。(如要進一步瞭解 STUN 和 TURN,請參閱「建構 WebRTC 應用程式所需的後端服務」)。

正在尋找連線候選項目
尋找轉介候選對象

如果 UDP 失敗,ICE 會嘗試 TCP。如果直接連線失敗 (尤其是因為企業 NAT 遍歷和防火牆),ICE 會使用中介 (轉送) TURN 伺服器。也就是說,ICE 會先使用 STUN 搭配 UDP,直接連線對等點,如果連線失敗,則會改用 TURN 轉發伺服器。尋找候選項目運算式是指尋找網路介面和通訊埠的程序。

WebRTC 資料路徑
WebRTC 資料路徑

WebRTC 工程師 Justin Uberti 在 2013 年 Google I/O WebRTC 簡報中,提供了更多有關 ICE、STUN 和 TURN 的資訊。(簡報投影片提供了 TURN 和 STUN 伺服器的實作範例。)

簡易的視訊通訊用戶端

如要試用 WebRTC,建議使用 STUN 伺服器完成 WebRTC,開始運用訊號進行網路位址轉譯 (NAT)/防火牆週遊,是 appr.tc 的視訊通訊示範影片。此應用程式使用 adapter.js,這個填充碼可用來將應用程式與規格變更和前置字串差異隔離。

在記錄中刻意輸入重複的程式碼。請查看控制台瞭解事件順序。以下是這個程式碼的詳細逐步操作說明。

網路拓撲

WebRTC 目前僅支援一對一通訊,但可用於較複雜的網路情境,例如讓多個對等點直接相互通訊,或是透過多點控制單元 (MCU) 伺服器 (可處理大量參與者進行選擇性串流轉送,以及混音或錄製音訊和視訊)。

多點控制單元拓撲圖
多點控制單元拓撲範例

許多現有的 WebRTC 應用程式都只能呈現網路瀏覽器之間的通訊,但閘道伺服器可讓在瀏覽器上執行的 WebRTC 應用程式與裝置互動,例如電話 (也稱為 PSTN) 和 VOIP 系統。2012 年 5 月,Doubango Telecom 以 WebRTC 和 WebSocket 建構的 sipml5 SIP 用戶端,可用於在 iOS 和 Android 上執行的瀏覽器和應用程式之間,啟用視訊通話功能。在 Google I/O 大會上,Tethr 和 Tropo 使用 OpenBTS 手機在公事包中示範災難復原架構,以便透過 WebRTC 進行功能型手機和電腦之間的通訊。沒有電信業者也能進行電話通訊!

Tethr/Tropo 在 2012 年 Google I/O 大會上示範活動
Tethr/Tropo:公事包中的災難復原

RTCDataChannel API

除了音訊和視訊外,WebRTC 也支援其他類型的資料的即時通訊。

RTCDataChannel API 支援點對點交換任意資料,不僅延遲時間短,處理量也高。如需單頁示範,並瞭解如何建構簡單的檔案傳輸應用程式,請分別參閱 WebRTC 範例WebRTC 程式碼研究室

API 有許多可能的用途,包括:

  • 遊戲
  • 遠端桌面應用程式
  • 即時文字即時通訊
  • 檔案傳輸
  • 分散式網路

這個 API 有多種功能可充分運用 RTCPeerConnection,並提供功能強大且靈活的點對點通訊功能:

  • 正在使用 RTCPeerConnection 工作階段設定
  • 設定優先順序的多個同時管道
  • 可靠和不可靠的傳送語意
  • 內建安全防護 (DTLS) 與壅塞控制
  • 能否搭配音訊或視訊使用

語法與 WebSocket 十分類似、包含 send() 方法和 message 事件:

const localConnection = new RTCPeerConnection(servers);
const remoteConnection = new RTCPeerConnection(servers);
const sendChannel =
  localConnection.createDataChannel('sendDataChannel');

// ...

remoteConnection.ondatachannel = (event) => {
  receiveChannel = event.channel;
  receiveChannel.onmessage = onReceiveMessage;
  receiveChannel.onopen = onReceiveChannelStateChange;
  receiveChannel.onclose = onReceiveChannelStateChange;
};

function onReceiveMessage(event) {
  document.querySelector("textarea#send").value = event.data;
}

document.querySelector("button#send").onclick = () => {
  var data = document.querySelector("textarea#send").value;
  sendChannel.send(data);
};

通訊是直接在瀏覽器之間進行,因此 RTCDataChannel 的運作速度會比 WebSocket 快上許多,即使在與防火牆及 NAT 發生衝突的情況下,必須使用轉發 (TURN) 伺服器。

RTCDataChannel 適用於 Chrome、Safari、Firefox、Opera 和 Samsung Internet。Cube Slam 遊戲會使用這個 API 傳達遊戲狀態。與好友或對熊玩耍!創新的 Sharefest 透過 RTCDataChannelpeerCDN 啟用檔案共用功能,讓 WebRTC 對點對點內容發布功能一目瞭然。

如要進一步瞭解 RTCDataChannel,請參閱 IETF 的草稿通訊協定規格

安全性

即時通訊應用程式或外掛程式可能透過多種方式侵害安全性。例如:

  • 未加密的媒體或資料可能會在瀏覽器之間,或是瀏覽器和伺服器之間遭到攔截。
  • 應用程式可能會在使用者不知情的情況下錄製及發布影片或音訊。
  • 惡意軟體或病毒可能會在無害的外掛程式或應用程式旁安裝。

WebRTC 提供多項功能來避免這些問題:

  • WebRTC 實作會使用安全通訊協定,例如 DTLSSRTP
  • 所有 WebRTC 元件 (包括訊號機制) 都必須加密。
  • WebRTC 並非外掛程式。它的元件是在瀏覽器沙箱中執行,而不是在獨立的處理程序中執行。元件不需要另外安裝,而且會在瀏覽器更新時更新。
  • 你必須明確授予相機和麥克風存取權,且相機或麥克風正在執行時,使用者介面即可清楚顯示這項資訊。

有關串流媒體安全性的完整討論不在本文的討論範圍。詳情請參閱 IETF 建議的「提議的 WebRTC 安全性架構」。

總結

WebRTC 的 API 和標準可普及化及分散工具,用於電話通訊、遊戲、影片製作、音樂製作和新聞收集等各種內容創作與通訊工具。

科技不會比這更造成乾擾

正如網誌網誌作者 Phil Edholm 所把:「可能,WebRTC 和 HTML5 都能促進與原始瀏覽器搜尋資訊的即時通訊。」

開發人員工具

瞭解詳情

標準和通訊協定

WebRTC 支援摘要

MediaStreamgetUserMedia API

  • Chrome 電腦 18.0.1008 以上版本;Android 29 以上版本的 Google Chrome
  • Opera 18 以上版本;適用於 Android 20 以上版本的 Opera
  • Opera 12,Opera Mobile 12 (基於 Presto 引擎)
  • Firefox 17 以上版本
  • Microsoft Edge 16 以上版本
  • Safari 11.2 以上版本 (iOS) 和 11.1 以上版本 (MacOS)
  • UC 11.8 以上版本 (適用於 Android)
  • Samsung Internet 4 以上版本

RTCPeerConnection API

  • Chrome 電腦 20 以上版本;適用於 Android 29 以上版本的 Chrome (無旗標)
  • Opera 18 以上版本 (預設為開啟);Android 20 以上版本的 Opera (預設為開啟)
  • Firefox 22 以上版本 (預設為開啟)
  • Microsoft Edge 16 以上版本
  • Safari 11.2 以上版本 (iOS) 和 11.1 以上版本 (MacOS)
  • Samsung Internet 4 以上版本

RTCDataChannel API

  • Chrome 26 以上版本的實驗版本,但在 Chrome 26 以上版本中更加穩定 (並與 Firefox 互通性);Android 29 以上版本的 Chrome
  • Opera 18 以上版本中的穩定版 (和 Firefox 互通性);適用於 Android 20 以上版本的 Opera
  • Firefox 22 以上版本 (預設為開啟)

如要進一步瞭解 API 跨平台支援 (例如 getUserMediaRTCPeerConnection),請參閱 caniuse.comChrome 平台狀態

webrtc.org 說明文件也可取得 RTCPeerConnection 的原生 API。