Imaginary Code

from kougaku-navi.net

Webカメラの映像をストリーミング配信してProcessingやp5.jsで受信する

 カメラ映像をネットワーク越しに送受信したいことがたまにありますよね。Processingやp5.jsで作る場合にどうしたらいいかを紹介します。

ストリーミング配信するソフト

 PCに接続されたWebカメラを使って映像をストリーミング配信したい場合、「Gmax IP Camera」というソフトがシンプルでおすすめです。公式サイトから「M-JPEG version」をダウンロードします。ソフトを起動したら、デバイス、解像度、フレームレート、ポート番号などを設定して「Start」ボタンを押すだけで配信が始まります。「Test」ボタンを押すと、ブラウザが起動して配信URLにアクセスするので、それで受信のチェックができます。


 ここではWindows用のソフトを使いましたが、スマホアプリで同様の機能を持つものもあります。例えば、iOSの場合は「ipCam - Mobile IP Camera」とか。

Processingで受信する

 Processingでストリーミング受信するライブラリとして「IPCapture」があるので、これをダウンロードし、インストールします。テスト用のサンプルプログラムが同梱されているので、配信元のURLの部分を書き変えて受信テストしましょう。以下のコードはサンプルコードとほぼ同じものですが、「192.168.11.50:8088」の部分が変更箇所です。

import ipcapture.*;

IPCapture cam;

void setup() {
  size(640, 480);
  cam = new IPCapture(this, "http://192.168.11.50:8088", "", "");
  cam.start();
}

void draw() {
  if (cam.isAvailable()) {
    cam.read();
    image(cam,0,0);
  }
}

void keyPressed() {
  if (key == ' ') {
    if (cam.isAlive()) cam.stop();
    else cam.start();
  }
}


p5.jsで受信する

 以下がサンプルコードです。これをHTMLファイルとして保存し、Webブラウザで開いてください。

<!DOCTYPE html>
<html>
  <head>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.3/p5.min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.3/addons/p5.dom.min.js"></script>
    <script>
      function setup() {
        createCanvas(640, 480);
      }

      function draw() {
        background(0);

        // 画像を読み込み
        var img = createImg("http://192.168.11.50:8088");
        img.id("received_image");

        // 画像を表示
        image( img, 0, 0 );

        // 画像を削除
        var element = document.getElementById("received_image");
        if ( element != null ) {
          element.parentNode.removeChild(element);
        }

        // 動作確認のためにマウスカーソルの位置に十字線を表示
        stroke(255, 255, 0);
        strokeWeight(3);
        line( mouseX, 0, mouseX, height );
        line( 0, mouseY, width, mouseY );
      }
    </script>
  </head>
  <body>
  </body>
</html>


ブラウザで開くと、受信した画像と十字線が表示されます。image()命令で表示できていますね。十字線はp5.jsがうまく機能してるかの確認用です。


 当初、loadImage()を使って画像の受信をできないか試したのですが、ダメでした。そこでcreateImg()を使ってみたところ、読み込めたのですが、これをdraw()で毎ループやってしまうと要素が延々追加されてしまうという新たな問題が発生。そこで、毎ループ要素を削除するコードを入れたらうまくいきました。あれこれ思考錯誤して出した答えですが、もっといい方法がありそうな予感。

以上。
 
 
関連:のちにこういう記事を書きました。5年たっても同じようなことやってるな。
kougaku-navi.hatenablog.com