5月 152012
 

 私事ながら、2年半ほど前に長男が誕生した。妊娠が判明する前は自分が親になるなど全く想像だにできなかったが、実際に産まれてみると、ベビーベッド上で今どうしているのか非常に気になるものでもある。なので、Gentoo Linux を入れた小型 PC と webcam を組み合わせてライブ監視カメラを作ってみた。その後、犬のケージの監視や、息子がたまにサーバの電源を切ってしまうのでそれの監視など、何かしら webcam を監視カメラとして使っている。

 当初、ベビーベッドカメラとして使用した PC は、今は亡き T・ZONE PC DIY SHOP で投げ売りされていたユニティ製 Piccolo。サイズは非常にいいのだが、VIA C3 1GHz と処理能力的にはかなり最低ラインに近いものになる。今では ZOTAC などからZOTAC から AMD Fusion E350 搭載 コンパクトベアボーンなども出ているので、このへんを投入するといいかと思われる。

Piccolo

Piccolo


 Webcam はロジクールの webcam ラインナップで当時最高だった Webcam Pro 9000。最近は USB webcam でも UVC という統一的なインターフェイスでアクセスできるようになったので、定番 webcam はほぼ使えるとみてよい。ただし、Webcam Pro 9000 も後継機種の HD Pro Webcam C910 も FullHD での吸出しはできなかった。色々試してみたが、負荷など総合的にみて VGA が一番扱いやすいと思われる。また、ロジクールの webcam 上位機種が持つオートフォーカス機能についても、Linux UVC 経由では使えない。

 正直、2,000 円前後で買える webcam でもいいのではないかという話もあるが、色再現性や広角など、明らかに差は出てくる。なので、カメラで何を監視したいか、どれくらいの画質が必要かという辺りを加味して決めるといいかと思う。例えば防犯カメラがわりに使うのであれば、それこそ 2,000 円程度のカメラを大量に付けるという選択肢もありだろう。以下に Webcam Pro 9000 と Webcam C270 の画像を貼ってみるが

QuickCam Pro 9000

QuickCam Pro 9000


Webcam C270

Webcam C270

画質は明らかに Webcam Pro 9000 のほうが上だろう。C270 は安いことは安いが蛍光灯下では青みがかるし、何よりもノイズが多すぎる上にフォーカスも甘い画像となる。

 さて、ハードウェアは決まったので、次はソフトウェア側が必要となる。今回の要件は

  • 定期的に画像を保存。
  • Web 公開はしない。したとしても NFS でマウントすればよい。
  • 動体検知できるといい。
  • できればストリーミング配信したい。

 これに該当するものとして、フリーソフトで motion があったので、これを組み合わせることにした。

 まず初めに、motion を使う上でのバッドノウハウ的なものとしては、Gentoo の場合は常に trunk にあるソースを使うべきだということ。libjpeg のバージョンが新しすぎて motion が Segmentation Fault で落ちたり、カーネルを 3.x にすると V4L2 で画像を吸い出せなかったりした。我が家のカメラの場合は ffmpeg を使わなかったので指定していないが、ffmpeg でストリーミング配信する場合は指定する必要がある。ただし、VIA C3 1GHz レベルではストリーミングできない。

svn export --force http://www.lavrsen.dk/svn/motion/trunk/ .
./configure --without-sqlite3 --without-mysql --without-pgsql

 インストールが終わると、motion.conf に設定を書いていく。今回は、

  • 640 × 480
  • 15 秒ごとに定時保存
  • 動体検知すれば 1 秒に最大 4 枚保存。
  • 保存先は NFS マウントしたディレクトリ。
  • チャンク転送で 4 fps のストリーミング配信。

 動体検知ありで 1 秒に 4 枚というのは、VIA C3 1GHz ではかなりぎりぎりのラインになる。実際、この設定でストリーミング視聴すると、ロードアベレージは 0.8 〜 1 をキープしていた。

 ここで、チャンク形式エンコーディングでのストリーミング配信だが、これは HTTP/1.1 で定義されていて、motion では複数の JPEG ファイルを流し続けることでブラウザで動画っぽく表示させる。表示部分はブラウザの実装に依存するので、全てのブラウザでは表示できないことに気をつける必要がある。こちらで確認した範囲では、

  • 動画として表示できるブラウザ
    • Firefox
    • Google Chrome
    • Safari 5
    • Mobile Safari (iPhone OS 3~iOS 5.1.1)
  • 全く表示できないブラウザ
    • IE6~IE9
    • Android 2.3 純正ブラウザ

といった感じになる。

 以上を踏まえて設定ファイルを書いていくわけだが、まずは webcam が認識されているかを確認する必要がある。まず lsusb で USB デバイスとして認識されているかを確認する。

$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 003: ID 046d:0825 Logitech, Inc. Webcam C270
Bus 001 Device 004: ID 046d:0990 Logitech, Inc. QuickCam Pro 9000

 さらに、Linux 側で正しくデバイスを認識できていれば、デバイスファイルができている。

$ ls -l /dev/video*
crw-rw---- 1 root video 81, 0  5月 15 21:18 /dev/video0
crw-rw---- 1 root video 81, 1  5月 15 21:18 /dev/video1

2 台繋いでいるので 2 デバイスあるが、ここは適宜読み替えて欲しい。

 正しく認識されていれば、あとは motion.conf を書けばよい。ストリーミングを除いて上記を満たす最低限の設定は以下を書き換えれば良さそう。

videodevice /dev/video0
width 640
height 480
framerate 4
minimum_frame_time 0
threshold 8000
threshold_tune off
noise_level 32
noise_tune on
despeckle_filter EedDl
locate_motion_mode off
text_right %Y-%m-%d %T-%q
target_dir /home/shared/monitor/
snapshot_filename %Y/%m/%d/snapshot/%t/%H_%M_%S
picture_filename %Y/%m/%d/%H/%t/%H_%M_%S-%q

 画像の保存先は、基本的に target_dir が起点となる。そこを起点として、定時スナップショットのパスは snapshot_filename, 動体検知時のパスは picture_filename となる。後々のローテーションなどを考えて、極力日付などの単位でひとまとめになるのが望ましいと思われる。後述するが、上記のような割とゆるめの仕様でも1日 4GB 以上のファイルが生成されるので、ローテーションしやすいディレクトリツリーは必須となる。

 動体検知は、threshold で指定したピクセル数だけ変化があれば動いたと検知される。locate_motion_mode を on にしておくと動体検知したと判定された部分にボックスが描画されるので、それをチェックしつつ最適なピクセル数を出していく。

動体検知時のボックス

動体検知時のボックス

 次にチャンク転送でのストリーミング設定について。これについては、以下の仕様で運用した。

  • 一般公開はしない。
  • とはいえみたいので、BASIC 認証をかける。
  • 上記を満たすために、ルータ上の Apache でリバースプロクシとしてカメラサーバを読みに行く。
  • VIA C3 の制約上、最大 4 fps。

 motion 単体でも BASIC 認証には対応しているが、どうせリバースプロクシがないと外からアクセスできないので、ルータ側の Apache で BASIC 認証をかけた。上記を満たすには、

stream_port 8080
stream_quality 60
stream_motion on
stream_maxrate 4
stream_localhost off
stream_limit 1
stream_auth_method 0

こんな感じになる。あとはルータから proxy_pass すれば外から見られるようになる。

<Location /path/to/streaming/>
        AuthType Basic
        AuthName "Private Webcam"
        AuthUserFile /path/to/htpasswd
        Require valid-user
        ProxyPass http://192.168.1.50:8080/
</Location>

 ほぼリアルタイムストリーミングとなるが、だいたい 1 ~ 2 秒くらい遅延して配信される。

 こんな感じで 3 年近くプライベートな webcam 監視システムを運用しているが、そこから得られた知見はこんな感じ。

  • 生後 1 ヶ月前後の反射でしか笑わない時期に笑顔の撮影が可能になる。
  • 1 つの USB ルートハブにぶら下げられる webcam は 2 台が限度。それ以上は USB 2.0 的に無理。
  • 上記のような保存仕様でも
    • 1 日で 4 ~ 8 GB 前後になる。ファイルのローテートをどうするかを検討する必要がある。
    • 1 時間に数千ファイルが生成されるので、ext4 ではディレクトリを読み出すだけでも負荷がかかる。保存先は ZFS や XFS を検討した方がよい。
  • VIA C3 は遅すぎる。Core2 Duo E7200 に移すと 2 台 × 30fps でも 1 コアを使い切らない。ffmpeg を使ったストリーミング再生・avi 保存も可能となる。
  • 保存先が無線 LAN 経由の NFS マウントの場合、電磁波ノイズなどでアンマウントされると motion が落ちる場合がある。ZABBIX などで motion のプロセス監視は必須。
  • 外の状況をモニタリングしたい場合、最新機種がいいとは限らない。HD Pro Webcam C910だとなんだかざらざらした画像になった。
  • そもそも本当に必要?

 最後は置いておくとして、我が家のベビーベッドカメラは半年ほど経過して息子がベビーベッドにいなくなった時点でお役ご免となったが、その後もペットをリアルタイムで見たいだとか、息子がサーバの電源を切るようになったことからサーバの電源が落ちた原因がハードウェアにあるのか息子にあるのかを切り分けるためのツールとしての監視カメラだとか、その後もいろいろと利用し続けている。実際、C270 の画像として上に上げた 2 枚目の写真は、実際に息子がサーバの電源を落とす直前に撮影されたものになる。3 枚目と比べると同一人物とは思えない成長ぶりで、子供の成長を記録するツールとしても有用だろう。また、我が家では完全にはその目的にはなっていないが、防犯用の監視カメラシステムの構築も可能となる。

 ただし、ペットを監視する場合、たとえば排便(特に大)を監視してアラートメールを出すなど用途はいろいろと考えられるが、この場合はカメラと PC を接続する USB ケーブルをいかに守るかが至上命題となる。我が家の場合はビニールのコルゲートチューブで保護していたが、あっさりとチューブごとケーブルを噛み切られてカメラを破壊されてしまった。

 いずれにしても、ニーズがあるなら自前で何とかするというのはエンジニアとして十分面白い内容だと思う。


Comments

comments

Powered by Facebook Comments