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.
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.
Search for the Frigate integration and select it.
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.
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
```