Frigate NVR with Docker and Home Assistant

Frigate NVR with Docker and Home Assistant

I have been using Frigate for a while now and recently I moved my whole Frigate setup first from Home Assistant as an add-on to a VirtualBox VM, and finally to a Dell Optiplex Micro running Frigate in a Docker Container. This post and related video are at the request of a number of you who asked to explain how to install Frigate using Docker and then integrating it with Home Assistant.

For those of you unfamiliar with Frigate, it is an "NVR" of sorts. The definition of NVR is loosely applied but is in the official description by the software's author so we'll go with it. It is a complete solution and is designed for Home Assistant. It comes complete with object detection using OpenCV and Tensorflow and can do this real-time with locally based IP cameras from a number of different manufacturers. You can read more about the specifics on their website.

For the sake of this video, I assume that you have a bare metal system running some variant of supported Linux. In addition, you also have Docker Compose installed. When I had this installed on VirtualBox Ubuntu with a Windows 10 host, I was never able to reliably pass my Coral TPU through to Frigate. Having a TPU greatly reduces overhead on the CPU and allows more cameras for the same or fewer compute resources. With that in mind, the Frigate author recommends bare metal Debian-based distributions. My OptiPlex is running Ubuntu 20.04.

Installing this via docker compose is simple. The hardest part (but not really that hard) is getting the environment set up via a docker-compose.yml file such as the one here.

version: "3.9"
services:
  frigate:
    container_name: frigate
    privileged: true # this may not be necessary for all setups
    restart: unless-stopped
    image: blakeblackshear/frigate:stable
    shm_size: "64mb" # update for your cameras based on calculation above
    devices:
      - /dev/bus/usb:/dev/bus/usb # passes the USB Coral, needs to be modified for other versions
      - /dev/apex_0:/dev/apex_0 # passes a PCIe Coral, follow driver instructions here https://coral.ai/docs/m2/get-started/#2a-on-linux
      - /dev/dri/renderD128 # for intel hwaccel, needs to be updated for your hardware
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /home/mostlychris/frigate/config.yml:/config/config.yml:ro
      - /home/mostlychris/frigate/storage:/media/frigate
      - type: tmpfs # Optional: 1GB of memory, reduces SSD/SD Card wear
        target: /tmp/cache
        tmpfs:
          size: 1000000000
    ports:
      - "5000:5000"
      - "1935:1935" # RTMP feeds
    environment:
      FRIGATE_RTSP_PASSWORD: "yourpassword"

The important parts are the volumes and ports. You need to make sure that you have mapped the local storage on your device to the location in the frigate docker container. You also need to have config.yml ready to go in the mapped directory of your choice. You can see mine below. It is in the home/mostlychris/frigate.

volumes:
      - /etc/localtime:/etc/localtime:ro
      - /home/mostlychris/frigate/config.yml:/config/config.yml:ro
      - /home/mostlychris/frigate/storage:/media/frigate
      - type: tmpfs # Optional: 1GB of memory, reduces SSD/SD Card wear
        target: /tmp/cache

Additionally, make sure the ports specified are free and not used by another application. The left-hand port is the port on your local machine and the right-hand port is the port inside the docker container. If you need to modify a port because that port is already being, make sure you change the left-hand side.

ports:
      - "5000:5000"
      - "1935:1935" # RTMP feeds     

Once you have the docker-compose.yml file set up and you have a valid config.yml for Frigate itself, you can start up the container. Make sure you are in the directory where your docker-compose.yml file and issue the following command (use sudo if you need to).

sudo docker compose up

If all goes well, you'll see log files that show Frigate is up and running.

Sample logfile output

If you are satisfied that it is working correctly, you can ctrl-c out of the running docker container and re-issue the command with a -d flag which will set the container running in the background.

Now that you have that running, you need to integrate into Home Assistant via an integration. Integrations bind external resources or add-ons in to Home Assistant core. For this, go to the Home Assistant intgrations page and add integration.

Add Integration Button on the bottom right of the integrations page

Search for the Frigate integration and select it.

Frigate Integration

You will be presented with a dialog box. An important note here is that you probably won't use the default URL. You will change these to the bare metal device's IP address that you installed Frigate Docker on. In my case, the URL is http://172.16.1.153:5001. You might notice that I have a different port specified. This is because I already had something else running on 5000 on that box, so I changed the docker-compose.yml file to map 5001 on the hardware to 5000 in the Frigate Docker container.

Dialog for integrating Frigate in Home Assistant

If all is successful, you will be presented a dialog showing all the cameras and camera zones you have configured in your Frigate config.yml file.

That about covers the installation of Frigate with Docker and integrating it with Home Assistant. For those asking about the config.yml file I use, I will post it below.

If you want more detail and a walk-through of the whole process, please take a moment to watch my video. Even if you don't need more detail, please watch it anyway ­čśü. It is super helpful and appreciated because, you know, YouTube algorithms and all. While you're at it, take a moment and do the subscribe thing. That also helps a bunch!

Frigate config.yml file at the time of this posting.

ui:
  use_experimental: true

mqtt:
  host: 172.16.1.121
  port: 1883
  topic_prefix: frigate
  client_id: frigate
  user: yourmqttuser
  password: yourmqttpassword
  stats_interval: 300

record:
  expire_interval: 10
 

timestamp_style:
  position: "tl"
  format: "%m/%d/%Y %H:%M:%S"
  color:
    red: 255
    green: 255
    blue: 255thickness: 2
  effect: shadow

cameras:
  driveway:
    ffmpeg:
      inputs:
        - path: rtsp://camerauser:camerapassword@172.16.1.26:554/cam/realmonitor?channel=1&subtype=1
          roles:
            - detect
        - path: rtsp://camerauser:camerapassword@172.16.1.26:554/cam/realmonitor?channel=1&subtype=0
          roles:
            - record
            - rtmp
    detect:                 
      width: 640
      height: 480
      fps: 5
    objects:
      track:
        - person
        - dog
        - bicycle
        - cat
    snapshots:
      enabled: true
      timestamp: true
      bounding_box: true
      required_zones:
        - drivewayclose_in
        - driveway_whole_area
        - driveway_right_side
      crop: True
      height: 500
      retain:
        default: 3
    zones:
      drivewayclose_in:
        coordinates: 0,480,429,480,443,335,460,173,263,133,88,120,36,212,0,279
        objects:
          - person
          - dog
          - cat
          - bicycle
      driveway_whole_area:
        coordinates: 383,52,497,105,569,316,575,480,261,480,0,480,0,225,148,57
        objects:
          - person
          - cat
          - dog
          - bicycle  
      driveway_right_side:
        coordinates: 424,96,345,438,70,405,307,88
        objects:
          - car
    motion:
      mask:
        - 2,465,328,468,330,432,5,431
        - 72,43,154,0,0,0,0,129
    record:
      enabled: True
      retain: 
        days: 0
      events:
        retain:
          default: 5 
          mode: motion 
        required_zones:
          - drivewayclose_in
          - driveway_whole_area
          - driveway_right_side
        pre_capture: 5
        post_capture: 15  

  front_porch:
    ffmpeg:
      inputs:
        - path: rtsp://camerauser:camerapassword@172.16.1.27:554/cam/realmonitor?channel=1&subtype=1
          roles:
            - detect
        - path: rtsp://camerauser:camerapassword@172.16.1.27:554/cam/realmonitor?channel=1&subtype=0
          roles:
            - record
    detect:
      width: 640
      height: 480
      fps: 5
    objects:
      track:
        - person
        - dog
        - bicycle
        - cat
      mask:
        - 0,480,198,480,200,449,0,451
        - 640,0,640,36,640,111,608,135,485,96,504,0
        - 439,200,441,324,512,320,532,261,554,188,540,129,451,134
        - 370,0,356,100,291,79,292,0
    snapshots:
      enabled: true
      timestamp: false
      bounding_box: false
      crop: True
      height: 500
      required_zones:
        - front_porch_close_in
      retain:
        default: 5
    motion:
      mask:
        - 0,480,191,480,193,450,0,449
        - 459,208,545,202,539,135,481,132
    zones:
      front_porch_close_in:
        coordinates: 45,480,362,480,640,480,640,213,554,145,524,252,458,259,408,272,348,70,253,64,181,118,67,178
    record:
      enabled: True
      retain:
        days: 0
        mode: active_objects 
      events:
        retain:
          default: 4
          mode: active_objects 
        required_zones:
         - front_porch_close_in
        pre_capture: 5
        post_capture: 15  

  front_doorbell:
    ffmpeg:
      inputs:
        - path: rtsp://camerauser:gVEixUL4KeH6gg@172.16.1.171:554/cam/realmonitor?channel=1&subtype=0
          roles:
            - record
        - path: rtsp://camerauser:gVEixUL4KeH6gg@172.16.1.171:554/cam/realmonitor?channel=1&subtype=1
          roles:
            - detect
    detect:
      width: 720 
      height: 576
      fps: 15
    objects:
      track:
        - person
        - dog
        - bicycle
        - cat
    snapshots:
      enabled: true
      timestamp: false
      bounding_box: false
      crop: True
      height: 500
      retain:
        default: 5
    motion:
      mask:
        - 720,0,720,28,430,22,428,0
    record:
      enabled: True
      retain:
        days: 0
        mode: active_objects 
      events:
        retain:
          default: 4
          mode: active_objects 
        pre_capture: 10 
        post_capture: 15  

  back_porch:
    ffmpeg:
      inputs:
        - path: rtsp://camerauser:camerapassword@172.16.1.29:554/Streaming/Channels/102
          roles:
            - detect
        - path: rtsp://camerauser:camerapassword@172.16.1.29:554/Streaming/Channels/101
          roles:
            - record
    detect:
      width: 640
      height: 480
      fps: 6
    objects:
      track:
        - person
        - dog
        - cat
        - bird
        - mouse
      filters:
        cat:
          min_score: 0.3
          threshold: 0.5
        dog:
          min_score: 0.3
          threshold: 0.5
      mask:
        - 23,480,333,480,333,442,26,440
        - 640,95,640,0,464,0
        - 258,211,323,246,357,142,274,140
        - 383,342,457,365,477,261,401,232
        - 425,131,553,227,640,251,640,213,607,176,460,88
    snapshots:
      enabled: true
      timestamp: false
      bounding_box: true
      retain:
        default: 3
    motion:
      mask:
        - 337,480,341,437,0,433,0,480,40,480

    zones:
      deck_area:
        coordinates: 0,284,0,457,207,480,474,480,640,480,540,406,392,259,253,106,166,31,108,49,0,72
    record:
      enabled: True
      retain: 
        days: 0
      events:
        retain:
          default: 4
          mode: motion 
        pre_capture: 5
        post_capture: 15  

  deck:
    ffmpeg:
      inputs:
        - path: rtsp://camerauser:camerapassword@172.16.1.28:554/Streaming/Channels/102
          roles:
            - detect
        - path: rtsp://camerauser:camerapassword@172.16.1.28:554/Streaming/Channels/101
          roles:
            - record
    detect:
      width: 640
      height: 480
      fps: 6
    objects:
      track:
        - person
        - dog
        - cat
        - bird
        - mouse
      filters:
        cat:
          min_score: 0.3
          threshold: 0.5
        dog:
          min_score: 0.3
          threshold: 0.5
        person:
          mask:
            - 79,385,107,480,287,480,259,313,107,268
            - 294,82,396,93,411,57,295,44
    snapshots:
      enabled: true
      timestamp: false
      bounding_box: true
      retain:
        default: 4
    motion:
      mask:
        - 374,480,640,480,640,442,372,442   
    record:
      enabled: True
      retain: 
        days: 0
      events:
        retain:
          default: 4
          mode: motion 
        pre_capture: 5
        post_capture: 15  


  garage:
    ffmpeg:
      inputs:
        - path: rtsp://camerauser:camerapassword@172.16.1.33:554/cam/realmonitor?channel=1&subtype=1
          roles:
            - detect
        - path: rtsp://camerauser:camerapassword@172.16.1.33:554/cam/realmonitor?channel=1&subtype=0
          roles:
            - record
    detect:
      width: 640
      height: 480
      fps: 5
    objects:
      track:
        - person
        - dog
        - cat
    snapshots:
      enabled: true
      timestamp: false
      bounding_box: true
      retain:
        default: 3
    record:
      enabled: True
      retain: 
        days: 0
      events:
        retain:
          default: 4
          mode: active_objects
        pre_capture: 5
        post_capture: 15  
    motion:
      mask:
        - 352,93,477,95,554,99,640,94,640,0,343,0
        - 457,480,640,480,640,445,453,444 

### Reolink

  reolink_portable:
    ffmpeg:
      inputs:
        - path: rtsp://camerauser:camerapassword@172.16.1.215:554/h264Preview_01_main
          roles:
            - record 
        - path: rtsp://camerauser:camerapassword@172.16.1.215:554/h264Preview_01_sub
          roles:
            - detect
    detect:
      width: 640
      height: 360
      fps: 7
    objects:
      track:
        - person
        - dog
        - bicycle
        - cat
    snapshots:
      enabled: true
      timestamp: true 
      bounding_box: true
      retain:
        default: 5
    record:
      enabled: true
      retain_days: 0
      events:
        retain:
          default: 5
    motion:
      mask:  
        - 640,360,640,330,411,325,415,360
        - 640,33,640,0,0,0,0,34
        - 640,109,640,170,576,121,589,78
 
detectors: 
  #  cpu1:
  #    type: cpu
  #    num_threads: 3
  coral:
    type: edgetpu
    device: usb

rtmp:
  enabled: false

birdseye:
  enabled: True
  width: 1280 
  height: 720
  quality: 1
  mode: objects
live:
  height: 640
  quality: 1
```