Frigate NVR Setup Guide¶
Dahua IPC-T54IR-AS-S3 + Intel iGPU + Home Assistant¶
Stack: Debian 13 · Docker · Mosquitto on a separate host (see Home Assistant)
Cameras: 3x Dahua/EmpireTech IPC-T54IR-AS-S3 4MP turret, H.265, PoE
Image: ghcr.io/blakeblackshear/frigate:0.18.2 (default image, includes OpenVINO)
Hardware: Intel Core i5-8500T with UHD Graphics 630, recordings on a dedicated 3 TB WD Red
Frigate now runs on the Intel iGPU: VAAPI for video decode and OpenVINO for object detection, both on the same UHD
630. It started out on an NVIDIA GTX 1080 with the -tensorrt image; that setup is kept below as an alternative in
the NVIDIA (TensorRT) tabs. A 6th-gen-or-newer Intel iGPU handles one to three cameras comfortably, uses a fraction
of the power of a discrete card, and needs no extra drivers on the host.
Hard-won lessons (masks breaking after a model change, parked cars alerting, debugging through the API) are in Lessons learned: smart home.
1. Physical Setup¶
HDD for Recordings¶
Recordings go on their own disk, not the main storage pool. Frigate writes 24/7, which would keep pool disks spinning,
churn SnapRAID parity (every new segment is a change to sync), and compete with media I/O. A dedicated drive also means
the NVR keeps recording while the pool is busy with maintenance. Frigate's database lives on the same disk
(database.path below), so recordings and their index move together.
This wipes the disk
fdisk and mkfs.ext4 destroy everything on the target disk. Double-check /dev/sdX with lsblk and back up anything you need first.
lsblk # identify new disk
sudo fdisk /dev/sdX # g (GPT), n (partition), accept defaults, w (write)
sudo mkfs.ext4 /dev/sdX1
sudo mkdir -p /mnt/frigate
sudo blkid /dev/sdX1 # copy UUID
echo "UUID=<uuid> /mnt/frigate ext4 defaults,noatime,nofail 0 2" | sudo tee -a /etc/fstab
sudo systemctl daemon-reload
sudo mount -a
df -h /mnt/frigate # verify
nofail lets the host boot if the drive is absent (Frigate then fails loudly instead of the whole server sitting in
emergency mode). noatime skips a metadata write every time a segment is read for playback. Keep an eye on the drive
with SMART monitoring: a surveillance disk works harder than any other disk in the house.
Camera Default IP¶
Warning
Dahua cameras ship with a static IP of 192.168.1.108 -- they do not DHCP by default. To access them initially (If on different VLAN):
- Set laptop NIC to
192.168.1.50 / 255.255.255.0 - Browse to
http://192.168.1.108 - Set admin password (required on first login)
- Go to Setup > Network > TCP/IP, assign static IoT VLAN IP
- Confirm RTSP enabled: Setup > Network > Port, default port 554
Assign cameras sequential statics in <IOT_SUBNET> (e.g. .101, .102, .103)
PoE Switch (SG2016P)¶
The SG2016P has 8 PoE+ ports (802.3at/af, 30W per port, 120W total budget). PoE ports are ports 1-8 -- confirm in Omada UI under Devices > [switch] > PoE. Each camera draws ~12-15W, well within budget for 3 cameras.
2. Camera Configuration¶
Stream Settings (Camera Web UI)¶
Main Stream (record -- full quality): - Resolution: 2688x1520 - Framerate: 20fps - Bitrate: 4096-6144 kbps - Codec: H.265 - I-frame interval: 40 (2x framerate)
Sub Stream 2 (detect -- use subtype=2, not subtype=1): - Resolution: 1280x720 - Framerate: 10fps - Bitrate: 1024 kbps - Codec: H.265 - I-frame interval: 20 (2x framerate)
Why Sub Stream 2:
Sub Stream 1 is hard-capped at 704x480 by Dahua firmware -- this is by design for legacy NVR compatibility. Sub Stream 2 allows up to 1280x720 and is referenced with subtype=2 in the RTSP URL.
Why not max resolution on sub stream:
Detection runs on every frame of the sub stream. Frigate crops regions of motion and scales them to the model's input size (320x320 on the iGPU, 640x640 on the NVIDIA build) regardless -- higher sub stream resolution adds decode cost with little detection gain. The main stream captures full resolution for recordings.
RTSP URL Format¶
Main: rtsp://admin:<YOUR_PASSWORD>@<CAMERA_IP>:554/cam/realmonitor?channel=1&subtype=0
Sub2: rtsp://admin:<YOUR_PASSWORD>@<CAMERA_IP>:554/cam/realmonitor?channel=1&subtype=2
Password note: Special characters (
#,$,@) in passwords break RTSP URL parsing. Use alphanumeric-only passwords on the cameras (or URL-encode them, e.g.@→%40).
Verify Streams Before Frigate¶
ffprobe -v quiet -print_format json -show_streams \
'rtsp://admin:<YOUR_PASSWORD>@<CAMERA_IP>:554/cam/realmonitor?channel=1&subtype=0'
Confirms codec, resolution, framerate. Run for all three cameras on both subtype=0 and subtype=2.
3. Host Prerequisites¶
Nothing to install: the i915 kernel driver is part of Debian's kernel, and the Frigate image ships the VAAPI and
OpenVINO user-space drivers. Just check the render node exists:
Optional, for watching GPU load from the host:
OpenVINO's GPU device needs a 6th-gen (Skylake) or newer Intel iGPU. The UHD 630 is gen 9.5, which is covered by
preset-vaapi. Gen 13+ and Arc GPUs use the preset-intel-qsv-* presets instead.
NVIDIA Driver + Container Toolkit (Debian 13)¶
Enable the contrib non-free non-free-firmware components in /etc/apt/sources.list.d/debian.sources, then:
sudo apt update
sudo apt install linux-headers-amd64 nvidia-kernel-dkms nvidia-driver libnvcuvid1
sudo reboot
# Verify driver and the video decode library
nvidia-smi
ldconfig -p | grep nvcuvid
# Install Container Toolkit
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
# Configure Docker runtime
# WARNING: nvidia-ctk writes to /etc/docker/daemon.json
# Do NOT set default-runtime to nvidia -- use deploy.resources in compose instead
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
# Verify
docker run --rm --gpus all debian:trixie-slim nvidia-smi
daemon.json warning:
nvidia-ctkcreates or edits/etc/docker/daemon.json. If Docker breaks after running it, check the file -- remove it entirely if it was empty before (sudo rm /etc/docker/daemon.json && sudo systemctl restart docker). Usedeploy.resourcesin compose instead of setting a default runtime.NVDEC library: ffmpeg's NVIDIA hardware decode needs
libnvcuvid.so.1. Debian'snvidia-driverpackage does not pull it in, so installlibnvcuvid1explicitly (on Ubuntu the same trap is the-serverdriver variant, which omits it). Debian 13's packaged driver is the 550 series; very new cards may need NVIDIA's own repo.
4. ONNX Detection Model¶
Frigate 0.16+ does not ship pre-built YOLO models. You build one once and drop it into config/model_cache/.
Both setups use YOLOv9 exported to ONNX, at different sizes.
YOLOv9-s at 320x320. Frigate's docs list YOLOv9 as the recommended model for OpenVINO on a GPU, and s at 320
as the starting point. RF-DETR needs an Xe iGPU or Arc card, so it isn't an option on a gen 9.5 UHD 630.
Why not the default SSDLite MobileNet v2 that OpenVINO ships with? It ran here first and was the root cause of a false-alert problem: under night IR it produced jittery detections that kept dying and respawning (each one a new alert) and it confidently labelled a parked camper as a person and as a car. YOLOv9-s (~46 mAP on COCO vs ~22) fixed that. On this iGPU it takes about 20 ms per inference against 8 ms for SSDLite, which is plenty of headroom at 5 fps detection.
mkdir -p /mnt/appdata/frigate/config/model_cache
cd /mnt/appdata/frigate/config/model_cache
docker build . --build-arg MODEL_SIZE=s --build-arg IMG_SIZE=320 --output . -f- <<'EOF'
FROM python:3.11 AS build
RUN apt-get update && apt-get install --no-install-recommends -y cmake libgl1 && rm -rf /var/lib/apt/lists/*
COPY --from=ghcr.io/astral-sh/uv:0.10.4 /uv /bin/
WORKDIR /yolov9
ADD https://github.com/WongKinYiu/yolov9.git .
RUN uv pip install --system -r requirements.txt
RUN uv pip install --system onnx==1.18.0 onnxruntime onnx-simplifier==0.4.* onnxscript
ARG MODEL_SIZE
ARG IMG_SIZE
ADD https://github.com/WongKinYiu/yolov9/releases/download/v0.1/yolov9-${MODEL_SIZE}-converted.pt yolov9-${MODEL_SIZE}.pt
RUN sed -i "s/ckpt = torch.load(attempt_download(w), map_location='cpu')/ckpt = torch.load(attempt_download(w), map_location='cpu', weights_only=False)/g" models/experimental.py
RUN python3 export.py --weights ./yolov9-${MODEL_SIZE}.pt --imgsz ${IMG_SIZE} --simplify --include onnx
FROM scratch
ARG MODEL_SIZE
ARG IMG_SIZE
COPY --from=build /yolov9/yolov9-${MODEL_SIZE}.onnx /yolov9-${MODEL_SIZE}-${IMG_SIZE}.onnx
EOF
Output: yolov9-s-320.onnx. It has one input (images, [1,3,320,320] float32) and one output ([1,84,2100]:
4 box coordinates + 80 COCO classes), which is the layout model_type: yolo-generic expects.
YOLOv9-m at 640x640. Same export, bigger model:
cd /path/to/appdata/frigate/config/model_cache
# same docker build command as the Intel tab, with:
docker build . --build-arg MODEL_SIZE=m --build-arg IMG_SIZE=640 --output . -f- <<'EOF'
...
EOF
Output: yolov9-m-640.onnx
Why 640px: The sub stream is 1280x720. Building at 320px throws away resolution you paid for -- 640px gives meaningfully better detection accuracy with negligible GPU overhead on a 1080.
Model variants:
t(tiny, 4.4MB) →s(small, 14MB) →m(medium, 38MB) →c(large, 49MB) →e(112MB). For 3 cameras on a GTX 1080,-mat 640px is the right balance -- inference ~15-25ms, meaningfully better accuracy than-sespecially for IR/night footage.
onnx-simplifier pinned to 0.4.x: Unpinned (
>=0.4.1) resolves to 0.5.0 which pullsonnxsim==0.6.2which fails to build from source. Frigate's own export snippet pins0.4.*for the same reason.
Labelmap changes with the model
YOLOv9 uses the 80-class COCO labelmap (/labelmap/coco-80.txt), not the 91-class one SSDLite uses. Every common
label (person, car, dog, cat, bird, bicycle, motorcycle, bear) exists in both, but deer does not exist in COCO at
all, so don't bother tracking it. And re-check your masks after any model change: see
masks stop working after you change the detector model.
5. Docker Compose¶
services:
frigate:
container_name: frigate
# Default image includes OpenVINO (Intel) support for detection + enrichments.
image: ghcr.io/blakeblackshear/frigate:0.18.2
restart: unless-stopped
stop_grace_period: 30s
# Frigate recommends more shared memory for multiple high-res cameras;
# 1gb is comfortable for 3x 4MP cameras and prevents dropped frames.
shm_size: "1gb"
env_file:
- .env
environment:
- TZ=<TZ>
dns:
- <YOUR_DNS_SERVER_IP>
devices:
- /dev/dri/renderD128:/dev/dri/renderD128 # Intel iGPU - VAAPI decode + OpenVINO GPU inference
volumes:
- /mnt/appdata/frigate/config:/config
- /mnt/frigate:/media/frigate
# 1GB tmpfs for the recording segment cache: saves disk wear from 24/7 video caching.
- type: tmpfs
target: /tmp/cache
tmpfs:
size: 1000000000
ports:
- "8971:8971" # Frigate Web UI (authenticated)
- "8554:8554" # RTSP restream from go2rtc
- "8555:8555/tcp" # WebRTC over TCP
- "8555:8555/udp" # WebRTC over UDP
services:
frigate:
container_name: frigate
image: ghcr.io/blakeblackshear/frigate:0.18.2-tensorrt
restart: unless-stopped
stop_grace_period: 30s
shm_size: "1gb"
env_file:
- .env
environment:
- TZ=<TZ>
dns:
- <YOUR_DNS_SERVER_IP>
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
volumes:
- /path/to/appdata/frigate/config:/config
- /mnt/frigate:/media/frigate
- type: tmpfs
target: /tmp/cache
tmpfs:
size: 1000000000
ports:
- "8971:8971"
- "8554:8554"
- "8555:8555/tcp"
- "8555:8555/udp"
GPU passthrough: NVIDIA uses
deploy.resources.reservations.devicesin compose, notdevices:mappings. The device mappings (/dev/dri/renderD128) are for Intel/AMD only.
FRIGATE_RTSP_PASSWORD=<YOUR_CAMERA_PASSWORD>
FRIGATE_MQTT_PASSWORD=<MQTT_FRIGATE_PASSWORD>
# Recommended: require a login for the go2rtc RTSP restream on :8554
FRIGATE_GO2RTC_RTSP_USERNAME=<RESTREAM_USER>
FRIGATE_GO2RTC_RTSP_PASSWORD=<RESTREAM_PASSWORD>
Frigate substitutes {FRIGATE_*} environment variables into specific config fields (MQTT credentials, camera and go2rtc
URLs, go2rtc RTSP credentials), so no password ever has to appear in config.yaml.
Image tag: pin an exact version (
0.18.2, or0.18.2-tensorrtfor NVIDIA).stablefloats to the newest release, including majors with breaking config changes. Read the release notes and back up/configbefore every upgrade.Config lives outside git:
/configis on the appdata disk because Frigate editsconfig.yamlitself when you change masks, zones or settings in the UI. Back it up with the rest of your appdata.Ports: the RTSP restream (8554) and WebRTC (8555) don't use the UI login. Set
go2rtc.rtsp.username/password(shown in the config below) and only expose these ports to trusted networks. Never publish the internal API port 5000, which has no authentication at all.tmpfs /tmp/cache: Frigate buffers recording segments in memory before writing to disk. Reduces small random writes to the HDD. 1GB is sufficient for 3 cameras.
dns: Required for containers to resolve
<YOUR_LOCAL_DOMAIN>hostnames via the local DNS resolver (AdGuard/Unbound chain).
6. Frigate Config¶
/mnt/appdata/frigate/config/config.yaml. This is the live config, trimmed of comments and sanitized. Pick the
detector/ffmpeg block from the tabs; everything else is shared.
version: 0.18-0
tls:
enabled: false # HA's Frigate integration and notification proxy can't verify Frigate's self-signed cert
mqtt:
enabled: true
host: <MQTT_BROKER_IP>
port: 1883
topic_prefix: frigate
client_id: frigate
user: frigate
password: "{FRIGATE_MQTT_PASSWORD}"
stats_interval: 60
database:
path: /media/frigate/frigate.db # on the recordings disk, next to the recordings it indexes
auth:
enabled: true
go2rtc:
rtsp: # login for clients of the :8554 restream (Frigate itself uses localhost, which is exempt)
username: "{FRIGATE_GO2RTC_RTSP_USERNAME}"
password: "{FRIGATE_GO2RTC_RTSP_PASSWORD}"
streams:
cam_01:
- rtsp://admin:{FRIGATE_RTSP_PASSWORD}@<CAMERA_1_IP>:554/cam/realmonitor?channel=1&subtype=0
- ffmpeg:cam_01#audio=opus # adds an Opus track so WebRTC live view has audio
cam_01_sub:
- rtsp://admin:{FRIGATE_RTSP_PASSWORD}@<CAMERA_1_IP>:554/cam/realmonitor?channel=1&subtype=2
cam_02:
- rtsp://admin:{FRIGATE_RTSP_PASSWORD}@<CAMERA_2_IP>:554/cam/realmonitor?channel=1&subtype=0
- ffmpeg:cam_02#audio=opus
cam_02_sub:
- rtsp://admin:{FRIGATE_RTSP_PASSWORD}@<CAMERA_2_IP>:554/cam/realmonitor?channel=1&subtype=2
cam_03:
- rtsp://admin:{FRIGATE_RTSP_PASSWORD}@<CAMERA_3_IP>:554/cam/realmonitor?channel=1&subtype=0
- ffmpeg:cam_03#audio=opus
cam_03_sub:
- rtsp://admin:{FRIGATE_RTSP_PASSWORD}@<CAMERA_3_IP>:554/cam/realmonitor?channel=1&subtype=2
detect:
enabled: true
fps: 5 # Frigate's recommended detect rate
objects:
track: [person, dog, cat, bird, car, motorcycle, bicycle, bear]
filters:
person: { min_area: 5000, min_score: 0.5, threshold: 0.7 }
car: { min_area: 5000, min_score: 0.5, threshold: 0.7 }
dog: { min_score: 0.5, threshold: 0.7 }
cat: { min_score: 0.5, threshold: 0.7 }
motion:
threshold: 30
contour_area: 10
improve_contrast: true
mqtt_off_delay: 30
review:
alerts:
labels: [person, bear, car]
detections:
labels: [dog, cat, bird, bicycle, motorcycle]
record:
enabled: true
continuous:
days: 7 # everything, 24/7, for a week
motion:
days: 14 # then only segments with motion, up to two weeks
preview:
quality: medium
alerts:
pre_capture: 5
post_capture: 5
retain:
days: 30
mode: motion
detections:
pre_capture: 5
post_capture: 5
retain:
days: 14
mode: motion
snapshots:
enabled: true
timestamp: false
bounding_box: true
quality: 70
retain:
default: 14
objects:
person: 30
bear: 30
birdseye:
enabled: true
mode: objects
telemetry:
stats:
intel_gpu_stats: true # GPU load on the System page (set false on NVIDIA)
version_check: true # lets the HA integration report new versions
cameras:
cam_01:
ffmpeg:
inputs:
- path: rtsp://127.0.0.1:8554/cam_01 # go2rtc restream: one connection per camera
input_args: preset-rtsp-restream
roles: [record]
- path: rtsp://127.0.0.1:8554/cam_01_sub
input_args: preset-rtsp-restream
roles: [detect, audio]
detect:
width: 1280 # match the sub stream resolution
height: 720
# cam_02 / cam_03: same as cam_01 with their own stream names
detectors:
ov:
type: openvino
device: GPU
model:
model_type: yolo-generic
width: 320
height: 320
input_tensor: nchw
input_dtype: float
path: /config/model_cache/yolov9-s-320.onnx
labelmap_path: /labelmap/coco-80.txt
ffmpeg:
hwaccel_args: preset-vaapi
output_args:
record: preset-record-generic-audio-copy
input_pixel_format is left at its default (RGB), which is what YOLOv9 wants; the bgr setting you'll see in
older SSDLite examples is SSD-specific.
detectors:
onnx:
type: onnx
model:
model_type: yolo-generic
width: 640
height: 640
input_tensor: nchw
input_dtype: float
path: /config/model_cache/yolov9-m-640.onnx
labelmap_path: /labelmap/coco-80.txt
ffmpeg:
hwaccel_args: preset-nvidia
output_args:
record: preset-record-generic-audio-copy
The -tensorrt image detects the GPU and runs the ONNX model through TensorRT automatically.
Per-camera software decode¶
One camera's H.265 sub stream kept failing VAAPI decode on the UHD 630 (hardware accelerator failed to decode picture,
Could not find ref with POC), restarting ffmpeg every few minutes and dropping frames each time. Recording uses stream
copy and needs no decode, so only detection was affected. The fix is to turn hardware decode off for that camera
only; software-decoding one 720p stream at 5 fps is trivial for the CPU:
cameras:
cam_03:
ffmpeg:
hwaccel_args: '' # software decode for this camera; others keep preset-vaapi
Enrichments¶
All of these run fine alongside detection on the iGPU host. The small models are a deliberate choice: the UHD 630 is shared by decode and detection, so the enrichments run on the CPU instead of competing for it.
face_recognition:
enabled: true
model_size: small # FaceNet on CPU; 'large' (ArcFace) wants a real GPU/NPU
min_area: 500
semantic_search:
enabled: true
model_size: small # quantized CPU model; quality difference is negligible
model: jinav1
audio:
enabled: true
min_volume: 500
listen: [bark, fire_alarm, scream, speech, yell, glass_breaking, crying, siren]
classification:
bird:
enabled: true # built-in model, no training
Don't track face
With a COCO model, face detection for face_recognition runs automatically when a person is detected. Adding face
to objects.track is only for Frigate+ or custom models that detect faces natively.
Zones, masks and stationary objects¶
The per-camera zones, objects.filters.<label>.mask and detect.stationary settings that stop parked cars from
alerting are tuned against real footage, so they're written up with the reasoning in
Lessons learned.
Draw zones and masks in the Frigate UI (Settings > Masks / Zones); Frigate writes them back into config.yaml.
Start Frigate¶
On Intel, OpenVINO compiles the model for the GPU when Frigate starts, which can take up to a minute. On NVIDIA, first boot takes several minutes while TensorRT builds an optimized engine from the ONNX model (one-time per model).
Get Initial Password¶
The admin password is only printed on first startup. Change it under Settings > Users after logging in. If you missed it or are locked out, set this, restart, and read the new password from the logs (then remove it again):
UI accessible at http://<YOUR_SERVER_IP>:8971 (https:// if you leave Frigate's TLS on).
7. Firewall Rules¶
IoT Interface (OPNsense)¶
Order matters -- first match wins.
| # | Action | Source | Destination | Port | Description |
|---|---|---|---|---|---|
| 1 | Pass | IOT net | <IOT_GATEWAY> |
53 | Force DNS to AdGuard |
| 2 | Block | IOT net | PrivateNetworks alias | any | Block IoT to all internal |
| 3 | Pass | IOT net | any | any | IoT internet access |
Rule 1 from the original setup (Allow IoT cameras → Frigate host, port any) was identified as unnecessary and overly permissive. OPNsense is a stateful firewall -- return traffic from cameras to Frigate is handled automatically via state table. Only Frigate initiating outbound RTSP needs an explicit rule, which lives on the SERVER interface.
Cameras don't need the internet
Consider blocking the cameras' internet access entirely (rule 3) once they're set up. Frigate pulls the streams locally and the cameras only need NTP, which you can point at the gateway.
SERVER Interface (OPNsense)¶
| # | Action | Source | Destination | Port | Description |
|---|---|---|---|---|---|
| 1 | Pass | <YOUR_SERVER_IP> (Frigate host) |
IOT net | 554 | Frigate → cameras RTSP |
| 2 | Block | SERVER net | LAN net | any | Block SERVER to LAN |
| 3 | Block | SERVER net | MGMT net | any | Block SERVER to MGMT |
| 4 | Pass | SERVER net | <SERVER_GATEWAY> |
53 | Force DNS to AdGuard |
| 5 | Pass | SERVER net | any | any | SERVER internet access |
Force DNS rule must be above the internet access pass rule -- first match wins and a catch-all pass above it would bypass DNS enforcement entirely.
Keep firewall rules pointed at the Frigate host's current IP: if you move Frigate to another machine, update rule 1 and delete the old one rather than leaving a stale allow rule behind.
8. Home Assistant Integration¶
Install Frigate Integration (HACS)¶
The official Frigate integration is HACS-only -- it is not in the built-in HA integration store.
- In HA: HACS > Integrations > Search "Frigate" > Install
- Restart Home Assistant
- Settings > Devices & Services > Add Integration > Frigate
- Enter:
http://<YOUR_SERVER_IP>:8971plus a Frigate username and password
Use
http://with Frigate's TLS disabled (as in the config above) -- the integration can't verify Frigate's self-signed cert.
Update the integration with Home Assistant
HACS integrations aren't covered by your image pins. A monthly HA release can break the Frigate integration
(entities fail to load, Error adding entity), so update it from HACS right after upgrading HA, and check the
integration's release notes for the HA version it needs.
What You Get¶
After integration:
- Camera entities for each cam (camera.cam_01 etc.) with live view
- Binary sensors for each detected object class per camera
- sensor.frigate_cam_01_person_count etc.
- Event entities for alerts and detections
- Full clip and snapshot access from HA
MQTT¶
Frigate communicates detections to HA via MQTT (Mosquitto). The HA MQTT integration must already be configured, and
Frigate needs its own broker user (frigate in the Mosquitto ACL). Frigate
publishes under the frigate/ topic prefix; frigate/available reads online once it's connected.
Confirm Frigate is publishing before troubleshooting the HA side (on the broker host):
docker exec -it mosquitto mosquitto_sub -u homeassistant -P '<MQTT_HA_PASSWORD>' -t 'frigate/available' -C 1 -v
Notifications are built on top of this: see Frigate + HA Notifications.
9. Issues?¶
| Issue | Root Cause | Fix |
|---|---|---|
| Camera not in ARP/DHCP | Dahua ships with static 192.168.1.108, not DHCP | Access at 192.168.1.108, set static IoT IP manually |
| RTSP URL 404 / empty ffprobe | Special chars in password break URL parsing | Use alphanumeric-only camera passwords |
| Sub stream capped at 704x480 | Sub Stream 1 is firmware-limited by design | Use Sub Stream 2 (subtype=2) |
ffmpeg restarting every few minutes, failed to decode picture |
VAAPI H.265 decode unstable on one stream (older iGPU) | hwaccel_args: '' on that camera only |
MQTT disconnected / Not authorized |
Missing or wrong MQTT user/password | Set mqtt.user + password: "{FRIGATE_MQTT_PASSWORD}"; check the broker log |
| Masked object alerts again after a model swap | Masks test the box's bottom-centre, which moves with the model | Redraw masks; see Lessons learned |
| libnvcuvid.so.1 missing (NVIDIA) | Debian's nvidia-driver doesn't pull in NVDEC |
sudo apt install libnvcuvid1 |
| Docker broke after nvidia-ctk | nvidia-ctk writes daemon.json, conflicts with -H fd:// |
Remove daemon.json, use deploy.resources in compose |
| ONNX loading None | Frigate 0.16+ ships no YOLO models | Build the YOLOv9 ONNX (section 4) |
| onnx-simplifier build fails | Unpinned resolves to 0.5.0 which pulls broken onnxsim 0.6.2 | Pin to onnx-simplifier==0.4.* |
| Firefox crashes on stream | Snap-packaged Firefox sandbox blocks WebSocket | Use a deb/Flatpak Firefox (e.g. Mozilla's APT repo) instead of the snap |
| Force DNS rule ineffective | Rule was below internet pass rule | Move Force DNS above internet access pass |
Sources & further reading¶
- Frigate: object detectors (OpenVINO, ONNX, YOLOv9 export)
- Frigate: video hardware acceleration (VAAPI/QSV/NVIDIA presets)
- Frigate: enrichments hardware
- Frigate: recording and retention
- Frigate: restream / go2rtc RTSP authentication
- Frigate: configuration file and environment variable substitution
- Frigate: authentication
- Frigate: updating
- Frigate HA integration
- Debian wiki: NVIDIA graphics drivers
- NVIDIA Container Toolkit install guide