Frigate NVR
Frigate (blakeblackshear/frigate) is a self-hosted, open-source NVR built around real-time object detection. This driver connects to a Frigate server on the LAN over its REST API (/api/… on port 5000 by default), polls per-camera events for motion and object-class detections (person, car, dog, license plate, …), and exposes per-camera toggles for object detection, motion detection, continuous recording, and snapshot capture.
One GEM device represents a single Frigate server. Each Frigate camera that GEM should track becomes a zone whose address is the camera name from Frigate's config.
Prerequisites
- A running Frigate server, version 0.13.x or newer, reachable on the LAN from the GEM host. Confirm this in a browser first — the Frigate UI should load at
http://<frigate-host>:5000/. - One or more cameras defined in Frigate's
config.yml(or via the web UI on 0.14+) and appearing undercameras:in/api/config. - If Frigate's native authentication is enabled (0.14+ with
AUTHENTICATIONon), a username and password GEM can use to log in. On earlier builds — or when Frigate is fronted by a reverse proxy that handles auth — leave both blank. - TCP to the Frigate host on the configured port (default
5000) open from the GEM host.
MQTT is Frigate's real-time event bus but is deliberately not required here. The driver reads from /api/events on its poll interval so an integrator can add Frigate without also standing up a broker; adding MQTT for sub-second reactions is a future upgrade path, not a prerequisite.
Setup
- Verify Frigate is reachable in a browser at
http://<frigate-host>:<port>/. Sort out any networking issues at this step, not from inside GEM. - In GEM admin, add a device with the Frigate NVR driver, placed under a Security or Cameras subsystem. Only one GEM device per Frigate server — cameras are added as zones underneath.
- Set the device attributes:
ip— Frigate host or IP.port— HTTP port Frigate is bound to. Default5000.protocol—http, orhttpsif Frigate sits behind a TLS-terminating reverse proxy.usernameandpassword— only when Frigate's native auth is enabled. Leave both blank otherwise.
- Save and reload the device. On boot the driver hits
/api/config, notes the configured cameras, and starts polling/api/eventseverystatus_intervalms. - Run the
get_camerascommand to print every camera name Frigate knows about. - For each camera you want to track, add a zone under the same subsystem, bind it to the Frigate device, and set its address to the camera name exactly as it appears in Frigate — camera names are case-sensitive and any renames in Frigate will break the binding until zone address is updated to match.
GEM does not auto-create zones from Frigate discovery. A camera only surfaces state once a zone whose address matches its Frigate name exists and is bound to the Frigate device. Cameras without a matching zone still appear in get_cameras, but their events are ignored — nothing is tracked for them until you add the zone. Copy the exact name from get_cameras.
Attribute reference
Device
| Attribute | Required | Description |
|---|---|---|
ip | yes | LAN IP / hostname of the Frigate server. |
port | no | HTTP port. Defaults to 5000. |
protocol | no | http (default) or https when Frigate is behind a TLS reverse proxy. |
username | no | Only when Frigate 0.14+ native auth is enabled. |
password | no | Only when Frigate 0.14+ native auth is enabled. Stored encrypted; used to mint a JWT held in memory. |
status_interval | no | Event-poll interval in milliseconds. Defaults to 3000. Lower it for tighter reaction times at the cost of more requests. |
Zone
| Attribute | Description |
|---|---|
state | motion while any active event exists for the camera, clear when the last event ends. Driver-managed. |
last_motion | Unix-millisecond timestamp of the last event start. Driver-managed. |
person, car, dog, license_plate, … | Object-class flags — 1 while a detected object of that class is present, 0 when its event ends. One attribute per object label Frigate emits, converted to snake_case. A flag auto-clears after 120 s if the event's end frame is never observed (server restart, network blip mid-detection). |
The zone address is required and must match the camera name in Frigate's config.
Commands
| Command | Args | Description |
|---|---|---|
get_config | — | Return the full /api/config document (Frigate's live config as JSON). |
get_cameras | — | List the camera names Frigate is running. |
get_stats | — | Return /api/stats — process and camera runtime stats. |
get_events | limit | Return the most recent events (default 50). |
snapshot | address | Fetch latest.jpg for the camera and save it under static/snapshots/<device-id>-<camera>.jpg. Returns the served URL, usable directly in a UI image widget or a notification. |
set_detect | address, state | Toggle object detection for a camera. state = ON / OFF. |
set_motion | address, state | Toggle motion detection for a camera. |
set_recording | address, state | Toggle continuous / event recording for a camera. |
set_snapshots | address, state | Toggle snapshot capture for a camera. |
restart | — | Ask Frigate to restart itself via /api/restart. |
Event polling
Every status_interval the driver requests /api/events?limit=50&after=<lastId>, walks the new events oldest-first, and applies them:
- On an event start (no
end_time) — the zone'sstateflips tomotion,last_motiongets the start timestamp, and the per-object-class flag (person,car, …) is set to1. - On an event end (
end_timepopulated) — the per-object-class flag goes back to0and the zonestateflips back toclear. The driver does not reference-count overlapping detections: the first event end it observes flipsstatetoclear, even if another object is still being tracked on the same camera (that object's own class flag stays1until its event ends or the 120 s timer clears it). - Missed end frames — a 120 s per-flag timer clears any object-class flag whose end frame never arrives, and a 30 s per-camera timer flips
stateback toclearif no further activity is observed. This bounds the "stuck at motion" failure mode when Frigate crashes mid-event.
The very first poll after connect seeds the "last seen event id" without emitting any state changes, so pre-existing events don't spam the log on startup.
Authentication
Frigate 0.13 and earlier have no built-in authentication — the API is open on the LAN and usually fronted by a reverse proxy that handles it externally. Leave username and password blank in that case.
Frigate 0.14 added native authentication with JWT. When the device has both username and password set, the driver:
- POSTs to
/api/loginon connect with{user, password}and stores the returned JWT. - Sends it in an
Authorization: Bearer …header on every subsequent request. - If any request returns 401 (token expired or invalidated), the driver re-logs in once and retries the request. A second 401 in a row surfaces
frigate 401 after re-login attemptas the error.
The token is held in memory only. A device reload triggers a fresh login. Persisting the token across restarts is a possible future addition but not needed for correctness — Frigate's JWTs are cheap to mint.
Limitations
- HTTP polling only in this build. MQTT-backed sub-second reactions require a broker and are not wired through yet.
status_interval(default 3 s) is the practical floor. - No live video. Snapshots only. The RTSP restream URL published by Frigate is not surfaced as a command here — use the ONVIF driver on the camera itself when you need streaming.
- PTZ control is not exposed. Frigate has a PTZ command surface for supported cameras; a future revision may add
ptz/ptz_moveverbs. - Manual events and audio detections are not tracked separately. They still show up in the events feed, so the zone
statewill still flip tomotion, but the object-class breakdown is what the driver focuses on. set_detect/set_motion/set_recording/set_snapshotslive under/api/<camera>/<endpoint>/setand are present in 0.13+. Very old builds without those routes return 404 — leave the toggles alone and manage state inconfig.ymlon those.
Troubleshooting
get_camerasreturns an empty list. Frigate's/api/configreturned no cameras or a non-200. Loadhttp://<host>:5000/api/configdirectly and confirm thecameras:block is populated. If it's empty, fixconfig.ymlfirst.- All commands return
frigate GET … status 401. Frigate's native auth is on butusername/passwordon the device are blank or wrong. Check the Frigate server log for the login attempt. - Zone
statestaysclearduring actual detections. Almost always a wrongzone.address— confirm againstget_cameras; names are case-sensitive. snapshotreturnssnapshot not available for camera <name>. Frigate returns 404 when snapshots are disabled per-camera or the camera has never captured one. Enable withset_snapshots ONand wait for a detection.- Object-class flags stuck at
1. Frigate lost the event's end frame (a server restart mid-detection is the usual cause). The 120 s auto-clear will resolve it; if it keeps happening, look at Frigate's own logs for restarts or watchdog kills. - Poll interval feels too slow. Lower
status_intervalon the device (500 ms is the enforced minimum). For real sub-second reaction times, wire an MQTT broker and consider Frigate → MQTT as a separate ingress alongside this driver.
Related documentation
- Devices — adding the Frigate server as a single device.
- Zones — creating one zone per Frigate camera, addressed by the camera name.
- Subsystems — the Security / Cameras subsystem the Frigate device and its camera zones live under.
- Commands — running
snapshot,set_detect, and the recording / snapshots toggles from the admin UI, macros, or automations. - Triggers — firing automations off a camera zone's
stateflipping tomotionor a class flag likepersongoing to1. - ONVIF — the vendor-neutral camera path when live RTSP video is needed instead of Frigate's event surface.
- UniFi Protect — the closest commercial-NVR equivalent for reference.