Frigateを動かす: (2) AI人検知をApple HomeKitの人感センサにする

非対応品を使う

前回の記事で、古い Intel NUC に Frigate をインストールしました。

Frigateを動かす: (1) 最初のカメラ映像が出るまで
以前の記事でインストールしたZoneMinderのマシンが不調でしたので、これを機に、Frigate に乗り換えました。Frigateは、AIで人や車を検知できる NVR(ネットワークビデオレコーダー)です。古い Intel NUC に U...

Frigate は、カメラの映像から AI で人や車を検知します。この検知結果を MQTT で Raspberry Pi に送り、Homebridge の mqttthing プラグインで受け取ると、Apple Home の人感センサーとして使えます。今回はその手順と、設定でつまずいたところをまとめます。

FrigateのMQTT機能を使う

Frigateには、動作状況の情報をMQTTに流したり、MQTTから指示を受けとる機能があります。私の環境では、Raspberry Piで、HomebridgeとMosquittoが動いています。このMosquittoをMQTTブローカーとして指定してみました。config.ymlの冒頭で、

mqtt:
  enabled: true
  host: <Raspberry PiのIP>
  port: 1883
  user: 'xxxxxxxx'      #user/passwordを指定している場合
  password: 'xxxxxxxx'  #user/passwordを指定している場合
  stats_interval: 300   # 5分ごと

と設定すると、MQTT機能が動き始めます。Raspberry Piで、

$ mosquitto_sub -u xxxxxxxx -P xxxxxxxx -t 'frigate/#' -v

とすれば、Frigateが流しているMQTTメッセージの全てを閲覧できます。最初見たときに、割と頻繁に長々とした状況情報が流れてきて、邪魔でした。MQTT通信を圧迫するのではと思ったので、上の設定では5分ごとに制限しました。

Frigateには、AIによる物体検知結果をMQTTメッセージで流す機能があります。試してみました。その準備として、Frigate UIで、カメラの検出機能をOnにして(下の状態ではOff)、

検出する物体を(人や車など)指定します。

そうすると、例えばカメラ名frontで人が1名検出されると、

frigate/front/person 1

というように、frigate/frong/personトピックに、人数がメッセージとして流れます。これを、Homebridgeで取り込めば、人を検出するセンサーを作ることができます。猫が検出されれば、

frigate/front/cat 1

というトピックにメッセージが流れるので、猫センサーにもなります。

HomeKitのセンサーにする

構成は以下になります。Intel NUCで動作しているFrigateが、人を検出すると、Raspberry Piで動作しているMQTTブローカーMosquittoに人数情報メッセージが流れます。これをHomebridgeのmqttthingプラグインで受け取り、HomeKitのoccupancySensorとして機能させます。なお、日本語版ホームアプリではoccupancySensorは「人感センサー」として表示されるので、以下「人感センサー」と呼びます。

Homebridgeのmqttthing pluginの設定は以下にします。Claudeがサクッと書いてくれました。

"accessories": [
    {
        "accessory": "mqttthing",
        "type": "occupancySensor",
        "name": "Front Person",
        "username": "xxxxxxxx",
        "password": "xxxxxxxx",
        "topics": {
            "getOccupancyDetected": {
                "topic": "frigate/front/person",
                "apply": "return message > 0;"
            },
            "getStatusActive": {
                "topic": "frigate/available",
                "apply": "return message === 'online';"
            }
        }
    },

topic, applyを使った書き方は、知らなかったのですが、applyの中には、JavaScriptのプログラムを1行にまとめて書けるそうです。MQTTのメッセージがmessageに入っているので、これを処理して、結果をreturnで返せば良いです。上のgetOccupancyDetectedに関して言うと、applyは、messageが0より大きければ(1人以上なら)trueを、そうでなければfalseを返す処理です。ちなみに、codecという方法もあって、こちらは別ファイルに複数行からなるJavaScriptの処理が書けるそうです。

人感センサーを使ってみる

config.jsonを保存して、Homebridgeを再起動すると、iPhoneやMacのホーム.appにセンサーが現れます。画面上の、「人感」のアイコンをクリックすると

上で定義したFront Personという人感センサーが見えます。

Frigateが人を検出し、frigate/front/personトピックに1以上のメッセージが流れると、センサーが反応します。

これまで、人感センサーとして焦電センサーやミリ波センサーを使ってきましたが、誤動作が多いのが悩みでした。焦電センサーは、人が止まっていると反応しませんし、ミリ波センサーは電波の揺らぎで誤動作することがありました。カメラの AI は「人の形をしているか」を見て判定するので、より理想に近い人感センサーになると思います。

FrigateのMQTTトピック一覧

Frigateが提供するMQTT機能をまとめておきます。

Frigateがpubするメッセージ

Frigateがパブリッシュする主なトピック/メッセージは、次の通りです。

トピック メッセージの内容
frigate/<カメラ名>/person そのカメラに映っている人の数(0、1、2…)。人数が変わったときだけ送られる。personの他に、car, catなど可。allとすれば検出対象のすべて。
frigate/<カメラ名>/person/active そのカメラに映り動いている人の数(0、1、2…)。人数が変わったときだけ送られる。personの他に、car, catなど可。allとすれば検出対象のすべて。
frigate/<カメラ名>/motion 今、動きがあるかどうか(ON / OFF)
frigate/<カメラ名>/person/snapshot 人を検知したときの静止画(JPEG のバイナリ)
frigate/reviews アラートの開始・更新・終了の詳細(JSON)
frigate/<カメラ名>/detect/state 検知の機能がオンかオフか。.../detect/set に ON / OFF を送ると切り替えられる
frigate/available Frigate が動いているか(online / offline)
frigate/<カメラ名>/status/... 生存確認の online。頻繁に届く

Frigateがsubするメッセージ

以下は、Frigate が受け取るメッセージの一部です。実際に全てを確認したわけではありませんので、注意して使ってください。

送るトピック 送る値 何ができるか
frigate/<カメラ名>/enabled/set ON / OFF カメラそのものを有効・無効にする。オフにすると、映像の取得、録画、検知がすべて止まる。在宅中に室内カメラを完全に止めたいときに
frigate/<カメラ名>/detect/set ON / OFF AI による物体検知。オフにすると、人の検知と person などのメッセージが止まる
frigate/<カメラ名>/recordings/set ON / OFF 録画の制御
frigate/<カメラ名>/snapshots/set ON / OFF 検知したときの静止画の保存
frigate/<カメラ名>/motion/set ON / OFF 動き検知(検知がオンの間はオフにできない)
frigate/<カメラ名>/review_alerts/set ON / OFF アラートの作成。録画や検知は続けたまま、アラートだけを止めたいときに
frigate/<カメラ名>/notifications/set ON / OFF Frigate のブラウザのプッシュ通知(通知を設定している場合)
frigate/<カメラ名>/notifications/suspend 分数 プッシュ通知を、指定した分数だけ止める
frigate/<カメラ名>/ptz preset_<名前> など PTZ(首振り)カメラを、登録した位置に動かす
frigate/restart (何でもよい) Frigate を再起動する

多くは .../set に送ると、結果が同じ名前の .../state で返ってきます。Frigateがstateを返すトピックには、以下のものがあります。これに対になったsetトピックで、stateの状態を変更できると考えられます。

frigate/front/enabled/state ON
frigate/front/recordings/state ON
frigate/front/snapshots/state OFF
frigate/front/audio/state OFF
frigate/front/audio_transcription/state OFF
frigate/front/detect/state ON
frigate/front/motion/state ON
frigate/front/improve_contrast/state ON
frigate/front/ptz_autotracker/state OFF
frigate/front/motion_threshold/state 30
frigate/front/motion_contour_area/state 10
frigate/front/birdseye/state ON
frigate/front/birdseye_mode/state OBJECTS
frigate/front/review_alerts/state ON
frigate/front/review_detections/state ON
frigate/front/object_descriptions/state OFF
frigate/front/review_descriptions/state OFF

これを元に、Homebridgeで設定すれば、Apple Homeから録画をOn/Offするスイッチを作成したり、さらには、「最後の人が出かけたら室内カメラの録画をオン、帰宅したらオフ」というようなオートメーションをHomeKitで作ることができます。

まとめ

Frigate は、設定により、MQTT に検知結果を流してくれます。そこで、Frigateの人検知結果を、Homebridge の mqttthing プラグインで受け取り、Apple HomeKit の人感センサーにしました。焦電センサーやミリ波センサーより誤報が少ない、理想に近い人感センサーになりました。このほか、自動車センサー、自転車センサー、猫センサーなど作れそうです。本来のNVRとしてだけでなく、AIセンサーとしても有効利用できると思います。

また、MQTTメッセージで、Frigateの機能をコントロールすることもできます。録画のOn/Offボタンやその自動化などが可能です。

付録:Frigate設定ファイルからパスワードを隠す

本文の、Frigate設定ファイル、config.ymlの例では、MQTTのユーザ・パスワードを平文で記載しました。一方で、IPカメラのユーザ・パスワードは、.envファイルに書き込んで、config.ymlからは隠してました。MQTTのユーザ・パスワードも、同様に、.envファイルに書いておくことができます。パスワードが目に触れる機会を減らせるので、より安全です。

まずは、~/frigate/.envに、MQTTの情報を、FRIGATE_MQTT_USER、FRIGATE_MQTT_PASSWORDとして追記しておきます。そして、docker compose up -d でコンテナを作り直します。

cd ~/frigate
cat >> .env << 'EOF'
FRIGATE_MQTT_USER=ユーザー名
FRIGATE_MQTT_PASSWORD=パスワード
EOF
docker compose up -d

次に、Frigate の config.yml の mqtt: に、Mosquitto ユーザー名とパスワードを、.envに書いた名前を {…} の中に入れて参照します。

mqtt:
  enabled: true
  host: <Raspberry PiのIP>
  port: 1883
  user: "{FRIGATE_MQTT_USER}"
  password: "{FRIGATE_MQTT_PASSWORD}"
  stats_interval: 300

ここで2点、注意する点があります。

  • .env を書き換えたら、docker compose up -d でコンテナを作り直す必要があります。.env の中身はコンテナを作るときに環境変数として渡されるので、docker compose restart や web UI の「保存後再起動」では反映されません。
  • 変数の名前は FRIGATE_ で始める必要があります。Frigate は、この名前で始まる環境変数だけを置き換えます。

コメント

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