WebRTC の getUserMedia の現状

FreeBSD は多少関係ないですが,デーモン君だけは登場させます.

WebRTC

ブラウザを使って,リアルタイムコミュニケーション (Real-Time Communication) をしようと言うのが,WebRTC だと思っています.

要素技術的には,Peer-to-Peer Communication や動画・音声をブラウザ上で扱う必要が出てくるわけですが,今回はその中の,動画・音声のための APIについて,スマホでの動作を確認しました.(結果は失敗.まだ次期尚早.)

動機

社内には,Bookan と呼ばれる書籍管理ツールがあるのですが,書籍を登録するには,ISBN または Amazon の ASIN を手で入力しなければなりません.

ちょうめんどくさいです.

スマートフォンのカメラでバーコードを読み込ませられたら,めんどくさがりやの僕でも登録するかもしれません.

さらに,本を登録するためだけにアプリケーションをインストールするのも面倒です.写真をとって,アップロードするのも面倒です.できれば,Bookanの登録ページから直接カメラを起動して,バーコードを読み込ませられれば,最高です.FreeBSD 上では graphics/zbar という ports がありました.画像を食わせればバーコードを解析してくれそうです.

なので,今回は,Web ブラウザからスマホのカメラを起動し,写真をサーバに送りたいのです.

getUserMedia

ブラウザからカメラを起動するには,getUserMedia という Javascript APIがあるようです.WebRTC のためのものなのかもしれませんが,これで十分な気がします.

getUserMedia の利用方法については,色々なウェブサイトで紹介されています.WebRTC getUserMedia 簡単Webカメラ が,サンプルコードとしては,僕は気に入っています.

navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;

こんな感じで,ブラウザ間の差異を吸収させます.WebKit ベースや Mozillaベースのブラウザでも,navigator.getUSerMedia で扱えるようにしています.

以下のようなコードで,ブラウザ上にカメラからの動画を表示できるようです.

navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL;

function getMedia() {
    navigator.getUserMedia(
        {video: true},
        function(localMediaStream) {
            var myVideo  = document.getElementById('myVideo');
            myVideo.src = window.URL.createObjectURL(localMediaStream);
            myVideo.play();
        },
        function(err) {
            alert('カメラから映像を取得することができませんでした。');
            console.log(err);
        }
    );

とりあえず,これで PC 上の Chrome では動作しました.

動作環境

次に,スマホのブラウザでどれくらい動作するのかについて調査しました.

Can I use getUserMedia/Stream API ここが良くまとまっています.

良く見ると,iOS はまだ対応していないようですね(泣

Android も標準ブラウザは対応してませんが,Chrome for Android やFirefox for Android,Opera Mobile などは対応している模様です.

社内の書籍登録の簡単にしたいだけなので,社内に大量に転がっているAndroid 端末を使えばいいやと判断.次に進むことにします.

Android 端末上での動作

先ほどのサンプルコードを Android で動作させてみると,当然のように画面と同じ方向にあるカメラが利用されてしまいました.

今回は,バーコードをとりたいので,反対側のカメラが利用したいです.

調べてみると,getSources というメソッドがあって,複数のカメラに割り当てられている ID を取得することができるようです.この ID がブラウザによって割り振られているのか,OS などのシステム関連の ID なのかまでは,現段階では調査していないです.

getSources を利用した,デバイスの選択

サンプルコードを以下に示します.

<div id="debu"></div>
    var debug = document.getElementById("debug"); 
    MediaStreamTrack.getSources(function (media_sources) {
        for (var i=0; i < media_sources.length; i++) {
            debug.innerHTML += "label: " + media_sources[i].label + ", kind: " + media_sour\
ces[i].kind + ", id: "+ media_sources[i].id + "<br>";
        }
    })

getSources を呼ぶと,callback の引数にデバイス情報が渡されるみたいです.上記の例では media_sources です.media_sources[0].id みたいにすると,カメラデバイスの ID がとれるみたいです.

また,media_sources[0].label には,”audio”,”video” のどちらかが入っていました.

確かに,デバイスが複数ある環境では,複数の video が表示され,デバイスID も表示されています.

今回は,Android の Chrome beta (v35) を利用してみました.が,インナーカメラまでは利用できるのですが,外側のカメラを利用しようとすると,うまくいかないです.Firefox mobile では,そもそもカメラデバイスのリストも出てこなかったです.

うーーーむ.残念….ということで,今回は失敗に終りました.半年くらい寝かせてから,再度やってみたいと思います.

サンプルコード

参考になるか分かりませんし,きれいにしてもいないですが,HTML,
Javascript 共に,掲載しておきます.

<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" id="iphone-viewport" content="width=320,initial-scale=1.0,user-scalable=yes,maximum-scale=0.6667" />
  <link rel="stylesheet" href="bootstrap/css/bootstrap.css" type="text/css">
  <link rel="stylesheet" href="bootstrap/css/bootstrap-responsive.css" type="text/css">
  <script src="js/camera.js">
  </script>
</head>
<body>
  <header>
    <h1>getUserMediaサンプル</h1>
  </header>
  <button onclick="getMedia()">キャプチャ開始</button><br/>
  <video id="myVideo"></video><br/>
  <button id="picture">写真撮影</button>

  <hr>
  <p>
  写真は以下に示すよ.<br>
  <canvas id="canvas"></canvas>

  <hr>
  デバッグ領域だよ.
  <div id="debug"></div>
</body>
</html>
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL;

if (!navigator.getUserMedia){
    alert('getUserMediaがサポートされていません');
}

function getMedia() {
    var ids = new Array(); 

    MediaStreamTrack.getSources(function (media_sources) {
    debug = document.getElementById("debug"); 
    debug.innerHTML += "user agent: " + navigator.userAgent + "<br>"; 
    for (var i=0; i < media_sources.length; i++) {
        debug.innerHTML += "label: " + media_sources[i].label + ", kind: " + media_sources[i].kind + ", id: "+ media_sources[i].id + "<br>"; 
        if (media_sources[i].label == "video") {
        ids.push(media_sources[i].id); 
        }
    }
    })

    navigator.getUserMedia(
    {video: {optional: [{sourceId: ids[1]}]}}, /* debug 時には,ここの添字を 0/1 適当に変更して実行.*/
    function(localMediaStream) {
        var myVideo  = document.getElementById('myVideo');
        myVideo.src = window.URL.createObjectURL(localMediaStream);
        myVideo.play();
    },
    function(err) {
        alert('カメラから映像を取得することができませんでした。');  
        console.log(err);
    }
    );

    var pic_btn = document.getElementById("picture");
    var canvas = document.getElementById("canvas"); 
    var context = canvas.getContext("2d"); 
    pic_btn.addEventListener("click", function(){
    context.drawImage(myVideo, 0, 0, canvas.width, canvas.height); 
    }); 
}
Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

榊原 寛

1980 年埼玉県生まれ。BPS COO。慶應義塾志木高校からそのまま慶應義塾大学湘南藤沢キャンパスへ。コンピュータの勉強がしたかったので、学部1年より徳田英幸研究室へ。無線ネットワークに関する研究、ユビキタスネットワークに関する研究、センサネットワークに関する研究、仮想ネットワークに関する研究等を行い、2010年慶應義塾大学政策・メディア研究科後記博士課程単位取得退学。 IPA 未踏事業 2006年度、2007年度開発責任者。日本学術振興会特別研究員(DC2) 2008年度。技術が実際に役に立つ現場に行きたく、BPSへ。BPSでは、主に電子書籍に関する事業に従事。マンガEPUBビューアや WebKit を利用した EPUB3 の日本語縦書きビューアプロジェクトを推進。全国中小企業団体中央会によるグローバル技術連携・創業支援補助金(創業枠)及び東京都中小企業振興公社「新製品・新技術助成事業 助成金」を MangaReborn 事業にて申請・獲得。電子書籍に関する次なるソリューションについて日々試行錯誤。慶應義塾大学環境情報学部非常勤講師兼任中。慶應義塾大学 SFC 研究所所員。W3C AC Representative。 http://techracho/bpsinc.jp/skk/ , http://www.ht.sfc.keio.ac.jp/~skk/

榊原 寛の書いた記事

開発
W3C/IDPF の統合に関して

2016年05月15日

週刊Railsウォッチ

インフラ

Rubyスタイルガイドを読む

BigBinary記事より

ActiveSupport探訪シリーズ