WebRTC は、オープンで制約のないウェブを実現するための長い戦いの新たな戦線です。
JavaScript の創始者、Brendan Eich
プラグインを使用しないリアルタイム コミュニケーション
スマートフォン、テレビ、パソコンが共通のプラットフォームで通信できる世界を想像してみてください。ビデオ チャットやピアツーピアのデータ共有をウェブアプリに簡単に追加できるとしたらどうでしょう。これが WebRTC のビジョンです。
お試しになる場合は、WebRTC は、パソコンとモバイルの Google Chrome、Safari、Firefox、Opera で利用できます。最初は、appr.tc のシンプルなビデオ チャット アプリを試してみることをおすすめします。
- ブラウザで appr.tc を開きます。
- [参加] をクリックしてチャットルームに参加し、アプリがウェブカメラを使用できるようにします。
- ページの最後に表示された URL を新しいタブで開きます。できれば、別のパソコンで開いてください。
クイック スタート
この記事を読む時間がない、またはコードのみが必要な場合は、
- WebRTC の概要については、次の Google I/O 動画またはこちらのスライドをご覧ください。
getUserMedia
API を使用したことがない場合は、HTML5 で音声と動画をキャプチャすると simpl.info getUserMedia をご覧ください。RTCPeerConnection
API の詳細については、次の例と simpl.info RTCPeerConnection をご覧ください。- WebRTC がシグナリング、ファイアウォール、NAT トラバーサルにサーバーをどのように使用するかを学ぶには、appr.tc のコードとコンソール ログをご覧ください。
- 待てずに今すぐ WebRTC を試したい場合は、WebRTC JavaScript API を実行する20 を超えるデモを試す。
- マシンと WebRTC で問題が発生している場合WebRTC Troubleshooter にアクセスします。
または、WebRTC Codelab に直接進んでください。この Codelab では、シンプルなシグナリング サーバーを含む、完全なビデオ チャット アプリを作成する方法を段階的に説明しています。
WebRTC の簡単な歴史
ウェブの最後の大きな課題の一つは、音声と動画による人間のコミュニケーションを可能にすることです。つまり、リアルタイム通信(RTC)です。RTC は、テキスト入力にテキストを入力するのと同じくらい自然にウェブアプリで使用できる必要があります。データがなければ、ユーザーとの新しいやり取りを開発したり、イノベーションを起こしたりする能力に限界が生じます。
これまで RTC は企業向けで複雑であり、高価な音声と動画の技術をライセンス取得または社内で開発する必要がありました。RTC テクノロジーを既存のコンテンツ、データ、サービスと統合することは、特にウェブでは困難で時間がかかっていました。
Gmail のビデオ通話は 2008 年に人気を博し、2011 年に Google は Gmail と同様に Talk を使用する Hangouts を導入しました。Google は、コーデックやエコー キャンセル技術など、RTC に必要な多くのコンポーネントを開発した GIPS を買収しました。Google は、GIPS によって開発された技術をオープンソース化し、業界のコンセンサスを確保するために、インターネット技術特別調査委員会(IETF)と World Wide Web Consortium(W3C)の関連する標準化団体と連携しました。2011 年 5 月、エリクソンは WebRTC の最初の実装を構築しました。
WebRTC は、プラグイン不要のリアルタイムの動画、音声、データ通信のためのオープン スタンダードを実装しています。ニーズは現実的でした。
- 多くのウェブサービスは RTC を使用していましたが、ダウンロード、ネイティブ アプリ、プラグインが必要でした。Skype、Facebook、ハングアウトなどです。
- プラグインのダウンロード、インストール、更新は複雑で、エラーが発生しやすく、面倒です。
- プラグインは、デプロイ、デバッグ、トラブルシューティング、テスト、メンテナンスが困難です。また、複雑で高価なテクノロジーの使用許可と統合が必要になる場合があります。そもそも、プラグインをインストールするようユーザーに説得するのは難しいものです。
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 シムの 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 を理解する最も簡単な方法は、実際に使用してみることです。
- ブラウザで WebRTC サンプル
getUserMedia
にアクセスします。 - Console を開きます。
- グローバル スコープにある
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 画像を生成します。
制約
制約を使用すると、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 フレームワークを使用してネットワーク インターフェースとポートを見つけるプロセスを指します)。
- Alice は、
onicecandidate
ハンドラを持つRTCPeerConnection
オブジェクトを作成します。このハンドラは、ネットワーク候補が利用可能になると実行されます。 - Alice は、WebSocket などのシグナリング チャネルを介して、シリアル化された候補データを Bob に送信します。
- Bob が Alice から候補メッセージを受信すると、
addIceCandidate
を呼び出して候補をリモートピアの説明に追加します。
WebRTC クライアント(ピア、この例ではアリスとボブ)は、解像度やコーデック機能など、ローカルとリモートの音声と動画のメディア情報を確認して交換する必要があります。メディア構成情報を交換するためのシグナリングは、セッション記述プロトコル(SDP)を使用してオファーと回答を交換することで行われます。
- Alice は
RTCPeerConnection
createOffer()
メソッドを実行します。この戻り値には、RTCSessionDescription
(アリスのローカル セッションの説明)が渡されます。 - コールバックで、アリスは
setLocalDescription()
を使用してローカル ディスクリプションを設定し、このセッション ディスクリプションをシグナリング チャネルを介してボブに送信します。setLocalDescription()
が呼び出されるまでは、RTCPeerConnection
は候補の収集を開始しません。これは JSEP IETF ドラフトで規定されています。 - ボブは、
setRemoteDescription()
を使用して、アリスが送信した説明をリモート記述として設定します。 - Bob は
RTCPeerConnection
createAnswer()
メソッドを実行し、Alice から取得したリモート記述を渡して、Alice と互換性のあるローカル セッションを生成します。createAnswer()
コールバックにはRTCSessionDescription
が渡されます。Bob はそれをローカルの説明として設定し、Alice に送信します。 - Alice は Bob のセッションの説明を取得し、
setRemoteDescription
を使用してリモート デスクリプションとして設定します。 - 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 のデモ動画では、シグナリングとストリーミングのプロセスを説明する優れたアニメーションが紹介されています。
シグナリング プロセスが正常に完了すると、データは呼び出し元と呼び出し先の間でピアツーピアで直接ストリーミングできます。ストリーミングに失敗した場合は、中継リレー サーバー経由でストリーミングできます(後述)。ストリーミングは RTCPeerConnection
の仕事です。
RTCPeerConnection
RTCPeerConnection
は、ピア間でのストリーミング データの安定した効率的な通信を処理する WebRTC コンポーネントです。
次の図は、RTCPeerConnection
の役割を示した WebRTC アーキテクチャ図です。ご覧のとおり、緑色の部分は複雑です。
JavaScript の観点からこの図で理解すべき主な点は、RTCPeerConnection
が、その下に潜む複雑な要素からウェブ デベロッパーを保護することです。WebRTC で使用されるコーデックとプロトコルは、信頼できないネットワークでもリアルタイム通信を可能にするために膨大な処理を行います。
- パケットロスの隠蔽
- エコー キャンセラ
- 帯域幅の適応性
- 動的ジッター バッファリング
- AGC
- ノイズの低減と抑制
- 画像のクリーニング
上記の W3C コードは、シグナリングの観点から WebRTC の簡略化された例を示しています。以下では、2 つの動作する WebRTC アプリのチュートリアルについて説明します。1 つ目は RTCPeerConnection
を示す簡単な例で、2 つ目は完全に機能するビデオ チャット クライアントです。
サーバーを使用しない RTCPeerConnection
次のコードは、WebRTC サンプルのピア接続から取得したものです。このサンプルでは、1 つのウェブページにローカル RTCPeerConnection
とリモート RTCPeerConnection
(およびローカル ビデオとリモート ビデオ)があります。呼び出し元と呼び出し先が同じページにあるため、これは特に有用なものではありませんが、ページ上の RTCPeerConnection
オブジェクトは、中間シグナリング メカニズムを使用せずにデータとメッセージを直接交換できるため、RTCPeerConnection
API の仕組みが少しわかりやすくなります。
この例では、pc1
はローカルピア(呼び出し元)を表し、pc2
はリモートピア(呼び出し先)を表します。
発信者
- 新しい
RTCPeerConnection
を作成し、getUserMedia()
からストリームを追加します。 ```js // Servers はオプションの構成ファイルです。(後述の TURN と STUN の説明をご覧ください)。 pc1 = new RTCPeerConnection(servers); // ... localStream.getTracks().forEach((track) => { pc1.addTrack(track, localStream); });
- オファーを作成し、
pc1
のローカルの説明とpc2
のリモートの説明として設定します。呼び出し元と呼び出し先の両方が同じページにあるため、シグナリングを使用せずにコード内で直接行うことができます。js pc1.setLocalDescription(desc).then(() => { onSetLocalSuccess(pc1); }, onSetSessionDescriptionError ); trace('pc2 setRemoteDescription start'); pc2.setRemoteDescription(desc).then(() => { onSetRemoteSuccess(pc2); }, onSetSessionDescriptionError );
呼び出し先
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 エンジニアの 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 で可能にする災害時の通信フレームワークをブリーフケースに収めたデモを行いました。携帯通信会社を利用しない電話通信
" 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 の実装では、DTLS や SRTP などの安全なプロトコルが使用されます。
- 暗号化は、シグナリング メカニズムを含むすべての WebRTC コンポーネントに必須です。
- WebRTC はプラグインではありません。コンポーネントは、別のプロセスではなくブラウザのサンドボックスで実行されます。コンポーネントは個別にインストールする必要はなく、ブラウザが更新されるたびに更新されます。
- カメラとマイクのアクセス権は明示的に付与する必要があります。カメラまたはマイクが実行されている場合は、ユーザー インターフェースに明確に表示されます。
ストリーミング メディアのセキュリティについて詳しく説明することは、この記事の範囲を超えています。詳細については、IETF が提案したWebRTC セキュリティ アーキテクチャの提案をご覧ください。
まとめ
WebRTC の API と標準により、電話、ゲーム、動画制作、音楽制作、ニュース収集など、コンテンツの作成と通信のためのツールを民主化し、分散化できます。
これほど破壊的なテクノロジーはありません。
ブロガーの Phil Edholm は、次のように述べています。「WebRTC と HTML5 は、元のブラウザが情報に対して行っていたような変換を、リアルタイム通信に対しても可能にする可能性があります。」
デベロッパー ツール
- 進行中のセッションの WebRTC 統計情報は、次の場所で確認できます。
- Chrome の about://webrtc-internals
- Opera の opera://webrtc-internals
- Firefox の about:webrtc
- クロスブラウザの相互運用に関する注意事項
- adapter.js は、ベンダーの接頭辞、ブラウザの違い、仕様の変更を抽象化する、Google が WebRTC コミュニティの協力を得て維持している WebRTC 用の JavaScript shim です。
- WebRTC シグナリング プロセスの詳細については、コンソールに表示される appr.tc ログ出力を確認してください。
- すべてが過剰な場合は、WebRTC フレームワークや完全な WebRTC サービスを使用することをおすすめします。
- バグレポートや機能リクエストはいつでも受け付けています。
その他の情報
- Google I/O 2012 での Justin Uberti の WebRTC セッション
- Alan B. Johnston と Daniel C. Burnett は、webrtcbook.com で、WebRTC に関する書籍(第 3 版)を印刷版と電子書籍版で公開しています。
- webrtc.org には、デモ、ドキュメント、ディスカッションなど、WebRTC に関するすべての情報が掲載されています。
- discuss-webrtc は、WebRTC の技術的なディスカッションのための Google グループです。
- @webrtc
- NAT トラバース、STUN、リレー サーバー、候補の収集の詳細については、Google Developers のTalk のドキュメントをご覧ください。
- GitHub の WebRTC
- WebRTC に関する回答を探したり、質問したりするには、Stack Overflow が適しています。
標準とプロトコル
- WebRTC W3C エディタのドラフト
- W3C 編集者のドラフト: メディア キャプチャとストリーム(
getUserMedia
とも呼ばれる) - IETF ワーキング グループの憲章
- IETF WebRTC データ チャネル プロトコル ドラフト
- IETF JSEP ドラフト
- IETF が提案した ICE の標準
- IETF RTCWEB ワーキング グループのインターネット ドラフト: Web Real-Time Communication Use-cases and Requirements
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 以降(デフォルトでオン)
getUserMedia
や RTCPeerConnection
などの API のクロスプラットフォーム サポートについて詳しくは、caniuse.com と Chrome プラットフォームのステータスをご覧ください。
RTCPeerConnection
のネイティブ API は、webrtc.org のドキュメントでも入手できます。