A complete and local NVR designed for HomeAssistant with AI object detection. Uses OpenCV and Tensorflow to perform realtime object detection locally for IP cameras.
Use of a [Google Coral Accelerator](https://coral.ai/products/) is optional, but highly recommended. The Coral will outperform even the best CPUs and can process 100+ FPS with very little overhead.
Cameras that output H.264 video and AAC audio will offer the most compatibility with all features of Frigate and HomeAssistant. It is also helpful if your camera supports multiple substreams to allow different resolutions to be used for detection, streaming, clips, and recordings without re-encoding.
Use the [helm chart](https://github.com/k8s-at-home/charts/tree/master/charts/frigate).
### Virtualization
For ideal performance, Frigate needs access to underlying hardware for the Coral and GPU devices for ffmpeg decoding. Running Frigate in a VM on top of Proxmox, ESXi, Virtualbox, etc. is not recommended. The virtualization layer typically introduces a sizable amount of overhead for communication with Coral devices.
#### Proxmox
Some people have had success running Frigate in LXC directly with the following config:
The default shm-size of 64m is fine for setups with 3 or less 1080p cameras. If frigate is exiting with "Bus error" messages, it could be because you have too many high resolution cameras and you need to specify a higher shm size.
HassOS users can manage their configuration directly in the addon Configuration tab. For other installations, the default location for the config file is `/config/config.yml`. This can be overridden with the `CONFIG_FILE` environment variable. Camera specific ffmpeg parameters are documented [here](docs/cameras.md).
Up to 4 inputs can be configured for each camera and the role of each input can be mixed and matched based on your needs. This allows you to use a lower resolution stream for object detection, but create clips from a higher resolution stream, or vice versa.
Each role can only be assigned to one input per camera. The options for roles are as follows:
|Role|Description|
|----|-----|
|`detect`|Main feed for object detection|
|`clips`|Clips of events from objects detected in the `detect` feed. [docs](#recording-clips)|
|`record`|Saves 60 second segments of the video feed. [docs](#247-recordings)|
|`rtmp`|Broadcast as an RTMP feed for other services to consume. [docs](#rtmp-streams)|
- **Google Coral**: It is strongly recommended to use a Google Coral, but Frigate will fall back to CPU in the event one is not found. Offloading TensorFlow to the Google Coral is an order of magnitude faster and will reduce your CPU load dramatically. A $60 device will outperform $2000 CPU.
- **Resolution**: For the `detect` input, choose a camera resolution where the smallest object you want to detect barely fits inside a 300x300px square. The model used by Frigate is trained on 300x300px images, so you will get worse performance and no improvement in accuracy by using a larger resolution since Frigate resizes the area where it is looking for objects to 300x300 anyway.
- **FPS**: 5 frames per second should be adequate. Higher frame rates will require more CPU usage without improving detections or accuracy. Reducing the frame rate on your camera will have the greatest improvement on system resources.
- **Hardware Acceleration**: Make sure you configure the `hwaccel_args` for your hardware. They provide a significant reduction in CPU usage if they are available.
- **Masks**: Masks can be used to ignore motion and reduce your idle CPU load. If you have areas with regular motion such as timestamps or trees blowing in the wind, frigate will constantly try to determine if that motion is from a person or other object you are tracking. Those detections not only increase your average CPU usage, but also clog the pipeline for detecting objects elsewhere. If you are experiencing high values for `detection_fps` when no objects of interest are in the cameras, you should use masks to tell frigate to ignore movement from trees, bushes, timestamps, or any part of the image where detections should not be wasted looking for objects.
Frigate works on Raspberry Pi 3b/4 and x86 machines. It is recommended to update your configuration to enable hardware accelerated decoding in ffmpeg. Depending on your system, these parameters may not be compatible.
Nvidia GPU based decoding via NVDEC is supported, but requires special configuration. See the [nvidia NVDEC documentation](docs/nvdec.md) for more details.
By default Frigate will look for a USB Coral device and fall back to the CPU if it cannot be found. If you have PCI or multiple Coral devices, you need to configure your detector devices in the config file. When using multiple detectors, they run in dedicated processes, but pull from a common queue of requested detections across all cameras.
Frigate supports `edgetpu` and `cpu` as detector types. The device value should be specified according to the [Documentation for the TensorFlow Lite Python API](https://coral.ai/docs/edgetpu/multiple-edgetpu/#using-the-tensorflow-lite-python-api).
Single USB Coral:
```yaml
detectors:
coral:
type: edgetpu
device: usb
```
Multiple USB Corals:
```yaml
detectors:
coral1:
type: edgetpu
device: usb:0
coral2:
type: edgetpu
device: usb:1
```
Mixing Corals:
```yaml
detectors:
coral_usb:
type: edgetpu
device: usb
coral_pci:
type: edgetpu
device: pci
```
CPU Detectors (not recommended):
```yaml
detectors:
cpu1:
type: cpu
cpu2:
type: cpu
```
[Back to top](#documentation)
## Reducing False Positives
Tune your object filters to adjust false positives: `min_area`, `max_area`, `min_score`, `threshold`.
For object filters in your configuration, any single detection below `min_score` will be ignored as a false positive. `threshold` is based on the median of the history of scores (padded to 3 values) for a tracked object. Consider the following frames when `min_score` is set to 0.6 and threshold is set to 0.85:
| Frame | Current Score | Score History | Computed Score | Detected Object |
In frame 2, the score is below the `min_score` value, so frigate ignores it and it becomes a 0.0. The computed score is the median of the score history (padding to at least 3 values), and only when that computed score crosses the `threshold` is the object marked as a true positive. That happens in frame 4 in the example.
[Back to top](#documentation)
## Masks
The following types of masks are supported:
-`poly`: (Recommended) List of x,y points like zone configuration
-`base64`: Base64 encoded image file
-`image`: Image file in the `/config` directory
`base64` and `image` masks must be the same aspect ratio and resolution as your camera.
1. Download a camera snapshot image with the same resolution as the camera feed (`/<camera_name>/latest.jpg`).
1. Upload the image to https://www.image-map.net/
1. Select "shape" poly - start in the lowest left corner and place the first marker (point) and continue upwards and then to the right until the polygon shape covers the area that you want to mask out (ignore).
1. When you are finished with the polygon click "Show me the code!" and copy all coordinates (point), ie. `"0,461,3,0,1919,0,1919,843,1699,492,1344,458,1346,336,973,317,869,375,866,432"`
1. Adjust any -1 values to 0 and then add it all to the configuration (see the example configuration for correct indentation and placement)
Example of a finished row corresponding to the below example image:
You can test your mask by temporarily configuring it as a [zone](#zones) and enabling `draw_zones` in your config. Zones are visible on the [MJPEG feed](#camera_name).
Zones allow you to define a specific area of the frame and apply additional filters for object types so you can determine whether or not an object is within a particular area. Zones cannot have the same name as a camera. If desired, a single zone can include multiple cameras if you have multiple cameras covering the same area by configuring zones with the same name for each camera.
During testing, `draw_zones` should be set in the config to draw the zone on the frames so you can adjust as needed. The zone line will increase in thickness when any object enters the zone. Zones are visible on the [MJPEG feed](#camera_name).
**Note**: Previous versions of frigate included `-vsync drop` in input parameters. This is not compatible with FFmpeg's segment feature and must be removed from your input parameters if you have overrides set.
Frigate can save video clips without any CPU overhead for encoding by simply copying the stream directly with FFmpeg. It leverages FFmpeg's segment functionality to maintain a cache of video for each camera. The cache files are written to disk at `/tmp/cache` and do not introduce memory overhead. When an object is being tracked, it will extend the cache to ensure it can assemble a clip when the event ends. Once the event ends, it again uses FFmpeg to assemble a clip by combining the video clips without any encoding by the CPU. Assembled clips are are saved to `/media/frigate/clips`. Clips are retained according to the retention settings defined on the config for each object type.
Event and clip information is managed in a sqlite database at `/media/frigate/clips/frigate.db`. If that database is deleted, clips will be orphaned and will need to be cleaned up manually. They also won't show up in the Media Browser within HomeAssistant.
-`max_seconds`: This limits the size of the cache when an object is being tracked. If an object is stationary and being tracked for a long time, the cache files will expire and this value will be the maximum clip length for the *end* of the event. For example, if this is set to 300 seconds and an object is being tracked for 600 seconds, the clip will end up being the last 300 seconds. Defaults to 300 seconds.
-`objects`: List of object types to save clips for. Object types here must be listed for tracking at the camera or global configuration. Defaults to all tracked objects.
**Note**: Previous versions of frigate included `-vsync drop` in input parameters. This is not compatible with FFmpeg's segment feature and must be removed from your input parameters if you have overrides set.
24/7 recordings can be enabled and are stored at `/media/frigate/recordings`. The folder structure for the recordings is `YYYY-MM/DD/HH/<camera_name>/MM.SS.mp4`. These recordings are written directly from your camera stream without re-encoding and are available in HomeAssistant's media browser. Each camera supports a configurable retention policy in the config.
[Back to top](#documentation)
## RTMP Streams
Frigate can re-stream your video feed as a RTMP feed for other applications such as HomeAssistant to utilize it. This allows you to use a video feed for detection in frigate and HomeAssistant live view at the same time without having to make two separate connections to the camera. The video feed is copied from the original video feed directly to avoid re-encoding. This feed does not include any annotation by Frigate.
The best way to integrate with HomeAssistant is to use the [official integration](https://github.com/blakeblackshear/frigate-hass-integration). When configuring the integration, you will be asked for the `Host` of your frigate instance. This value should be the url you use to access Frigate in the browser and will look like `http://<host>:5000/`. If you are using HassOS with the addon, the host should be `http://ccab4aaf-frigate:5000` (or `http://ccab4aaf-frigate-beta:5000` if your are using the beta version of the addon). HomeAssistant needs access to port 5000 (api) and 1935 (rtmp) for all features. The integration will setup the following entities within HomeAssistant:
- Rich UI with thumbnails for browsing event clips
- Rich UI for browsing 24/7 recordings by month, day, camera, time
API:
- Notification API with public facing endpoints for images in notifications
### Notifications
Frigate publishes event information in the form of a change feed via MQTT. This allows lots of customization for notifications to meet your needs. Event changes are published with `before` and `after` information as shown [here](#frigateevents).
Here is a simple example of a notification automation of events which will update the existing notification for each change. This means the image you see in the notification will update as frigate finds a "better" image.
Note that the image url has `?format=android`. This adjusts the aspect ratio to be idea for android notifications. For iOS optimized snapshots, no format parameter needs to be passed.
You can find some additional examples for notifications [here](docs/notification-examples.md).
|`bbox`|int|Show bounding boxes for detected objects (0 or 1)|
|`timestamp`|int|Print the timestamp in the upper left (0 or 1)|
|`zones`|int|Draw the zones on the image (0 or 1)|
|`mask`|int|Overlay the mask on the image (0 or 1)|
|`motion`|int|Draw blue boxes for areas with detected motion (0 or 1)|
|`regions`|int|Draw green boxes for areas where object detection was run (0 or 1)|
You can access a higher resolution mjpeg stream by appending `h=height-in-pixels` to the endpoint. For example `http://localhost:5000/back?h=1080`. You can also increase the FPS by appending `fps=frame-rate` to the URL such as `http://localhost:5000/back?fps=10` or both with `?fps=10&h=1000`.
Events from the database. Accepts the following query string parameters:
|param|Type|Description|
|----|-----|--|
|`before`|int|Epoch time|
|`after`|int|Epoch time|
|`camera`|str|Camera name|
|`label`|str|Label name|
|`zone`|str|Zone name|
|`limit`|int|Limit the number of events returned|
### `/events/summary`
Returns summary data for events in the database. Used by the HomeAssistant integration.
### `/events/<id>`
Returns data for a single event.
### `/events/<id>/snapshot.jpg`
Returns a snapshot for the event id optimized for notifications. Works while the event is in progress and after completion. Passing `?format=android` will convert the thumbnail to 2:1 aspect ratio.
Publishes a jpeg encoded frame of the detected object type. When the object is no longer detected, the highest confidence image is published or the original image
The labelmap can be customized to your needs. A common reason to do this is to combine multiple object types that are easily confused when you don't need to be as granular such as car/truck. You must retain the same number of labels, but you can change the names. To change:
- Download the [COCO labelmap](https://dl.google.com/coral/canned_models/coco_labels.txt)
- Modify the label names as desired. For example, change `7 truck` to `7 car`
- Mount the new file at `/labelmap.txt` in the container with an additional volume
If you see repeated "On connect called" messages in your config, check for another instance of frigate. This happens when multiple frigate containers are trying to connect to mqtt with the same client_id.