この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
WebRTCとは
WebRTCは、Web Real-Time Communicationの略で、WebブラウザだけでJavaScript APIを介してリアルタイムコミュニケーション機能を実現するためのAPIです。WebRTCでは、P2Pのコネクション確立からデータ通信を行うための仕様が定義されています。
よって、WebRTCを使うとプラグイン無しで、双方向のリアルタイムコミュニケーション機能を必要とするコンテンツが容易に開発できます。
現状は、W3Cでドラフトが公開されています。http://www.w3.org/TR/webrtc/
WebRTCはいくつかの関連するAPIがあります。その中には、前回紹介したMedia Stream APIも含まれます。
まだドラフトなのでWebRTCに対応ブラウザは、下記のようになっています。
PC
- Google Chrome 23
- Mozilla Firefox 22
- Opera 12
Android
- Google Chrome 28 (29 から標準で有効)
- Mozilla Firefox 24
- Opera Mobile 12
WebRTCの使い方
まずはWebRTCを接続手順を説明します。
最初にベンダープレフィクスのついているクラスがいくつかあるので、使えるかどうか確認します。
window.RTCPeerConnection = ( window.webkitPeerConnection00 ||
window.webkitRTCPeerConnection ||
window.mozRTCPeerConnection);
window.RTCSessionDescription = ( window.mozRTCSessionDescription ||
window.RTCSessionDescription);
window.RTCIceCandidate = ( window.mozRTCIceCandidate ||
window.RTCIceCandidate);
次に接続用のwindow.RTCPeerConnectionを生成します。 今回ローカル接続なので、引数は無しです。
var pc1 = new RTCPeerConnection(); //送信側
var pc2 = new RTCPeerConnection(); //受信側
ICEの候補が取得できるイベントをハンドリングしておきます。 ICEの候補が見つかったら受信側に設定します。
pc1.onicecandidate = onIceCandidate1;
function onIceCandidate1(evt) {
if (evt.candidate) {
pc2.addIceCandidate(new RTCIceCandidate(evt.candidate));
}
}
受信側にもICEの候補が取得できるイベントをハンドリングしておきます。 ICEの候補が見つかったら送信側に設定します。
pc2.onicecandidate = onIceCandidate2;
function onIceCandidate2(event){
if (event.candidate) {
pc1.addIceCandidate(new RTCIceCandidate(event.candidate));
}
}
次に受信側は、ストリームを受け取った時のハンドリングを行います。
pc2.onaddstream = onRemoteStreamAdded
function onRemoteStreamAdded(event) {
video2.src = URL.createObjectURL(event.stream);
}
次に送信側は、事前に取得しておいたMediaStreamを設定します。
pc1.addStream(localMediaStream);
これで準備が整ったので、オファーを作成して受信側に設定します。 受信側は、オファーに応答するためのアンサーを作成して送信側に設定します。
pc1.createOffer(gotOffer);
function gotOffer(description){
pc1.setLocalDescription(description);
pc2.setRemoteDescription(description);
pc2.createAnswer(gotAnswer);
}
function gotAnswer(description){
pc2.setLocalDescription(description);
pc1.setRemoteDescription(description);
}
上記で説明した接続するまでのソースです。 この処理の前にMediaStreamを取得しておく必要があります。詳しくはこちら
var pc1;
var pc2;
function createPeerConnection() {
pc1 = new RTCPeerConnection();
pc1.onicecandidate = onIceCandidate1;
pc2 = new RTCPeerConnection();
pc2.onicecandidate = onIceCandidate2;
pc2.onaddstream = onRemoteStreamAdded;
pc1.addStream(localMediaStream);
pc1.createOffer(gotOffer);
}
function onIceCandidate1(evt) {
if (evt.candidate) {
pc2.addIceCandidate(new RTCIceCandidate(evt.candidate));
}
}
function onIceCandidate2(event){
if (event.candidate) {
pc1.addIceCandidate(new RTCIceCandidate(event.candidate));
}
}
function onRemoteStreamAdded(event) {
remoteVideo.src = URL.createObjectURL(event.stream);
}
function gotOffer(description){
pc1.setLocalDescription(description);
pc2.setRemoteDescription(description);
pc2.createAnswer(gotAnswer);
}
function gotAnswer(description){
pc2.setLocalDescription(description);
pc1.setRemoteDescription(description);
}
ライブデモ
ローカルのみでRTCPeerConnectionを試すデモです。ライブデモ
サンプル:ライブチャット
WebRTCをつかったライブチャットを作成してみましょう。
事前準備
WebRTCは、インターネット超えたP2P接続を行うためにNAT越えするためのサーバが必要になります。これは、P2P通信を開始するためには、お互いの端末のグローバルアドレスを知る必要があるからです。
そのために必要なのが、ICE( Interactive Connectivity Establishment )と呼ばれる仕組みです。
ICEは、STUNやTURNなどのNAT越えの手順をまとめたものです。ICEで取得したグローバルIPアドレスとポート番号を通信するホスト間で交換するとNAT越えすることが可能です。
STUNサーバやTURNサーバは、自作できますが、今回は、STUNサーバーとして、googleが公開しているサーバーを利用します。stun.l.google.com です。
そして、STUNサーバから受け取ったICE情報を受け渡しするためのWebアプリケーションが必要になります。今後チャットサーバと呼びます。
オファー側
まずは、googleが公開しているSTUNサーバーを定義しておきます。
var peerConnectionConfig = {
"iceServers" : [
{ "url" : "stun:stun.l.google.com:19302" }
]
};
次にピアコネクション間のデータチャンネルを使用する設定を定義しておきます。
var peerDataConnectionConfig = {
"optional" : [
{ "RtpDataChannels" : true }
]
};
チャットを開始する前に前回の解説したMediaStreamを取得しておきます。
function requireUserMedia() {
navigator.getUserMedia({
video : true
}, gotUserMedia, error);
}
MediaStreamの取得成功のコールバックでWebRTCの設定を行います。
1.ピアコネクションの生成
2.メッセージ用のDataChannelの生成
3.オファーを生成します。
function gotUserMedia(stream) {
localVideo.src = window.URL.createObjectURL(stream);
localMediaStream = stream;
createPeerConnection(); //1
sendChannel = peerCon.createDataChannel("sendDataChannel", {reliable: false}); //2
peerCon.createOffer(gotOffer, error); //3
}
ピアコネクションの生成する引数に、STUNサーバーを定義とデータチャンネルを使用する設定を指定します。
function createPeerConnection() {
peerCon = new RTCPeerConnection(peerConnectionConfig,peerDataConnectionConfig);
peerCon.onicecandidate = peerCon_onIceCandidate;
peerCon.onaddstream = peerCon_onAddStream;
peerCon.addStream(localMediaStream);
}
オファーが生成できたらピアコネクションのsetLocalDescriptionにオファーを設定しておきます。 それが成功したら、チャットサーバにオファーを送信します。
function gotOffer(description) {
peerCon.setLocalDescription(description, function() {
sendMessage({
type : 'offer',
offer : description
});
}, error);
}
アンサーが返ってきたらピアコネクションのsetRemoteDescriptionにアンサーを設定しておきます。 これでハンドシェイクが完了します。
function setupAnswer(answer) {
peerCon.setRemoteDescription(new RTCSessionDescription(answer));
}
アンサー側
アンサー側も同様にMediaStreamの取得成功のコールバックでWebRTCのピアコネクションの生成しておきます。
そして、オファーを受け取るとピアコネクションのsetRemoteDescriptionにオファーを設定しておきます。 オファーを設定したらその応答となるアンサーを生成します。
function createAnswer(offer) {
peerCon.setRemoteDescription(new RTCSessionDescription(offer));
peerCon.createAnswer(gotAnswer, error);
}
アンサーの生成が成功したらピアコネクションのsetLocalDescriptionにオファーを設定しておきます。
function gotAnswer(answer) {
peerCon.setLocalDescription(answer, function() {
sendMessage({
type : 'answer',
answer : answer
});
}, error);
}
データ送受信
データ送受信するためには、データチャンネルを取得します。
sendChannel = peerCon.createDataChannel(...);
送信は、データチャンネルのsendメソッドつかって送信します。
sendChannel.send(value);
受信は、データチャンネルのonmessageのイベントで取得します。
sendChannel.onmessage = function (event) {
console.log( event.data );
};
ライブチャットデモ
名称とルーム名を入れて参加ボタンをクリックしてください。1ルームにつき2人までは入れます。ライブチャットデモ
まとめ
今回は、WebRTCを使ってリアルタイムコミュニケーション機能をつかってみました。 まだ全てのブラウザでは使えませんが、サーバなしでP2P機能を使えるとなるとビデオ会議室にデータ交換などに応用してみてはいかがでしょうか。
また、WebRTCのAPIは、複雑なのでライブラリを使うことをお勧めします。
- webRTC.io (https://github.com/webRTC/webRTC.io)
- simpleWebRTC (https://github.com/HenrikJoreteg/SimpleWebRTC)