Files
frigate_w_audio/README.md
T
2026-04-25 11:06:10 -04:00

274 lines
9.4 KiB
Markdown

# Home camera stack
Frigate NVR + Mosquitto MQTT + frigate-notify -> ntfy push notifications,
with face recognition and license plate recognition on the Frigate side.
Includes a planned Pi Zero W "doorbell speaker" stack (push-to-talk web
page fronted by Caddy) that's wired but not yet deployed.
## Architecture
```
Cameras (RTSP) Phone / browser
| |
v v
+------------+ MQTT events +----------------+ +-------------+
| Frigate | <-------------> | Mosquitto | | Pi |
| (NVR) | | broker | | (planned) |
+-----+------+ +-------+--------+ | speaker |
| WebRTC / MSE | +------+------+
v v ^
+------------+ +------------------+ |
| Caddy |<--HTTPS--------| frigate-notify | |
| proxy | | (event consumer) | |
+------------+ +--------+---------+ |
| | |
| cam.yourdomain.com ntfy push |
| doorbell.yourdomain.com |
+-------HTTPS---------------> PTT button ------------+
```
## What's deployed vs planned
| Component | Status |
|---|---|
| Frigate 0.17 | Deployed |
| Mosquitto MQTT broker | Deployed |
| frigate-notify -> ntfy | Deployed |
| Face recognition | Configured, needs training |
| License plate recognition | Configured |
| Caddy reverse proxy | Whatever your existing Caddy does |
| Pi Zero W doorbell speaker | Planned, not deployed yet |
## Repo layout
```
home-cameras/
|-- docker-compose.yml # frigate + mosquitto + frigate-notify
|-- .env.example # template -- copy to .env, fill in
|-- .gitignore
|-- README.md # this file
|
|-- frigate_config/
| |-- config.yml # production: main stream for detect
| `-- alternatives/
| `-- config-simple.yml # lower-CPU fallback: sub-stream detect
|
|-- frigate-notify/
| `-- config.yml # MQTT in, ntfy out, face-aware templates
|
|-- mosquitto/
| |-- config/
| | `-- mosquitto.conf # broker config (allow_anonymous false)
| |-- data/.gitkeep
| `-- log/.gitkeep
|
|-- caddy/
| `-- Caddyfile # reverse proxy for both subdomains
|
`-- pi/ # runs on the Pi, NOT on the Frigate host
|-- README.md # Pi-specific setup
|-- server.py # Flask + WebSocket PTT receiver
|-- doorbell.service # systemd unit
`-- install.sh # one-shot installer
```
## First-run on the Frigate host
Prerequisites:
- Docker + docker compose v2
- DNS records for any subdomains you intend to use, pointing at your Caddy
host
- An existing Caddy instance (separate from this stack) handling TLS at the
edge, OR adapt for whatever reverse proxy you use
- Coral USB stick plugged in (or adjust `detectors:` for a different accel)
- A media disk mounted on the host; update the `/media/frigate` path in
`docker-compose.yml`
Steps:
```bash
git clone https://github.com/YOU/home-cameras.git
cd home-cameras
# 1) Configure secrets
cp .env.example .env
$EDITOR .env
# 2) Make mosquitto dirs writable by the container's mosquitto user (UID 1883)
sudo chown -R 1883:1883 mosquitto/
# 3) Bootstrap mosquitto BEFORE applying the production config.
# The committed mosquitto.conf has allow_anonymous false + password_file,
# which means we need to create the password file first OR temporarily
# flip to allow_anonymous true to start.
#
# Easiest: temporarily edit mosquitto/config/mosquitto.conf:
# allow_anonymous false -> allow_anonymous true
# comment out: password_file /mosquitto/config/passwd
# Then start:
docker compose up -d mosquitto
docker compose logs mosquitto --tail 10 # expect "running"
# 4) Create the MQTT user (use the password from your .env)
docker compose exec mosquitto mosquitto_passwd -c -b \
/mosquitto/config/passwd frigate \
"$(grep ^FRIGATE_MQTT_PASSWORD .env | cut -d= -f2)"
sudo chown 1883:1883 mosquitto/config/passwd
sudo chmod 0640 mosquitto/config/passwd
# 5) Restore mosquitto.conf to its committed state:
# allow_anonymous true -> allow_anonymous false
# uncomment: password_file /mosquitto/config/passwd
git checkout mosquitto/config/mosquitto.conf
docker compose restart mosquitto
# 6) Verify auth works
sudo apt install -y mosquitto-clients
mosquitto_sub -h 127.0.0.1 -u frigate \
-P "$(grep ^FRIGATE_MQTT_PASSWORD .env | cut -d= -f2)" \
-t 'test/#' -v &
mosquitto_pub -h 127.0.0.1 -u frigate \
-P "$(grep ^FRIGATE_MQTT_PASSWORD .env | cut -d= -f2)" \
-t 'test/hello' -m 'ok'
# expect: test/hello ok
kill %1
# 7) Bring up the rest
docker compose up -d
docker compose logs -f
```
Healthy startup looks like:
- Frigate: `frigate.comms.mqtt INFO : MQTT connected`
- frigate-notify: `Successfully connected to http://frigate:5000` then
`Connected to MQTT.` then `Subscribed to MQTT topic: frigate/events`
- mosquitto: incoming client connections from both
## Caddy
On whichever host runs Caddy, copy `caddy/Caddyfile` (or merge the relevant
site blocks into your existing one), edit IPs and domains, then:
```bash
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
```
Until the Pi is deployed, comment out the `doorbell.yourdomain.com` block.
## Train face recognition
1. Let Frigate run with normal foot traffic for a day. Face crops are
captured automatically and appear under **Face Library -> Train** in
the Frigate UI.
2. For each person, label 5-10 **diverse** clear crops -- different angles,
lighting, times of day. Diversity beats quantity; 30 near-identical
frames from one event hurts recognition.
3. Walk past the camera again. Events should now show the person's name as
the sub-label, and frigate-notify's ntfy push will say their name
instead of "person".
Training images live on the Frigate host at
`/media/frigate/clips/faces/<n>/`. Not version-controlled (privacy).
## Switching config profiles
This repo ships with two Frigate configs:
- `frigate_config/config.yml` -- active. Main 2688x1520 stream for both
detect and record. Better face recognition at distance, higher CPU.
- `frigate_config/alternatives/config-simple.yml` -- lower-CPU fallback.
Sub-stream 640x480 for detect, main for record only.
To switch:
```bash
cp frigate_config/config.yml frigate_config/config.yml.bak
cp frigate_config/alternatives/config-simple.yml frigate_config/config.yml
docker compose restart frigate
```
## Adding a camera with a mic
When adding a camera with a built-in microphone (e.g. an Anpviz with mic),
see the comment block at the bottom of `frigate_config/config.yml` for the
exact edits needed to enable live audio in the Frigate UI.
## Pi doorbell speaker (when you're ready)
See `pi/README.md`. Summary:
1. Flash Pi OS Lite, scp `pi/` to the Pi, run `install.sh`.
2. Add the `doorbell.yourdomain.com` site block in Caddy.
3. Open the URL on your phone.
## Security notes
- `.env` has RTSP credentials, MQTT password, ntfy URL. Never commit it.
This repo's `.gitignore` blocks it; review `git status` before committing.
- The Pi's Flask server binds only to `127.0.0.1`. Caddy is what exposes it.
Do NOT bind `server.py` to `0.0.0.0` -- it has no auth of its own.
- Mosquitto's port 1883 is LAN-only. Use a VPN for any remote MQTT clients.
- For the doorbell page, optionally add basic auth in Caddy (`caddy
hash-password`).
## Troubleshooting
### Frigate can't reach cameras
```bash
docker compose exec frigate ping -c 2 <camera_ip>
```
RTSP path varies by camera vendor:
- Dahua / Amcrest: `/cam/realmonitor?channel=1&subtype=0`
- Hikvision / Anpviz H-series: `/Streaming/Channels/101`
If your password contains `%`, `@`, `/`, `?`, `#`, `&`, or `+`, either
URL-encode it or change the password to avoid those characters.
### Mosquitto restarts in a loop
Almost always permission on `mosquitto/config/passwd`:
```bash
sudo chown -R 1883:1883 mosquitto/
sudo chmod 0640 mosquitto/config/passwd
docker compose restart mosquitto
```
Or the config file or password file simply doesn't exist yet -- see the
"First-run on the Frigate host" section above for the bootstrap flow.
### frigate-notify connects to MQTT but doesn't send pings
```bash
docker compose logs frigate-notify --tail 30
```
- "webapi" in logs but expecting MQTT? Check `webapi.enabled: false` and
`mqtt.enabled: true` in `frigate-notify/config.yml`.
- MQTT auth fails? Verify `FN_FRIGATE__MQTT__PASSWORD` (note DOUBLE
underscores) matches what you set with `mosquitto_passwd`.
- Confirm what reached the container:
`docker inspect frigate-notify --format '{{range .Config.Env}}{{println .}}{{end}}' | grep FN_`
### Always see "person" instead of trained name
- Increase `alerts.general.recheck_delay` in `frigate-notify/config.yml`
from 10 to 15 or 20 seconds.
- Check the Frigate UI event timeline -- if the event itself doesn't
show a sub_label, the face crop was too small / too blurry / too
obscured for recognition.
## Hardware reference
Current:
- NVR host: x86_64 + Docker, USB Coral
- Cameras: Amcrest (Dahua RTSP)
- Notifier: self-hosted ntfy
Planned:
- Anpviz 4K camera with built-in mic (front door audio)
- Back door + squirrel feeder cameras
- Pi Zero W + USB speaker at the door