In the winter months, I get spammed with false CCTV motion alerts. With the winter months being darker, headlights from passing traffic often cast shadows and silhouettes that cause the motion zones to trigger when nothing is really happening.

I run a Ubiquiti home network with G3 cameras – if we ignore the issue with the false CCTV alerts, I've been really happy with the setup, and the G3 cameras are still working well. In newer generations of the camera range (G4 and newer), Ubiquiti has added Smart Detection, which can perform person and vehicle detection in addition to basic motion detection.

I wanted to gain the benefits of smarter AI-based CCTV alerts without upgrading all of my cameras, which would be a costly exercise. Instead, I've adopted Frigate NVR and Coral AI to provide smarter CCTV alerts. Frigate NVR can use an artificial intelligence object-detection model to send CCTV alerts based on objects detected rather than more primitive motion detection techniques.

What is Frigate NVR?

Frigate is a Network Video Recorder (NVR) capable of recording camera feeds and performing motion and object detection to highlight events of interest. Frigate is a solution that you must self-host; as a result, all processing and storage happens on your own hardware.

Frigate NVR UI
Frigate NVR UI

Frigate is compatible with any camera that can provide an RTSP feed.

Hardware and Google Coral TPU

I have an NUC dedicated to running Home Assistant that I will also use to run Frigate.

I have also purchased a Google Coral USB Accelerator to use as a hardware detector. Whilst Frigate can run without a hardware detector, a hardware detector will provide much better performance than a CPU because the detector is a device that is optimised for running model inferences.

Google Coral USB Accelerator — Edge TPU coprocessor

The official Frigate documentation recommends using a Coral detector or similar:

It is strongly recommended to use a Google Coral. A $60 device will outperform $2000 CPU. Frigate should work with any supported Coral device from https://coral.ai

Installing Frigate NVR

I am installing Frigate on my NUC, which runs Home Assistant OS.

Firstly, navigate to the Add-on store via Settings > Add-ons > Add-on Store.

A new repository will need to be added using the repositories menu option in the top right:

Select "Repositories" menu option from Add-on store
Settings > Add-ons > Add-on Store

Add the repository:

https://github.com/blakeblackshear/frigate-hass-addons
Frigate repo added to Home Assistant Add-on Store
Frigate repo added to Home Assistant Add-on Store

You will now be able to install the Frigate add-on.

After some experimentation, I found that I have the best results using "Frigate (Full Access)" with Protection mode disabled because I would otherwise encounter the following error:

Failed to load delegate from libedgetpu.so.1.0

Protection mode is designed to limit and restrict the level of access that an Add-on has by default. The problem I had with the standard "Frigate" add-on was that it couldn't see my Coral TPU. I therefore opted for the Full Access version with protection mode disabled.

My Configuration

Below is the configuration that I use for Frigate.

In order to configure Frigate for your cameras, you'll need access to the RSTP feeds. For UniFi cameras, you can get this from UniFi Protect by clicking on the camera in question, opening up the Settings panel and enabling the relevant resolution feed under the Advanced section.

In short, my Frigate config:

  • Publishes events which can be picked up by the Home Assistant integration (which we'll cover later)
  • Uses hardware acceleration with FFmpeg, because my device supports this.
  • Sets up each camera with respective motion masks
  • Enables the use of the USB Coral TPU
  • Records events and associated clips for up to 21 days

I have also restricted detection processing to 5 frames per second as I want Frigate to be accurate with its detection, but I also don't want it to dominate my NUCs resources. Based on various articles, 5 fps seems widely recommended, and I've opted for this without regrets.

mqtt:
  host: 192.168.1.5
  user: mymqttuser
  password: mymqttpassword

ffmpeg:
  hwaccel_args: 
    - -hwaccel
    - vaapi 
    - -hwaccel_device 
    - /dev/dri/renderD128 
    - -hwaccel_output_format 
    - yuv420p

cameras:
  camera1:
    ffmpeg:
      inputs:
        - path: rtsp://192.168.1.2:7447/camera1
          roles:
            - detect
    detect:
      width: 1920
      height: 1080
      fps: 5
    motion:
      mask:
        - 750,0,0,0,0,485
  camera2:
    ffmpeg:
      inputs:
        - path: rtsp://192.168.1.2:7447/camera2
          roles:
            - detect
    detect:
      width: 1600
      height: 1200
      fps: 5
    motion:
      mask:
        - 750,0,0,0,0,485

  camera3:
    ffmpeg:
      inputs:
        - path: rtsp://192.168.1.2:7447/camera3
          roles:
            - detect
    detect:
      width: 1920
      height: 1080
      fps: 5
    motion:
      mask:
        - 750,0,0,0,0,485

  camera4:
    ffmpeg:
      inputs:
        - path: rtsp://192.168.1.2:7447/camera4
          roles:
            - detect
    detect:
      width: 1920
      height: 1080
      fps: 5
    motion:
      mask:
        - 750,0,0,0,0,485

  camera5:
    ffmpeg:
      inputs:
        - path: rtsp://192.168.1.2:7447/camera5
          roles:
            - detect
    detect:
      width: 1920
      height: 1080
      fps: 5

detectors:
  coral:
    type: edgetpu
    device: usb

record:
  enabled: True
  events:
    retain:
      default: 21

snapshots:
  # Optional: Enable writing jpg snapshot to /media/frigate/clips (default: shown below)
  enabled: True
  # Optional: save a clean PNG copy of the snapshot image (default: shown below)
  clean_copy: True
  # Optional: print a timestamp on the snapshots (default: shown below)
  timestamp: False
  # Optional: draw bounding box on the snapshots (default: shown below)
  bounding_box: True
  # Optional: crop the snapshot (default: shown below)
  crop: False
  # Optional: Camera override for retention settings (default: global values)
  retain:
    # Required: Default retention days (default: shown below)
    default: 21

Home Assistant Integration

Although the previous steps have installed Frigate, which will post events to MQTT based on the configuration above, we need to install the integration for Home Assistant, which will then consume these events.

This can be done by going into Devices & services and using the Add Integration option from the Integrations tab to add a new Frigate integration.

When you do this, you will be prompted for the Frigate URL to connect to:

Home Assistant - Frigate Integration URL prompt

Depending on how you have installed Frigate will depend on what the URL should be. If you have installed it like I have as a Home Assistant Add-on, the URL will be http://ccab4aaf-frigate:5000 or http://ccab4aaf-frigate-fa:5000 depending on whether you have used the Full Access version or not.

When Home Assistant connects to Frigate, it will set up a comprehensive set of devices and entities, for example:

Entites for a single camera in Home Assistant provided by Frigate
Entities for a single camera in Home Assistant provided by Frigate

Because the doorbell is set up to perform person object detection, Frigate will configure a number of entities on the device just for the person detection. For instance, I have:

  • a camera entity that shows the last event captured
  • a "person count" entity that shows the number of people currently detected
  • a "person occupancy" entity to indicate if any persons have been detected

Notifications

I also set up Home Assistant to send us push notifications whenever Frigate detects an event. This was done using a simple automation in Home Assistant:

alias: Frigate Notifications
mode: single
description: ""
trigger:
  - platform: mqtt
    topic: frigate/events
    payload: new
    value_template: "{{ value_json.type }}"
action:
  - service: notify.family
    data:
      message: 'A {{trigger.payload_json["after"]["label"]}} was detected.'
      data:
        image: >-
          https://my-home-assistant-url/api/frigate/notifications/{{trigger.payload_json["after"]["id"]}}/thumbnail.jpg
        tag: '{{trigger.payload_json["after"]["id"]}}'
        when: '{{trigger.payload_json["after"]["start_time"]|int}}'
        entity_id: camera.{{trigger.payload_json["after"]["camera"] | replace("-","_") | lower}}

Performance

Before adopting Frigate, the CPU utilisation for my NUC running Home Assistant would sit between 10-20%, depending on the workload.

When I first installed and configured Frigate with 5 cameras but without Coral or hardware acceleration, the CPU usage jumped to around ~60%. When I added both Coral and hardware acceleration, this dropped to around 40-50%.

Memory usage also typically sits around 1.5-2.0 GB out of the 8GB RAM available on my NUC.

htop showing CPU and memory utilisation for Home Assistant and Frigate
htop showing CPU and memory utilisation for Home Assistant and Frigate

Whilst I'm quoting hard stats here, I haven't noticed any degradation in the performance of Home Assistant.

UniFi Protect vs Frigate NVR

It is worth noting that I still run UniFi Protect on my CloudKey – in part to serve up the RSTP feeds, but I also continue to use UniFi Protect for 24/7 video recording as the CloudKey has plenty of storage built in.

I am purely using Frigate NVR to provide alerts for activity and to record clips and snapshots when any activity of interest occurs so that these can be provided with the push notification. As a result, I have disabled all motion-based notifications in UniFi Protect.

Conclusion

I've put off doing this project for a while as it felt like a lot of effort to migrate CCTV notifications away from UniFi Protect. However, the entire process has been straightforward and I've been running Frigate for a number of weeks now, and the number of false CCV notifications I receive is now nearly non-existent!