The stack

  • Cameras — any camera that exposes an RTSP / RTMP stream. Most ONVIF cameras (Reolink, Amcrest, Hikvision, Annke, Dahua) and Frigate-specific options like the Reolink Duo / Doorbell Pro.
  • Frigate — the recorder + detector. One container; reads RTSP, runs detection on a sampled subset of frames, writes recordings to disk.
  • An AI accelerator (not strictly required, but the difference between "happy" and "100% CPU on a quad-core"). Options below.
  • An MQTT broker (see that tutorial) — Frigate publishes detection events; Home Assistant / automations subscribe.

Pick an accelerator

  • Google Coral USB / M.2 — the canonical Frigate pick. Detects ~20 ms / inference; about $60. The M.2 form factor needs an M.2-E key slot or a PCIe adapter.
  • Intel iGPU (8th gen Core or newer) with OpenVINO — works well, no extra hardware needed, slightly slower than Coral.
  • NVIDIA GPU — overkill for detection alone but useful when running other inference on the same box.
  • CPU only — fine for one or two cameras at low resolution; doesn't scale.

Plan storage

Frigate writes two stream copies:

  • The detect substream — low resolution (640×480), used only for object detection. Discarded after analysis.
  • The record stream — high resolution, kept on disk. Continuous, event-only, or hybrid.

Rule of thumb: 4 cameras at 4 MP 24/7 continuous ≈ 200–300 GB/day. Event-only recording is much smaller. Always put recordings on a separate dedicated disk or volume — the writes are relentless.

Install via Docker Compose

# docker-compose.yml
services:
  frigate:
    container_name: frigate
    image: ghcr.io/blakeblackshear/frigate:stable
    restart: unless-stopped
    privileged: true       # for hardware accelerator access
    shm_size: "512mb"      # for camera frame buffer; scale with #cameras

    devices:
      - /dev/bus/usb:/dev/bus/usb   # for Coral USB
      - /dev/dri/renderD128:/dev/dri/renderD128  # Intel iGPU

    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./config:/config
      - /mnt/recordings/frigate:/media/frigate
      - type: tmpfs
        target: /tmp/cache
        tmpfs: { size: 1000000000 }   # 1 GB
    ports:
      - "5000:5000"        # web UI
      - "8554:8554"        # RTSP restream
      - "8555:8555/tcp"    # WebRTC
      - "8555:8555/udp"
    environment:
      FRIGATE_RTSP_PASSWORD: '<long-random>'

Configuration

Frigate's config is one YAML file at ./config/config.yml:

mqtt:
  enabled: true
  host: mqtt.lab.example.com
  user: frigate
  password: '<mqtt-password>'

detectors:
  coral:
    type: edgetpu
    device: usb
  # or, for OpenVINO on Intel iGPU:
  # ov:
  #   type: openvino
  #   device: GPU

go2rtc:
  streams:
    backyard:
      - rtsp://camera-user:camera-pass@192.168.1.50:554/h264Preview_01_main
    backyard_sub:
      - rtsp://camera-user:camera-pass@192.168.1.50:554/h264Preview_01_sub

cameras:
  backyard:
    ffmpeg:
      inputs:
        - path: rtsp://127.0.0.1:8554/backyard
          input_args: preset-rtsp-restream
          roles: [record]
        - path: rtsp://127.0.0.1:8554/backyard_sub
          input_args: preset-rtsp-restream
          roles: [detect]

    detect:
      enabled: true
      width:  640
      height: 480
      fps:    5

    objects:
      track: [person, dog, car, cat]
      filters:
        person: { min_score: 0.6, threshold: 0.75 }

    record:
      enabled: true
      retain:
        days: 14
        mode: motion          # only keep frames with motion across 14 days
      events:
        retain:
          default: 30         # event-tagged clips kept for 30 days

    zones:
      driveway:
        coordinates: 0,0,640,0,640,300,0,300
        objects: [person, car]

    snapshots:
      enabled: true
      retain: { default: 30 }
      required_zones: [driveway]

Two cameras worth of config explained

  • go2rtc — Frigate's bundled restreamer. Cameras have one source feeding both detect and record paths; without it, FFmpeg opens two simultaneous RTSP sessions per camera, which some cameras don't tolerate.
  • Two FFmpeg inputs per camera — main stream for recording, substream for detection. Most ONVIF cameras provide both.
  • Zones — named polygons within the frame. An event is only emitted if a tracked object enters the zone. This is how "ignore the neighbour's dog but alert on people in the driveway" gets implemented.
  • objects.track — the COCO classes the model can detect (person, car, dog, cat, bicycle, motorcycle, etc.). The default ssd_mobilenet_v2 model trained on COCO handles common indoor/outdoor objects well.

MQTT events and Home Assistant

Every detection / event publishes to frigate/events:

{
  "type": "new" | "update" | "end",
  "after": {
    "id": "1727450000.12345-abc",
    "camera": "backyard",
    "label": "person",
    "zones": ["driveway"],
    "score": 0.91,
    "box": [123, 456, 250, 580],
    "snapshot_time": 1727450000.12,
    "current_zones": ["driveway"]
  }
}

Home Assistant's official Frigate integration parses these and exposes per-camera, per-object sensors plus a media_player for the live stream. Set up via Settings → Devices & Services → Add Integration → Frigate (after installing it from HACS or the built-in repo).

The web UI

At http://<host>:5000/:

  • Live camera grid with WebRTC playback
  • Events timeline with filterable object/zone/camera
  • Per-event clip viewer with the bounding box overlaid
  • Settings → Debug feed with the live detection annotations

The web UI is functional but minimal; for full home-automation surface integration, Home Assistant's Frigate card is the polished consumer view.

Hardening

  • Put Frigate behind a reverse proxy with auth (it has its own auth in 0.14+; older versions need an outer proxy with basic auth or an OIDC layer via Authentik / Step CA).
  • Camera RTSP credentials are baked into the config — restrict the YAML's file permissions and don't commit secrets to a public repo.
  • Run cameras on an isolated VLAN with no internet access. Most cheap IP cameras phone home in ways their datasheets don't disclose.

Performance worth knowing

  • One Coral TPU handles roughly 5–8 cameras at 5 FPS detection. Two Corals or a more powerful GPU for more.
  • Detection at 5 FPS × 640×480 is enough for object tracking; pushing to 10 FPS doubles inference work for marginal accuracy gain.
  • Recording bitrate — most cameras default to 8–12 Mbps for 4 MP H.264. H.265 cuts that in half if the camera and downstream players support it.