Top/Devel/電子工作/RaspberryPi/ウェブカメラでストリーミング

ウェブカメラでストリーミング の変更点はてなブックマーク


#ref(mjpg_streamer.jpg,right,around,50%)
[[Raspberry Pi>../]]とウェブカメラを使って、動画のストリーミング配信をしてみます。

なお、この方法で配信できるのは映像のみです。音声は配信できません。

OSのインストールやWiFiドングルのセットアップなどの初期設定は[[こちら>../Raspbianのインストール]]をご覧ください。

#amazon(B00T356SFO,left)
#amazon(B01CFHHYF4,left)
#clear

*必要なもの
#amazon(B003YUB660)
-[[RaspbianがインストールされたRaspberry Pi>../Raspbianのインストール]]
-[[UVC対応ウェブカメラ>http://www.amazon.co.jp/s/url=node%3D2152019051&field-keywords=uvc/cubic9com-22]](私はたまたま家にあった [[Logitech QuickCam V-UBU48 (C905)>http://www.amazon.co.jp/exec/obidos/ASIN/B004ER7XAK/cubic9com-22]] を使用しました)

~
より詳しいUVC対応ウェブカメラの一覧は[[こちら>http://www.ideasonboard.org/uvc/]]で見れます。

#clear

*あった方がいいもの
#amazon(B001QS17WA)
-[[ACアダプタつきのUSBハブ>http://www.amazon.co.jp/exec/obidos/ASIN/B001QS17WA/cubic9com-22]]

電力が不足することがあるらしいです。
#clear
#ref(../raspberry_pi.jpg,right,around,20%)
なお、Raspberry Pi用にUSBハブを新調する場合は、Raspberry Piの電源の弱さをサポートするために、[[ACアダプタつきのUSBハブ>http://www.amazon.co.jp/exec/obidos/ASIN/B001QS17WA/cubic9com-22]]が良いようです。

右の写真では、スマホ用充電専用MicroUSBケーブルを使って、Raspberry Pi自体の電源もUSBハブから取っています。(黒いカールコード)

通常の通信もできるMicroUSBケーブルを使うとループ接続になってしまうので、要注意です。

#clear

*手順
+Raspberry PiのIPを確認する。(下記の場合は192.168.0.10がIPです)
#code(bash,nonumber){{
LANG=C ifconfig | grep Bcast
}}
>
#code(bash,nonumber){{
          inet addr:192.168.0.10  Bcast:192.168.0.255  Mask:255.255.255.0
}}
<
+前準備として、パッケージを最新化する。
#code(bash,nonumber){{
sudo aptitude update
sudo aptitude upgrade
}}
+ウェブカメラが認識されているか確認する。(下記の場合はDevice 004がウェブカメラです)
#code(bash,nonumber){{
lsusb
}}
>
#code(bash,nonumber){{
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 046d:0991 Logitech, Inc. QuickCam Pro for Notebooks
Bus 001 Device 005: ID 2019:ab2a PLANEX GW-USNano2 802.11n Wireless Adapter[Realtek RTL8188CUS]
}}
<
+必要なパッケージをインストールする。
#code(,nonumber){{
sudo aptitude install libv4l-dev libjpeg8-dev subversion imagemagick
}}
+mjpeg-streamerをダウンロードしてmakeする。
#code(,nonumber){{
make USE_LIBV4L2=true clean all
}}
+まずはインストールしないで実行してみる。
#code(,nonumber){{
./mjpg_streamer -i "./input_uvc.so -d /dev/video0 -r 640x480 -f 1" -o "./output_http.so -p 8080 -w ./www"
}}
+ブラウザで http://【Raspberry PiのIP】:8080/javascript.html を開く。
+動画が表示されたら、必要であれば、/usrにインストールする。
#code(,nonumber){{
sudo make DESTDIR=/usr install
}}
+インストール後は下記のようにして起動する。(フレームレートは毎秒1フレームにしています。私の環境では、60fps以上を指定しても56〜59fpsになりました。)
#code(,nonumber){{
mjpg_streamer -i "/usr/lib/input_uvc.so -d /dev/video0 -r 640x480 -f 1" -o "/usr/lib/output_http.so -p 8080 -w /usr/www"
}}

*コマンドラインオプションの意味
|オプション|>|説明|h
|-b|>|バックグラウンドで起動。デーモンになる。停止する場合は kill -9 `pidof mjpg_streamer` とする。|
|-i|>|入力修飾子を指定する(-i 以降にダブルクォーテーションでくくって指定する)|
|~|-d|カメラデバイス|
|~|-r|解像度(QSIF/QCIF/CGA/QVGA/CIF/VGA/SVGA/XGA/SXGA あるいは 横幅x縦幅)|
|~|-f|フレームレート[fps]|
|~|-y|YUYVフォーマットを指定するか否か(MJPEGがウェブカメラでサポートされていない場合)|
|~|-q|JPEGのクオリティ(1-100)|
|~|-m|最小サイズ。ウェブカメラがゴミフレームを送ってくる場合にそれを除外するために指定する。|
|~|-n|dynctrlsを初期化しない。(カメラ操作無効か?)|
|~|-l|LEDの状態。(on/off/blink/auto)|
|-o|>|出力修飾子を指定する(-o 以降にダブルクォーテーションでくくって指定する)|
|~|-p|ポート|
|~|-w|ウェブコンテンツのあるディレクトリ。/usr配下にインストールした場合は/usr/www。|
|~|-c|認証情報。ユーザ名とパスワードを「:」区切りで指定する。|
|~|-n|デモページのControlでのコマンド実行を無効化する。(Brightnessなどが変更できなくなります)|

より正確なオプションの説明は下記のようにすると参照できます。
#code(bash,nonumber){{
./mjpg_streamer -i "input_uvc.so --help"
./mjpg_streamer -o "output_http.so --help"
}}

*Raspberry Pi起動時に起動するには
mjpg_streamerを起動するスクリプトを起動スクリプトとして登録します。
#code(bash,nonumber){{
nano mjpg_streamer
}}
>
#code(bash,nonumber){{
#!/bin/sh

### BEGIN INIT INFO
# Provides: mjpg_streamer
# Required-Start: $local_fs $network
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: Start or stop mjpg-streamer
### END INIT INFO

mjpg_streamer -b \
  -i "/usr/lib/input_uvc.so -d /dev/video0 -r 640x480 -f 30" \
  -o "/usr/lib/output_http.so -p 8080 -w /usr/www"
}}
<
#code(bash,nonumber){{
chmod a+x mjpg_streamer
sudo mv mjpg_streamer /etc/init.d/
sudo insserv mjpg_streamer
}}

*ウェブサイトへ埋め込むには
下記のようなJavascript、HTMLで埋め込みができる。

なお、<img src="http://【Raspberry PiのIPアドレス】:【ポート】/?action=stream">として埋め込めると記述されているサイトもあるが、この方法が使えるのはFirefoxなど一部のブラウザに限られる。

Javascriptの方式であれば、ほぼすべてのブラウザで閲覧できる。

以下は付属のjavascript_simple.htmlから転記したもの。
#code(html,nonumber){{

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>MJPEG-Streamer</title>
</head>
<script type="text/javascript">

/* Copyright (C) 2007 Richard Atterer, richardツゥatterer.net
   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License, version 2. See the file
   COPYING for details. */

var imageNr = 0; // Serial number of current image
var finished = new Array(); // References to img objects which have finished downloading
var paused = false;

function createImageLayer() {
  var img = new Image();
  img.style.position = "absolute";
  img.style.zIndex = -1;
  img.onload = imageOnload;
  img.onclick = imageOnclick;
  img.src = "http://【Raspberry PiのIPアドレス】:【ポート】/?action=snapshot&n=" + (++imageNr);
  var webcam = document.getElementById("webcam");
  webcam.insertBefore(img, webcam.firstChild);
}

// Two layers are always present (except at the very beginning), to avoid flicker
function imageOnload() {
  this.style.zIndex = imageNr; // Image finished, bring to front!
  while (1 < finished.length) {
    var del = finished.shift(); // Delete old image(s) from document
    del.parentNode.removeChild(del);
  }
  finished.push(this);
  if (!paused) createImageLayer();
}

function imageOnclick() { // Clicking on the image will pause the stream
  paused = !paused;
  if (!paused) createImageLayer();
}

</script>
<body onload="createImageLayer();">

<div id="webcam"><noscript><img src="http://【Raspberry PiのIPアドレス】:【ポート】/?action=snapshot" /></noscript></div>

</body>
</html>
}}

ただし、LAN外に公開する場合は、上記IPはグローバルIPである必要がある。

必要に応じてルータでポートマッピングをすること。

なお、その際は-cオプションで認証をかけること。

*トラブルシューティング
**下記のようなエラーが出る場合
ストリーミングは開始するが、下記のようなエラーが出る場合、使用しているウェブカメラが遠隔操作に対応していません。

そのままでも特に問題はありませんが、入力側の修飾子に-nを指定するとエラーが出力されなくなります。
#code(,nonumber){{
Adding control for Pan (relative)
UVCIOC_CTRL_ADD - Error: Inappropriate ioctl for device
Adding control for Tilt (relative)
UVCIOC_CTRL_ADD - Error: Inappropriate ioctl for device
Adding control for Pan Reset
UVCIOC_CTRL_ADD - Error: Inappropriate ioctl for device
Adding control for Tilt Reset
UVCIOC_CTRL_ADD - Error: Inappropriate ioctl for device
Adding control for Pan/tilt Reset
UVCIOC_CTRL_ADD - Error: Inappropriate ioctl for device
Adding control for Focus (absolute)
UVCIOC_CTRL_ADD - Error: Inappropriate ioctl for device
mapping control for Pan (relative)
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Tilt (relative)
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Pan Reset
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Tilt Reset
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Pan/tilt Reset
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Focus (absolute)
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for LED1 Mode
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for LED1 Frequency
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Disable video processing
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
mapping control for Raw bits per pixel
UVCIOC_CTRL_MAP - Error: Inappropriate ioctl for device
}}

**音が出ない場合
mjpg-streamerには音声を配信する機能はありません。

**カメラが突然切れる
こんなエラーメッセージが出てmjpg_streamerが死んで、lsusbでウェブカメラが見つからない場合は、恐らく電力不足です。
#code(,nonumber){{
Unable to requeue buffer: No such device
 i: Error grabbing frames
}}

[[セルフパワーのUSBハブ>http://www.amazon.co.jp/exec/obidos/ASIN/B001QS17WA/cubic9com-22]]を買いましょう。


*Amazon
#amazon(B00T356SFO,left)
#amazon(B00SXYGOQ4,left)
#amazon(B01CFHHYF4,left)
#amazon(480071172X,left)
#amazon(B003YUB660,left)
#amazon(B001QS17WA,left)
差分 一覧