WebRTCへの最近の僕
今年最初のブログ記事ポスト。いやーもう4月も半ば。桜も散っちゃいました。ほんと、更新頻度の低いブログです・・・今日は、WebRTC関連の話題。
DataChannel(映像、音声以外の任意のデータを送受信できる機能)が実装されたり、Firefox nightlyでも実装が始まったり、Chrome for Android(beta)でも実装が始まったりと、最近ホットなニュースが目白押しのWebRTC(Web Real Time Communication)。僕も、ちょいちょいプロトタイプ実装を試しています。
例えば、3/22のWeb先端味見部の時に、当日講師の吉川さんに取り上げていただいたチャット実装(github)とか(その後、吉川さん、大津谷さんのcontributeのおかげで、ビデオチャット機能実装とかバグ改修とか進められています)
なお、上のコードは、サンプルサイト公開もしています。(http://rtcdc.komasshu.info/)お互いに、room no も含め、同一URLにアクセスしたら、両側で"start"をクリック後、片方から"send Offer"をクリックすると p2p でのビデオ and テキストチャットができます。
とにかく面倒くさい
ただ、このWebRTCですが、とにかく面倒くさい。特にRTCPeerConnection APIの部分が、ほんと酷い。細かい話は、僕の以前のブログを参照頂ければ(すみません、この記事書いた時とAPI実装が変わっているので細かい部分は現在とは違っています。あくまで、大枠だけ見てください)と思いますが、
- セッション情報をやり取りするために、ブローカーサーバーとの通信(WebSocketなんかを使うことが多い)を実装
- Peer間で、p2pの通信を行うための API call(offer、answer : 映像フォーマットなどのネゴシエーション、candidate : p2p通信用アドレス・ポートのやりとり)や、それにまつわるイベントハンドリング
- イベントハンドラに応じた、UI(DOM)の制御
上にあげたサンプルコードのクライアントJSの部分はこちらから確認できますが、すごいシンプルなチャットのコーディングでもこれぐらい必要なっちゃう(普通にWebSocketだけで書いたほうが、遥かに簡単)。とてもじゃありませんが、これをスクラッチで使って、もっと複雑なコードを書こうとは思えません。
簡単 WebRTC フレームワーク。Peer.js
てな不満は色んな人達が感じているようで、WebRTC用のフレームワークライブラリがすでに複数公開されています。で、今回は、その中の一つ http://peerjs.com/ を調べてみたので、今回はその内容を紹介します。ちなみに、昨日 NTT-AT の金城さん主催で開催された ふらっと勉強会 WebRTC自習会の際に、色々と調べたものです。
とりあえず、ページのスニペット(UDPサーバー・クライアントのコード)を見ると分かるのですが、とにかくシンプルにWebRTCを使うことができます。多分、WebSocketやsocket.ioのプログラミングに慣れている人であれば、殆ど類似の考え方で使えますので、そんなに苦労しないと思います。
また、WebRTCには別にWebSocketなどによるブローカーサーバーを作らなければならないのですが、これも公開されていて、API keyの申請は必要(僕は試していませんが・・・)ですが、特にブローカーサーバーを作らなくても、簡単にWebRTCを試すことができます。また、ブローカーサーバー自体もOpen Sourceで公開されており、簡単に自分で立てることも可能です(僕は、今回そのアプローチを使いました)。ただし、こちらのAPIはDataChannelのみのフレームワーク(多分)ですので、その点には注意してください。
こちらの、Peer.js。APIが簡単なのもさることながら、内部的に結構充実した機能が実装されており、
- 各種データタイプへの対応
- WebRTCのDataChannelでは、データ送受信フォーマットがバイナリーのみとなっているため、データ送受信時に各種変換処理が必要なのですが、その辺りが簡単に対応出来ます(connect()メソッドの第二引数でデータタイプを指定する。例えば、UTF8でのデータ送受信時には
を指定する。{serialization: binary-utf8}
- reliable通信への対応
- WebRTCのDataChannelはUDP通信のため、パケットロスが起きると、データが欠落してしまいます。WebRTCでは、これを防ぐため reliable (再送制御)通信をサポートする仕様策定を進めていますが、現状まだ実装されていません。ここで、実験的ですが、connect()の第二引数で
を指定すると、ライブラリにより再送制御が行われるようになります。ただし、現状のDataChannel実装ではデータ送信にトラフィック制限がかかっており、ファイルなどのデータを送信するのに異常に時間がかかったりしますので、あくまで、ショートデータのみに使ったほうが得策です。あと、コードを見ると、reliable:trueを設定した際、serializationの設定がスルーされてしまう実装となっているため、例えばUTF8を送受信するとおかしなことになります。{reliable: true}
- ブローカーサーバーとのWebSocket / XHR フォールバック
- ブローカーサーバーとの通信は、通常はWebSocketが使われますが、失敗するとXHRにフォールバックします。コードを見ると、socket.ioは用いておらず、独自実装のようです。
チャットサンプル
ということで、Peer.jsを使ったチャットサンプルを作ってみました(UTF-8対応版)(reliableはdefaultでfalseになっているので、ロスがあるとデータが途中で落ちちゃいますが・・・)。
まずは、ブローカーサーバー。今回は、自前で立ててみました。nodeのインストールと
$ npm peer
が必要です。無茶苦茶簡単ですw
var PeerServer = require('peer').PeerServer;
var server = new PeerServer({ port: 9000 });
次に、クライアントのコード JavaScritpのみ示します。今回は、ブローカーを独自に立てたため、Peerオブジェクトのコンストラクト時に、オプションでサーバーのアドレスとポートを指定しています。また、UTF-8をサポートするために、connect()メソッドでやはりオプション指定しています。
チャット実装時にUDPサーバーとクライアントのコードを同居しなければならないため、WebSocketのみでコーディングするよりも若干コード量が増えていますが、かなり簡単にWebRTCを利用できることがわかると思います。(生で書くのに比べると段違いの差です)
var peer_, conn_;
var enableForm_ = function(id) {
$("form").each(function(e){
$(this).find("button").attr("disabled", $(this).attr("id") === id ? false : "disabled");
})
}
var setupForRemote_ = function(conn) {
if(!!conn) conn_ = conn;
enableForm_("chat");
conn_.on("data", function(data){
showChat_(conn_.peer, data)
});
}
var showChat_ = function(id, mesg) {
$("<dt>"+id+"</dt><dd>"+mesg+"</dd>").appendTo("dl")
}
$("form#connect").submit(function(e){
e.preventDefault();
$(this).find("button").attr("disabeld", "disabled")
var id = $(this).find("input[name=myid]").val();
peer_ = Peer(id, {
"host": "localhost",
"port": 9000
});
peer_.on('connection', setupForRemote_);
enableForm_("call")
})
$("form#call").submit(function(e){
e.preventDefault();
var id = $(this).find("input[name=remoteid]").val();
conn_ = peer_.connect(id, {"serialization": "binary-utf8"});
conn_.on('open', setupForRemote_);
})
$("form#chat").submit(function(e){
e.preventDefault();
var mesg = $(this).find("input").val();
showChat_("me", mesg)
conn_.send(mesg)
})
function init(){
enableForm_("connect")
}
init();
HTMLも含めた全体は、gistで確認してください。
まとめ
今回は、WebRTCのDataChannelを簡単に使えるようにするフレームワーク Peer.js を紹介しました。ネットワークゲームとか連携系のサービスなどで、レスポンス性をあげ、かつサーバー負荷を下げることが期待されるWebRTCのDataChannelですが、このライブラリを使うことで、そのコーディング障壁をかなり下げることができます。興味の有る方は、是非お試しを
人気ブログランキングへ
