こんにちは、がねこまさしです。以前WebRTCに関する連載を書かせていただきましたが、今回はそのフォロー記事を書きたいと思います。
4月に記事をベースにしたハンズオンを行ったり、別のイベントで参加者の方とお話しさせていただく機会がありました。すると、みなさんいろいろな部分で引っ掛かってしまうケースが多いことが分かりました。私の記事の説明不足も多いので、以下のつまずきやすいポイントについて、この機会に改めて補足させていただきます。
- カメラがつながらない
- 手動シグナリングがうまくいかない
- シグナリングサーバーでつながらない
- Firefoxでも使いたい
カメラがつながらない
第1回のHTML5でWebRTCを使ってみよう!「カメラを使ってみよう」編ではまずカメラにアクセスします。ところが、カメラにつながらないケースが時々発生しているようです。
ブラウザが違うケース
記事に書いたソースコードは、Chrome用になっていますので、Chromeでお試しください。FirefoxもWebRTCに対応していますが、JavaScriptの書き方がちょっと違います。
※Chrome/Firefox両方に対応させる書き方もあります。この記事の最後でご説明します。
権限の制限に引っ掛かっている
ChromeでWebRTCを使ってカメラにアクセスするには、HTML/JavaScriptをローカルディスクから読み込む(file://~)ではなく、Webサーバーから読み込まなくてはなりません(http://~、https://~)。お手数ですが、ApacheやnginxといったWebサーバー、あるいはpython,ruby,node.js,go等を使ってテスト用サーバーを動かしてください。HTMLファイルは、Webサーバー側に配置してくださいね。
Node.jsを使った簡易Webサーバー
例として簡易WebサーバーをNode.jsで作った場合のサンプルをこちらに掲載します。※HTML5エキスパートの方のソースを一部拝借させていただきました。
1 2 3 4 5 6 |
var port = 9000; var html = require('fs').readFileSync(__dirname + '/hand.html'); // 任意のHTMLファイル var server = require('http').createServer(function(req, res) { res.writeHead(200, {'Content-Type': 'text/html', 'Content-Length': html.length}); res.end(html); }).listen(port); |
こちらを例えば http.js として保存し、htmlファイルも(この例ではhand.html)同じディレクトリに保存してください。
次に、コマンドプロンプト/ターミナルから、
1 |
node http.js |
のように簡易Webサーバーを起動してください。ブラウザからは http://localhost:9000/ にアクセスしてくださいね。
うっかり「拒否」してしまった
ブラウザがカメラやマイクにアクセスする許可を求めてきた際に、うっかり「拒否」してしまった場合、カメラの映像は取得できません。
そんな場合は、アドレスバーの右端に「カメラに×印」が表示されます。
ここで「カメラに×印」のアイコンをクリックすると、カメラのアクセス許可状態を変更するメニューが現れます。
「カメラやマイクへのアクセスを要求しているか確認する」を選択し、[完了]をクリックすると、リロードを促されます。
[再読み込み]ボタンをクリックして、再度挑戦してみてください。
なぜかカメラを認識しないケース
そもそもブラウザがカメラを認識していないことがあります。確実ではありませんが、次の手順で認識してくれることもあります。
- USB接続の場合、カメラを抜き差しする → 再挑戦
- ブラウザを終了し、再度起動する → 再挑戦
- OSを再起動 → 再挑戦
USBの抜き差しが一番可能性が高く、後ろに行くにしたがって、成功する可能性は下がる印象です。不思議です。
手動シグナリングが上手く行かない
第2回の「WebRTCに触ってみたいエンジニア必見!手動でWebRTC通信をつなげてみよう」では、SDPとICEを手動でコピー&ペーストしてPeer-to-Peer通信を確立しました。ところが実際にやってみると、うまくいかないケースが多々ありました。実感としては約半数のケースでうまくいかず、ただ黒い画面が表示されるだけでした。
正確な原因はよく分かっていませんが、コピーする範囲(選択した範囲)が1文字でもずれていると、正しく接続できないことは確かです。そのため、対象の文字列を自動で選択するようにちょっとだけ改良しました。記事の最後に「手動シグナリングの改良版ソース(2014年4月21日追加)」として改良したソースを載せていますので、うまくいかなかった人もこちらで再チャレンジしてみてください。
また、この機会に同一LAN上の別のマシン間でも手動シグナリングを試しました。テキストファイル経由でSDP/ICEを交換して、無事通信することができました。
シグナリングサーバーでつながらない
第3回の「WebRTC初心者でも簡単にできる!Node.jsで仲介(シグナリング)を作ってみよう」では、Node.jsを使ってシグナリングサーバーを作りました。こちらもnode.jsをよく触っている方に、勘違いさせてしまったようです。
Node.jsでもexpressなどのフレームワークを使って、Webアプリケーションを作ることが多いです。なので今回もシグナリングサーバーでWebサーバーも兼ねていて、HTMLもそこから取得できると思われた方がいたようです。第3回の記事では、Node.jsでWebSocketを使ったシグナリングサーバーのみ作成しています。お手数ですが、Webサーバーは別途用意してくださいね。
もちろん先ほどと同じく、Node.jsで簡易Webサーバーを作ることも可能ですので、お好みでどうぞ。
Firefoxでも使いたい
FirefoxでもWebRTCが使えますが、私が書いた記事のソースはChromeにしか対応していません。Chrome/Firefox共通で使える様にクロスブラウザ対応にしてみましょう。
クロスブラウザ対応する書き方はいろいろありますが、今回はGoogleで用意しているadapter.jsを使ってみます。題材には、第3回のシグナリングサーバーを使った1対1の通信を用います。
adapter.jsを使うには、まずHTMLの最初でJavaScriptを読み込みます。
1 2 3 4 5 |
<html> <head> <title>WebRTC 1 to 1 signaling</title> <script src="https://webrtc.googlecode.com/svn/trunk/samples/js/base/adapter.js"></script> </head> |
次に、ブラウザ固有のクラス、メソッドを置き換えます。
- navigator.webkitGetUserMedia() —> getUserMedia()
- video.src = window.webkitURL.createObjectURL(stream) —> attachMediaStream(video, stream)
- webkitRTCPeerConnection –> RTCPeerConnection
具体的には、次の箇所になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function startVideo() { //navigator.webkitGetUserMedia({video: true, audio: false}, getUserMedia({video: true, audio: false}, function (stream) { // success localStream = stream; //localVideo.src = window.webkitURL.createObjectURL(stream); attachMediaStream(localVideo, stream); localVideo.play(); localVideo.volume = 0; }, function (error) { // error console.error('An error occurred: [CODE ' + error.code + ']'); return; } ); } |
1 2 3 4 5 6 7 8 9 |
function prepareNewConnection() { var pc_config = {"iceServers":[]}; var peer = null; try { //peer = new webkitRTCPeerConnection(pc_config); peer = new RTCPeerConnection(pc_config); } catch (e) { console.log("Failed to create peerConnection, exception: " + e.message); } |
1 2 3 4 5 |
function onRemoteStreamAdded(event) { console.log("Added remote stream"); //remoteVideo.src = window.webkitURL.createObjectURL(event.stream); attachMediaStream(remoteVideo, event.stream) } |
すると、このようにChromeとFirefox間で通信ができるようになります。
おわりに
ありがたいことに実際にWebRTCの記事を試してくださった方々の言葉を聞くチャンスがあり、そこで出てきた疑問に答えるために、今回の記事を書かせていただきました。貴重なフィードバックをいただいた方々にお礼申し上げます。ありがとうございました。
一連の記事についてでも、そうでなくても、WebRTCに関する質問やご意見があれば、どんどんお寄せください。私の分かる範囲でまた補足記事を書かせていただきます。よろしくお願いします。