From 616eb5f96af95a78f73c2c20388a50f823c49a00 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Fri, 16 Feb 2024 06:09:30 -0600 Subject: [PATCH 01/14] Use zoom space id in Onvif RelativeMove setup (#9859) * use zoom space id in onvif relativemove setup * better handle cases when zooming is disabled --- frigate/ptz/onvif.py | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/frigate/ptz/onvif.py b/frigate/ptz/onvif.py index a7a2cd68b..c4f0fbc01 100644 --- a/frigate/ptz/onvif.py +++ b/frigate/ptz/onvif.py @@ -151,7 +151,10 @@ class OnvifController: # autoracking relative panning/tilting needs a relative zoom value set to 0 # if camera supports relative movement - if self.config.cameras[camera_name].onvif.autotracking.zooming: + if ( + self.config.cameras[camera_name].onvif.autotracking.zooming + != ZoomingModeEnum.disabled + ): zoom_space_id = next( ( i @@ -182,23 +185,21 @@ class OnvifController: try: if ( self.config.cameras[camera_name].onvif.autotracking.zooming - == ZoomingModeEnum.relative + != ZoomingModeEnum.disabled ): if zoom_space_id is not None: move_request.Translation.Zoom.space = ptz_config["Spaces"][ "RelativeZoomTranslationSpace" - ][0]["URI"] + ][zoom_space_id]["URI"] + else: + move_request.Translation.Zoom = [] except Exception: - if ( - self.config.cameras[camera_name].onvif.autotracking.zooming - == ZoomingModeEnum.relative - ): - self.config.cameras[ - camera_name - ].onvif.autotracking.zooming = ZoomingModeEnum.disabled - logger.warning( - f"Disabling autotracking zooming for {camera_name}: Relative zoom not supported" - ) + self.config.cameras[ + camera_name + ].onvif.autotracking.zooming = ZoomingModeEnum.disabled + logger.warning( + f"Disabling autotracking zooming for {camera_name}: Relative zoom not supported" + ) if move_request.Speed is None: move_request.Speed = configs.DefaultPTZSpeed if configs else None @@ -387,7 +388,11 @@ class OnvifController: move_request.Translation.PanTilt.x = pan move_request.Translation.PanTilt.y = tilt - if "zoom-r" in self.cams[camera_name]["features"]: + if ( + "zoom-r" in self.cams[camera_name]["features"] + and self.config.cameras[camera_name].onvif.autotracking.zooming + == ZoomingModeEnum.relative + ): move_request.Speed = { "PanTilt": { "x": speed, @@ -403,7 +408,11 @@ class OnvifController: move_request.Translation.PanTilt.x = 0 move_request.Translation.PanTilt.y = 0 - if "zoom-r" in self.cams[camera_name]["features"]: + if ( + "zoom-r" in self.cams[camera_name]["features"] + and self.config.cameras[camera_name].onvif.autotracking.zooming + == ZoomingModeEnum.relative + ): move_request.Translation.Zoom.x = 0 self.cams[camera_name]["active"] = False From 42bf6141314baa176d02a5ebbf57d08513666399 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Fri, 16 Feb 2024 07:43:46 -0700 Subject: [PATCH 02/14] Fix birdseye camera comparison (#9887) --- frigate/output.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frigate/output.py b/frigate/output.py index 465c07786..33596f500 100644 --- a/frigate/output.py +++ b/frigate/output.py @@ -445,7 +445,7 @@ class BirdsEyeFrameManager: if len(self.active_cameras) - len(active_cameras) == 0: if ( len(self.active_cameras) == 1 - and self.active_cameras[0] == active_cameras[0] + and self.active_cameras != active_cameras ): reset_layout = True elif max_camera_refresh: From 6476f8ade78a337be2244ead486d68e6d6365807 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Fri, 16 Feb 2024 08:35:21 -0700 Subject: [PATCH 03/14] Format (#9889) --- frigate/output.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frigate/output.py b/frigate/output.py index 33596f500..91899ef46 100644 --- a/frigate/output.py +++ b/frigate/output.py @@ -443,10 +443,7 @@ class BirdsEyeFrameManager: # check if we need to reset the layout because there is a different number of cameras if len(self.active_cameras) - len(active_cameras) == 0: - if ( - len(self.active_cameras) == 1 - and self.active_cameras != active_cameras - ): + if len(self.active_cameras) == 1 and self.active_cameras != active_cameras: reset_layout = True elif max_camera_refresh: reset_layout = True From 47fba0d55389ccff287a5456e636b6db7b3cb92c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeppe=20St=C3=A6rk?= Date: Sun, 25 Feb 2024 13:35:32 +0100 Subject: [PATCH 04/14] Update onvif table with tapo c220 (#9905) * Update cameras.md Tapo C220 added to ONVIF PTZ camera recommendations * Update docs/docs/configuration/cameras.md Co-authored-by: Nicolas Mowen --------- Co-authored-by: Nicolas Mowen --- docs/docs/configuration/cameras.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/configuration/cameras.md b/docs/docs/configuration/cameras.md index a95ffae86..401b6ba9e 100644 --- a/docs/docs/configuration/cameras.md +++ b/docs/docs/configuration/cameras.md @@ -94,5 +94,6 @@ This list of working and non-working PTZ cameras is based on user feedback. | Sunba 405-D20X | ✅ | ❌ | | | Tapo C200 | ✅ | ❌ | Incomplete ONVIF support | | Tapo C210 | ❌ | ❌ | Incomplete ONVIF support | +| Tapo C220 | ✅ | ❌ | Incomeplete ONVIF support, ONVIF Service Port: 2020 | | Uniview IPC672LR-AX4DUPK | ✅ | ❌ | Firmware says FOV relative movement is supported, but camera doesn't actually move when sending ONVIF commands | | Vikylin PTZ-2804X-I2 | ❌ | ❌ | Incomplete ONVIF support | From b9c0e345e9b9099dbe080eefd791d71b49a39606 Mon Sep 17 00:00:00 2001 From: Andreas Ehn Date: Mon, 26 Feb 2024 20:14:19 +0800 Subject: [PATCH 05/14] Update cameras.md (#10030) Document Hanwha XNP-6550RH capabilities --- docs/docs/configuration/cameras.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/configuration/cameras.md b/docs/docs/configuration/cameras.md index 401b6ba9e..7463200c8 100644 --- a/docs/docs/configuration/cameras.md +++ b/docs/docs/configuration/cameras.md @@ -86,6 +86,7 @@ This list of working and non-working PTZ cameras is based on user feedback. | Ctronics PTZ | ✅ | ❌ | | | Dahua | ✅ | ✅ | | | Foscam R5 | ✅ | ❌ | | +| Hanwha XNP-6550RH | ✅ | ❌ | | | Hikvision | ✅ | ❌ | Incomplete ONVIF support (MoveStatus won't update even on latest firmware) - reported with HWP-N4215IH-DE and DS-2DE3304W-DE, but likely others | | Reolink 511WA | ✅ | ❌ | Zoom only | | Reolink E1 Pro | ✅ | ❌ | | From 57cddc537247632d73ee1468600a3f2774eab172 Mon Sep 17 00:00:00 2001 From: Florisz <19168937+Floriszz@users.noreply.github.com> Date: Tue, 27 Feb 2024 14:08:30 +0100 Subject: [PATCH 06/14] Update installation.md (#10020) * Update installation.md According to the v13 release the config.yml mapping needs to be the entire directory and not only the config.yml file * Update docs/docs/frigate/installation.md --------- Co-authored-by: Blake Blackshear --- docs/docs/frigate/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/frigate/installation.md b/docs/docs/frigate/installation.md index 99565acf8..9669c868c 100644 --- a/docs/docs/frigate/installation.md +++ b/docs/docs/frigate/installation.md @@ -240,7 +240,7 @@ There may be other services running on your NAS that are using the same ports th You need to configure 2 paths: -- The location of your config file in yaml format, this needs to be file and you need to go to the location of where your config.yml is located, this will be different depending on your NAS folder structure e.g. `/docker/frigate/config/config.yml` will mount to `/config/config.yml` within the container. +- The location of your config directory which will be different depending on your NAS folder structure e.g. `/docker/frigate/config` will mount to `/config` within the container. - The location on your NAS where the recordings will be saved this needs to be a folder e.g. `/docker/volumes/frigate-0-media` ![image](https://user-images.githubusercontent.com/4516296/232585872-44431d15-55e0-4004-b78b-1e512702b911.png) From 8034613bebce0752b706eeac6a09f3780cc54a3e Mon Sep 17 00:00:00 2001 From: Sjoerd Oostdijck Date: Wed, 28 Feb 2024 04:41:56 +0100 Subject: [PATCH 07/14] Update cameras.md add tapo C225 camera (#10101) --- docs/docs/configuration/cameras.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/docs/configuration/cameras.md b/docs/docs/configuration/cameras.md index 7463200c8..1a45f7e8c 100644 --- a/docs/docs/configuration/cameras.md +++ b/docs/docs/configuration/cameras.md @@ -81,7 +81,7 @@ This list of working and non-working PTZ cameras is based on user feedback. | Brand or specific camera | PTZ Controls | Autotracking | Notes | | ------------------------ | :----------: | :----------: | ----------------------------------------------------------------------------------------------------------------------------------------------- | -| Amcrest | ✅ | ✅ | ⛔️ Generally, Amcrest should work, but some older models (like the common IP2M-841) don't support autotracking | +| Amcrest | ✅ | ✅ | ⛔️ Generally, Amcrest should work, but some older models (like the common IP2M-841) don't support autotracking | | Amcrest ASH21 | ❌ | ❌ | No ONVIF support | | Ctronics PTZ | ✅ | ❌ | | | Dahua | ✅ | ✅ | | @@ -95,6 +95,7 @@ This list of working and non-working PTZ cameras is based on user feedback. | Sunba 405-D20X | ✅ | ❌ | | | Tapo C200 | ✅ | ❌ | Incomplete ONVIF support | | Tapo C210 | ❌ | ❌ | Incomplete ONVIF support | -| Tapo C220 | ✅ | ❌ | Incomeplete ONVIF support, ONVIF Service Port: 2020 | +| Tapo C220 | ✅ | ❌ | Incomeplete ONVIF support, ONVIF Service Port: 2020 | +| Tapo C225 | ✅ | ❌ | Incomeplete ONVIF support, ONVIF Service Port: 2020 | | Uniview IPC672LR-AX4DUPK | ✅ | ❌ | Firmware says FOV relative movement is supported, but camera doesn't actually move when sending ONVIF commands | | Vikylin PTZ-2804X-I2 | ❌ | ❌ | Incomplete ONVIF support | From 034aaa7ef75ecf4884d395a04832777f2241cad1 Mon Sep 17 00:00:00 2001 From: Tacheev Alexey <43005917+lexeyt@users.noreply.github.com> Date: Sat, 9 Mar 2024 15:03:40 +0300 Subject: [PATCH 08/14] Fixed incorrect label link (#10342) --- docs/docs/frigate/glossary.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/frigate/glossary.md b/docs/docs/frigate/glossary.md index 5e31f4485..8ab86250c 100644 --- a/docs/docs/frigate/glossary.md +++ b/docs/docs/frigate/glossary.md @@ -27,7 +27,7 @@ Motion masks prevent detection of [motion](#motion) in masked areas from trigger ### Object Mask -Object filter masks drop any bounding boxes where the bottom center (overlap doesn't matter) is in the masked area. It forces them to be considered a [false positive](#false_positive) so that they are ignored. +Object filter masks drop any bounding boxes where the bottom center (overlap doesn't matter) is in the masked area. It forces them to be considered a [false positive](#false-positive) so that they are ignored. ## Min Score @@ -55,4 +55,4 @@ The top score for an object is the highest median score for an object. ## Zone -Zones are areas of interest, zones can be used for notifications and for limiting the areas where Frigate will create an [event](#event). [See the zone docs for more info](/configuration/zones) \ No newline at end of file +Zones are areas of interest, zones can be used for notifications and for limiting the areas where Frigate will create an [event](#event). [See the zone docs for more info](/configuration/zones) From e46b020395d9e328e45183f777ce4bc1f4c8adf6 Mon Sep 17 00:00:00 2001 From: Kyler <39353605+fisher60@users.noreply.github.com> Date: Sat, 9 Mar 2024 09:01:09 -0600 Subject: [PATCH 09/14] Fix: rename docker images and tags in Jetson configuration docs (#10263) * rename docker image tags in configuration docs for jetson, add correct image in sample codeblocks, fix typo in 'come' The image names/tags for Jetson instructions were incorrect. I have updated the docs to point to the correct images. * revert jetson docs phrasing to properly refer to Jetpack docker images --- docs/docs/configuration/hardware_acceleration.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/docs/configuration/hardware_acceleration.md b/docs/docs/configuration/hardware_acceleration.md index 8bd303fdf..6aaa1a106 100644 --- a/docs/docs/configuration/hardware_acceleration.md +++ b/docs/docs/configuration/hardware_acceleration.md @@ -286,10 +286,10 @@ These instructions were originally based on the [Jellyfin documentation](https:/ ## NVIDIA Jetson (Orin AGX, Orin NX, Orin Nano\*, Xavier AGX, Xavier NX, TX2, TX1, Nano) -A separate set of docker images is available that is based on Jetpack/L4T. They comes with an `ffmpeg` build +A separate set of docker images is available that is based on Jetpack/L4T. They come with an `ffmpeg` build with codecs that use the Jetson's dedicated media engine. If your Jetson host is running Jetpack 4.6, use the -`frigate-tensorrt-jp4` image, or if your Jetson host is running Jetpack 5.0+, use the `frigate-tensorrt-jp5` -image. Note that the Orin Nano has no video encoder, so frigate will use software encoding on this platform, +`stable-tensorrt-jp4` tagged image, or if your Jetson host is running Jetpack 5.0+, use the `stable-tensorrt-jp5` +tagged image. Note that the Orin Nano has no video encoder, so frigate will use software encoding on this platform, but the image will still allow hardware decoding and tensorrt object detection. You will need to use the image with the nvidia container runtime: @@ -300,7 +300,7 @@ You will need to use the image with the nvidia container runtime: docker run -d \ ... --runtime nvidia - ghcr.io/blakeblackshear/frigate-tensorrt-jp5 + ghcr.io/blakeblackshear/frigate:stable-tensorrt-jp5 ``` ### Docker Compose - Jetson @@ -310,7 +310,7 @@ version: '2.4' services: frigate: ... - image: ghcr.io/blakeblackshear/frigate-tensorrt-jp5 + image: ghcr.io/blakeblackshear/frigate:stable-tensorrt-jp5 runtime: nvidia # Add this ``` From 13b4e5ff4190a59df15c7d648f6c005b3dd686c2 Mon Sep 17 00:00:00 2001 From: itsmesid <693151+arevindh@users.noreply.github.com> Date: Tue, 19 Mar 2024 17:25:04 +0530 Subject: [PATCH 10/14] Add C520WS to ONVIF PTZ camera recommendations. (#10466) * Add C520WS to onvif supported camera list * Spelling corrections * Tapo C210 PTZ is working in version 1.3.11 --- docs/docs/configuration/cameras.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/docs/configuration/cameras.md b/docs/docs/configuration/cameras.md index 1a45f7e8c..806450f0a 100644 --- a/docs/docs/configuration/cameras.md +++ b/docs/docs/configuration/cameras.md @@ -81,7 +81,7 @@ This list of working and non-working PTZ cameras is based on user feedback. | Brand or specific camera | PTZ Controls | Autotracking | Notes | | ------------------------ | :----------: | :----------: | ----------------------------------------------------------------------------------------------------------------------------------------------- | -| Amcrest | ✅ | ✅ | ⛔️ Generally, Amcrest should work, but some older models (like the common IP2M-841) don't support autotracking | +| Amcrest | ✅ | ✅ | ⛔️ Generally, Amcrest should work, but some older models (like the common IP2M-841) don't support auto tracking | | Amcrest ASH21 | ❌ | ❌ | No ONVIF support | | Ctronics PTZ | ✅ | ❌ | | | Dahua | ✅ | ✅ | | @@ -94,8 +94,9 @@ This list of working and non-working PTZ cameras is based on user feedback. | Reolink RLC-823A 16x | ✅ | ❌ | | | Sunba 405-D20X | ✅ | ❌ | | | Tapo C200 | ✅ | ❌ | Incomplete ONVIF support | -| Tapo C210 | ❌ | ❌ | Incomplete ONVIF support | -| Tapo C220 | ✅ | ❌ | Incomeplete ONVIF support, ONVIF Service Port: 2020 | -| Tapo C225 | ✅ | ❌ | Incomeplete ONVIF support, ONVIF Service Port: 2020 | +| Tapo C210 | ✅ | ❌ | Incomplete ONVIF support, ONVIF Service Port: 2020 | +| Tapo C220 | ✅ | ❌ | Incomplete ONVIF support, ONVIF Service Port: 2020 | +| Tapo C225 | ✅ | ❌ | Incomplete ONVIF support, ONVIF Service Port: 2020 | +| Tapo C520WS | ✅ | ❌ | Incomplete ONVIF support, ONVIF Service Port: 2020 | | Uniview IPC672LR-AX4DUPK | ✅ | ❌ | Firmware says FOV relative movement is supported, but camera doesn't actually move when sending ONVIF commands | | Vikylin PTZ-2804X-I2 | ❌ | ❌ | Incomplete ONVIF support | From b65aa640c98c40233e2e3eeb22b21c1bcadfc16c Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Sat, 30 Mar 2024 06:44:44 -0400 Subject: [PATCH 11/14] Remove all AGPL licensed YOLO references from Frigate (#10716) * Remove yolov8 support from Frigate * Remove automatic build * Formatting and remove yolov5 * Formatting --------- Co-authored-by: Nicolas Mowen --- .github/workflows/ci.yml | 18 ++-- docker/rockchip/Dockerfile | 9 +- docs/docs/configuration/object_detectors.md | 105 +------------------- docs/docs/configuration/reference.md | 2 +- docs/docs/frigate/hardware.md | 11 -- frigate/detectors/detector_config.py | 2 - frigate/detectors/plugins/openvino.py | 41 -------- frigate/detectors/plugins/rknn.py | 94 ++---------------- frigate/events/audio.py | 6 +- frigate/http.py | 30 +++--- frigate/ptz/autotrack.py | 18 ++-- frigate/ptz/onvif.py | 24 ++--- frigate/test/test_ffmpeg_presets.py | 54 +++++----- migrations/003_create_recordings_table.py | 1 + migrations/011_update_indexes.py | 1 + migrations/017_update_indexes.py | 1 + migrations/019_create_regions_table.py | 1 + migrations/020_update_index_recordings.py | 1 + 18 files changed, 92 insertions(+), 327 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6fad8817..dda353776 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,15 +79,15 @@ jobs: rpi.tags=${{ steps.setup.outputs.image-name }}-rpi *.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-arm64 *.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-arm64,mode=max - - name: Build and push RockChip build - uses: docker/bake-action@v3 - with: - push: true - targets: rk - files: docker/rockchip/rk.hcl - set: | - rk.tags=${{ steps.setup.outputs.image-name }}-rk - *.cache-from=type=gha + #- name: Build and push RockChip build + # uses: docker/bake-action@v3 + # with: + # push: true + # targets: rk + # files: docker/rockchip/rk.hcl + # set: | + # rk.tags=${{ steps.setup.outputs.image-name }}-rk + # *.cache-from=type=gha jetson_jp4_build: runs-on: ubuntu-latest name: Jetson Jetpack 4 diff --git a/docker/rockchip/Dockerfile b/docker/rockchip/Dockerfile index b27e4f223..8685bd779 100644 --- a/docker/rockchip/Dockerfile +++ b/docker/rockchip/Dockerfile @@ -12,8 +12,8 @@ RUN pip3 wheel --wheel-dir=/rk-wheels -c /requirements-wheels.txt -r /requiremen FROM deps AS rk-deps ARG TARGETARCH -RUN --mount=type=bind,from=rk-wheels,source=/rk-wheels,target=/deps/rk-wheels \ - pip3 install -U /deps/rk-wheels/*.whl +RUN --mount=type=bind,from=rk-wheels,source=/rk-wheels,target=/deps/rk-wheels \ + pip3 install -U /deps/rk-wheels/*.whl WORKDIR /opt/frigate/ COPY --from=rootfs / / @@ -21,10 +21,7 @@ COPY --from=rootfs / / ADD https://github.com/MarcA711/rknpu2/releases/download/v1.5.2/librknnrt_rk356x.so /usr/lib/ ADD https://github.com/MarcA711/rknpu2/releases/download/v1.5.2/librknnrt_rk3588.so /usr/lib/ -ADD https://github.com/MarcA711/rknn-models/releases/download/v1.5.2-rk3562/yolov8n-320x320-rk3562.rknn /models/rknn/ -ADD https://github.com/MarcA711/rknn-models/releases/download/v1.5.2-rk3566/yolov8n-320x320-rk3566.rknn /models/rknn/ -ADD https://github.com/MarcA711/rknn-models/releases/download/v1.5.2-rk3568/yolov8n-320x320-rk3568.rknn /models/rknn/ -ADD https://github.com/MarcA711/rknn-models/releases/download/v1.5.2-rk3588/yolov8n-320x320-rk3588.rknn /models/rknn/ +# TODO removed models, other models support may need to be added back in RUN rm -rf /usr/lib/btbn-ffmpeg/bin/ffmpeg RUN rm -rf /usr/lib/btbn-ffmpeg/bin/ffprobe diff --git a/docs/docs/configuration/object_detectors.md b/docs/docs/configuration/object_detectors.md index f5e068522..38fb0400a 100644 --- a/docs/docs/configuration/object_detectors.md +++ b/docs/docs/configuration/object_detectors.md @@ -13,7 +13,7 @@ The CPU detector type runs a TensorFlow Lite model utilizing the CPU without har :::tip -If you do not have GPU or Edge TPU hardware, using the [OpenVINO Detector](#openvino-detector) is often more efficient than using the CPU detector. +If you do not have GPU or Edge TPU hardware, using the [OpenVINO Detector](#openvino-detector) is often more efficient than using the CPU detector. ::: @@ -131,7 +131,7 @@ model: labelmap_path: /openvino-model/coco_91cl_bkgr.txt ``` -This detector also supports some YOLO variants: YOLOX, YOLOv5, and YOLOv8 specifically. Other YOLO variants are not officially supported/tested. Frigate does not come with any yolo models preloaded, so you will need to supply your own models. This detector has been verified to work with the [yolox_tiny](https://github.com/openvinotoolkit/open_model_zoo/tree/master/models/public/yolox-tiny) model from Intel's Open Model Zoo. You can follow [these instructions](https://github.com/openvinotoolkit/open_model_zoo/tree/master/models/public/yolox-tiny#download-a-model-and-convert-it-into-openvino-ir-format) to retrieve the OpenVINO-compatible `yolox_tiny` model. Make sure that the model input dimensions match the `width` and `height` parameters, and `model_type` is set accordingly. See [Full Configuration Reference](/configuration/reference.md) for a list of possible `model_type` options. Below is an example of how `yolox_tiny` can be used in Frigate: +This detector also supports YOLOX. Other YOLO variants are not officially supported/tested. Frigate does not come with any yolo models preloaded, so you will need to supply your own models. This detector has been verified to work with the [yolox_tiny](https://github.com/openvinotoolkit/open_model_zoo/tree/master/models/public/yolox-tiny) model from Intel's Open Model Zoo. You can follow [these instructions](https://github.com/openvinotoolkit/open_model_zoo/tree/master/models/public/yolox-tiny#download-a-model-and-convert-it-into-openvino-ir-format) to retrieve the OpenVINO-compatible `yolox_tiny` model. Make sure that the model input dimensions match the `width` and `height` parameters, and `model_type` is set accordingly. See [Full Configuration Reference](/configuration/reference.md) for a list of possible `model_type` options. Below is an example of how `yolox_tiny` can be used in Frigate: ```yaml detectors: @@ -302,104 +302,3 @@ Replace `` and `` with the IP address and p To verify that the integration is working correctly, start Frigate and observe the logs for any error messages related to CodeProject.AI. Additionally, you can check the Frigate web interface to see if the objects detected by CodeProject.AI are being displayed and tracked properly. # Community Supported Detectors - -## Rockchip RKNN-Toolkit-Lite2 - -This detector is only available if one of the following Rockchip SoCs is used: - -- RK3588/RK3588S -- RK3568 -- RK3566 -- RK3562 - -These SoCs come with a NPU that will highly speed up detection. - -### Setup - -Use a frigate docker image with `-rk` suffix and enable privileged mode by adding the `--privileged` flag to your docker run command or `privileged: true` to your `docker-compose.yml` file. - -### Configuration - -This `config.yml` shows all relevant options to configure the detector and explains them. All values shown are the default values (except for one). Lines that are required at least to use the detector are labeled as required, all other lines are optional. - -```yaml -detectors: # required - rknn: # required - type: rknn # required - # core mask for npu - core_mask: 0 - -model: # required - # name of yolov8 model or path to your own .rknn model file - # possible values are: - # - default-yolov8n - # - default-yolov8s - # - default-yolov8m - # - default-yolov8l - # - default-yolov8x - # - /config/model_cache/rknn/your_custom_model.rknn - path: default-yolov8n - # width and height of detection frames - width: 320 - height: 320 - # pixel format of detection frame - # default value is rgb but yolov models usually use bgr format - input_pixel_format: bgr # required - # shape of detection frame - input_tensor: nhwc -``` - -Explanation for rknn specific options: - -- **core mask** controls which cores of your NPU should be used. This option applies only to SoCs with a multicore NPU (at the time of writing this in only the RK3588/S). The easiest way is to pass the value as a binary number. To do so, use the prefix `0b` and write a `0` to disable a core and a `1` to enable a core, whereas the last digit coresponds to core0, the second last to core1, etc. You also have to use the cores in ascending order (so you can't use core0 and core2; but you can use core0 and core1). Enabling more cores can reduce the inference speed, especially when using bigger models (see section below). Examples: - - `core_mask: 0b000` or just `core_mask: 0` let the NPU decide which cores should be used. Default and recommended value. - - `core_mask: 0b001` use only core0. - - `core_mask: 0b011` use core0 and core1. - - `core_mask: 0b110` use core1 and core2. **This does not** work, since core0 is disabled. - -### Choosing a model - -There are 5 default yolov8 models that differ in size and therefore load the NPU more or less. In ascending order, with the top one being the smallest and least computationally intensive model: - -| Model | Size in mb | -| ------- | ---------- | -| yolov8n | 9 | -| yolov8s | 25 | -| yolov8m | 54 | -| yolov8l | 90 | -| yolov8x | 136 | - -:::tip - -You can get the load of your NPU with the following command: - -```bash -$ cat /sys/kernel/debug/rknpu/load ->> NPU load: Core0: 0%, Core1: 0%, Core2: 0%, -``` - -::: - -- By default the rknn detector uses the yolov8n model (`model: path: default-yolov8n`). This model comes with the image, so no further steps than those mentioned above are necessary. -- If you want to use a more precise model, you can pass `default-yolov8s`, `default-yolov8m`, `default-yolov8l` or `default-yolov8x` as `model: path:` option. - - If the model does not exist, it will be automatically downloaded to `/config/model_cache/rknn`. - - If your server has no internet connection, you can download the model from [this Github repository](https://github.com/MarcA711/rknn-models/releases) using another device and place it in the `config/model_cache/rknn` on your system. -- Finally, you can also provide your own model. Note that only yolov8 models are currently supported. Moreover, you will need to convert your model to the rknn format using `rknn-toolkit2` on a x86 machine. Afterwards, you can place your `.rknn` model file in the `config/model_cache/rknn` directory on your system. Then you need to pass the path to your model using the `path` option of your `model` block like this: - -```yaml -model: - path: /config/model_cache/rknn/my-rknn-model.rknn -``` - -:::tip - -When you have a multicore NPU, you can enable all cores to reduce inference times. You should consider activating all cores if you use a larger model like yolov8l. If your NPU has 3 cores (like rk3588/S SoCs), you can enable all 3 cores using: - -```yaml -detectors: - rknn: - type: rknn - core_mask: 0b111 -``` - -::: diff --git a/docs/docs/configuration/reference.md b/docs/docs/configuration/reference.md index 816bfd456..f27e5055d 100644 --- a/docs/docs/configuration/reference.md +++ b/docs/docs/configuration/reference.md @@ -80,7 +80,7 @@ model: # Valid values are nhwc or nchw (default: shown below) input_tensor: nhwc # Optional: Object detection model type, currently only used with the OpenVINO detector - # Valid values are ssd, yolox, yolov5, or yolov8 (default: shown below) + # Valid values are ssd, yolox (default: shown below) model_type: ssd # Optional: Label name modifications. These are merged into the standard labelmap. labelmap: diff --git a/docs/docs/frigate/hardware.md b/docs/docs/frigate/hardware.md index e1bb2a63e..47e0e4ce1 100644 --- a/docs/docs/frigate/hardware.md +++ b/docs/docs/frigate/hardware.md @@ -95,17 +95,6 @@ Frigate supports all Jetson boards, from the inexpensive Jetson Nano to the powe Inference speed will vary depending on the YOLO model, jetson platform and jetson nvpmodel (GPU/DLA/EMC clock speed). It is typically 20-40 ms for most models. The DLA is more efficient than the GPU, but not faster, so using the DLA will reduce power consumption but will slightly increase inference time. -#### Rockchip SoC - -Frigate supports SBCs with the following Rockchip SoCs: - -- RK3566/RK3568 -- RK3588/RK3588S -- RV1103/RV1106 -- RK3562 - -Using the yolov8n model and an Orange Pi 5 Plus with RK3588 SoC inference speeds vary between 20 - 25 ms. - ## What does Frigate use the CPU for and what does it use a detector for? (ELI5 Version) This is taken from a [user question on reddit](https://www.reddit.com/r/homeassistant/comments/q8mgau/comment/hgqbxh5/?utm_source=share&utm_medium=web2x&context=3). Modified slightly for clarity. diff --git a/frigate/detectors/detector_config.py b/frigate/detectors/detector_config.py index ca1915449..7fc958a38 100644 --- a/frigate/detectors/detector_config.py +++ b/frigate/detectors/detector_config.py @@ -30,8 +30,6 @@ class InputTensorEnum(str, Enum): class ModelTypeEnum(str, Enum): ssd = "ssd" yolox = "yolox" - yolov5 = "yolov5" - yolov8 = "yolov8" class ModelConfig(BaseModel): diff --git a/frigate/detectors/plugins/openvino.py b/frigate/detectors/plugins/openvino.py index 5cb1ea39c..c259bda64 100644 --- a/frigate/detectors/plugins/openvino.py +++ b/frigate/detectors/plugins/openvino.py @@ -131,44 +131,3 @@ class OvDetector(DetectionApi): object_detected[6], object_detected[5], object_detected[:4] ) return detections - elif self.ov_model_type == ModelTypeEnum.yolov8: - out_tensor = infer_request.get_output_tensor() - results = out_tensor.data[0] - output_data = np.transpose(results) - scores = np.max(output_data[:, 4:], axis=1) - if len(scores) == 0: - return np.zeros((20, 6), np.float32) - scores = np.expand_dims(scores, axis=1) - # add scores to the last column - dets = np.concatenate((output_data, scores), axis=1) - # filter out lines with scores below threshold - dets = dets[dets[:, -1] > 0.5, :] - # limit to top 20 scores, descending order - ordered = dets[dets[:, -1].argsort()[::-1]][:20] - detections = np.zeros((20, 6), np.float32) - - for i, object_detected in enumerate(ordered): - detections[i] = self.process_yolo( - np.argmax(object_detected[4:-1]), - object_detected[-1], - object_detected[:4], - ) - return detections - elif self.ov_model_type == ModelTypeEnum.yolov5: - out_tensor = infer_request.get_output_tensor() - output_data = out_tensor.data[0] - # filter out lines with scores below threshold - conf_mask = (output_data[:, 4] >= 0.5).squeeze() - output_data = output_data[conf_mask] - # limit to top 20 scores, descending order - ordered = output_data[output_data[:, 4].argsort()[::-1]][:20] - - detections = np.zeros((20, 6), np.float32) - - for i, object_detected in enumerate(ordered): - detections[i] = self.process_yolo( - np.argmax(object_detected[5:]), - object_detected[4], - object_detected[:4], - ) - return detections diff --git a/frigate/detectors/plugins/rknn.py b/frigate/detectors/plugins/rknn.py index 01c58b94d..f5836dc13 100644 --- a/frigate/detectors/plugins/rknn.py +++ b/frigate/detectors/plugins/rknn.py @@ -1,10 +1,7 @@ import logging import os.path -import urllib.request from typing import Literal -import numpy as np - try: from hide_warnings import hide_warnings except: # noqa: E722 @@ -24,14 +21,6 @@ DETECTOR_KEY = "rknn" supported_socs = ["rk3562", "rk3566", "rk3568", "rk3588"] -yolov8_suffix = { - "default-yolov8n": "n", - "default-yolov8s": "s", - "default-yolov8m": "m", - "default-yolov8l": "l", - "default-yolov8x": "x", -} - class RknnDetectorConfig(BaseDetectorConfig): type: Literal[DETECTOR_KEY] @@ -73,35 +62,12 @@ class Rknn(DetectionApi): elif "rk3588" in soc: os.rename("/usr/lib/librknnrt_rk3588.so", "/usr/lib/librknnrt.so") - self.model_path = config.model.path or "default-yolov8n" self.core_mask = config.core_mask self.height = config.model.height self.width = config.model.width - if self.model_path in yolov8_suffix: - if self.model_path == "default-yolov8n": - self.model_path = "/models/rknn/yolov8n-320x320-{soc}.rknn".format( - soc=soc - ) - else: - model_suffix = yolov8_suffix[self.model_path] - self.model_path = ( - "/config/model_cache/rknn/yolov8{suffix}-320x320-{soc}.rknn".format( - suffix=model_suffix, soc=soc - ) - ) - - os.makedirs("/config/model_cache/rknn", exist_ok=True) - if not os.path.isfile(self.model_path): - logger.info( - "Downloading yolov8{suffix} model.".format(suffix=model_suffix) - ) - urllib.request.urlretrieve( - "https://github.com/MarcA711/rknn-models/releases/download/v1.5.2-{soc}/yolov8{suffix}-320x320-{soc}.rknn".format( - soc=soc, suffix=model_suffix - ), - self.model_path, - ) + if True: + os.makedirs("/config/model_cache/rknn", exist_ok=True) if (config.model.width != 320) or (config.model.height != 320): logger.error( @@ -137,60 +103,12 @@ class Rknn(DetectionApi): "Error initializing rknn runtime. Do you run docker in privileged mode?" ) - def __del__(self): - self.rknn.release() - - def postprocess(self, results): - """ - Processes yolov8 output. - - Args: - results: array with shape: (1, 84, n, 1) where n depends on yolov8 model size (for 320x320 model n=2100) - - Returns: - detections: array with shape (20, 6) with 20 rows of (class, confidence, y_min, x_min, y_max, x_max) - """ - - results = np.transpose(results[0, :, :, 0]) # array shape (2100, 84) - scores = np.max( - results[:, 4:], axis=1 - ) # array shape (2100,); max confidence of each row - - # remove lines with score scores < 0.4 - filtered_arg = np.argwhere(scores > 0.4) - results = results[filtered_arg[:, 0]] - scores = scores[filtered_arg[:, 0]] - - num_detections = len(scores) - - if num_detections == 0: - return np.zeros((20, 6), np.float32) - - if num_detections > 20: - top_arg = np.argpartition(scores, -20)[-20:] - results = results[top_arg] - scores = scores[top_arg] - num_detections = 20 - - classes = np.argmax(results[:, 4:], axis=1) - - boxes = np.transpose( - np.vstack( - ( - (results[:, 1] - 0.5 * results[:, 3]) / self.height, - (results[:, 0] - 0.5 * results[:, 2]) / self.width, - (results[:, 1] + 0.5 * results[:, 3]) / self.height, - (results[:, 0] + 0.5 * results[:, 2]) / self.width, - ) - ) + raise Exception( + "RKNN does not currently support any models. Please see the docs for more info." ) - detections = np.zeros((20, 6), np.float32) - detections[:num_detections, 0] = classes - detections[:num_detections, 1] = scores - detections[:num_detections, 2:] = boxes - - return detections + def __del__(self): + self.rknn.release() @hide_warnings def inference(self, tensor_input): diff --git a/frigate/events/audio.py b/frigate/events/audio.py index ed457adf1..a4fbd7186 100644 --- a/frigate/events/audio.py +++ b/frigate/events/audio.py @@ -256,9 +256,9 @@ class AudioEventMaintainer(threading.Thread): def handle_detection(self, label: str, score: float) -> None: if self.detections.get(label): - self.detections[label][ - "last_detection" - ] = datetime.datetime.now().timestamp() + self.detections[label]["last_detection"] = ( + datetime.datetime.now().timestamp() + ) else: self.inter_process_communicator.queue.put( (f"{self.config.name}/audio/{label}", "ON") diff --git a/frigate/http.py b/frigate/http.py index d634e9b8e..606b8c1d7 100644 --- a/frigate/http.py +++ b/frigate/http.py @@ -700,9 +700,9 @@ def event_snapshot(id): else: response.headers["Cache-Control"] = "no-store" if download: - response.headers[ - "Content-Disposition" - ] = f"attachment; filename=snapshot-{id}.jpg" + response.headers["Content-Disposition"] = ( + f"attachment; filename=snapshot-{id}.jpg" + ) return response @@ -889,9 +889,9 @@ def event_clip(id): if download: response.headers["Content-Disposition"] = "attachment; filename=%s" % file_name response.headers["Content-Length"] = os.path.getsize(clip_path) - response.headers[ - "X-Accel-Redirect" - ] = f"/clips/{file_name}" # nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers + response.headers["X-Accel-Redirect"] = ( + f"/clips/{file_name}" # nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers + ) return response @@ -1187,9 +1187,9 @@ def config(): config["plus"] = {"enabled": current_app.plus_api.is_active()} for detector, detector_config in config["detectors"].items(): - detector_config["model"][ - "labelmap" - ] = current_app.frigate_config.model.merged_labelmap + detector_config["model"]["labelmap"] = ( + current_app.frigate_config.model.merged_labelmap + ) return jsonify(config) @@ -1596,9 +1596,9 @@ def get_recordings_storage_usage(): total_mb = recording_stats["total"] - camera_usages: dict[ - str, dict - ] = current_app.storage_maintainer.calculate_camera_usages() + camera_usages: dict[str, dict] = ( + current_app.storage_maintainer.calculate_camera_usages() + ) for camera_name in camera_usages.keys(): if camera_usages.get(camera_name, {}).get("usage"): @@ -1785,9 +1785,9 @@ def recording_clip(camera_name, start_ts, end_ts): if download: response.headers["Content-Disposition"] = "attachment; filename=%s" % file_name response.headers["Content-Length"] = os.path.getsize(path) - response.headers[ - "X-Accel-Redirect" - ] = f"/cache/{file_name}" # nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers + response.headers["X-Accel-Redirect"] = ( + f"/cache/{file_name}" # nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers + ) return response diff --git a/frigate/ptz/autotrack.py b/frigate/ptz/autotrack.py index ee5ad9f31..2bfdcec03 100644 --- a/frigate/ptz/autotrack.py +++ b/frigate/ptz/autotrack.py @@ -297,12 +297,12 @@ class PtzAutoTracker: self.ptz_metrics[camera][ "ptz_max_zoom" ].value = camera_config.onvif.autotracking.movement_weights[1] - self.intercept[ - camera - ] = camera_config.onvif.autotracking.movement_weights[2] - self.move_coefficients[ - camera - ] = camera_config.onvif.autotracking.movement_weights[3:] + self.intercept[camera] = ( + camera_config.onvif.autotracking.movement_weights[2] + ) + self.move_coefficients[camera] = ( + camera_config.onvif.autotracking.movement_weights[3:] + ) else: camera_config.onvif.autotracking.enabled = False self.ptz_metrics[camera]["ptz_autotracker_enabled"].value = False @@ -566,9 +566,9 @@ class PtzAutoTracker: ) ** self.zoom_factor[camera] if "original_target_box" not in self.tracked_object_metrics[camera]: - self.tracked_object_metrics[camera][ - "original_target_box" - ] = self.tracked_object_metrics[camera]["target_box"] + self.tracked_object_metrics[camera]["original_target_box"] = ( + self.tracked_object_metrics[camera]["target_box"] + ) ( self.tracked_object_metrics[camera]["valid_velocity"], diff --git a/frigate/ptz/onvif.py b/frigate/ptz/onvif.py index c4f0fbc01..29f30ad77 100644 --- a/frigate/ptz/onvif.py +++ b/frigate/ptz/onvif.py @@ -123,9 +123,9 @@ class OnvifController: logger.debug(f"Onvif config for {camera_name}: {ptz_config}") service_capabilities_request = ptz.create_type("GetServiceCapabilities") - self.cams[camera_name][ - "service_capabilities_request" - ] = service_capabilities_request + self.cams[camera_name]["service_capabilities_request"] = ( + service_capabilities_request + ) fov_space_id = next( ( @@ -241,9 +241,9 @@ class OnvifController: supported_features.append("zoom-r") try: # get camera's zoom limits from onvif config - self.cams[camera_name][ - "relative_zoom_range" - ] = ptz_config.Spaces.RelativeZoomTranslationSpace[0] + self.cams[camera_name]["relative_zoom_range"] = ( + ptz_config.Spaces.RelativeZoomTranslationSpace[0] + ) except Exception: if ( self.config.cameras[camera_name].onvif.autotracking.zooming @@ -260,9 +260,9 @@ class OnvifController: supported_features.append("zoom-a") try: # get camera's zoom limits from onvif config - self.cams[camera_name][ - "absolute_zoom_range" - ] = ptz_config.Spaces.AbsoluteZoomPositionSpace[0] + self.cams[camera_name]["absolute_zoom_range"] = ( + ptz_config.Spaces.AbsoluteZoomPositionSpace[0] + ) self.cams[camera_name]["zoom_limits"] = configs.ZoomLimits except Exception: if self.config.cameras[camera_name].onvif.autotracking.zooming: @@ -279,9 +279,9 @@ class OnvifController: and configs.DefaultRelativePanTiltTranslationSpace is not None ): supported_features.append("pt-r-fov") - self.cams[camera_name][ - "relative_fov_range" - ] = ptz_config.Spaces.RelativePanTiltTranslationSpace[fov_space_id] + self.cams[camera_name]["relative_fov_range"] = ( + ptz_config.Spaces.RelativePanTiltTranslationSpace[fov_space_id] + ) self.cams[camera_name]["features"] = supported_features diff --git a/frigate/test/test_ffmpeg_presets.py b/frigate/test/test_ffmpeg_presets.py index 0d3dab856..f333ef3ec 100644 --- a/frigate/test/test_ffmpeg_presets.py +++ b/frigate/test/test_ffmpeg_presets.py @@ -45,9 +45,9 @@ class TestFfmpegPresets(unittest.TestCase): assert self.default_ffmpeg == frigate_config.dict(exclude_unset=True) def test_ffmpeg_hwaccel_preset(self): - self.default_ffmpeg["cameras"]["back"]["ffmpeg"][ - "hwaccel_args" - ] = "preset-rpi-64-h264" + self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["hwaccel_args"] = ( + "preset-rpi-64-h264" + ) frigate_config = FrigateConfig(**self.default_ffmpeg) frigate_config.cameras["back"].create_ffmpeg_cmds() assert "preset-rpi-64-h264" not in ( @@ -58,9 +58,9 @@ class TestFfmpegPresets(unittest.TestCase): ) def test_ffmpeg_hwaccel_not_preset(self): - self.default_ffmpeg["cameras"]["back"]["ffmpeg"][ - "hwaccel_args" - ] = "-other-hwaccel args" + self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["hwaccel_args"] = ( + "-other-hwaccel args" + ) frigate_config = FrigateConfig(**self.default_ffmpeg) frigate_config.cameras["back"].create_ffmpeg_cmds() assert "-other-hwaccel args" in ( @@ -68,9 +68,9 @@ class TestFfmpegPresets(unittest.TestCase): ) def test_ffmpeg_hwaccel_scale_preset(self): - self.default_ffmpeg["cameras"]["back"]["ffmpeg"][ - "hwaccel_args" - ] = "preset-nvidia-h264" + self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["hwaccel_args"] = ( + "preset-nvidia-h264" + ) self.default_ffmpeg["cameras"]["back"]["detect"] = { "height": 1920, "width": 2560, @@ -89,9 +89,9 @@ class TestFfmpegPresets(unittest.TestCase): def test_default_ffmpeg_input_arg_preset(self): frigate_config = FrigateConfig(**self.default_ffmpeg) - self.default_ffmpeg["cameras"]["back"]["ffmpeg"][ - "input_args" - ] = "preset-rtsp-generic" + self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["input_args"] = ( + "preset-rtsp-generic" + ) frigate_preset_config = FrigateConfig(**self.default_ffmpeg) frigate_config.cameras["back"].create_ffmpeg_cmds() frigate_preset_config.cameras["back"].create_ffmpeg_cmds() @@ -102,9 +102,9 @@ class TestFfmpegPresets(unittest.TestCase): ) def test_ffmpeg_input_preset(self): - self.default_ffmpeg["cameras"]["back"]["ffmpeg"][ - "input_args" - ] = "preset-rtmp-generic" + self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["input_args"] = ( + "preset-rtmp-generic" + ) frigate_config = FrigateConfig(**self.default_ffmpeg) frigate_config.cameras["back"].create_ffmpeg_cmds() assert "preset-rtmp-generic" not in ( @@ -135,9 +135,9 @@ class TestFfmpegPresets(unittest.TestCase): ) def test_ffmpeg_output_record_preset(self): - self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["output_args"][ - "record" - ] = "preset-record-generic-audio-aac" + self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["output_args"]["record"] = ( + "preset-record-generic-audio-aac" + ) frigate_config = FrigateConfig(**self.default_ffmpeg) frigate_config.cameras["back"].create_ffmpeg_cmds() assert "preset-record-generic-audio-aac" not in ( @@ -148,9 +148,9 @@ class TestFfmpegPresets(unittest.TestCase): ) def test_ffmpeg_output_record_not_preset(self): - self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["output_args"][ - "record" - ] = "-some output" + self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["output_args"]["record"] = ( + "-some output" + ) frigate_config = FrigateConfig(**self.default_ffmpeg) frigate_config.cameras["back"].create_ffmpeg_cmds() assert "-some output" in ( @@ -158,9 +158,9 @@ class TestFfmpegPresets(unittest.TestCase): ) def test_ffmpeg_output_rtmp_preset(self): - self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["output_args"][ - "rtmp" - ] = "preset-rtmp-jpeg" + self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["output_args"]["rtmp"] = ( + "preset-rtmp-jpeg" + ) frigate_config = FrigateConfig(**self.default_ffmpeg) frigate_config.cameras["back"].create_ffmpeg_cmds() assert "preset-rtmp-jpeg" not in ( @@ -171,9 +171,9 @@ class TestFfmpegPresets(unittest.TestCase): ) def test_ffmpeg_output_rtmp_not_preset(self): - self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["output_args"][ - "rtmp" - ] = "-some output" + self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["output_args"]["rtmp"] = ( + "-some output" + ) frigate_config = FrigateConfig(**self.default_ffmpeg) frigate_config.cameras["back"].create_ffmpeg_cmds() assert "-some output" in ( diff --git a/migrations/003_create_recordings_table.py b/migrations/003_create_recordings_table.py index 82b15eb9c..77f9827cf 100644 --- a/migrations/003_create_recordings_table.py +++ b/migrations/003_create_recordings_table.py @@ -20,6 +20,7 @@ Some examples (model - class or model name):: > migrator.add_default(model, field_name, default) """ + import peewee as pw SQL = pw.SQL diff --git a/migrations/011_update_indexes.py b/migrations/011_update_indexes.py index ddb0ba9a6..5c13baa54 100644 --- a/migrations/011_update_indexes.py +++ b/migrations/011_update_indexes.py @@ -20,6 +20,7 @@ Some examples (model - class or model name):: > migrator.add_default(model, field_name, default) """ + import peewee as pw SQL = pw.SQL diff --git a/migrations/017_update_indexes.py b/migrations/017_update_indexes.py index 8aa53f8ee..66d1fcc6a 100644 --- a/migrations/017_update_indexes.py +++ b/migrations/017_update_indexes.py @@ -20,6 +20,7 @@ Some examples (model - class or model name):: > migrator.add_default(model, field_name, default) """ + import peewee as pw SQL = pw.SQL diff --git a/migrations/019_create_regions_table.py b/migrations/019_create_regions_table.py index e1492581b..2900b78d2 100644 --- a/migrations/019_create_regions_table.py +++ b/migrations/019_create_regions_table.py @@ -20,6 +20,7 @@ Some examples (model - class or model name):: > migrator.add_default(model, field_name, default) """ + import peewee as pw SQL = pw.SQL diff --git a/migrations/020_update_index_recordings.py b/migrations/020_update_index_recordings.py index 0aa86572d..7d0c2b860 100644 --- a/migrations/020_update_index_recordings.py +++ b/migrations/020_update_index_recordings.py @@ -20,6 +20,7 @@ Some examples (model - class or model name):: > migrator.add_default(model, field_name, default) """ + import peewee as pw SQL = pw.SQL From 2d5a3c696300dd1c7d3c5e92dba638ab3e9f6eac Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Thu, 11 Apr 2024 04:42:45 -0700 Subject: [PATCH 12/14] Clarify Proxmox LXC instructions; reference #5773 instead of #1111 (#10759) * Clarify Proxmox LXC instructions There is a lot of confusing information online. This provides some simple general guidelines to help people get started. * Update docs/docs/frigate/installation.md Co-authored-by: Nicolas Mowen * Reference #5773 instead of #1111 --------- Co-authored-by: Nicolas Mowen --- docs/docs/frigate/installation.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/docs/frigate/installation.md b/docs/docs/frigate/installation.md index 9669c868c..59c196d0d 100644 --- a/docs/docs/frigate/installation.md +++ b/docs/docs/frigate/installation.md @@ -13,7 +13,7 @@ Frigate is a Docker container that can be run on any Docker host including as a ### Operating System -Frigate runs best with docker installed on bare metal debian-based distributions. For ideal performance, Frigate needs access to underlying hardware for the Coral and GPU devices. Running Frigate in a VM on top of Proxmox, ESXi, Virtualbox, etc. is not recommended. The virtualization layer often introduces a sizable amount of overhead for communication with Coral devices, but [not in all circumstances](https://github.com/blakeblackshear/frigate/discussions/1837). +Frigate runs best with Docker installed on bare metal Debian-based distributions. For ideal performance, Frigate needs low overhead access to underlying hardware for the Coral and GPU devices. Running Frigate in a VM on top of Proxmox, ESXi, Virtualbox, etc. is not recommended though [some users have had success with Proxmox](#proxmox). Windows is not officially supported, but some users have had success getting it to run under WSL or Virtualbox. Getting the GPU and/or Coral devices properly passed to Frigate may be difficult or impossible. Search previous discussions or issues for help. @@ -202,7 +202,16 @@ To install make sure you have the [community app plugin here](https://forums.unr ## Proxmox -It is recommended to run Frigate in LXC for maximum performance. See [this discussion](https://github.com/blakeblackshear/frigate/discussions/1111) for more information. +It is recommended to run Frigate in LXC, rather than in a VM, for maximum performance. The setup can be complex so be prepared to read the Proxmox and LXC documentation. Suggestions include: + +- For Intel-based hardware acceleration, to allow access to the `/dev/dri/renderD128` device with major number 226 and minor number 128, add the following lines to the `/etc/pve/lxc/.conf` LXC configuration: + - `lxc.cgroup2.devices.allow: c 226:128 rwm` + - `lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file` +- The LXC configuration will likely also need `features: fuse=1,nesting=1`. This allows running a Docker container in an LXC container (`nesting`) and prevents duplicated files and wasted storage (`fuse`). +- Successfully passing hardware devices through multiple levels of containerization (LXC then Docker) can be difficult. Many people make devices like `/dev/dri/renderD128` world-readable in the host or run Frigate in a privileged LXC container. +- The virtualization layer often introduces a sizable amount of overhead for communication with Coral devices, but [not in all circumstances](https://github.com/blakeblackshear/frigate/discussions/1837). + +See the [Proxmox LXC discussion](https://github.com/blakeblackshear/frigate/discussions/5773) for more general information. ## ESXi From 46f68ccd7374f91e8954c4c44099e5baca9de87f Mon Sep 17 00:00:00 2001 From: Johann Date: Wed, 15 May 2024 13:08:14 +0200 Subject: [PATCH 13/14] Update to frigate+ documentation (#11371) * Update to frigate+ documentation Added shortcuts + advices for objects partly out of frame and the 'difficult' tag. * Update docs/docs/plus/improving_model.md * Update docs/docs/plus/improving_model.md --------- Co-authored-by: Blake Blackshear --- docs/docs/plus/improving_model.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/docs/plus/improving_model.md b/docs/docs/plus/improving_model.md index be9075f65..0e97b21a5 100644 --- a/docs/docs/plus/improving_model.md +++ b/docs/docs/plus/improving_model.md @@ -17,7 +17,9 @@ For the best results, follow the following guidelines. **Make tight bounding boxes**: Tighter bounding boxes improve the recognition and ensure that accurate bounding boxes are predicted at runtime. -**Label the full object even when occluded**: If you have a person standing behind a car, label the full person even though a portion of their body may be hidden behind the car. This helps predict accurate bounding boxes and improves zone accuracy and filters at runtime. +**Label the full object even when occluded**: If you have a person standing behind a car, label the full person even though a portion of their body may be hidden behind the car. This helps predict accurate bounding boxes and improves zone accuracy and filters at runtime. If an object is partly out of frame, label it only when a person would reasonably be able to recognize the object from the visible parts. + +**Label objects hard to identify as difficult**: When objects are truly difficult to make out, such as a car barely visible through a bush, or a dog that is hard to distinguish from the background at night, flag it as 'difficult'. This is not used in the model training as of now, but will in the future. **`amazon`, `ups`, and `fedex` should label the logo**: For a Fedex truck, label the truck as a `car` and make a different bounding box just for the Fedex logo. If there are multiple logos, label each of them. @@ -31,3 +33,21 @@ False positives will be shown with a read box and the label will have a strike t Misidentified objects should have a correct label added. For example, if a person was mistakenly detected as a cat, you should submit it as a false positive in Frigate and add a label for the person. The boxes will overlap. ![add image](/img/plus/false-positive-overlap.jpg) + +## Shortcuts for a faster workflow + +|Shortcut Key|Description| +|-----|--------| +|`?`|Show all keyboard shortcuts| +|`w`|Add box| +|`d`|Toggle difficult| +|`s`|Switch to the next label| +|`tab`|Select next largest box| +|`del`|Delete current box| +|`esc`|Deselect/Cancel| +|`← ↑ → ↓`|Move box| +|`Shift + ← ↑ → ↓`|Resize box| +|`-`|Zoom out| +|`=`|Zoom in| +|`f`|Hide/show all but current box| +|`spacebar`|Verify and save| From 87d3ee09b0d0a1feefeeffaab15c058dc54c6be7 Mon Sep 17 00:00:00 2001 From: Lachlan MacPhee Date: Mon, 20 May 2024 23:55:25 +1000 Subject: [PATCH 14/14] Minimal config in installation guide (#11339) * Minimal config in installation guide (#11339) + Adds a subsection to the installation guide that mentions the requirement for a minimal config to start Frigate successfully. + Adds a warning not to proceed any further into the guide without this valid config * Add spacing between Markdown title and text Co-authored-by: Nicolas Mowen * Remove subsection in favour of exclusively adding a warning * Adjust wording for the warning Co-authored-by: Nicolas Mowen --------- Co-authored-by: Nicolas Mowen --- docs/docs/frigate/installation.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/docs/frigate/installation.md b/docs/docs/frigate/installation.md index 59c196d0d..9399f775e 100644 --- a/docs/docs/frigate/installation.md +++ b/docs/docs/frigate/installation.md @@ -28,6 +28,12 @@ Frigate uses the following locations for read/write operations in the container. - `/tmp/cache`: Cache location for recording segments. Initial recordings are written here before being checked and converted to mp4 and moved to the recordings folder. Segments generated via the `clip.mp4` endpoints are also concatenated and processed here. It is recommended to use a [`tmpfs`](https://docs.docker.com/storage/tmpfs/) mount for this. - `/dev/shm`: Internal cache for raw decoded frames in shared memory. It is not recommended to modify this directory or map it with docker. The minimum size is impacted by the `shm-size` calculations below. +:::warning + +For Frigate to start, it requires a valid configuration file inside the `/config/` directory mentioned above. There is a step by step guide to creating a minimal configuration in the [getting started guide](https://docs.frigate.video/guides/getting_started#configuring-frigate). + +::: + #### Common docker compose storage configurations Writing to a local disk or external USB drive: