イントロ
こちらは、WebRTC Advent Calendar 2014の21日目のエントリーです。
実現すること
PC に USB で有線接続された Android端末を用い、その Android端末のカメラ映像を PC のブラウザ上に表示させる、というものを実現します。PC に USB接続された Android端末を、Webカメラ的に使うイメージです。
このようなことをやろうとした経緯は「以前の投稿(Android端末をプレゼン用途でWebカメラ的に使おうとした話【設計編】)」をご覧ください。
実装や設定の概要
上記の内容を実現する方法は、おおまかにはこのようになります。
※ PC でも Android端末上でも、Chrome を利用
- 概要
- getUserMedia を使い、カメラ映像をブラウザ上に表示するページを実装@ローカルPC。
- Android端末の USBデバッグを有効にし、PC と USB で接続された状態にする。
- 手順2の内容を「localhost:8080」などといった形で、ローカルPC上で参照できるよう、PC側でサーバ立ち上げ。
- Android側と PC側の両方で Chrome を起動し、PC側の Chrome からリモートデバッグ。
その際、Android からローカルPCのサーバを参照できるよう、Port forwarding を設定。 - PC側の Chrome のインスペクタで、Android上の Chrome の表示内容を、PC側で表示。
実装や設定の詳細
手順1:カメラ映像をブラウザ上に表示
getUserMedia を使ったカメラ映像取得・取得した映像のブラウザ上への表示、を実装します。
Javascript の部分は下記のように、だいたいはよくある感じの実装です( htmlファイルには、「id を video とした videoタグ」を配置しています )。
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL;
if (navigator.getUserMedia) {
navigator.getUserMedia (
{
video: true,
audio: true
},
function(localMediaStream) {
var video = document.querySelector('video');
video.src = window.URL.createObjectURL(localMediaStream);
},
function(err) {
console.log("エラー: " + err);
}
);
} else {
alert('getUserMediaがサポートされていません');
}
ただし、この実装だと、この後に行う「Android端末の Chrome上で、Android端末のカメラ映像を取得する」という部分で、フロントカメラの映像が取得されてしまい、Webカメラ的に利用するのには不便です。
そこで、バックカメラを利用できるよう以下のような処理に変更します。以下は、Chrome for Android のバックカメラを指定する処理になっています。
# Firefox だとフロントカメラ/バックカメラの選択が、カメラの利用許可の選択時に行えるのですが・・・
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL;
if (navigator.getUserMedia) {
var selectCam = null;
if (typeof MediaStreamTrack === 'undefined'){
alert('MediaStreamTrackがサポートされていません');
} else {
MediaStreamTrack.getSources(function(data) {
for (var i = 0; i != data.length; ++i) {
if ((data[i].kind === 'video')&&(data[i].facing === 'environment')) {
selectCam = data[i].id;
}
}
navigator.getUserMedia (
{
video: {
optional: [{sourceId: selectCam}]
},
audio: true
},
function(localMediaStream) {
var video = document.querySelector('video');
video.src = window.URL.createObjectURL(localMediaStream);
},
function(err) {
console.log("エラー: " + err);
});
});
}
} else {
alert('getUserMediaがサポートされていません');
}
手順2〜4:Android端末の Chrome上で、USB接続されているローカルPCの htmlファイルを表示
ここで、Android の Chrome(※ Android 4.0以上 + Chrome for Android )の、リモートデバッグ機能を利用します。
そのために、まずは Android端末の設定で USBデバッグを有効にしておき、Android端末と PC を USB接続します。
PC上でのサーバ立ち上げ
ローカルPC上の html を「localhost:8080」などといった形で参照できるよう、PC側でサーバ立ち上げます。
いくつか方法はありますが、今回は Python を使った簡易サーバの起動を行いました。
ターミナル/コマンドプロンプト上で htmlファイルなどがあるフォルダへ移動し、「 python -m SimpleHTTPServer 8080 」を実行します。
PC上のブラウザから「localhost:8080」にアクセスし、先ほど準備した htmlファイルが表示できることを確認してみてください。
リモートデバッグの設定
その後、Android側 と PC側とで、それぞれ Chrome を起動します。
PC側の Chrome で、以下の画像にあるとおり「デバイスを検証」を選択します。
「デバイスを検証」の選択をした後の画面で、「Discover USB devices」にチェックを入れます。
そうすると、以下の画像にあるとおり、接続した端末の名前と(以下の例では Nexus 5)、Android の Chrome で開いているタブの一覧が表示されます。
これで、PC上の Chrome から、Android上の Chrome で開いている Webページの内容などを見ることができるようになりました。
ポートフォワーディングとスクリーンキャスト
しかし、これだけだと、Android上の Chrome から、ローカルPCに立ち上げたサーバを有線経由で参照できません。そのために Port forwarding を設定します。
上記の画像で、「Discover USB devices」の右側にある「Port forwarding...」を選択します。
その後の画面で、以下の画像の赤枠内のとおりに設定します。
そして、画像中の矢印で示した「Enable port forwarding」にチェックを入れ、その右のボタン「Done」を押して下さい。
そうすると、Android上の Chrome で「 localhost:8080 」にアクセスすると、PC側でローカルで立ち上げたサーバにアクセスできます。
そして、Android上の Chrome で開いているタブの一覧が見えている以下の画像の画面(PC上の Chrome で表示させた画面)で、赤矢印で示した「inspect」を選択します。
そうすると、以下のようなデバッグ用のウィンドウが表示されます。
以下の画像の青で塗りつぶした部分に、Android上の Chrome で表示した Webページが表示されていると思います。もし、その部分が表示されてないようでしたら、画像の赤矢印で示した部分を押して「screencast」を有効にしてください。
これで、今回やろうとしていた内容が実現できました。