WebRTC スタートガイド

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

JavaScript の創始者、Brendan Eich

プラグインを使用しないリアルタイム コミュニケーション

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

お試しになる場合は、WebRTC は、パソコンとモバイルの Google Chrome、Safari、Firefox、Opera で利用できます。最初は、appr.tc のシンプルなビデオ チャット アプリを試してみることをおすすめします。

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

クイック スタート

この記事を読む時間がない、またはコードのみが必要な場合は、

または、WebRTC Codelab に直接進んでください。この Codelab では、シンプルなシグナリング サーバーを含む、完全なビデオ チャット アプリを作成する方法を段階的に説明しています。

WebRTC の簡単な歴史

ウェブの最後の大きな課題の一つは、音声と動画による人間のコミュニケーションを可能にすることです。つまり、リアルタイム通信(RTC)です。RTC は、テキスト入力にテキストを入力するのと同じくらい自然にウェブアプリで使用できる必要があります。データがなければ、ユーザーとの新しいやり取りを開発したり、イノベーションを起こしたりする能力に限界が生じます。

これまで RTC は企業向けで複雑であり、高価な音声と動画の技術をライセンス取得または社内で開発する必要がありました。RTC テクノロジーを既存のコンテンツ、データ、サービスと統合することは、特にウェブでは困難で時間がかかっていました。

Gmail のビデオ通話は 2008 年に人気を博し、2011 年に Google は(Gmail と同様に)Talk を使用する Hangouts を導入しました。Google は、コーデックやエコー キャンセル技術など、RTC に必要な多くのコンポーネントを開発した GIPS を買収しました。Google は、GIPS によって開発された技術をオープンソース化し、業界のコンセンサスを確保するために、インターネット技術特別調査委員会(IETF)とワールドワイド ウェブ コンソーシアム(W3C)の関連する標準化団体と連携しました。2011 年 5 月、エリクソンは 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 をご覧ください。このアプリは、WebRTC コミュニティの協力を得て Google が管理している JavaScript シムの adapter.js を使用して、ブラウザの違いや仕様の変更を抽象化しています。

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

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 には label'Xk7EuLhsuHKbnjLWkW4yYGNJJ8ONsgwHBvLQ' など)があります。getAudioTracks() メソッドと getVideoTracks() メソッドは、MediaStreamTrack の配列を返します。

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

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

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

getUserMedia() に対して権限を付与する必要があるのは 1 回だけです。初めてアクセスしたときに、ブラウザのinfobarに [許可] ボタンが表示されます。getUserMedia() の HTTP アクセスは、強力な機能に分類されたため、2015 年末に Chrome で非推奨になりました。

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

getUserMedia() は、他の JavaScript API やライブラリと組み合わせることで、その真価を発揮します。

  • Webcam Toy は、WebGL を使用して写真に奇妙で素晴らしい効果を追加し、共有またはローカルに保存できるフォトブート アプリです。
  • FaceKat は、headtrackr.js で作成された顔トラッキング ゲームです。
  • ASCII Camera は、Canvas API を使用して ASCII 画像を生成します。
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 では、Node サーバーで実行される Socket.io を使用します。

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

  • セッション制御メッセージ: 通信の初期化または終了、エラーの報告に使用します。
  • ネットワーク構成: 外部から見たパソコンの IP アドレスとポート
  • メディア機能: ブラウザと、ブラウザが通信する相手が処理できるコーデックと解像度

ピアツーピア ストリーミングを開始するには、シグナリングによる情報交換が正常に完了している必要があります。

たとえば、Alice が Bob と通信するとします。以下は、シグナリング プロセスの動作を示す 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 クライアント(ピア、この例ではアリスとボブ)は、解像度やコーデック機能など、ローカルとリモートの音声と動画のメディア情報を確認して交換する必要があります。メディア構成情報を交換するためのシグナリングは、セッション記述プロトコル(SDP)を使用してオファー回答を交換することで行われます。

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

RTCSessionDescription オブジェクトは、セッション記述プロトコル(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 Session Establishment Protocol(JSEP)と呼ばれます。最初の WebRTC 実装に関する Ericsson のデモ動画では、シグナリングとストリーミングのプロセスを説明する優れたアニメーションが紹介されています。

JSEP アーキテクチャ図
JSEP アーキテクチャ

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

RTCPeerConnection

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

次の図は、RTCPeerConnection の役割を示した WebRTC アーキテクチャ図です。ご覧のとおり、緑色の部分は複雑です。

WebRTC アーキテクチャ図
WebRTC アーキテクチャ(webrtc.org より)

JavaScript の観点からこの図で理解すべき主な点は、RTCPeerConnection が、その下に潜む複雑な要素からウェブ デベロッパーを保護することです。WebRTC で使用されるコーデックとプロトコルは、信頼できないネットワークでもリアルタイム通信を可能にするために膨大な処理を行います。

  • パケットロスの隠蔽
  • エコー キャンセラ
  • 帯域幅の適応性
  • 動的ジッター バッファリング
  • AGC
  • ノイズの低減と抑制
  • 画像のクリーニング

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

サーバーのない RTCPeerConnection

次のコードは、WebRTC サンプルのピア接続から取得したものです。このサンプルでは、1 つのウェブページにローカル RTCPeerConnection とリモート RTCPeerConnection(およびローカル ビデオとリモート ビデオ)があります。呼び出し元と呼び出し先が同じページにあるため、これは特に有用なものではありませんが、ページ上の RTCPeerConnection オブジェクトは中間シグナリング メカニズムを使用せずにデータとメッセージを直接交換できるため、RTCPeerConnection API の仕組みが少しわかりやすくなります。

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

発信者

  1. 新しい RTCPeerConnection を作成し、getUserMedia() からストリームを追加します。 ```js // Servers はオプションの構成ファイルです。(後述の 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 には次の 4 種類のサーバーサイド機能が必要です。

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

NAT トラバーサル、ピアツーピア ネットワーキング、ユーザー検出とシグナリング用のサーバーアプリを構築するための要件については、この記事では説明しません。STUN プロトコルとその拡張機能である TURN は、ICE フレームワークで使用され、RTCPeerConnection が NAT トラバーサルやその他のネットワークの不確実性に対処できるようにします。

ICE は、2 つのビデオチャット クライアントなどのピアを接続するためのフレームワークです。最初に、ICE は UDP を介して可能な限り低いレイテンシでピアを直接接続しようとします。このプロセスでは、STUN サーバーのタスクは 1 つだけです。NAT の背後にあるピアがパブリック アドレスとポートを検出できるようにすることです。(STUN と TURN の詳細については、WebRTC アプリに必要なバックエンド サービスを構築するをご覧ください)。

接続候補の検索
接続候補の検出

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

WebRTC データパスウェイ
WebRTC データパスウェイ

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

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

STUN サーバーを使用したシグナリングと NAT/ファイアウォールの走査を備えた WebRTC を試すには、appr.tc のビデオチャット デモがおすすめです。このアプリは、仕様の変更や接頭辞の違いからアプリを保護する shim である adapter.js を使用しています。

このコードは、ロギングを意図的に冗長にしています。コンソールでイベントの順序を確認します。以下に、コードの詳細なチュートリアルを示します。

ネットワーク トポロジ

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

マルチポイント コントロール ユニットのトポロジ図
マルチポイント制御ユニットのトポロジの例

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

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 では RTCDataChannel を介してファイル共有が可能になり、peerCDN では WebRTC を介してピアツーピア コンテンツ配信を実現する方法が紹介されました。

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

セキュリティ

リアルタイム コミュニケーション アプリやプラグインがセキュリティを侵害する方法はいくつかあります。次に例を示します。

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

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

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

ストリーミング メディアのセキュリティの詳細については、この記事では取り上げません。詳細については、IETF が提案したWebRTC セキュリティ アーキテクチャの提案をご覧ください。

まとめ

WebRTC の API と標準により、電話、ゲーム、動画制作、音楽制作、ニュース収集など、コンテンツの作成と通信のためのツールを民主化し、分散化できます。

これほど破壊的なテクノロジーはありません。

ブロガーの Phil Edholm は、次のように述べています。「WebRTC と HTML5 は、元のブラウザが情報に対して行っていたような変換を、リアルタイム通信に対しても可能にする可能性があります。」

デベロッパー ツール

その他の情報

標準とプロトコル

WebRTC サポートの概要

MediaStream API と getUserMedia API

  • Chrome デスクトップ版 18.0.1008 以降、Chrome for Android 29 以降
  • Opera 18 以降、Opera for Android 20 以降
  • Opera 12、Opera Mobile 12(Presto エンジンをベースとする)
  • Firefox 17 以降
  • Microsoft Edge 16 以降
  • iOS では Safari 11.2 以降、MacOS では 11.1 以降
  • Android 版 UC 11.8 以降
  • Samsung Internet 4 以降

RTCPeerConnection API

  • Chrome デスクトップ 20 以降、Chrome for Android 29 以降(フラグなし)
  • Opera 18 以降(デフォルトでオン); Android 版 Opera 20 以降(デフォルトでオン)
  • 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 版 Opera 20 以降
  • Firefox 22 以降(デフォルトでオン)

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

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