WebRTC スタートガイド

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

JavaScript の発明者 Brendan Eich

プラグイン不要のリアルタイム通信

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

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

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

クイックスタート

この記事を読む時間がない場合や、コードだけが必要な場合は、

または、WebRTC Codelab に直接移動することもできます。WebRTC Codelab は、シンプルなシグナリング サーバーを含む完全なビデオチャット アプリを作成する手順ガイドです。

WebRTC の歴史

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

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

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

WebRTC は、プラグイン不要のリアルタイムな動画、音声、データ通信のためのオープン スタンダードを実装しています。本当に必要とされていたのは、

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

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

私たちは今、どこにいるのでしょうか?

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

WebRTC は、次の 3 つの API を実装します。 - MediaStream(別名 getUserMedia) - RTCPeerConnection - RTCDataChannel

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

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

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

RTCPeerConnection: 簡単なデモと完全に機能するビデオチャット アプリについては、WebRTC サンプルのピア接続appr.tc をご覧ください。このアプリは、WebRTC コミュニティの支援を受けて Google が管理する JavaScript shim の 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. コンソールを開きます。
  3. グローバル スコープの stream 変数を調べます。

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

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

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

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

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

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 を組み込むこともできます。audioCapturevideoCapture権限をマニフェストに追加すると、インストール時に 1 回だけ権限をリクエストして付与できるようになります。その後、ユーザーはカメラまたはマイクへのアクセス許可を求められません。

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

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

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

  • Webcam Toy は、WebGL を使用して写真に不思議で素晴らしい効果を加えるフォトブース アプリです。この効果はローカルで共有、保存できます。
  • FaceKatheadtrackr.js で作成された顔追跡ゲームです。
  • ASCII カメラ: 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 では、ノードサーバーで実行されている 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);
  }
};

まず、Alice と Bob はネットワーク情報を交換します。(候補を見つけるという表現は、ICE フレームワークを使用してネットワーク インターフェースとポートを見つけるプロセスを指します)。

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

WebRTC クライアント(ピア、この例では Alice と Bob とも呼ばれます)も、解像度やコーデック機能など、ローカルとリモートの音声と動画のメディア情報を確認し、交換する必要があります。メディア構成情報を交換するためのシグナリングでは、セッション記述プロトコル(SDP)を使用してオファーと応答を交換します。

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

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

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

この例では、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 には、次の 4 種類のサーバーサイドの機能が必要です。

  • ユーザー発見とコミュニケーション
  • シグナリング
  • NAT/ファイアウォール トラバーサル
  • ピアツーピア通信に失敗した場合の中継サーバー

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

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 が、2013 年の Google I/O WebRTC プレゼンテーションで ICE、STUN、TURN について詳しく説明しています。(プレゼンテーションのスライドは、TURN および STUN サーバーの実装例を示しています)。

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

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

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

ネットワーク トポロジ

現在実装されている WebRTC は 1 対 1 の通信のみをサポートしていますが、複数のピア同士が直接通信したり、多数の参加者を処理して選択的にストリーム転送したり、音声と動画のミキシングや録画を行うサーバーであるマルチポイント コントロール ユニット(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 でご利用いただけます。キューブ ヒット ゲームでは、API を使用してゲームの状態を伝えます。友だちと遊ぶか、クマと遊ぼう!革新的なプラットフォーム Sharefest により、RTCDataChannelpeerCDN を介したファイル共有が可能になり、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 以降、Android 向け Opera 20 以降
  • 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 用 Opera 20 以降(デフォルトで有効)
  • Firefox 22 以降(デフォルトで有効)
  • Microsoft Edge 16 以降
  • iOS の場合は Safari 11.2 以降、MacOS の場合は 11.1 以降
  • Samsung Internet 4 以降

RTCDataChannel API

  • Chrome 25 の試験運用版バージョンです。Chrome 26 以降、Chrome for Android 29 以降の場合は、より安定しています(Firefox との相互運用性もあります)。
  • Opera 18 以降、Opera(Android 20 以降)の Stable バージョン(および Firefox との相互運用)
  • Firefox 22 以降(デフォルトで有効)

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

RTCPeerConnection のネイティブ API は、webrtc.org のドキュメントでもご覧いただけます。