ZoneMinderのよくあるトラブルと解決方法(監視カメラシステム)

スポンサーリンク

ZoneMinderはオープンソースの高機能な監視カメラソフトです。

動画の記録はNVRへ、ZoneMinderは別途動体検知とスマホなどから画像として確認するために使用していますが、色々とトラブルがあったので解決方法をメモしておきます。

ZoneMinderの各種ファイル

ZoneMinder自体の設定ファイル

  • /etc/zm

基本的にはMySQLのデータベース名・ユーザー名・パスワードを指定するだけです。

# ZoneMinder database name
ZM_DB_NAME=zm

# ZoneMinder database user
ZM_DB_USER=zmuser

# ZoneMinder database password
ZM_DB_PASS=**********

共有メモリが大量にある場合は以下も設定しておくと高速化します。

ZM_PATH_SWAP=/dev/shm

初期データベースや本体

  • /usr/share/zoneminder

初期データベースはZoneminderのセットアップ時に使います。

httpdの設定

  • /etc/httpd/conf.d/zoneminder.conf

Zoneminderのインストール時に上記が生成されます。

zmsとnph-zms

  • /usr/libexec/zoneminder/cgi-bin/

キャッシュ

  • /dev/shm

ドキュメント

  • /usr/share/doc/zoneminder

ログ

特にフィルタしていない場合は「/var/log/messages」に出力されます。

rsyslog.conf

/etc/rsyslog.conf へ以下のように記述しておくと /var/log/zoneminder/zm.log へまとめて出力されます。

:syslogtag,startswith,"zmc_" /var/log/zoneminder/zm.log
& stop

:syslogtag,startswith,"zma_" /var/log/zoneminder/zm.log
& stop

:syslogtag,startswith,"zms_" /var/log/zoneminder/zm.log
& stop

:syslogtag,startswith,"zmdc" /var/log/zoneminder/zm.log
& stop

:syslogtag,startswith,"zmwatch" /var/log/zoneminder/zm.log
& stop

:syslogtag,startswith,"zoneminder" /var/log/zoneminder/zm.log
& stop

/var/log/zoneminder へは zm.log以外にも出力されますが、ZoneminderはモニターIDで管理されているので、ログファイルやログ出力時もIDに注目して確認します。

例えば「zmc_m2.log」は「m2」となっていますので、「モニターIDが2」のカメラのログという意味です。

ログ内での識別も同様にモニターIDで行います。

以下はログ例ですが、先頭から見ていくと「zmc_m2」という文字が確認でき、「m2」となっていますので、「モニターIDが2」のカメラと判断できます。

11/08/20 10:44:26.571479 zmc_m2[11918].INF-zmc.cpp/223 [Starting Capture version 1.35.13]

複数のカメラを監視している場合は上記のようにモニターIDを確認しましょう。

ZoneMinderを別サーバに移行

ZoneMinderはカメラごとの設定値やゾーンもすべてMySQLへ保存しています。

このため、別のサーバへ移行する場合は「mysqldump」で吐き出したものを取り込めばすべての設定が復元できます。

イベントをすべて削除した状態で約18MBほどと結構なサイズですが、MySQLの構文が書かれたテキストファイルのため圧縮すると1.7MBほどにまで縮小できます。
ある程度設定が済んだらバックアップしておきましょう。

設定もMySQLデータベースにあるため「drop」すると設定が全部消えますので注意してください

イベントの削除

記録されているイベントを削除するとエクスポートされる.sqlファイルは小さくなりますが、イベント0件で18MB(zip圧縮後1.5MB)ほど、イベント13000件で68MB(zip圧縮後6MB)ほどです。
圧縮すると非常に小さくなるため、面倒な場合はイベントは残したままエクスポートしてもOKです。

イベントの削除はZoneminderのWebコンソールから行えます。

上部メニューの「Filters」へ入ります。

ここでイベントを絞り込みできますが、今回はすべてのイベントを削除したいので「Archive Status」「equal to」「Unarchived Only」を選択します。

その下で一度に表示する件数を指定できますが、一気に削除したい場合は大きめの値を入力します。

チェックボックスの「Delete all matches」にチェックを入れると、上記の条件に一致したイベントを削除するという意味になります。

「EXECUTE」ボタンを押すと削除が始まります。

削除中の件数などは表示してくれないため、処理の進み具合はWebコンソールのイベント件数で確認します。

Webコンソールの最下部にはイベント総数が表示されていますが、削除を実行中に「F5」キーでページを更新すると、イベント総数の数字が減っていくはずです。

長い期間使っていた場合は数十分などかかる場合がありますので、上記で総数を確認しながら待ちましょう。

「イベントの自動削除」をする方法は本ページ下部にあります。

データベースのエクスポート

保存したいディレクトリへ移動し、以下を実行します。

mysqldump -uroot -p zm > dump.sql

バックアップとして保管しておきたい場合は圧縮すると1/10程度にまで縮小できます。

頻繁にエクスポートする場合は以下を「backup.sh」などとして保存して実行すると、日付と時刻を含む「dump-20201121_153006.sql」などのファイル名で手軽にバックアップできます。

mysqldump -uroot -p zm > dump-`date "+%Y%m%d_%H%M%S"`.sql

パスワード入力も省いて「dump-zoneminder-20201121_153006.sql」などに出力する場合。

「backup-zoneminder.sh」

#!/bin/sh

USER_NAME="ユーザー名"
PASSWORD="パスワード"
DB_NAME="zm"

mysqldump -u$USER_NAME -p$PASSWORD $DB_NAME > dump-zoneminder-`date "+%Y%m%d_%H%M%S"`.sql

パスワードも含める場合は「–defaults-extra-file=」でログイン情報を渡したり、expectなどを使った方法もあります。

データベースのインポート

mysqlログイン

mysql -u root -p

受け入れデータベースが無い場合は作成(新規サーバーセットアップなど)

create database zm;

mysqlを抜けます

exit;

データベースのインポート

パスワードは「test」の場合「-ptest」と入力してください。

mysql -uzmuser -pパスワード zm < dump.sql

データベースの更新

古いバージョンからのインポート時はデータベースのアップグレードが必要です。

この場合、ログに以下のように出力されZoneminderが起動しません。

Job for zoneminder.service failed because the control process exited with error code. See "systemctl status zoneminder.service" and "journalctl -xe" for details.

データベースアップグレード用ツール「zmupdate.pl」はパスが通っているので単に実行するだけ更新できます。

以下のメッセージが出たら「Enter」キーで進みます。

Please ensure that ZoneMinder is stopped on your system prior to upgrading the database.
Press enter to continue or ctrl-C to stop :

アップグレード前にデータベースのバックアップを取るか聞かれますので不要な場合は「n」で進みます。

Do you wish to take a backup of your database prior to upgrading?
This may result in a large file in /var/lib/zoneminder/temp if you have a lot of events.
Press 'y' for a backup or 'n' to continu

データベースのアップグレードが必要無い場合は何も起こりませんので、移行後はとりあえず実行しておくと良いと思います。

ZoneMinder起動時にエラー

ZoneMinderアップデート後のエラー

ZoneMinderをアップデートするとデータベースの更新が必要になります。

更新用の「zmupdate.pl」というツールが付属してくるので実行してやるとデータベースが更新されます。

このとき以下のようなエラーが出ており、よく見ると「zmupdate.pl」を実行して更新してくださいと書いてあります。

FAT [Version mismatch, system is version 1.33.12, database is 1.30.4, please run zmupdate.pl to update.]

「zmupdate.pl」はパスが通っているので単に実行するだけです。

以下のメッセージが出たら「Enter」キーで進みます。

Please ensure that ZoneMinder is stopped on your system prior to upgrading the database.
Press enter to continue or ctrl-C to stop :

アップグレード前にデータベースのバックアップを取るか聞かれますので不要な場合は「n」で進みます。

Do you wish to take a backup of your database prior to upgrading?
This may result in a large file in /var/lib/zoneminder/temp if you have a lot of events.
Press 'y' for a backup or 'n' to continue :

バージョンが一気に大きくなった場合は何度かデータベースのアップグレードがあります。

Database successfully upgraded to version 1.33.7.
Upgrading DB to 1.33.8 from 1.30.4

Database successfully upgraded to version 1.33.12.
Database upgrade to version 1.33.12 successful.

データベースのユーザー名やパスワード違いのエラー

ZoneMinder起動時に以下のエラーが出る場合、MySQLに登録したユーザー名&パスワードと、/etc/zm.confで指定したものが異なりますので確認します。

ERROR 1045 (28000): Access denied for user 'zmuser'@'localhost' (using password: YES)
ZoneMinder を起動中: DBI connect('database=zm;host=localhost','zmuser',...) failed: Access denied for user 'zmuser'@'localhost' (using password: YES) at /usr/share/perl5/vendor_perl/ZoneMinder/Config.pm line 102
Can't connect to db at /usr/share/perl5/vendor_perl/ZoneMinder/Config.pm line 129
BEGIN failed--compilation aborted at /usr/share/perl5/vendor_perl/ZoneMinder/Config.pm line 129.
Compilation failed in require at /usr/share/perl5/vendor_perl/ZoneMinder.pm line 33.
BEGIN failed--compilation aborted at /usr/share/perl5/vendor_perl/ZoneMinder.pm line 33.
Compilation failed in require at /usr/bin/zmpkg.pl line 48.
BEGIN failed--compilation aborted at /usr/bin/zmpkg.pl line 48.

カメラのRTSPストリーミングURLが分からない(調査方法)

nmapで調査する

比較的新しいバージョンのnmapコマンドにはよくあるRTSPストリーミングのURLを調査できるコマンドがあります。

Windows用のnmapならコマンドプロンプトからも確認できます。

書式は以下のとおりです。

nmap --script rtsp-url-brute -p [RTSPポート] [IPアドレス]

RTSPのポートが「554」、カメラのIPアドレスが「192.168.251.254」の場合は以下のように実行します。

nmap --script rtsp-url-brute -p 554 192.168.251.254

かなり長いので中間を省略してありますが、実行結果は以下のとおりです。

「discovered:」の直下にあるURLが発見されたRTSPのURLで、それ以降は「401」のレスポンスが返ってきていますね。

今回は「discovered:」のURLが正しいものでしたが、「401」のレスポンスは認証情報が不足している(ユーザー名やパスワード)なので、これにユーザー名やパスワードの引数をつけることでアクセスできる場合があります。
「403」の場合は拒否されているという意味です。

C:\Users\Sakue>nmap --script rtsp-url-brute -p 554 192.168.251.254
Starting Nmap 7.70 ( https://nmap.org ) at 2020-11-10 10:59 ???? (?W?€??)
Nmap scan report for 192.168.251.254
Host is up (0.0019s latency).

PORT STATE SERVICE
554/tcp open rtsp
| rtsp-url-brute:
| discovered:
| rtsp://192.168.251.254/user=admin_password=tlJwpbo6_channel=1_stream=0.sdp?real_stream
| other responses:
| 401:
| rtsp://192.168.251.254/
| rtsp://192.168.251.254/0
| rtsp://192.168.251.254/0/video1
| rtsp://192.168.251.254/1/cif
| rtsp://192.168.251.254/1/stream1

~~ 長いので省略

| rtsp://192.168.251.254/video2.mjpg
| rtsp://192.168.251.254/videoinput_1:0/h264_1/onvif.stm
| rtsp://192.168.251.254/videostream.cgi?rate=0
| rtsp://192.168.251.254/vis
|_ rtsp://192.168.251.254/wfov

Nmap done: 1 IP address (1 host up) scanned in 5.97 seconds

発見されたURLは以下のものですが、よく見ると「&」が「_」に置き換えられています。

あと、「user=」のユーザー名と、「password=」のパスワードも実際のものに修正が必要です。

rtsp://192.168.251.254/user=admin_password=tlJwpbo6_channel=1_stream=0.sdp?real_stream

「_」を「&」へ戻した正しい書式は以下のようになります。

rtsp://192.168.251.254/user=admin&password=tlJwpbo6&channel=1&stream=0.sdp

また、対象がカメラでなくレコーダー(NVR)の場合、複数のカメラが接続されている事が多いと思います。

パラメータの「channel」部分の数字を修正することで、指定したカメラの映像が取得できます。

例えば4chのカメラの場合は「channel=1」から「channel=4」までありますので、URLのリストは以下のようになります。

rtsp://192.168.251.254/user=admin&password=tlJwpbo6&channel=1&stream=0.sdp
rtsp://192.168.251.254/user=admin&password=tlJwpbo6&channel=2&stream=0.sdp
rtsp://192.168.251.254/user=admin&password=tlJwpbo6&channel=3&stream=0.sdp
rtsp://192.168.251.254/user=admin&password=tlJwpbo6&channel=4&stream=0.sdp

もう1点、カメラやレコーダーはストリームを複数持っている場合が多く(設定から変更可)、メインストリームが高解像度、サブストリームが低解像度のストリーミング映像になっています。

以下の例では「stream=0.sdp」がメインストリーム、「stream=1.sdp」がサブストリームです。

メインストリームの例

rtsp://192.168.251.254/user=admin&password=tlJwpbo6&channel=1&stream=0.sdp

サブストリームの例

rtsp://192.168.251.254/user=admin&password=tlJwpbo6&channel=1&stream=1.sdp

高解像度の映像が必要無い場合、低解像度のサブストリーム映像を使うことで負荷を抑えることができます。

お値打ちなカメラやレコーダーだとメインストリームの映像を取得し続けると落ちる事があるので、仕方なくサブストリームを使う場合もあります。

RTSPなどのURLが正しいか確認したい

スナップショットjpgなどの場合はブラウザで確認できますが、RTSPストリームの映像の場合はVLCなどのメディアプレイヤーで確認できます。

RTSPのURLが全く分からない場合は前項にある「nmap」で確認する方法がありますが、実際に映像が取得できるかどうか、どういった解像度やfpsなのかを確認できます。

メディア > ネットワークストリームを開く

URLの入力はRTSPの場合は「rtsp://」で始まるURLを入れます。

末尾のパラメータなどはカメラごとに異なります。

rtsp://admin:password@192.168.254.254/11

BASIC認証がかかっている場合、カメラのIPアドレスの前に認証情報を入力します。

rtsp://[ユーザー名]:[パスワード]@[カメラのIP]/[パラメータ]

例えばユーザー名が「admin」、パスワードが「password」、IPアドレスが「192.168.254.254」、パラメータが「11」の場合は以下のようにします。

rtsp://admin:password@192.168.254.254/11

Zoneminder側で指定するカメラの解像度が不明な場合は以下で確認できます。

VLC上で右クリック > ツール > メディア情報

Zoneminder側での入力例です。

RTSPのURLが以下だったとします。

rtsp://admin:password@192.168.254.254/11

この場合は各項目に以下を入力します。

「Path」は先頭の「/」はつけないのと、認証情報がある場合はHost Nameの先頭につけます。

Protocol

RTSP

Medhod

RTP/RTSP

Host Name

admin:password@192.168.254.254

Path

11

カメラ映像が全く映らない

解像度が異なる

設定変更後はキャプチャデーモンが再起動するので一時的に真っ黒や真っ青の画面になりますので少し待ちます。

新しめのZoneminderでは実際の解像度と異なってもアスペクト比がおかしくなるだけで映像は映る場合がありますが、カメラの接続方法によるものなのか不具合なのか不明ですが、正しい解像度を指定しないと映らないカメラもありました。
一部のカメラでは元の映像のアスペクト比が既におかしい場合もあるので、ここでの設定で正しくなるよう調整するのも良いです。

今どきの監視カメラの場合、ブラウザなどでカメラにログインして設定を行う場合が多いので、まず設定や仕様を確認します。

不明な場合、RTSPの場合はVLCなどのネットワークストリームを開けるメディアプレイヤーで対象URLを開いてプロパティを確認します。

画像の場合はブラウザで開いて同様にプロパティを確認して正しい値を設定します。

エラーもまちまちですが、解像度が異なる場合のエラー例は以下のとおりです。

Failed requesting writeable buffer for reading JPEG image.
Held buffer is undersized for requested buffer

ネットワークカメラで設定とカメラの解像度が異なる場合 /var/log/zoneminder/zm.log に以下の警告が出ていました。

「モニターの設定は720×480だけど、カメラからは1920×1080の映像が送信されてるよ」と言ってるので、モニターの設定で1920×1080にすればOKです。

WAR [zmc_m6] [Monitor dimensions are 720x480 but camera is sending 1920x1080]

カメラの Source > Device Channelが間違っている(ローカルのカメラ)

ローカルのカメラの場合、Device Channelをあわせる必要があります。

私の場合はこのトラブル時は時刻などが表示されるものの、「灰色一色」の映像になっていました。

このときに出ていたエラーは以下のとおりです。

ERR 'zmc -d /dev/video3' exited abnormally, exit status 255    zmdc.pl
FAT Failed to set camera source 1: Invalid argument     zm_local_camera.cpp   888

モニターがいつの間にか停止している

RTSPの場合はFFmpegやLibvlcを試してみる

ZoneminderのRTSPの設定以外にffmpegやlibvlcがインストールされていれば、そちらでRTSPストリームを取得させる事もできます。

カメラによってはZoneminderのRTSP設定だと頻繁に落ちたり不安定になることがありますが、そういった場合はffmpegを試すと安定することがあります。

ただし、私の環境では負荷がやや高めで、それまでロードアレべレージが0.7前後だったものが、2つのカメラをffmpegにしたところ1.3前後まで上昇しました。
ですので、調子が悪い場合のみffmpegなどを試すと良いと思います。

あと、私の環境だけかもしれませんが、ffmpegにするとキャプチャデーモン(zmc)の再起動にやや時間がかかり、映像が映るのが少し遅れるのと、設定直後にプレビューを見るとコマ落ち(カメラが出力する時刻の秒で確認)するほか、アラーム映像もコマ落ちが発生しますが、しばらくすると安定してコマ落ちしなくなります。

以下にffmpegの場合の設定例を記載します。

Source Path

RTSPの場合は「rtsp://」から始まるURLを記述します。

URLが不明な場合はこのページ内のnmapなどで調査する方法をご確認ください。

BASIC認証のような認証がかかっている場合はIPアドレスの前に認証情報を記載します。

rtsp://[カメラユーザー名]:[カメラパスワード]@[IPアドレス]:[RTSPポート]/channel=4&stream=0.sdp

そうでない場合はURLのパラメータ部分に認証情報を記述します。

rtsp://[IPアドレス]:[RTSPポート]/user=[カメラユーザー名]&password=[カメラパスワード]&channel=4&stream=0.sdp

Method

TCP

Options

rtsp_transport=tcp, buffer_size=10000000

ffmpegに渡すオプション

ffmpegにオプションを渡す場合は以下のように「オプション=値」のように記述します。

buffer_size=10000000

複数入力する場合はカンマで区切ります。

rtsp_transport=tcp, buffer_size=10000000

オプションが認識出来ない場合、ログに以下のようにログレベル「WAR」で「Could not parse ffmpeg input options~」が残ります。

以下の場合は「an」というオプションを渡してみましたが認識してくれず、警告が出た時のものです。

zmc_m8[18580]: WAR [zmc_m8] [Could not parse ffmpeg input options 'rtsp_transport=tcp, buffer_size=10000000, an']

旧バージョンではRTSPストリームをTCPで取得する場合「rtsp_transport=tcp」のオプションが必要でしたが、比較的新しいバージョンではカメラの設定内の「Source」設定から「Method」を「TCP」にすると「rtsp_transport=tcp」がffmpegに渡されるようになりました。

「rtsp_transport=tcp」オプションを残しておいても不具合はありません。

各種デーモンのステータス確認

Zoneminderには「zmdc.pl」というデーモンのコントロールツールが付属しています。

zmdc.pl –help

No daemon given
Usage:
    zmdc.pl {command} [daemon [options]]
Options:
    {command} - One of 'startup|shutdown|status|check|logrot' or
    'start|stop|restart|reload|version'. [daemon [options]] - Daemon name
    and options, required for second group of commands

各種デーモンが動作しているかどうかは以下のコマンドで確認できます。

zmdc.pl status

「zmdc.pl status」の実行結果例

'zmc -m 3' running since 20/11/11 00:00:54, pid = 10105, valid
'zma -m 8' running since 20/11/10 18:01:46, pid = 2922, valid
'zmc -m 6' running since 20/11/09 12:43:57, pid = 13775, valid
'zmc -m 4' running since 20/11/10 16:07:29, pid = 21426, valid
'zma -m 2' running since 20/11/10 08:29:12, pid = 15842, valid
'zmc -m 9' running since 20/11/09 12:43:58, pid = 13794, valid
'zmc -m 7' running since 20/11/10 00:01:10, pid = 14956, valid
'zmfilter.pl --filter_id=2 --daemon' running since 20/11/09 12:43:58, pid = 13809, valid
'zmc -m 8' running since 20/11/10 18:01:45, pid = 2892, valid
'zma -m 3' running since 20/11/11 00:00:55, pid = 10195, valid
'zmstats.pl' running since 20/11/09 12:43:59, pid = 13836, valid
'zmtelemetry.pl' running since 20/11/09 12:43:59, pid = 13832, valid
'zma -m 9' running since 20/11/09 12:43:58, pid = 13799, valid
'zma -m 7' running since 20/11/10 00:01:11, pid = 14961, valid
'zmc -m 2' running since 20/11/09 15:18:31, pid = 23334, valid
'zmwatch.pl' running since 20/11/09 12:43:59, pid = 13822, valid
'zma -m 4' running since 20/11/10 16:11:51, pid = 30834, valid
'zmc -m 1' running since 20/11/10 15:54:27, pid = 25358, valid
'zmfilter.pl --filter_id=3 --daemon' running since 20/11/09 12:43:58, pid = 13816, valid
'zma -m 1' running since 20/11/10 15:59:52, pid = 4551, valid
'zma -m 6' running since 20/11/09 12:43:57, pid = 13778, valid
'zmfilter.pl --filter_id=1 --daemon' running since 20/11/09 12:43:58, pid = 13805, valid

zmcやzmaという文字がありますが以下のような意味です。

  • zmc(Capture|キャプチャー用のデーモン)
  • zma(Analys|解析用のデーモン)

ただし、上記はデーモンが動作しているかどうかの確認で、実際にキャプチャされているかどうかの判断はできません。

モニターID8のキャプチャーデーモンの状態確認

zmdc.pl check zmc -m 8

実行結果例

running

キャプチャデーモンの再起動(コマンドライン)

それまで正常だった映像が取得できなくなったときは、対象モニターのキャプチャデーモン(zmc)を再起動すると復帰します。

Webコンソールから映像が映らなくなったモニターの設定を保存すると復帰するのは、キャプチャーデーモンの再起動が行われているからですね。

ログを監視して特定のエラーが出ていたら再起動でも良いのですが、バージョンアップにより出力形式が変わったりするのと、1台のカメラだけで不定期に発生するため、諦めてcronで定期的に再起動させています。

キャプチャーデーモンを再起動するには以下のように実行します。

zmdc.pl restart zmc -m [モニターID]

モニターIDが8の場合は以下です。

zmdc.pl restart zmc -m 8

各モニター(カメラ映像)にはわかりやすい名称をつけていると思いますが、Zoneminder内部ではモニターIDで管理されています。

モニターIDはWebコンソール上の各所で確認できますが、以下の例だとモニターIDが「3」のカメラと判断できます。

各モニターの設定やイベント一覧でも、URLにモニターIDが含まれているので、それで判断してもOKです。

シェルスクリプトでの再起動は以下の記事にあります。

Zoneminderのモニターステータスの確認と再起動(コマンドライン&シェルスクリプト)
ZoneminderのWebコンソールで映像が映っていて、ステータスを示す丸のアイコンが緑であれば正常と判断できます。 ここではコマンドでのモニターの稼働状況確認と、モニターの再起動コマンドについてメモしていきます。 Zoneminderの...

キャプチャデーモンの再起動(Webコンソール)

Webコンソール上からはZoneminderの再起動は行なえますが、個々のキャプチャーデーモンの再起動は現在のところ行えないようです。

以下の操作などによってキャプチャーデーモンが再起動するので代替として利用できます。

モニターの設定をSaveする(個々のカメラの設定)

モニターの設定を保存すると、反映させるためにキャプチャーデーモンが再起動されます。

このため、キャプチャーデーモンを再起動したい場合はモニター設定を保存すればOKです。

キャプチャーデーモンの再起動は数秒かかりますので、Webコンソールで表示されない場合はキーボードの「F5」を何度か押して更新してやると映像が表示されます。

Zoneminderを再起動する

Zoneminder自体の再起動でも各種デーモンが一緒に再起動されます。

Webコンソールから再起動するには右上にある「RUNNING」をクリックします。

「Restart」にし「APPLY」をクリックするとZoneminderが再起動します。

映像に横スジが入る

カメラの設定の「Capture Palette」が「auto」の場合に出ました。

トラブルが出たカメラは「YUYV」で改善しましたが、不明な場合は別の設定も試してみてください。

zmNinjaのトラブル(ZoneMinderクライアント)

APIが動作しているか確認

ブラウザで以下のようなURLにアクセスしてみます。

https://ホスト名/zm/api/host/getVersion.json

正しく設定されている場合、以下のようにバージョンが返ってくるはずです。

APCuに関わるトラブル

PHP7.xでZoneMinderのAPIを使う場合、php-pecl-apcu-bcが必要です。
7.xでは完全な下位互換をサポートしていないので別途インストールする必要があります。

remiなどのレポジトリを有効化し、以下のようにインストールします。

yum install --enablerepo=remi-php71 php-pecl-apcu-bc

上記トラブル時に「/var/log/httpd/ssl_error_log」に出ていたエラーです。

[Fri Apr 27 07:19:31 2018] [error] [client 192.168.2.2] PHP Fatal error:  Uncaught Error: Call to undefined function apc_fetch() in /usr/share/zoneminder/www/api/lib/Cake/Cache/Engine/ApcEngine.php:78\nStack trace:\n#0 /usr/share/zoneminder/www/api/lib/Cake/Cache/Cache.php(363): ApcEngine->read('myapp_cake_core...')\n#1 /usr/share/zoneminder/www/api/lib/Cake/I18n/I18n.php(235): Cache::read('cake_dev_ja', '_cake_core_')\n#2 /usr/share/zoneminder/www/api/lib/Cake/basics.php(636): I18n::translate('Cache engine "%...', NULL, 'cake_dev')\n#3 /usr/share/zoneminder/www/api/lib/Cake/Cache/Cache.php(184): __d('cake_dev', 'Cache engine "%...', '_cake_core_')\n#4 /usr/share/zoneminder/www/api/lib/Cake/Cache/Cache.php(151): Cache::_buildEngine('_cake_core_')\n#5 /usr/share/zoneminder/www/api/app/Config/core.php(375): Cache::config('_cake_core_', Array)\n#6 /usr/share/zoneminder/www/api/lib/Cake/Core/Configure.php(72): include('/usr/share/zone...')\n#7 /usr/share/zoneminder/www/api/lib/Cake/bootstrap.php(434): Configure::bootstrap(true)\n#8 /usr/share/zoneminder/www/api/app/webroot/index.php(90): include in /usr/share/zoneminder/www/api/lib/Cake/Cache/Engine/ApcEngine.php on line 78

zmNinjaで”Login validated but API failed”

APIディレクトリの所有者をapacheにするとうまくいきました。

apacheの場合

chown -R apache:apache /usr/share/zoneminder/www/api/

www-dataの場合

chown -R www-data:www-data /usr/share/zoneminder/www/api/

APIの各ページで「An Internal Error Has Occurred」

セットアップ中の場合は、zoneminderのデータベースが存在しているか、ユーザー名やパスワードが正しいか確認します。

Zoneminderのアップデート後は「zmupdate.pl」を実行してデータベースを更新します。

元々取得できていた各.jsonでこのエラーが出ている場合はOSを再起動してみます。

私の場合はZoneminder v1.35.14へアップデートした後に発生し、「zm/api/host/getVersion.json」以外のAPIが全て「An Internal Error Has Occurred」に、zmNinjaでは「Please check your credentials」のエラーが出ていましたが、再起動で治りました。

普段は全く問題なかったので、おそらくZoneminderのアップデートが関係していると思いますが原因不明です。

zmNinjaで動画再生できない(画像は取得できる)

いくつか原因がありますが、私が遭遇したのは以下のものです。

ログの確認

まず以下のログを確認してみます。

/var/log/zoneminder/web_php.log

今回は下のようなログがずらずらと表示されてました。

Socket /var/lib/zoneminder/sock/zms-126285s.sock does not exist.

/var/lib/zoneminder/sock/ ディレクトリの確認

zmNinjaから再生してみてxxx.sockが生成されるのを確認します。

/var/lib/zoneminder/sock/

xxx.sockのパスが異なる場合は以下の設定ファイルを修正します。

/etc/zm/conf.d/01-system-paths.conf

以下の行です。

ZM_PATH_SOCKS=/var/lib/zoneminder/sock

zoneminder.confの確認

以下の設定ファイルでapacheに対するzoneminderの設定を行っています。

/etc/httpd/conf.d/zoneminder.conf

今回のトラブルの原因だったのは以下の行でした。

ScriptAlias /cgi-bin/zm "/usr/libexec/zoneminder/cgi-bin"

スクリプトのエイリアスを指定するものですが、zoneminder.confの設定と、zmNinjaの設定を一致させる必要があります。

ScriptAlias /zm/cgi-bin "/usr/libexec/zoneminder/cgi-bin"

修正したら以下でapacheを再起動して再生できるか確認します。

systemctl restart httpd

サムネイル画像が検知の瞬間でない(イベント一覧などの代表画像)

サムネイルに使われるスナップショットは「スコアの一番高い瞬間」が使われます。

ZoneminderのWebコンソール(トップページ)には、Houur、Dayなどの列に記録されているイベント数が表示されていますので、対象のカメラのイベント数をクリックしてイベントビューへ進みます。

最上部を見ると「Alarm Frames」の列が確認できますので、その数字をクリックするとイベント内のフレーム一覧画面へ移動します。

既に再生画面に移動している場合は、上部の「FRAMES」をクリックするとイベント内のフレーム一覧画面へ移動します。

アラームのフレームは色付けされており、何らかの動きを検知した事がわかります。

ここで「Score」の列に注目し、一番Scoreが高い画像を確認するとサムネイル画像と同じであることが確認できると思います。

ゾーンをいくつも設定すると思いますが、このようにスコアによって代表のサムネイルが決定するため、カメラ映像内の特定の箇所の変化をサムネイル画像(代表画像)にしたい場合、そのゾーンの感度を上げるなどしてスコアが高くなるようにします。

ただし、感度を上げすぎると誤検知の原因になりますので、ゾーンを小分けして個々に設定を調整したり、プリセットの「Fast, ~」の「ピクセル比較」と、「Best, ~」の「輪郭による検知(Blobs)」を切り替えて最適な検知方法を探したりと試行錯誤が必要です。

サムネイルが小さすぎる・大きすぎる

Options > Web

以下のWidth(幅)かHeight(高さ)に値を設定すると、収まるようなサイズになります。
片方だけ指定すればよく、未指定の場合は「0」にしておきます。

例えば「WEB_LIST_THUMB_WIDTH」に「300」を指定した場合、カメラの解像度が「1920 x 1080」では「288 x 162」のサムネイルになりました。

WEB_LIST_THUMB_WIDTH

WEB_LIST_THUMB_HEIGHT

イベント一覧が途中で途切れる

負荷の高いサーバで1ページあたりの表示件数を多くするとPHPのタイムアウトに達してしまい、ページが途切れる事があります。

この場合は1ページあたりの表示件数を下げるか、PHPのタイムアウトを長くします。

httpdのログを確認すると以下のようなログが残っていればPHPのタイムアウトが原因です。

[Fri Apr 27 11:54:37 2018] [error] [client 192.168.2.2] PHP Fatal error:  Maximum execution time of 30 seconds exceeded in /usr/share/zoneminder/www/includes/Event.php on line 287

/etc/php.iniの編集

デフォルトでは以下が30などになっており、30秒以上実行するとタイムアウトしてしまいます。

環境によりますが90(秒)くらいにして様子をみてみます。

max_execution_time = 90

イベントの並び順がおかしい

Zoneminderのイベントページのソート順序は以下から設定できます。

Options > Web

  • WEB_EVENT_SORT_FIELD(何でソートするか)
  • WEB_EVENT_SORT_ORDER(昇順または降順)
  • WEB_EVENTS_PER_PAGE(1ページあたりの表示件数)

しかし、中途半端な時刻のものが最新として表示される場合があります(バージョンによって正常になったりまたおかしくなったり)

ページの表示設定をCookieに保存している(デフォルト拡大率なども)

イベントページの順序や件数などはCookieに保存されて次回も同じ値が使われますが、Zoneminderの設定よりCookieの値が優先されます。

Firefoxの開発者ツールなどでZoneminderのCookieを確認すると以下のような項目が確認できると思いますが、イベントページで並び替えや件数、ズーム倍率の変更をすると作成され、この値が優先されます。

  • zmEventsTable.bs.table.pageList(1ページあたりの表示件数)
  • zmEventsTable.bs.table.sortName(並び替え対象の項目)
  • zmEventsTable.bs.table.sortOrder(並び順)
  • zmEventScale3(ズーム倍率・150で1.5倍)

試しに上記Cookieを削除してF5などでページを更新してみると戻るのが確認できます。

表示がおかしいと思ったらイベントページで設定を変更するか、ログアウトしますがCookieを削除してみると良いです。

Firefoxの開発者ツールの場合は「ストレージ」タブで、表示中のサイトのCookieが確認できます。

右クリックから個別にCookieを削除でき、削除後にF5でページ更新すると削除した設定がOptionsで指定した設定に戻るのが確認できます。

1ページあたりの取得数の問題

こちらはバージョンアップなどのタイミングで起こる事があったりしますが、「WEB_EVENTS_PER_PAGE」の分のイベントをデータベースから持ってくるときに、「WEB_EVENT_SORT_ORDER」の値が反映されずに取得され、その後に並び替えをしているためにこういった状態になっているのではないかと思います。

イベントビューの上部にある「Start Time」などをクリックすれば再度データベースから取ってくるのか正常に並び替えが行われます。

とりあえずの回避策として、「WEB_EVENTS_PER_PAGE」を「0」にします。

こうすると、イベントビューの1ページあたり表示件数は無制限になり、全てのイベントを持ってきてから並び替えが行われます。

ただし件数があまりに多いとPHPがタイムアウトするかもしれません。

イベントが全く記録されない

ZoneのTypeが広範囲に「Inactive」になっている

これは自分のミスですが、検知エリアを指定する「Zone」の設定で、「Type」というのがあり、そのゾーンのタイプを指定します。

「Active」がアラームが発生しイベントを記録するタイプですが、ゾーンは残したまま無効化しようと「Inactive」にしたところ、一切記録されなくなりました。

この「Inactive」は無効という意味だと思ったのですが、そうではなく指定したエリアを非活性(アラームが発生しない)にするための設定でした。

ゾーンを残したまま無効化したい場合は、感度を最低まで下げて事実上無効化するのが良さそうです。

感度が低すぎる場合

Zoneで検知するエリアを複数指定できますが、デフォルトのUnitsは「Percent」となっており、その他の設定もデフォルト値を使うと、Thresholdのデフォルトは「20」なので、指定範囲で20%以上の変化がないとアラームが発生しません。

Zoneは何個でも設定できるので、広範囲を一気に指定するより、範囲を区分けして細かく設定してやると、相対的に個々の感度も高くなり、不要な動き(草などのゆらぎ)を避けながらZoneの指定ができます。

イベントが記録できるか確認する(設定に問題がないか)

アラームは自分で発生させることができますので、手動で発生させて正しくイベントが保存されるかを確認します。

例えば保存ディレクトリの指定ミスやパーミッションが正しいかなどの確認ができます。

Webコンソールの左にはカメラの映像が並んでいますが、クリックするとカメラのプレビューページが表示されます。

プレビュー上部に「!」アイコンの「Force Alarm」ボタンがあります。

これをクリックするとアラームを発生させることができ、再びクリックするとアラームが停止しますので、クリックして数秒してから再度クリックして停止させてください。

Webコンソールに戻り、イベント一覧ページへ移動、先程発生させたアラームのイベントが記録されていたら、Zoneminderの設定のうち、保存に関しては問題が無いと判断できます。

解析画像が表示されない(Analysis images)

デフォルトでは解析画像を残しませんが、残す設定にするとアラーム発生時のブレンドした画像(解析画像)も同時に保存され、何に反応したのかを把握することができます。

解析画像も残すと負荷も多少上がるため、普段は無効にし、動体検知が希望した動きでない場合のみ確認するのが良いです。

解析画像を残す設定

比較的新しいバージョンの場合

最近のバージョンではカメラごとに保存するかどうかを指定できます。

カメラの設定 > Storage > Save JPEGs

以下の4つから選択できます。

Disabled

画像を一切保存しません。

Frames only

通常の画像のみを残します(デフォルト)

Analysis images only(if available)

解析画像のみを残します。

Frames + Analysis images(if available)

通常の画像と解析画像の両方を残します。

旧バージョンの場合

旧バージョンではカメラごとの設定でなく「Option」に設定があります。

「CREATE_ANALYSIS_IMAGES」のチェックを「ON」にすると解析画像を残します。

Options > Config > CREATE_ANALYSIS_IMAGES

解析画像を確認する

旧バージョンの場合は「CREATE_ANALYSIS_IMAGES」のチェックを「ON」にすると、イベントの再生時に解析画像が再生されます。

新しいバージョンの場合はイベントビューから確認します。

ZoneminderのWebコンソール(トップページ)には、Houur、Day、Week、Monthなどの列に記録されているイベント数が表示されていますので、対象のカメラのイベント数をクリックしてイベントビューへ進みます。

ここでも同様に最上部を見ると「Alarm Frames」の列が確認できますので、その数字をクリックするとイベント内のフレーム一覧画面へ移動します。

既に再生画面に移動している場合は、上部の「FRAMES」をクリックするとイベント内のフレーム一覧画面へ移動します。

以下が実際の解析画像の一部を切り取ったものです。

人物の形状に中央が透けたようになっていますが、前フレームとブレンドした結果の画像(解析画像)で、これを元に判定が行われます。

解析画像はクリックすると通常画像と切り替わりますので、何度か切り替えながら見比べると、差を確認できます。

「輪郭の検出」は次項にあります。

解析画像で輪郭線が表示されない(Analysis images – Blobs)

解析には「画像のピクセル比較」と、「輪郭の検出と比較」の2つがあり、どちらで動体検知をするかはZoneの設定で、個々のZoneごとに設定できます。

Zoneの「Alarm Check Method」が「Blobs」の場合は輪郭による動き検出になり、解析画像を保存する設定の場合は検出された輪郭が確認できます。

Blobsでの検出はやや負荷が高めですが、ピクセル比較よりうまく検出してくれる場合が多いです。

以下は「Blobs」に設定したゾーンでアラームが発生したものですが、床のタイル形状の輪郭が検出されており、それが変化(人が通った)ためにアラームが発生したというのがわかります。

「Blobs」もプリセットが3つ用意されており、「Best, ~」で始まるプリセットがBlobsのものです。

最初はパラメータをどうしたら良いかわからないと思いますので、「Best,~」のプリセットから選択しましょう。

  • Best, low sensitivity(低感度)
  • Best, medium sensitivity(中感度)
  • Best, high sensitivity(高感度)

輪郭検出された際の線の色ですが、同じくゾーンの設定で行えます。

RGB(赤・緑・青)で指定し、初期値は「255/0/0」なので赤です。

上記にある例の緑の輪郭線の場合「0/255/0」という感じで指定しています。

Reference Image Blend %が数値で指定できない

Optionの「FAST_IMAGE_BLENDS」が有効になっていると画像のブレンドが高速化しますが、感度調整の「Reference Image Blend」は、50%、25%、12.5%、6.25%、3.25%、1.5%からの選択式になります。

速度を犠牲にしても微調整したい場合は、Optionの「FAST_IMAGE_BLENDS」のチェックを外してSaveすると、「Reference Image Blend」が選択式でなく数値の入力で設定できるようになります。

ノイズやゆらぎが検知されてしまう(不要な動きが検知される)

検知されたゾーンの確認

イベント一覧ページを開き、「Cause」の列を確認します。

ここにはイベント記録の要因になったゾーン名が表示されていますので、特定のゾーンだけで無関係な動き(草などのゆらぎなど)が検知されている場合はゾーン設定で「+」ボタンを押して多角形の辺を増やしてうまく避けるようにしたり、そのゾーンの感度を下げたりしてみます。

ZoneのMethodを「Blobs」にしてみる

検知方法は画像のピクセル比較と、輪郭線が変化したことを検知するBlobsがあります。

カメラの映像を見て、輪郭線(例えばドアの輪郭や床のタイル形状など)がはっきりしている場合はBlobsにするとノイズの影響を受けにくくなります。

Zoneのプリセットだと「Best,~」のものを選択すると「Method」が「Blobs」になると思いますが、これで輪郭で判断してくれます。

監視箇所によって向き不向きがありますので、個々のゾーンごとに調整していく必要がありますが、ある程度の輪郭がある監視箇所ではBlobsの方が誤検知が少なめです。

ゾーンを小分けして個々に感度調整

一部でのみゆらぎ(木々のゆらぎや光の差し込み)が発生している場合、カメラ単位で指定する感度設定はデフォルトにしておき、ゾーンを小分けして個々に感度を調整するのが最も良いです。

調整の際は解析画像(検知したところを赤線で表示)を生成しておくと、どの変化に反応したのかわかりやすいので、それを参考に調整していきます。

Alarm Frame Count

カメラ > Buffers > Alarm Frame Count

連続したアラームのフレームが指定数以上出た場合にイベントとして記録するもので、2の場合は2フレーム連続でアラームがあった場合にイベントとして記録します。

大きくすると感度が鈍くなりますが、必要なアラームが無視される事があるため、上げても2~3程度にしておき、次項の「Reference Image Blend %ge」で感度を調整するのが良いです。

Reference Image Blend %ge

動きを検知する解析画像に影響するもので、「No Blending」だとわずかなノイズでもアラームが発生し、50%(alarm lasts a moment)になると非常ににぶい感度になります。

屋外のカメラで太陽の光などによる影響が大きい場合はこれを調整してみます。

屋内のカメラでも日が差し込む場所はある程度感度を落とすか、ゾーンを区分けして細かく感度を調整する必要があります。

ノイズやゆらぎで無関係なアラームが発生する場合は一段回ずつ大きくして(感度をにぶくして)様子を見ます。

Optionの「FAST_IMAGE_BLENDS」はデフォルトで有効になっていますが、画像のブレンドが高速化する代わりに、感度調整の「Reference Image Blend」は、50%、25%、12.5%、6.25%、3.25%、1.5%からの選択式です。

速度を犠牲にしても微調整したい場合は、Optionの「FAST_IMAGE_BLENDS」のチェックを外してSaveすると、「Reference Image Blend」が選択式でなく数値の入力で設定できるようになります。

Alarm Reference Image Blend %ge

これはアラーム発生後の持続に影響します。

余計なアラームが発生して無駄にイベントが長くなってしまう場合、値を大きくすると多少のアラームでもイベントが終了します。

イベントに記録された映像が乱れている(壊れた画像・動画)

UDPでの送受信(ffmpegなど)

「TCP」の通信はお互いに確認しあってデータを送受信しますが、「UDP」は垂れ流しです。

一方的に送る・受けるができるのでUDPは効率は良いですがパケットロスする事が結構あり、映像を見てる程度なら気にならないものの静止画にするとノイズが気になることがあり、酷いと壊れた画像のようになります。

この場合はカメラの設定内の「Source」設定かr「Method」を「TCP」にします。

ffmpegなどで設定出来る項目のため、「Source Type」によっては選択できません。

カメラの能力不足によるもの(フレームレートなどを下げて対処)

そこそこ動いてくれればOKという場所には安価なネットワークカメラを使っていますが、カメラのスペックにある最大解像度・最大フレームレートで動作させるとストリーミング映像が乱れるカメラがいくつかありました。

この場合はZoneminderでなく、ネットワークカメラ自体の設定から「FPS」を下げてみる(30 > 25など)、VBRでなくCBRにしてみる、ビットレートを下げてみる等で改善することがあります。
これでも駄目なら解像度を下げると改善することがあるので、とりあえずカメラの設定はそのままにしておき、低解像度のサブストリーム映像のURLをZoneminderに設定して様子を見るのも良いです。

以下が実際に出たもので、2人映っているように見えますが同じ人物が上から下へ歩いているだけです。

以下も同様のもので、黄色の車にぶつかりそうですが、実際には残像が残ってるだけで通り過ぎたあとの映像です。

ゴーストみたいになっていますが、ghostingやsmearingとか呼ばれる現象みたいです。

以下がゴーストが出ていた時の設定です。

FPSが「30」、VBR(可変ビットレート)、クオリティは「Better」です。

以下のようにしたところ改善しました。

FPSを「25」、CBR(固定ビットレート)、固定ビットレートではビットレートを指定するので「5213kb/s」を選択しました。

VBR(可変ビットレート)からCBR(固定ビットレート)にしていますが、VBRだとゴーストが出る時と出ない時がありました。
これはVBRだと動きが激しい箇所でビットレートが増加するためで、CBRだとファイルサイズは増加しますがビットレートは一定なので、トラブルがあった場合はとりあえずCBRにしたうえでビットレートを調整して様子を見るのが良さそうです。

映像をH264パススルーで保存する(画像と併用)

デフォルトでは画像として残しますが、動画も同時に残してプレビューでは動画を参照することもできます。

パススルーではストリーミング映像がそのまま保存されるため、ストリーミング映像の時点で乱れているのか、スナップショット後の画像のみが乱れているのかなど、問題の切り分けにも役立ちます。

カメラの設定 > Storage > Video Writer

「Video Writer」のプルダウンメニューをクリックし「H264 Camera Passthrough」を選択して「SAVE」します。

これを有効にすると静止画のjpgは同じように保存されますが、記録されたイベントを表示するとパラパラ漫画みたいなコマ送り映像だったものが、滑らかな動画再生になっていると思います。

保存される動画は画像と同じ以下のディレクトリ下です。

/var/lib/zoneminder/events

FTPクライアントなどで上記ディレクトリを見ると、以下のように拡張子「.mp4」の動画が一緒に保存されているのが確認できますので、サーバー上で何かしたい場合はこれを使います。

ZoneminderのWebコンソールからは、イベント再生画面の上部にある「DOWNLOAD MP4」のボタンをクリックすることでmp4動画が保存できます。

ffmpegでRTSPをjpgに保存する

この方法で安定した事がありましたが、新しいバージョンだとZoneminderのカメラ設定で「RTP/RTSP」が安定するようになりましたので、そちらの方がおすすめです。

ZoneminderはRTSPプロトコルにも対応しているので、スナップショット画像が取れなくてもRTSPで監視できますが、カメラによっては負荷が高くなって落ちるものがあります。

こういった場合はffmpegを使い、RTSPの映像をjpgへ保存する処理をcronへ登録し、落ちない程度の頻度で取得すれば良いです。

ただし、単に保存してそのファイルを参照させているだけだと、ダウンロード中にZoneminderが取得してしまい、壊れた画像がイベント一覧に並んでしまいます。

完全には防げませんが、ダウンロードは一時ファイルに保存し、mvでリネームしてやれば、壊れた画像が並ぶというのはある程度防ぐことができます。

例えば以下のように保存していると、ダウンロード中にZoneMinderに取得されてしまう頻度が高いです。

# スナップショット
local SNAPSHOTJPG1="/var/www/html/web/SnapShot/cam1/snapshot.jpg"

# 取得
ffmpeg -rtsp_transport tcp -loglevel fatal -stimeout 8000000 -y -i "rtsp://192.168.2.200:554/stream2" -f image2 -s 720:480 $SNAPSHOTJPG1

以下のようにすれば、mvコマンドは一瞬で終わるので壊れる可能性が低くなります。

# スナップショット
local SNAPSHOTJPG1="/var/www/html/web/SnapShot/cam1/snapshot.jpg"

# 一時ファイル
local SNAPSHOTTMP1="/var/www/html/web/SnapShot/cam1/tmp.jpg"

# 取得
ffmpeg -rtsp_transport tcp -loglevel fatal -stimeout 8000000 -y -i "rtsp://192.168.2.200:554/stream2" -f image2 -s 720:480 $SNAPSHOTTMP1

# 更新
mv -f $SNAPSHOTTMP1 $SNAPSHOTJPG1

今回は上記で問題なく動きましたが、排他ロックを入れるともっと確実になるかもしれません。

映像の一部が黒塗りになっている(残る)

ZoneのタイプでPrivacy(プライバシー)というのがあり、指定したゾーンを黒塗りにできます。

解除しても黒塗りが残ることがありますが、この場合はZoneMinderを再起動するか、カメラの設定を保存してカメラが再起動すると解除されました。

Webコンソールの表示が崩れる(ZoneMinder管理画面)

skinなどを保存しているディレクトリ指定がない

Zoneminderはセットアップ時に自動で諸々の設定をしてくれますが、これがうまく行かない事があり、Webコンソール画面の表示が崩れていたので、Firefoxの開発者ツールで確認したところ、「404」のエラーが大量に出ていました。

httpd用の.confが付属してきますので、これを指定してやると改善します。

以下の「zoneminder.conf」は「zoneminder.conf.bak」とリネームして読み込まないようにしておきます。

/etc/httpd/conf.d/zoneminder.conf

/etc/httpd/conf/httpd.confの末尾あたりに以下を追加します。

# Zoneminderの設定ファイルを読み込む
Include /etc/zm/www/zoneminder.httpd.conf

httpdを再起動して正常に素材が読み込まれたか確認します。

SSL環境でhttpsでアクセスしていない

SSL必須の環境でhttpでアクセスすると、以下のように「SSL connection required」と警告され、各種ファイルが読み込めないので表示崩れが起こります。

[Tue Jul 30 18:59:07.875010 2019] [ssl:error] [pid 15131] [client 192.168.2.2:3916] AH02219: access to /usr/share/zoneminder/www/skins/classic/js/moment.min.js failed, reason: SSL connection required, referer: http://192.168.2.160/zm/skins/classic/js/moment.min.js

上記はhttpsのURLにアクセスすれば解決します。

ScriptAliasが効いていない

Firefoxの開発者ツールで見るとnph-zmsが「404」になっていました。

httpdのAlias行を確認したところ、短いパスを先に書いてしまっていました。

Aliasは先に書いた方がマッチするとそれ以降は見てくれないので、Aliasが反映されずnph-zmsが見えないという状態になっていました。

Alias /hoge "/var/www/hoge/"
Alias /hoge/piyo "/var/www/piyo/"

以下のように長いパスを先に記述してやればOKです。

Alias /hoge/piyo "/var/www/piyo/"
Alias /hoge "/var/www/hoge/"

プレビューのサムネイルが表示されない(404)

Firefoxの開発者ツールなどの「ネットワーク」タブで、「nph-zms」が「404」のエラーになってないか確認します。

「nph-zms」のパスは以下のファイルでも指定が必要で、これが間違っているとモニターのプレビュー画像が表示されません。

/etc/zm/conf.d/01-system-paths.conf

以下の箇所ですが、httpdの設定と合わせます。

# ZoneMinder url path to the zms streaming server
ZM_PATH_ZMS=/cgi-bin-zm/nph-zms

私の場合は以下のように指定が必要でした。

# ZoneMinder url path to the zms streaming server
ZM_PATH_ZMS=/zm/cgi-bin/nph-zms

httpdの zoneminder.conf で以下のようにスクリプトエイリアスを指定していますが、この「cgi-bin」ディレクトリ下に「nph-zms」があるので、これに合わせて指定する感じです。

ScriptAlias /zm/cgi-bin "/usr/libexec/zoneminder/cgi-bin"

上記の場合は /zm/cgi-bin なので 01-system-paths.conf で指定するパスは /zm/cgi-bin/nph-zms という感じです。

スナップショットを取得したい(Zoneminderから)

Zoneminderから最新のスナップショットを取得

以下のようなURLで取得できます。

環境によって「cgi-bin/zm」か「zm/cgi-bin」かは異なるのと、Zoneminderのパスの「zm」部分も異なる場合があるので環境によって合わせてください。

以下の項目は実際のパラメータに置き換えてください。

  • [ホスト名]
  • [モニターID]
  • [ユーザー名]
  • [パスワード]
https://[ホスト名]/cgi-bin/zm/nph-zms?mode=single&monitor=[モニターID]&scale=100&maxfps=1&buffer=1000&user=[ユーザー名]&pass=[パスワード]

Zoneminderをインストールしたサーバ内で、wgetでスナップショットを取得する場合はホスト名は「localhost」にし、証明書のエラーを回避するために「–no-check-certificate」オプションもつけます。

以下の例は取得した画像をカレントディレクトリの「test.jpg」へ保存する例です。

wget --no-check-certificate "https://localhost/cgi-bin/zm/nph-zms?mode=single&monitor=[モニターID]&scale=100&maxfps=1&buffer=1000&user=[ユーザー名]&pass=[パスワード]" -O ./test.jpg

.htaccessのRewriteで「/cam1」へアクセスされたとき、Zoneminderのスナップショットを返す例です。

そのまま見えてしまうため、Apacheなどから別途認証をかけた方が良いと思います。

<IfModule mod_rewrite.c>
   RewriteEngine On
   RewriteBase /
   RewriteRule ^cam1[/]?$ /cgi-bin/zm/nph-zms?mode=single&monitor=[モニターID]&scale=100&maxfps=1&user=[ユーザー名]&pass=[パスワード] [L]
</IfModule>

eventsディレクトリのスナップショット

以下にモニターIDのディレクトリがあり、イベントごとのディレクトリが作成されて「snapshot.jpg」がありますが、こちらはイベント発生時点のスナップショットです。

最新のイベントのスナップショットが欲しい場合はこちらを使うと良いです。

/var/lib/zoneminder/events/[モニターID]

以下のようにすると全てのsnapshot.jpgが返ってきます。

find /var/lib/zoneminder/events/[モニターID] -name snapshot.jpg -type f | xargs ls -l --time-style=long-iso | sort -k 6,7

なので、以下のようにすると「モニターIDが8」のカメラの最新スナップショットを「test.jpg」にコピーします。

find /var/lib/zoneminder/events/8 -name snapshot.jpg -type f | xargs ls -l --time-style=long-iso | sort -k 6,7 | tail -1 | gawk '{print $8}' | xargs -i cp '{}' ./test.jpg

最後のイベント発生時点のスナップショットが取れるので、外から見るときはこれの方が使いやすいかもしれませんね。

スナップショットの取得で「401 Unauthorized」のエラー

「401」のエラーは認証情報の不足や間違いです。

「403」のエラーと同様ですが、apache2.4から書き方が変わったため、localhostからのアクセスでも認証が効いた状態になっている場合があるので、Zoneminderの認証とBasic認証を併用している場合は確認します。

以下は /etc/httpd/conf.d/zoneminder.conf の例です。

「許可する」は「Require ~」に変わったのと、localhostを許可する場合は「Require local」とする必要があります。

<Location "/zm">
  AuthUserFile /etc/httpd/conf/.htpasswd
  AuthName "Basic Auth"
  AuthType Basic

  Require all denied
  Require valid-user

  # apache 2.4~
  Require local
  Require ip 192.168.2.0/24
  Require ip 127.0.0.1
</Location>

以下ディレクトリ下のログに401のエラーが出ている場合はapache(もしくはWebサーバ)の設定を疑います。

/var/log/httpd/

ログの振り分けをしていないZoneminderは以下にログを出すので、こちらに認証エラーが出ている場合はZoneminderの設定を疑います。

/var/log/messages

スナップショットの取得で「403 Forbidden」のエラー

「403」のエラーはアクセスが拒否されたというエラーです。

他にもあると思いますが、私の場合はZoneminderでなくapacheのバージョン2.4系からアクセス制限の書き方が変わった事が原因でした。

[Thu Feb 25 08:56:15.753530 2021] [authz_core:error] [pid 6406] [client ::1:59476] AH01630: client denied by server configuration: /var/www/html/web/cgi-bin mod_authz_core.c(873): "Wget/1.14 (linux-gnu)"

2.2系ではディレクティブ内で以下のように書いていたところを、

Order allow,deny
Allow from all

2.4系からは以下のように書きます。

Require all granted

今回はlocalhostが許可できていなかったので以下のように許可します。

# localhost許可
Require local

スナップショットの取得で「404 Not Found」のエラー

「404」のエラーはURLが存在しなかったというエラーです。

apacheの設定により、nph-zmsのパスが異なります。

デフォルトだと以下のように設定されていたと思いますが、

https://localhost/cgi-bin/zm/nph-zms~

以下のような場合があるので確認します。

https://localhost/zm/cgi-bin/nph-zms~

この設定は「ScriptAlias」によるものなので、以下の設定とスナップショット取得URLを見比べます。

/etc/httpd/conf.d/zoneminder.conf

ZoneMinderの負荷を下げたい(ロードアベレージ)

locateの検索対象からイベントディレクトリを除外する

locateはインデックスを使ったLinuxのファイル検索コマンドで、findなどに比べて非常に高速ですが、ファイル数が膨大だとデータベースの更新でそれなりの負荷がかかります。
ZoneMinderのイベントをインデックス登録する必要はないので除外しておきます。

以下が設定ファイルです。

/etc/updatedb.conf

設定内の以下の箇所で除外するファイルを指定しており、

PRUNENAMES = ".git .hg .svn"

以下で除外するディレクトリを指定しているので、ZoneMinderのイベントディレクトリが無い場合は追記しておきます。

PRUNEPATHS = "/afs /media /mnt /net /sfs /tmp /udev /var/cache/ccache /var/lib/yum/yumdb /var/spool/cups /var/spool/squid /var/tmp /var/lib/ceph"

ゾーンを最小限にする

解析するエリアが多いと負荷も大きくなるため、対象とするゾーンを最小限にします。

例えば出入りを検知する場合はドアや門などを対象にし、それ以外の箇所はゾーン設定しない等です。

解析FPSを下げる

ローカルに接続されたカメラ(USBカメラなど)は「Maximum FPS」で映像自体のフレームレートを調整できますが、IPカメラでは非推奨のため、解析のフレームレートの「Analysis FPS」を下げます。

公式FAQなどにもありますが、よほど早い動きの箇所でないかぎり「5」で十分です。

解像度を下げる

解像度が高いとロードアベレージもメモリ使用量も飛躍的に増加します。

一般的なIPカメラは低解像度のサブストリームも持っているため、それを設定してみます。

グレースケールにする

解像度と同様にカラー映像もロードアベレージやメモリ使用量が増加するため、カラー映像が必要ない箇所はグレースケールにすると負荷が下がります。

ディスクスペースが圧迫されるのを防ぐ

イベントの自動削除

フィルタでは自動削除などが行え、デフォルトでいくつかのフィルタが定義されて有効になっているので、ハードディスクスペースが足りなくようなこれを修正します。
SSDやmicroSDに保存するようなサーバだと結構きつくなるんじゃないかと思います。

定義されている「n日以上経過したイベントは削除」と「ディスクスペースがn%以上の場合に削除」の2つのフィルタがあれば大抵OKですが、独自のフィルタを定義して自動実行させることもできます。

フィルタは手動での検索や削除も行えますが、「Run filter in background」にチェックが入っているフィルタは「自動実行される」のがポイントです。

フィルタの確認や修正をするため、ZoneminderのWebコンソールから「Filters」をクリックします。

「Use Filter」の「Choose Filter」をクリックして展開します。

以下がデフォルトで定義されているフィルタです。

「DeleteOldEvents」は「n日以上経過したイベントを削除」するフィルタで、「PurgeWhenFull」は「ディスクスペースがn%以上の場合に削除」するフィルタです。

「DeleteOldEvents」のフィルタを見てみます。

「Start Date」「less than」「-5 day」となっていますので、5日以上古いイベントは削除するという意味です。

過去のデータがそれほど必要無い場合で過去3日分だけ残す場合は「-5 day」を「-3 day」と修正して「SAVE」ボタンをクリックします。

「SAVE」ボタンを押さないと反映されないので適用したい場合は必ずポチっとします。

同様に「PurgeWhenFull」のフィルタですが、これはイベントでディスクスペースが満タンにならないようにするフィルタです。

他のアプリケーションでディスクスペースが圧迫した場合でも、指定した%を保つために削除します。

90~95%でOKだと思いますが、必要に応じて修正して「SAVE」で保存すれば自動削除してくれます。

即座に実行する場合は「EXECUTE」ボタンをクリックします。

「DeleteOldEvents」などは一度に削除する限度が設定されているので、大量に削除したい場合は「Limit to first」の数値を増やします。

「Limit to first」が「100」だと100件までしか1度のフィルタ実行で削除されませんが、「1000」にすると1000件まで削除されるので、希望の動作に合わせて増やします。

イベントの残骸の削除

ZoneMinderの「Filters」での削除は、データベースを照会して対応するイベントディレクトリも削除するという動きのため、データベースに無いイベントの場合は events ディレクトリ内に残骸が残ってしまう場合があります。
自動削除も「Filters」の機能で行っているため、データベースに無いイベント画像や動画は削除されず残ってしまいます。

データベースをバックアップから復元すると、ほぼ確実に残骸が発生しますので、復元する場合は必ずイベントディレクトリに残骸が無いか合わせてチェックしてください。

場合によっては数百GB~数TB単位の残骸が出ることがあるため、たまに以下のディレクトリをチェックして明らかに古いイベントが残っていないかチェックすると良いです。

/var/lib/zoneminder/events/

例えば「モニターID」が「10」の場合は以下のようなディレクトリが残っている場合がありますが、日付があまりに古いようなら単なる残骸なので削除しても構いません。

本当に残骸なら、ZoneMinderの「Filters」で対象モニターIDの一覧を表示してみると、対象日時のイベントが存在しないはずです。

/var/lib/zoneminder/events/10/2020-11-12/

大量に出るログ

ログサイズが肥大化した際に確認してみると、以下のようなログが延々と記録されていました。

05/20/21 04:35:53.047285 zmc_m4[15227].WAR-zm_packetqueue.cpp/96 [You have set the max video packets in the queue to 120. The queue is full. Either Analysis is not keeping up or your camera's keyframe interval is larger than this setting. We are dropping packets.]

05/20/21 04:35:53.047423 zmc_m4[15227].ERR-zm_packetqueue.cpp/131 [Unable to free up older packets. Not queueing this video packet.]

これはカメラの映像に対して Maximum Image Buffer Size (frames) が不足していることが原因なので、ZoneMinderのモニター設定からこの値を少し上げて様子を見ます。

上記のログは「You have set the max video packets in the queue to 120.」とありますが、この「120」という値はモニター設定内の「Buffers」にある以下の値のことです。

だいたい10~50くらい上げて様子を見て、まだ出るようならもう少し上げていく感じで設定します。

カメラ側で対処できる設定としては、キーフレーム(Iフレーム)の間隔を少し短くしてみる、CBRならVBRにしてみる、フレームレートを落としてみる、どうしても駄目な場合はZoneMinderで扱う映像は解像度の低く軽いサブストリームにする等です。
Iフレームの間隔を短くするとビットレートが上がってしまったり重くなったり、VBRにすると動きのある場面で乱れるようなカメラもあるため、色々試してみる必要があります。

Maximum Image Buffer Size (frames) の値だけどんどん上げていくとメモリを大量に消費することがありますので、カメラ側とZoneminder側と両方触りながら良い状態を探す必要があります。

サーバでメモリ使用量を確認する場合は以下のようにします。

「RSS」の値が物理メモリの使用量で、最上部のモニター4(-m 4)は「6426768」となっていますが、KB単位なので「6426MB = 6.4GB」消費しています。
フルHD以上の映像だとGB単位で食ってしまいますね。

[root@sakue ~]# ps aux --sort -rss | head -20
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
apache 10486 68.3 10.4 7169260 6426768 ? Sl 06:59 17:57 /usr/bin/zmc -m 4
apache 32478 65.3 7.2 5133592 4460788 ? Sl 06:52 21:11 /usr/bin/zmc -m 3
apache 27728 43.6 5.8 4254148 3576640 ? Sl 03:26 104:13 /usr/bin/zmc -m 10
apache 27718 40.8 4.7 3588168 2937848 ? Sl 03:26 97:39 /usr/bin/zmc -m 8
apache 27697 58.7 4.5 3425608 2807388 ? Sl 03:26 140:22 /usr/bin/zmc -m 2
mysql 1773 1.7 0.4 3802580 299376 ? Ssl 5月20 24:09 /usr/sbin/mysqld
apache 27714 5.2 0.2 786728 179468 ? Sl 03:26 12:33 /usr/bin/zmc -m 6
apache 21027 3.8 0.1 720880 115528 ? Sl 06:25 2:18 /usr/bin/zmc -m 1
apache 27704 6.8 0.1 655236 89704 ? Sl 03:26 16:29 /usr/bin/zmc -m 9
root 556 0.0 0.0 104960 56008 ? Ss 5月20 0:13 /usr/lib/systemd/systemd-journald
apache 2252 0.0 0.0 720200 47740 ? S 5月20 0:15 php-fpm: pool www
apache 2244 0.0 0.0 722240 45968 ? S 5月20 0:15 php-fpm: pool www
apache 2241 0.0 0.0 716112 45532 ? S 5月20 0:15 php-fpm: pool www
apache 2240 0.0 0.0 720064 45112 ? S 5月20 0:15 php-fpm: pool www
apache 2980 0.0 0.0 720176 44592 ? S 5月20 0:14 php-fpm: pool www
apache 2257 0.0 0.0 720200 44500 ? S 5月20 0:15 php-fpm: pool www
apache 2246 0.0 0.0 716072 44300 ? S 5月20 0:15 php-fpm: pool www
apache 2249 0.0 0.0 718140 43240 ? S 5月20 0:15 php-fpm: pool www

「Maximum Image Buffer Size 」だけをどんどん上げていったところ、フルHDの映像で「Maximum Image Buffer Size」が「500」のとき、12GBくらい食ってた事があります。
メモリ搭載量によってはスワップが発生してパフォーマンスが急激に低下するため、メモリの使用状況も合わせて確認する必要があります。

ZoneMinderのダウングレード(バージョンダウン)

ZoneMinderをダウングレードする(バージョンダウン)
ZoneMinderについて ZoneMinderはオープンソースの高機能な監視カメラソフトです。 ZoneMinderのパッケージは「zmrepo」から入手できるのでyumなどのパッケージ管理ツールで導入・アップデート可能です。 ただ、2...

ZoneMinderでイベントの保存先を外付けHDDに変更する

ZoneMinderでイベントの保存先を外付けHDDに変更する
ZoneMinderは自宅サーバとしてHPの「DL360 G7」上で使っていますが、300GBのSAS 4台でRAID1+0(10)を構成しているため、実質580GBほどしか使えません。 最初のうちは良かったのですが、カメラを増設して8台に...

おわりに

まだまだトラブルがあったので、思い出したら追記しておきます。

コメントフォーム

タイトルとURLをコピーしました