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 コードラボに直接進んでください。このコードラボでは、シンプルなシグナリング サーバーを含む、完全なビデオチャット アプリを構築する方法を段階的に説明しています。
WebRTC の簡単な歴史
ウェブの最後の大きな課題の 1 つは、音声と動画による人間同士のコミュニケーション、つまりリアルタイム通信(RTC)を可能にすることです。RTC は、ウェブアプリでテキスト入力にテキストを入力するのと同じくらい自然なものにする必要があります。それがないと、イノベーションを起こしたり、ユーザーが交流するための新しい方法を開発したりする能力が制限されます。
これまで、RTC は企業向けで複雑なものであり、高価な音声技術や動画技術をライセンス取得するか、自社で開発する必要がありました。RTC テクノロジーを既存のコンテンツ、データ、サービスと統合することは、特にウェブ上で困難で時間がかかりました。
Gmail のビデオチャットは 2008 年に人気を博し、2011 年には Google が Hangouts を導入しました。Hangouts は Gmail と同様に Talk を使用していました。Google は、コーデックやエコー キャンセルの手法など、RTC に必要な多くのコンポーネントを開発した GIPS という会社を買収しました。Google は、GIPS で開発された技術をオープンソース化し、インターネット技術特別調査委員会(IETF)とワールドワイド ウェブ コンソーシアム(W3C)の関連する標準化団体と連携して、業界のコンセンサスを確保しました。2011 年 5 月、Ericsson が 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 のサンプルをご覧ください。また、Chris Wilson 氏の素晴らしい例では、getUserMedia
をウェブ オーディオの入力として使用しています。
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>
要素を混同しないでください。<track>
要素はまったく異なるものです)。
MediaStream
API を理解する最も簡単な方法は、実際の使用例を確認することです。
- ブラウザで WebRTC サンプル
getUserMedia
に移動します。 - Console を開きます。
- グローバル スコープにある
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
を動画要素にアタッチできます。以前は、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 回付与するだけで済みます。初回は、ブラウザの情報バーに [許可] ボタンが表示されます。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 を使用して、単一のブラウザタブやデスクトップ全体のライブ動画を共有することもできます。(デモと詳細については、WebRTC を使用した画面共有をご覧ください。この記事は数年前のものですが、今でも興味深い内容です)。
試験運用版の chromeMediaSource
制約を使用すると、Chrome で画面キャプチャを MediaStream
ソースとして使用することもできます。スクリーン キャプチャには HTTPS が必要です。また、この投稿で説明されているように、コマンドライン フラグで有効にするため、開発でのみ使用してください。
シグナリング: セッション制御、ネットワーク、メディア情報
WebRTC は RTCPeerConnection
を使用してブラウザ(ピアとも呼ばれます)間でストリーミング データを通信しますが、通信を調整して制御メッセージを送信するメカニズム(シグナリングと呼ばれるプロセス)も必要です。シグナリング方法とプロトコルは WebRTC で指定されていません。シグナリングは RTCPeerConnection
API の一部ではありません。
代わりに、WebRTC アプリ デベロッパーは、SIP や XMPP など、任意のメッセージング プロトコルと、適切な全二重(双方向)通信チャネルを選択できます。appr.tc の例では、シグナリング メカニズムとして XHR と Channel API を使用しています。この codelab では、Node サーバーで実行されている 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 フレームワークを使用してネットワーク インターフェースとポートを見つけるプロセスを指します)。
- Alice は、ネットワーク候補が利用可能になったときに実行される
onicecandidate
ハンドラを使用してRTCPeerConnection
オブジェクトを作成します。 - Alice は、WebSocket などのシグナリング チャネルを使用して、シリアル化された候補データを Bob に送信します。
- Bob が Alice から候補メッセージを受け取ると、
addIceCandidate
を呼び出して候補をリモート ピアの説明に追加します。
WebRTC クライアント(ピアとも呼ばれます。この例では Alice と Bob)は、解像度やコーデック機能などのローカルとリモートの音声と動画のメディア情報を確認して交換する必要もあります。メディア構成情報を交換するためのシグナリングは、セッション記述プロトコル(SDP)を使用してオファーとアンサーを交換することで行われます。
- Alice が
RTCPeerConnection
createOffer()
メソッドを実行します。この戻り値はRTCSessionDescription
(Alice のローカル セッションの説明)に渡されます。 - コールバックで、アリスは
setLocalDescription()
を使用してローカルの説明を設定し、シグナリング チャネルを介してこのセッションの説明をボブに送信します。RTCPeerConnection
は、setLocalDescription()
が呼び出されるまで候補の収集を開始しません。これは JSEP IETF ドラフトで明文化されています。 - Bob は、
setRemoteDescription()
を使用して、Alice から送信された説明をリモートの説明として設定します。 - 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 セッション確立プロトコル(JSEP)と呼ばれます(最初の WebRTC 実装に関する Ericsson のデモ動画で、シグナリングとストリーミングのプロセスを説明する優れたアニメーションが紹介されています)。
シグナリング プロセスが正常に完了すると、発信者と着信者の間でピアツーピアで直接データをストリーミングできます。失敗した場合は、仲介リレーサーバーを介してストリーミングできます(詳しくは後述)。ストリーミングは RTCPeerConnection
のジョブです。
RTCPeerConnection
RTCPeerConnection
は、ピア間のストリーミング データの安定した効率的な通信を処理する WebRTC コンポーネントです。
次の図は、RTCPeerConnection
の役割を示す WebRTC アーキテクチャ図です。ご覧のとおり、緑色の部分は複雑です。
JavaScript の観点からこの図で理解すべき主な点は、RTCPeerConnection
がウェブ デベロッパーを、その下に潜む無数の複雑さから守っているということです。WebRTC で使用されるコーデックとプロトコルは、信頼性の低いネットワークでもリアルタイム通信を可能にするために、膨大な量の処理を行っています。
- パケットロス隠蔽
- エコー キャンセリング
- 帯域幅の適応性
- 動的ジッター バッファリング
- AGC
- ノイズ リダクションとノイズ サプレッション
- イメージのクリーニング
上記の W3C コードは、シグナリングの観点から見た WebRTC の簡略化された例を示しています。以下では、2 つの動作する WebRTC アプリのチュートリアルを紹介します。1 つ目は RTCPeerConnection
を示す簡単な例で、2 つ目は完全に動作するビデオチャット クライアントです。
サーバーなしの RTCPeerConnection
次のコードは、1 つのウェブページにローカルとリモートの RTCPeerConnection
(ローカルとリモートの動画)がある WebRTC サンプル ピア接続から取得したものです。これはあまり役に立ちませんが(呼び出し元と呼び出し先が同じページにあるため)、ページ上の 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 );
Callee
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 が、2013 年の Google I/O WebRTC プレゼンテーションで ICE、STUN、TURN について詳しく説明しています。(プレゼンテーションのスライドで、TURN サーバーと STUN サーバーの実装例を確認できます)。
シンプルなビデオチャット クライアント
WebRTC を試すのに最適な場所は、appr.tc のビデオチャット デモです。ここでは、STUN サーバーを使用したシグナリングと NAT/ファイアウォール走査が完了しています。このアプリは、仕様の変更や接頭辞の違いからアプリを分離するためのシムである adapter.js を使用します。
このコードは、ログ記録を意図的に詳細にしています。コンソールでイベントの順序を確認します。以下に、コードの詳細なチュートリアルを示します。
ネットワーク トポロジ
現在実装されている WebRTC は一対一の通信のみをサポートしていますが、複数のピアが互いに直接通信したり、マルチポイント制御ユニット(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 が提案した Proposed WebRTC Security Architecture をご覧ください。
まとめ
WebRTC の API と標準は、電話、ゲーム、動画制作、音楽制作、ニュース収集など、コンテンツ作成とコミュニケーションのためのツールを民主化し、分散化することができます。
これほど破壊的なテクノロジーは他にありません。
ブロガーの Phil Edholm 氏が述べているように、「WebRTC と HTML5 は、情報に対してブラウザが実現したのと同じ変革をリアルタイム コミュニケーションにもたらす可能性があります。」
デベロッパー ツール
- 進行中のセッションの WebRTC 統計情報は、次の場所にあります。
- Chrome の about://webrtc-internals
- Opera の opera://webrtc-internals
- Firefox の about:webrtc
chrome://webrtc-internals のスクリーンショット
- クロスブラウザの相互運用性に関するメモ
- adapter.js は、Google が WebRTC コミュニティの協力を得て保守している WebRTC 用の JavaScript シムで、ベンダー プレフィックス、ブラウザの違い、仕様の変更を抽象化します。
- WebRTC シグナリング プロセスの詳細については、appr.tc のログ出力をコンソールで確認してください。
- すべてを自分で実装するのが難しい場合は、WebRTC フレームワークや完全な WebRTC サービスを使用することもできます。
- バグレポートと機能リクエストはいつでも歓迎します。
その他の情報
- Google I/O 2012 での Justin Uberti による WebRTC セッション
- Alan B. ジョンストンとダニエル C. Burnett は、webrtcbook.com で、WebRTC の書籍の第 3 版を印刷版と電子書籍版で公開しています。
- webrtc.org は、デモ、ドキュメント、ディスカッションなど、WebRTC に関するあらゆる情報が集まる場所です。
- discuss-webrtc は、WebRTC の技術的な議論を行うための Google グループです。
- @webrtc
- Google Developers の Talk ドキュメントには、NAT 走査、STUN、リレー サーバー、候補の収集に関する詳細情報が記載されています。
- GitHub の WebRTC
- Stack Overflow は、WebRTC に関する回答を探したり、質問をしたりするのに適した場所です。
標準とプロトコル
- WebRTC W3C エディタのドラフト
- W3C 編集者草案: メディア キャプチャとストリーム(
getUserMedia
とも呼ばれます) - IETF ワーキング グループ憲章
- IETF WebRTC データチャネル プロトコル ドラフト
- IETF JSEP ドラフト
- ICE の IETF 提案標準
- 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 の Safari 11.1 以降
- Android の UC 11.8 以降
- Samsung Internet 4 以降
RTCPeerConnection
API
- Chrome デスクトップ 20 以降、Android 版 Chrome 29 以降(フラグなし)
- Opera 18 以降(デフォルトでオン)、Opera for Android 20 以降(デフォルトでオン)
- Firefox 22 以降(デフォルトでオン)
- Microsoft Edge 16 以降
- iOS の Safari 11.2 以降、macOS の Safari 11.1 以降
- Samsung Internet 4 以降
RTCDataChannel
API
- Chrome 25 で試験運用版がリリースされましたが、Chrome 26 以降(Android 版 Chrome 29 以降)ではより安定したバージョンがリリースされています(Firefox との相互運用性も備わっています)。
- Opera 18 以降、Opera for Android 20 以降で安定版(Firefox との相互運用性あり)
- Firefox 22 以降(デフォルトでオン)
getUserMedia
や RTCPeerConnection
などの API のクロスプラットフォーム サポートについて詳しくは、caniuse.com と Chrome プラットフォームのステータスをご覧ください。
RTCPeerConnection
のネイティブ API は、webrtc.org のドキュメントでも入手できます。