WebRTC スタートガイド

WebRTC は、オープンで制約のないウェブを巡る長い戦いの新たな戦いです。

JavaScript の発明者、Brendan Eich 氏

スマートフォン、テレビ、パソコンが共通のプラットフォームで通信できる世界を想像してみてください。ウェブアプリにビデオチャットとピアツーピアのデータ共有を簡単に追加できると想像してみてください。これが WebRTC のビジョンです。

お試しになる場合は、WebRTC はパソコンとモバイル デバイスの Google Chrome、Safari、Firefox、Opera でご利用いただけます。appr.tc にあるシンプルなビデオチャット アプリを使用することをおすすめします。

  1. ブラウザで appr.tc を開きます。
  2. [参加] をクリックしてチャットルームに参加し、アプリにウェブカメラの使用を許可します。
  3. ページの最後に表示された URL を新しいタブまたは別のパソコンで開きます。

クイック スタート

この記事をお読みになる時間がない場合や、コードが本当に必要な場合は、

または、WebRTC Codelab に直接移動することもできます。この手順では、シンプルなシグナリング サーバーを含む完全なビデオチャット アプリを作成する方法が説明されています。

WebRTC の歴史はとても短い

ウェブの最後の大きな課題の一つは、音声と動画による人間同士のコミュニケーションを可能にすることです。リアルタイム通信、略して RTC です。RTC は、ウェブアプリでテキスト入力にテキストを入力するのと同じくらい自然である必要があります。これがないと、イノベーションを起こし、人々が交流する新しい方法を開発する能力が制限されます。

従来、RTC は企業規模で複雑であり、高価な音声および映像技術を自社でライセンス取得するか、社内で開発する必要がありました。RTC テクノロジーを既存のコンテンツ、データ、サービスと統合することは、特にウェブでは困難で時間がかかります。

Gmail のビデオチャットが普及したのは 2008 年で、2011 年には Google がハングアウトを導入しました。Google のトークでは Gmail と同様、Google は GIPS を買収しました。GIPS は、コーデックやエコー キャンセラなどの RTC に必要なコンポーネントを数多く開発した企業です。Google は、GIPS が開発した技術をオープンソース化し、インターネット技術特別調査委員会(IETF)や World Wide Web Consortium(W3C)の関連標準化団体と連携し、業界の合意を形成しました。2011 年 5 月、Ericsson は WebRTC の最初の実装を構築しました。

WebRTC は、プラグインなしでリアルタイムで動画、音声、データ通信を行えるオープン スタンダードを実装しました。真のニーズがあったのです。

  • 多くのウェブサービスでは RTC が使用されていましたが、ダウンロード、ネイティブ アプリ、プラグインが必要でした。たとえば、Skype、Facebook、ハングアウトなどです。
  • プラグインのダウンロード、インストール、更新は複雑で、エラーが発生しやすく、面倒な作業です。
  • プラグインの導入、デバッグ、トラブルシューティング、テスト、保守は難しく、ライセンスが必要で、複雑で費用のかかるテクノロジーとの統合が必要になる場合もあります。そもそもプラグインをインストールするよう促すことは、多くの場合、難しいことです。

WebRTC プロジェクトの指針は、その API がオープンソースで、無料で、標準化されており、ウェブブラウザに組み込まれており、既存のテクノロジーよりも効率的であるべきだというものです。

今どこにいるのか?

WebRTC は、Google Meet などのさまざまなアプリで使用されています。WebRTC は、WebKitGTK+ および Qt ネイティブ アプリとも統合されています。

WebRTC は、次の 3 つの API を実装します。 - MediaStreamgetUserMedia とも呼ばれます) - RTCPeerConnection - RTCDataChannel

API は、次の 2 つの仕様で定義されています。

これら 3 つの API はすべて、モバイルとパソコンで Chrome、Safari、Firefox、Edge、Opera でサポートされています。

getUserMedia: デモとコードについては、WebRTC のサンプルをご覧ください。または、getUserMedia をウェブ オーディオの入力として使用する Chris Wilson の素晴らしい例をお試しください。

RTCPeerConnection: 簡単なデモと完全に機能するビデオチャット アプリについては、WebRTC のサンプル ピア接続appr.tc をそれぞれご覧ください。このアプリでは adapter.jsWebRTC コミュニティのサポートにより Google が管理している JavaScript shim)を使用して、ブラウザの違いや仕様の変更を抽象化しています。

RTCDataChannel: 実際の動作を確認するには、WebRTC サンプルにあるデータチャネルのデモの 1 つをご覧ください。

WebRTC Codelab では、3 つの API すべてを使用して、ビデオチャットとファイル共有用のシンプルなアプリを作成する方法を紹介しています。

初めての WebRTC

WebRTC アプリでは、次のことを行う必要があります。

  • 音声や動画などのストリーミング データを取得します。
  • IP アドレスやポートなどのネットワーク情報を取得し、他の WebRTC クライアント(ピアと呼ばれます)と交換して、NAT やファイアウォールを経由する場合でも接続を有効にします。
  • シグナリング通信を調整してエラーを報告し、セッションを開始または終了する。
  • 解像度やコーデックなど、メディアとクライアント機能に関する情報を交換します。
  • ストリーミングの音声、動画、データを通信できます。

ストリーミング データを取得して通信するために、WebRTC では次の API が実装されています。

  • MediaStream は、ユーザーのカメラやマイクなどからのデータ ストリームにアクセスできます。
  • RTCPeerConnection を使用すると、暗号化と帯域幅の管理機能を備えた音声通話またはビデオ通話が可能になります。
  • RTCDataChannel を使用すると、汎用データのピアツーピア通信が可能になります。

(WebRTC のネットワークやシグナリングの側面については、後ほど詳しく説明します)。

MediaStream API(別名 getUserMedia API)

MediaStream API は、メディアの同期ストリームを表します。たとえば、カメラとマイク入力から取得されたストリームには、動画トラックと音声トラックが同期されています。(MediaStreamTrack<track> 要素はまったく異なるものですので混同しないでください)。

MediaStream API を理解する最も簡単な方法は、実際の環境で見ることです。

  1. ブラウザで、WebRTC のサンプル getUserMedia に移動します。
  2. Console を開きます。
  3. グローバル スコープにある stream 変数を調べます。

MediaStream には入力(getUserMedia() によって生成された MediaStream など)と、動画要素または RTCPeerConnection に渡される出力があります。

getUserMedia() メソッドは MediaStreamConstraints オブジェクト パラメータを受け取り、MediaStream オブジェクトに解決される Promise を返します。

MediaStream には、'Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ' などの label があります。MediaStreamTrack の配列は、getAudioTracks() メソッドと getVideoTracks() メソッドによって返されます。

getUserMedia の例では、stream.getAudioTracks() は空の配列を返します(音声がないため)。また、動作しているウェブカメラが接続されていると仮定すると、stream.getVideoTracks() は、ウェブカメラからのストリームを表す MediaStreamTrack の配列を返します。各 MediaStreamTrack は種類('video' または 'audio')と label'FaceTime HD Camera (Built-in)' など)を持ち、音声または動画の 1 つ以上のチャンネルを表します。この場合、動画トラックは 1 つしかなく、音声はありませんが、前面カメラ、背面カメラ、マイクからストリーミングを取得するチャットアプリや、画面を共有するアプリが使用するなど、多数のユースケースがあることは容易に想像できます。

MediaStream を動画要素に添付するには、srcObject 属性を設定します。以前は、src 属性を URL.createObjectURL() で作成したオブジェクト URL に設定していましたが、これは非推奨となりました

getUserMediaWeb 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権限を追加すると、インストール時に権限のリクエストと付与を 1 回だけ行うことができます。それ以降は、カメラやマイクへのアクセス許可をユーザーに求めることはありません。

権限は、getUserMedia() に対して 1 回だけ付与する必要があります。初回は、ブラウザの情報バーに [許可] ボタンが表示されます。getUserMedia() への HTTP アクセスは、強力な機能に分類されていたため、2015 年末に Chrome でサポートを終了しました。

カメラやマイクだけでなく、あらゆるストリーミング データソースに対して MediaStream を有効にすることを目的としています。これにより、保存されたデータや、センサーやその他の入力などの任意のデータソースからのストリーミングが可能になります。

getUserMedia() は、他の JavaScript API やライブラリと組み合わせることで実際に使用できます。

  • Webcam Toy は、WebGL を使用して写真に奇妙な効果を追加し、ローカルで共有または保存できるフォトブース アプリです。
  • FaceKat は、headtrackr.js で構築された顔追跡ゲームです。
  • ASCII カメラ: Canvas API を使用して ASCII 画像を生成します。
で確認できます。 <ph type="x-smartling-placeholder">
</ph> idevelop.ro/ascii-camera が生成した ASCII 画像
gUM ASCII アート!

制約

制約を使用して、getUserMedia() の動画解像度の値を設定できます。また、アスペクト比など、その他の制約のサポートも可能です。対面モード(前面カメラまたは背面カメラ)フレームレート、高さ、幅applyConstraints() メソッドを使用します。

例については、WebRTC のサンプル getUserMedia: 解像度を選択するをご覧ください。

許可されていない制約値を設定すると、たとえばリクエストされた解決が利用できない場合に DOMException または OverconstrainedError が提供されます。実際の動作を確認するには、デモの WebRTC サンプル getUserMedia: 解像度を選択するをご覧ください。

画面とタブのキャプチャ

Chrome アプリでは、chrome.tabCapture API と chrome.desktopCapture API を使用して、1 つのブラウザタブまたはデスクトップ全体のライブ動画を共有することもできます。(デモと詳細については、WebRTC を使用した画面共有をご覧ください)。数年前の記事ですが、今も面白そうです)。

試験運用版の chromeMediaSource 制約を使用して、Chrome でスクリーン キャプチャを MediaStream ソースとして使用することもできます。スクリーン キャプチャには HTTPS が必要です。また、こちらの投稿で説明されているように、コマンドライン フラグで有効にするため、開発でのみ使用してください。

シグナリング: セッション コントロール、ネットワーク、メディアの情報

WebRTC は RTCPeerConnection を使用してブラウザ間(ピアとも呼ばれます)のストリーミング データを通信しますが、通信を調整し、制御メッセージを送信するメカニズム(シグナリングと呼ばれるプロセス)も必要です。シグナリング方法とプロトコルは WebRTC では指定されていません。シグナリングは RTCPeerConnection API の一部ではありません。

その代わりに、WebRTC アプリのデベロッパーは、SIP や XMPP などの任意のメッセージング プロトコルと、任意の適切な二重通信(双方向)通信チャネルを選択できます。appr.tc の例では、XHR と Channel API をシグナリング メカニズムとして使用しています。この Codelab では、ノードサーバーで実行される Socket.io を使用します。

シグナリングは、次の 3 種類の情報の交換に使用されます。

  • セッション制御メッセージ: 通信を初期化または終了してエラーを報告します。
  • ネットワーク構成:外部から見たコンピュータの 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);
  }
};

まず、アリスとボブがネットワーク情報を交換します。(「検出結果の候補」という式は、ICE フレームワークを使用してネットワーク インターフェースとポートを検出するプロセスを指します)。

  1. Alice は、ネットワーク候補が利用可能になると実行される onicecandidate ハンドラを使用して RTCPeerConnection オブジェクトを作成します。
  2. Alice は、WebSocket やその他のメカニズムなど、使用しているシグナリング チャネルを介してシリアル化された候補データを Bob に送信します。
  3. Bob は Alice から候補メッセージを受け取ると、addIceCandidate を呼び出してリモートピアの説明にその候補を追加します。

WebRTC クライアント(ピア、この例では Alice と Bob)も、解像度やコーデック機能などのローカルおよびリモートの音声と映像のメディア情報を確認し、交換する必要があります。メディア構成情報を交換するためのシグナリングは、Session Description Protocol(SDP)を使用してオファー回答を交換することで処理されます。

  1. Alice は RTCPeerConnection createOffer() メソッドを実行します。このからの戻り値には、RTCSessionDescription(Alice のローカル セッションの説明)が渡されます。
  2. コールバックで、Alice は setLocalDescription() を使用してローカルの説明を設定し、このセッションの説明をシグナリング チャネル経由で Bob に送信します。RTCPeerConnection は、setLocalDescription() が呼び出されるまで候補の収集を開始しません。これは JSEP IETF ドラフトに体系化されています。
  3. Bob は、setRemoteDescription() を使用して、Alice が送信した説明をリモートの説明として設定します。
  4. Bob は RTCPeerConnection createAnswer() メソッドを実行し、Alice から取得したリモートの説明をそのメソッドに渡して、Alice と互換性のあるローカル セッションを生成できるようにします。createAnswer() コールバックには RTCSessionDescription が渡されます。ユーザー A はそれをローカルの説明として設定し、Alice に送信します。
  5. アリスはボブのセッションの説明を取得すると、それを setRemoteDescription のリモートの説明として設定します。
  6. ping!
で確認できます。

RTCSessionDescription オブジェクトは、Session Description Protocol(SDP)に準拠する blob です。シリアル化された 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)と呼ばれています。(最初の WebRTC 実装については、Ericsson のデモ動画にシグナリングとストリーミングのプロセスを説明するアニメーションがあります)。

<ph type="x-smartling-placeholder">
</ph> JSEP アーキテクチャの図
JSEP アーキテクチャ

シグナリング プロセスが正常に完了すると、呼び出し元と呼び出し先の間でデータがピアツーピアに直接ストリーミングされます。失敗した場合は、中継リレーサーバー経由でストリーミングできます(詳しくは後述)。ストリーミングは RTCPeerConnection が担います。

RTCPeerConnection

RTCPeerConnection は、ピア間のストリーミング データの安定した効率的な通信を処理する WebRTC コンポーネントです。

以下は、RTCPeerConnection のロールを示す WebRTC アーキテクチャ図です。お気づきのとおり、緑色の部分は複雑です。

<ph type="x-smartling-placeholder">
</ph> WebRTC アーキテクチャの図
WebRTC アーキテクチャ(webrtc.org より)

JavaScript の観点から説明すると、この図から理解すべき最も重要なことは、RTCPeerConnection がウェブ デベロッパーを潜在的に無数の複雑さから守っているということです。WebRTC で使用されるコーデックとプロトコルは、信頼性が低いネットワークでもリアルタイム通信を可能にするために、大量の処理を行います。

  • パケットロス隠蔽
  • エコー キャンセラ
  • 帯域幅の適応
  • 動的ジッター バッファリング
  • AGC
  • ノイズ リダクションとサプレッション
  • イメージ クリーニング

上記の W3C コードは、シグナリングの観点から WebRTC の簡略化した例を示しています。以下に、動作する 2 つの WebRTC アプリについて解説します。1 つ目は RTCPeerConnection を説明する簡単な例で、2 つ目は完全に機能するビデオチャット クライアントです。

サーバーなしの RTCPeerConnection

次のコードは、1 つのウェブページにローカルとリモートの RTCPeerConnection(およびローカルとリモートの動画)を持つ WebRTC のサンプルピア接続からの抜粋です。呼び出し元と呼び出し先が同じページ上にあるため、あまり役に立ちません。ただし、ページ上の RTCPeerConnection オブジェクトは、中間のシグナリング メカニズムを使用せずにデータとメッセージを直接交換できるため、RTCPeerConnection API の動作がやや明確になります。

この例では、pc1 はローカルピア(呼び出し元)を表し、pc2 はリモートピア(呼び出し元)を表します。

発信者

  1. 新しい RTCPeerConnection を作成し、getUserMedia() からのストリームを追加します。 ```js // Servers は省略可能な構成ファイル。(後述の TURN と STUN の説明をご覧ください)。 pc1 = new RTCPeerConnection(servers); // ... localStream.getTracks().forEach((track) =&gt; { 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 には、次の 4 種類のサーバーサイド機能が必要です。

  • ユーザーの発見と通信
  • シグナリング
  • NAT/ファイアウォール トラバーサル
  • ピアツーピア通信が失敗した場合のリレーサーバー

NAT トラバーサル、ピアツーピア ネットワーキング、ユーザーの検出とシグナリング用のサーバーアプリを構築するための要件は、この記事の範囲外です。説明すれば、STUN プロトコルとその拡張である TURNICE フレームワークによって使用され、これにより RTCPeerConnection が NAT トラバーサルやその他のネットワークの曖昧さに対処できるようになるとだけ述べておきます。

ICE は、2 つのビデオチャット クライアントなど、ピアを接続するためのフレームワークです。最初に ICE は UDP を経由してピアを直接接続しようとし、レイテンシを最小限に抑えます。このプロセスでは、STUN サーバーは単一のタスク(NAT の背後にあるピアがパブリック アドレスとポートを特定できるようにする)を担います。(STUN と TURN について詳しくは、WebRTC アプリに必要なバックエンド サービスをビルドするをご覧ください)。

<ph type="x-smartling-placeholder">
</ph> 接続候補の検索
接続候補の検索

UDP に失敗した場合、ICE は TCP を試みます。特に企業の NAT トラバーサルとファイアウォールが原因で直接接続に失敗した場合、ICE は中間(リレー)TURN サーバーを使用します。つまり、ICE はまず UDP で STUN を使用してピアを直接接続し、接続が失敗した場合は TURN リレー サーバーにフォールバックします。「検出候補」という式は、ネットワーク インターフェースとポートを検出するプロセスを指します。

<ph type="x-smartling-placeholder">
</ph> WebRTC データパスウェイ
WebRTC データパスウェイ

WebRTC エンジニアの Justin Uberti が、2013 Google I/O WebRTC プレゼンテーションで ICE、STUN、TURN について詳しく説明しています。(プレゼンテーションのスライドに、TURN サーバーと STUN サーバーの実装例が記載されています)。

シンプルなビデオチャット クライアント

STUN サーバーを使用したシグナリングと NAT/ファイアウォール トラバーサルが備わった WebRTC を試すには、appr.tc のビデオチャット デモをおすすめします。このアプリは adapter.js という shim を使用して、アプリを仕様の変更やプレフィックスの違いから分離します。

ロギングでは、コードが冗長にされています。イベントの順序については、コンソールでご確認ください。コードの詳細なチュートリアルは、以下のとおりです。

ネットワーク トポロジ

WebRTC は現在実装されているように 1 対 1 の通信しかサポートしていませんが、より複雑なネットワーク シナリオで使用できます。たとえば、複数のピアが互いに直接通信したり、マルチポイント コントロール ユニット(MCU)というサーバーを介して多数の参加者を処理して選択的なストリーム転送や、音声と動画のミキシングや録画を行ったりする場合などが考えられます。

<ph type="x-smartling-placeholder">
</ph> マルチポイント制御ユニットのトポロジ図
マルチポイント制御ユニットのトポロジ例

既存の WebRTC アプリの多くは、ウェブブラウザ間の通信のみを示していますが、ブラウザで実行されている WebRTC アプリは、電話PSTN とも呼ばれます)や VOIP システムなどのデバイスやと通信できます。2012 年 5 月、Doubango Telecom は、WebRTC と WebSocket で構築された sipml5 SIP クライアントをオープンソース化しました。これは、iOS と Android で動作するブラウザとアプリ間でのビデオ通話を可能にするために使用されています。Google I/O で Tethr と Tropo は、OpenBTS セルを使用して、WebRTC を介したフィーチャー フォンとパソコン間の通信を可能にする災害情報通信のフレームワークブリーフケースで実証しました。携帯通信会社なしでの電話通信

<ph type="x-smartling-placeholder">
</ph> Google I/O 2012 での Tethr と Tropo のデモ
Tethr/Tropo: ブリーフケースに入った災害情報通信

" id="rtcdatachannel_api" tabindex="-1">RTCDataChannel API

WebRTC は、音声や動画だけでなく、他の種類のデータのリアルタイム通信もサポートしています。

RTCDataChannel API を使用すると、低レイテンシと高スループットで任意のデータをピアツーピアで交換できます。単一ページのデモとシンプルなファイル転送アプリの作成方法については、それぞれ WebRTC サンプルWebRTC Codelab をご覧ください。

API には次のようなさまざまなユースケースが考えられます。

  • ゲーム
  • リモート デスクトップ アプリ
  • リアルタイムのテキスト チャット
  • ファイル転送
  • 分散型ネットワーク

この API には、RTCPeerConnection を最大限に活用し、強力で柔軟なピアツーピア通信を可能にするいくつかの機能があります。

  • RTCPeerConnection セッション設定を活用
  • 複数のチャネルを同時に利用して優先順位を付ける
  • 信頼性が高い配信セマンティクスと信頼性の低い配信セマンティクス
  • 組み込みのセキュリティ(DTLS)と輻輳制御
  • 音声や動画の有無にかかわらず使用できる

構文は、send() メソッドと message イベントがある WebSocket と意図的に類似しています。

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

通信はブラウザ間で直接行われるため、ファイアウォールや NAT に対応するためのホールパンチ処理が失敗した場合、リレー(TURN)サーバーが必要な場合でも、RTCDataChannel は WebSocket よりもはるかに高速です。

RTCDataChannel は Chrome、Safari、Firefox、Opera、Samsung Internet でご利用いただけます。Cube Slam ゲームは、API を使用してゲームの状態を伝達します。友だちとプレイするか、クマとプレイしましょう!革新的なプラットフォームである Sharefest は、RTCDataChannelpeerCDN を通じてファイル共有を可能にし、WebRTC によってピアツーピア コンテンツ配信がどのように可能になるかを垣間見ることができました。

RTCDataChannel の詳細については、IETF のプロトコル仕様ドラフトをご覧ください。

セキュリティ

リアルタイム通信アプリやプラグインがセキュリティを侵害する方法はいくつかあります。例:

  • 暗号化されていないメディアやデータは、ブラウザ間、またはブラウザとサーバー間で傍受される可能性があります。
  • アプリは、ユーザーが気付かないうちに動画や音声を記録し、配信することがあります。
  • 無害に見えるプラグインやアプリと一緒に、マルウェアやウイルスがインストールされることがあります。

WebRTC には、こうした問題を回避するための機能がいくつかあります。

  • WebRTC の実装では、DTLSSRTP などのセキュア プロトコルを使用します。
  • 暗号化は、シグナリング メカニズムを含むすべての WebRTC コンポーネントで必須です。
  • WebRTC はプラグインではありません。そのコンポーネントは、別のプロセスではなく、ブラウザのサンドボックス内で実行されます。コンポーネントは個別のインストールを必要とせず、ブラウザが更新されるたびに更新されます。
  • カメラとマイクへのアクセスは、明示的に許可する必要があります。また、カメラまたはマイクが動作している場合は、それがユーザー インターフェースに明示されます。

ストリーミング メディアのセキュリティに関する詳細な説明は、この記事の対象外です。詳細については、IETF が提案している WebRTC Security Architecture 案をご覧ください。

まとめ

WebRTC の API と標準により、電話、ゲーム、動画制作、音楽制作、ニュース収集など、コンテンツの作成とコミュニケーションのためのツールを誰もが利用できるようにし、分散化できます。

テクノロジーがこれほど破壊的なものになることはありません。

ブロガーの Phil Edholm 氏は、次のように述べています。「WebRTC と HTML5 なら、元のブラウザが情報提供をしていたのと同じ、リアルタイムのコミュニケーションを変革できる可能性があります。」

デベロッパー ツール

その他の情報

標準とプロトコル

WebRTC サポートの概要

MediaStream API と getUserMedia API

  • Chrome デスクトップ 18.0.1008 以降Chrome for Android 29 以降
  • Opera 18 以降Android 20 以降の Opera
  • Opera 12、Opera Mobile 12(Presto エンジンに基づく)
  • Firefox 17 以降
  • Microsoft Edge 16 以降
  • iOS の場合は Safari 11.2 以降、MacOS の場合は 11.1 以降
  • UC 11.8 以降(Android)
  • Samsung Internet 4 以降

RTCPeerConnection API

  • Chrome デスクトップ 20 以降Chrome for Android 29 以降(フラグレス)
  • Opera 18 以降(デフォルトで有効)Android 20 以降の Opera(デフォルトで有効)
  • Firefox 22 以降(デフォルトで有効)
  • Microsoft Edge 16 以降
  • iOS の場合は Safari 11.2 以降、MacOS の場合は 11.1 以降
  • Samsung Internet 4 以降

RTCDataChannel API

  • Chrome 25 の試験運用版、Chrome 26 以降では安定性が向上(および Firefox の相互運用性)Chrome for Android 29 以降
  • Opera 18 以降の安定版(Firefox と相互運用可能)Android 20 以降の Opera
  • Firefox 22 以降(デフォルトで有効)

API(getUserMediaRTCPeerConnection など)のクロス プラットフォーム サポートについて詳しくは、caniuse.comChrome プラットフォームのステータスをご覧ください。

RTCPeerConnection のネイティブ API は、webrtc.org のドキュメントでも確認できます。