Compare commits

...

110 Commits

Author SHA1 Message Date
Nicolas Mowen
7d589bd6e1 Point go2rtc links in docs to 1.2.0 specifically (#5816)
* Point to specific tag of go2rtc docs

* Point to go2rtc 1.2.0 docs

* Point to go2rtc 1.2.0 docs

* Update camera_specific.md
2023-03-23 17:12:53 -05:00
Chris Cox
1bf3b83ef3 Fixed extension of config file (#5803)
* Fixed extension of config file

Using frigate.yml as the config file for the HA addon gives a validation error, the same contents in frigate.yaml work.

* More accurate description of config file handling.

* Update docs/docs/configuration/index.md

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
2023-03-22 19:48:24 -05:00
Nicolas Mowen
b61b6f46cd Update ha integration instructions to reflect new settings names (#5806) 2023-03-22 19:47:13 -05:00
Nicolas Mowen
ac339d411c Make note that snapshots are required for Frigate+ (#5807)
* Make note that snapshots are required for Frigate+

* Fix spacing
2023-03-22 19:46:43 -05:00
Nicolas Mowen
3f17f871fa Fix cleaning logs with rtsp in middle (#5800) 2023-03-21 17:21:37 -05:00
Nicolas Mowen
e454daf727 Fix timezone issues with strftime (#5762)
* Fix timezone issues with strftime

* Fix timezone adjustment

* Fix bug
2023-03-18 07:32:39 -05:00
luzik
732e527401 RTSP instead of RTMP in HA integration docs (#5761)
I believe that it should be RTSP there
2023-03-18 07:29:04 -05:00
luzik
b44e6cd5dc typo in live config documentation (#5760)
I believe that we should use defined rtsp_cam_sub, not test_cam_sub
2023-03-17 17:15:38 -05:00
Blake Blackshear
2d9556f5f3 set threads to 2 (#5747) 2023-03-17 17:14:57 -05:00
Blake Blackshear
e82f72a9d3 clarify that mqtt is required in frigate config for home assistant (#5722) 2023-03-15 17:43:36 -05:00
Blake Blackshear
ce2d589a28 fix config (#5721) 2023-03-14 08:51:09 -05:00
Blake Blackshear
750bf0e79a Revert "Update ffmpeg args with low risk improvements (#5519)" (#5715)
This reverts commit 52459bf348.
2023-03-14 08:25:27 -05:00
John Ritsema
4dc6c93cdb docs: adds note about dynamic config (#4882)
* docs: adds note about dynamic config

* less technical verbiage

* removes `dynamic configuration` verbiage

* list all replaceable values
2023-03-07 06:28:51 -06:00
Nicolas Mowen
f7e9507bee Fix typo (#5655) 2023-03-06 21:06:36 -06:00
Dermot Duffy
e8d8cc4f55 Return sub_labels in event summary information. (#5642) 2023-03-05 11:39:41 -06:00
Blake Blackshear
c20c982ad0 free up some disk space (#5644) 2023-03-05 09:14:11 -06:00
Nicolas Mowen
962bdc7fa5 Update detector support to be more generic (#5638) 2023-03-04 21:37:18 -06:00
Nicolas Mowen
a5e561c81d Restrict menu height to ensure it does not overflow (#5601) 2023-03-03 17:45:25 -06:00
Nicolas Mowen
c4ebafe777 Fix plus menu not showing (#5606)
* Set end time for download event

* Set the value
2023-03-03 17:44:58 -06:00
Nicolas Mowen
7ed715b371 Make note of other supervised limitations (#5627) 2023-03-03 17:44:32 -06:00
Martin Weinelt
161e7b3fd7 Allow using full tensorflow in cpu/edgetpu detector plugins (#5611)
It supports the same entrypoints, given that tflite is a small cut-out
of the big tensorflow picture.

This patch was created for downstream usage in nixpkgs, where we don't
have the tflite python package, but do have the full tensorflow package.
2023-03-03 17:44:17 -06:00
Nicolas Mowen
42eaa13402 Enable CORS for go2rtc by default (#5610)
* Enable CORS for go2rtc by default

* Fix typo
2023-03-03 17:43:50 -06:00
Nicolas Mowen
17c26c9fa9 Sub label filter fixes (#5602)
* Fix list access issue

* Specifically include item when in list or individual only

* Formatting

* Sort sub labels to ensure consistent list
2023-03-03 17:43:27 -06:00
Nicolas Mowen
318240c14c Add docs for time / date styling (#5572)
* Add docs for time / date styling

* Convert 12hour time format option to enum

* Change option in web

* Add docs with examples

* Fix errors in docs

* Fix mismatched names
2023-02-26 09:37:18 -06:00
Nicolas Mowen
34bdf2fc10 Clean up output for vainfo and ffprobe (#5586)
* Clean up output for vainfo and ffprobe

* Fix cleanup

* Format vainfo display

* Fix ffprobe output

* Fix stringification

* remove unused
2023-02-26 07:05:27 -06:00
Nicolas Mowen
d97fa99ec5 Fix logging for corrupt segments (#5582)
* Fix logging for corrupt segments

* Formatting
2023-02-24 19:13:33 -06:00
Nicolas Mowen
9621b4b9a1 Add tips for debugging playback issues (#5574) 2023-02-23 21:23:14 -06:00
Bernt Christian Egeland
3611e874ca Events Page: Added option to override browser time format and style (#5538)
* use12hour optional config

* use12hour config arg

* added use12HourFormat arg to format function

* dateStyle & timeStyle option

* moved timezone & locales to format function

* added dateStyle & timeStyle

* re-formatted

* added strftime_fmt config entry

* strftime package

* added strftime option

* underscore instead of camelCase

* underscore props instead of camelCase
2023-02-22 06:54:16 -07:00
Felipe Santos
fbf29667d4 Upgrade s6-overlay from 3.1.4.0 to 3.1.4.1 (#5558) 2023-02-21 06:30:32 -06:00
Nicolas Mowen
c13dd132ee Clean up camera specific docs (#5556) 2023-02-21 06:26:43 -06:00
Nicolas Mowen
3524d1a055 Fix go2rtc dashboard link (#5546)
* Fix go2rtc dashboard link

* Add trailing /
2023-02-20 20:16:26 -06:00
Felipe Santos
a8c567d877 Add healthcheck for go2rtc service (#5545)
* Upgrade s6-overlay from 3.1.3.0 to 3.1.4.0

* Add go2rtc healthcheck service

Also don't make go2rtc exits cause the container to fail.

* Reword healthcheck message

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>

* Add timeout to go2rtc healthcheck

* Update healthcheck message

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>

* Give additional time for go2rtc start/restart

* Fix typo

* Avoid creating go2rtc config multiple times

* Fix healthcheck not starting

* Fix sleep

* Fix more hidden logs

* Decrease time window and use curl's timeout flag

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
2023-02-19 13:11:12 -06:00
Nicolas Mowen
80135342c2 Update Go2rtc to 1.2.0 (#5528)
* Update dep

* Update docs
2023-02-19 07:49:12 -06:00
yeahme49
c2b13fdbdf Add new models to docs (#5533)
Yolov7-640, Yolov7-320, Yolov7x-640 and Yolov7x-320 models got added to the download_yolo.sh script that gets used as part of generating tensorrt models so they can now be generated
2023-02-19 07:41:55 -06:00
Nicolas Mowen
2797a60d4f Don't fail if openvino fails to import (#5532)
* Don't fail if openvino fails to import

* Ensure all modules are imported safely

* Undo

* Fix list append
2023-02-19 07:41:14 -06:00
Anil Ozyalcin
0592c8b0e2 YOLOv5 & YOLOv8 support for the OpenVINO Detector (#5523)
* Initial commit that adds YOLOv5 and YOLOv8 support for OpenVINO detector

* Fixed double inference bug with YOLOv5 and YOLOv8

* Modified documentation to mention YOLOv5 and YOLOv8

* Changes to pass lint checks

* Change minimum threshold to improve model performance

* Fix link

* Clean up YOLO post-processing

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
2023-02-19 07:39:47 -06:00
Nicolas Mowen
2b685ac343 Plus upload in progress (#5521)
* Fix frigate+ uploading bug

Fixes https://github.com/blakeblackshear/frigate/issues/5515

* wording

* Formatting

* Don't show button when event is in progress

* Don't show in download menu either
2023-02-19 07:38:16 -06:00
Nicolas Mowen
c901707670 Docs & WebUI Cleanup (#5527)
* Remove browser from timezone description

* Remove outdated info
2023-02-17 11:02:33 -06:00
Nicolas Mowen
27d3676ba5 Fix rpi birdseye encode (#5522)
* Remove invalid bframe argument for rpi encoder

* Remove gop size arg as well
2023-02-16 18:38:32 -06:00
Nicolas Mowen
52459bf348 Update ffmpeg args with low risk improvements (#5519)
* Add threads 1 to input / output args

* Remove cuvid from hwaccel

* Update docs for new args

* Formatting
2023-02-16 15:44:10 -07:00
Nicolas Mowen
6cfa73a284 Add link to go2rtc in system page (#5478)
* Add link to go2rtc in the system page

* Open in new page

* Add color and underline behavior

* Cleanup

* Cleanup

* Fix color

* fix tests
2023-02-16 07:50:03 -06:00
Nicolas Mowen
7b26935462 Ensure birdseye restream is not left with partially read frames (#5504)
* Ensure birdseye pipe does not get corrupted

* Fix conditionals

* Change log

* Formatting
2023-02-16 07:49:31 -06:00
Bernt Christian Egeland
c9cd810c9f reposition the modal when close to bottom (#5507) 2023-02-16 07:47:18 -06:00
Nicolas Mowen
1715e2e09d Init birdseye restream command in S6 (#5494)
* remove restream from frigate logic

* Migrate birdseye stream definition to S6

* Cleanup

* Use consts to import as well
2023-02-15 07:09:25 -06:00
Nicolas Mowen
b69c0daadb Add docs for required_zones (#5499)
* Add docs for required_zones

* fix spacing
2023-02-15 06:30:29 -06:00
Nicolas Mowen
56d2978bc8 Remove more outdated restream from docs (#5497) 2023-02-14 17:19:07 -06:00
Nicolas Mowen
1ef109e171 Remove restream role mention (#5468) 2023-02-12 15:29:08 -06:00
Nicolas Mowen
08ab9dedf7 Update ffmpeg_presets.py (#5462) 2023-02-12 08:02:40 -06:00
Nicolas Mowen
3d90366af2 Fix Webui Default Stream (#5455)
* Pass restream enabled

* Use livemode for birdseye as well
2023-02-12 07:36:36 -06:00
Nicolas Mowen
c74c9ff161 Add nvidia detector inference times from survey (#5456)
* Add nvidia detector inference times from survey

* Fix typo

* Update hardware.md
2023-02-11 19:59:36 -06:00
Blake Blackshear
27a31e731f install i965-va-driver-shaders (#5451) 2023-02-11 09:57:15 -06:00
Nicolas Mowen
562e2627c2 Auto select gpu for hwaccel presets (#5406)
* Add ability to GPU device to be automatically detected when multiple exist

* Add logging info

* Fix access

* Fix

* Formatting

* Fix path of device

* Use log error instead of raise

* Remove log which could apply to other caess

* Set default value

* rework logic and support auto gpu selection for encoding gpu as well
2023-02-11 08:00:58 -06:00
Felipe Santos
babd976533 Bump go2rtc from 1.1.1 to 1.1.2 (#5440)
* Bump go2rtc from 1.1.1 to 1.1.2

* Update go2rtc version in docs
2023-02-09 09:32:46 -06:00
Felipe Santos
748815b6ce Fix logging IP instead of WebRTC port (#5417) 2023-02-08 21:28:20 -06:00
Nicolas Mowen
88252e0ae6 Update ffmpeg_presets.py (#5433) 2023-02-08 21:27:43 -06:00
Nicolas Mowen
c0bf69b4bf add note about go2rtc webui (#5430) 2023-02-08 21:26:38 -06:00
Nicolas Mowen
b6b10e753f Update docs for H265 (#5398)
* Update hwaccel docs for h265

* Update camera specific

* Update hardware_acceleration.md

* Update hardware_acceleration.md
2023-02-06 07:54:01 -06:00
Nicolas Mowen
4a45089b95 Scrollbar juddering (#5383)
* added scrollbar width to observer width.

* subtract scrollBarWidth from scaledWidth

* useMemo dependencies

---------

Co-authored-by: Bernt Christian Egeland <cbegelan@gmail.com>
2023-02-05 09:13:15 -06:00
Blake Blackshear
3b9bcb356b update presets docs (#5386) 2023-02-05 09:12:40 -06:00
Blake Blackshear
e10ddb343c additional shutdown optimizations (#5380) 2023-02-04 08:58:45 -06:00
Blake Blackshear
e8cd25ddf2 Docs tweaks (#5379)
* add note about cameras needing ffmpeg for go2rtc

* clarify error message on GPU stats
2023-02-04 08:47:27 -06:00
Blake Blackshear
624c314335 Fast restart (#5378)
* dont wait so long for queues

* implement stop methods for comms

* set the detection events on exit and return early from processing

* handle the stop event in the broadcast threads

* short circuit the detection process exit code if it already exited

* some logging for stats thread

* just keep the log process alive 1 second after the last log message

* ensure the multiprocessing queues are emptied and closed

* Update frigate/log.py

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>

* Update frigate/log.py

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>

* mypy fixes

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
2023-02-03 20:15:47 -06:00
Anil Ozyalcin
b33094207c YOLOX support for OpenVINO Detector (#5285)
* Initial commit to enable Yolox models with OpenVINO in Frigate

* Fix ModelEnumtType import error in openvino.py

* Initial edit of the docs to include verbage about yolox

* Initial edit of the docs to include verbage about yolox

* Elaborate configuration and limitations in docs.

* Add capability to dynamically determine number of classes in yolox model

* Further refinements

* Removed unnecesarry comments, improved documentation, addressed PR items

* Fixed lint formatting issues
2023-02-03 19:36:37 -06:00
jvrobert
7083a5c9b6 Try to limit nvidia GPU queries to included GPUs (#5356)
* Try to limit nvidia GPU queries to included GPUs

* ignore non digit GPU indexes

* formatting

* Formatting

* Remove trailing spaces

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
2023-02-03 19:34:07 -06:00
Nicolas Mowen
db131d4971 Add Low latency preset (#5367)
* Create new low latency preset

* Update chart for new preset
2023-02-03 19:33:25 -06:00
Nicolas Mowen
74d6ab0555 Fix copying logs (#5373) 2023-02-03 19:32:31 -06:00
Nicolas Mowen
66881eb89f Add examples of intel inference times from survey answers (#5332) 2023-02-01 18:10:24 -06:00
Nicolas Mowen
ad60f4894b Update go2rtc to 1.1.1 (#5333)
* Update go2rtc to 1.1.1

* Remove redundant qualifiers

* Remove qualifiers

* Set default_query

* Update version
2023-02-01 18:09:56 -06:00
James L
8d21c950a3 Name capture processes (#5340) 2023-02-01 17:49:18 -06:00
Felipe Santos
ea8ec23cbe Upgrade go2rtc from v1.0.1 to v1.1.0 (#5320)
* Upgrade go2rtc to v1.1.0 and set AAC audio as preferred

* Remove change from Python file
2023-01-31 19:43:29 -06:00
Blake Blackshear
f06e8b47be Docs updates, fix recording warnings, default log level for ws4py (#5294)
* set default log level for ws4py

* proactively cleanup cache in all retain modes

* docs updates

* typo

* fix link

* updates
2023-01-30 17:42:53 -06:00
Nicolas Mowen
7edeaa3407 Add warning for below suggested SHM calculation (#5312)
* Add warning for below suggested SHM calculation

* Remove debug check

* Make names more clear

* Fix

* fix log
2023-01-30 17:42:23 -06:00
dependabot[bot]
7a7e30e1ff Bump ASzc/change-string-case-action from 1 to 5 (#5308)
Bumps [ASzc/change-string-case-action](https://github.com/ASzc/change-string-case-action) from 1 to 5.
- [Release notes](https://github.com/ASzc/change-string-case-action/releases)
- [Commits](https://github.com/ASzc/change-string-case-action/compare/v1...v5)

---
updated-dependencies:
- dependency-name: ASzc/change-string-case-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-30 06:15:04 -06:00
CZonin
78dc75a4f1 Add "" to go2rtc docs examples (#5292)
* Update live.md

Placed `ffmpeg:http_cam#audio=opus` in quotes so it doesn't appear as commented out in docs.

* Update restream.md

Placed `ffmpeg:http_cam#audio=opus` in quotes so it doesn't appear as commented out in docs.
2023-01-29 17:25:51 -06:00
Bernt Christian Egeland
a5078b8517 rework - ts, interval (#5291) 2023-01-29 17:25:28 -06:00
Nicolas Mowen
77876bd663 Add docs for adding authentication to rtsp restream (#5289)
* Add docs for adding authentication to rtsp restream

* Update restream.md

* Update restream.md

* Remove duplicate docs
2023-01-29 17:22:40 -06:00
Sammy1Am
a0697b81a1 Replace hardcoded package name in CI workflow (#5281) 2023-01-29 17:21:31 -06:00
Nicolas Mowen
88b903ba39 Restart ffmpeg if process exceeds detect fps by 10 (#5280)
* Restart ffmpeg if process exceeds detect fps by 10

* Update frigate/video.py

Co-authored-by: Felipe Santos <felipecassiors@gmail.com>

* spelling

---------

Co-authored-by: Felipe Santos <felipecassiors@gmail.com>
2023-01-29 17:20:42 -06:00
Nicolas Mowen
116edce3dc Set jsmpeg manually when restream is disabled (#5265) 2023-01-28 08:15:52 -06:00
Blake Blackshear
7130d93616 warn if unable to keep up with moving segments (#5264) 2023-01-27 07:32:55 -06:00
James L
11054daebe System page: add last updated time ago (#5195) 2023-01-27 06:20:41 -06:00
Nicolas Mowen
7926ddd008 Clear file before unlinking (#5259) 2023-01-27 06:16:40 -06:00
Nicolas Mowen
93f2316711 Update live.md (#5254) 2023-01-27 06:14:02 -06:00
Felipe Santos
fd3688a9c7 Upgrade s6-overlay from 3.1.2.1 to 3.1.3.0 (#5239) 2023-01-25 21:33:47 -06:00
Nicolas Mowen
a63dd9bccd Add low delay args to restream input args (#5231) 2023-01-25 18:39:35 -06:00
Nicolas Mowen
f54b223adf Print webrtc info to stderr (#5227)
* Update create_config.py

* Print to stderr
2023-01-25 18:38:45 -06:00
Nicolas Mowen
9ddcf7b1fe Add exec docs (#5230) 2023-01-25 18:37:48 -06:00
James L
07c635d822 Add config option to disable version check (#5208)
* Add config option to disable version check

* Add note to docs
2023-01-25 18:36:26 -06:00
Nicolas Mowen
6ed8977548 Update flv docs (#5238)
* Update camera_specific.md

* Update restream.md
2023-01-25 18:35:27 -06:00
Felipe Santos
e50cccc78a Upgrade go2rtc from 1.0.0 to 1.0.1 (#5235)
https://github.com/AlexxIT/go2rtc/releases/tag/v1.0.1
2023-01-25 18:35:12 -06:00
Felipe Santos
feeb7107d5 Fix Frigate stuck at finishing when restarting from UI (#5216) 2023-01-24 07:27:57 -06:00
Nicolas Mowen
f52de322d3 Set hard frame rate limit (#5210) 2023-01-24 07:27:07 -06:00
Felipe Santos
2f3e046130 Fix HA IP address and WebRTC port inferring (#5209)
* Fix HA IP address and WebRTC port inferring

* Add note for when candidates aren't being injected
2023-01-24 07:26:16 -06:00
sev
edbdbb7f07 Update NVIDIA hwdecode docs (#5182)
Closes #4716
2023-01-22 10:27:13 -06:00
Nicolas Mowen
4bb5785d89 Update go2rtc to 1.0.0 (#5173)
* Update Dockerfile

* update version in docs

Co-authored-by: Blake Blackshear <blakeb@blakeshome.com>
2023-01-20 20:59:03 -06:00
Nicolas Mowen
36c6ee73fe Update Nvidia Hwaccel Docs (#5172)
* Update hardware_acceleration.md

* Update hardware_acceleration.md

* Update hardware_acceleration.md

* Update hardware_acceleration.md

* Update docs/docs/configuration/hardware_acceleration.md

Co-authored-by: Felipe Santos <felipecassiors@gmail.com>

Co-authored-by: Felipe Santos <felipecassiors@gmail.com>
2023-01-20 20:41:34 -06:00
Nicolas Mowen
924f946e46 Fix birdseye snapshot (#5171) 2023-01-20 20:40:55 -06:00
Nicolas Mowen
d22e25064b Fix reolink docs and add example of manual ffmpeg restream (#5165)
* Update camera_specific.md

* Update restream.md
2023-01-19 08:14:38 -06:00
James L
12d51d3c73 System page: fix 0 FPS for disabled camera (#5155) 2023-01-18 18:05:18 -06:00
Nicolas Mowen
5fa1fbafed Use frigate env var substitution (#5153) 2023-01-18 17:51:35 -06:00
Felipe Santos
d36ab05bf1 Do not wait forever for services to exit (#5149)
* Fix frigate service restarting inside devcontainer

* Add timeouts to services exit process

So s6 won't wait forever.
2023-01-18 17:50:51 -06:00
Nicolas Mowen
fb85c8ca54 Optimize restream docs (#5132)
* Update live.md

* Update restream.md

* Update live.md

* Update camera_specific.md

* Update restream.md

* Update live.md

* Update live.md

* Update restream.md

* Typo

Co-authored-by: Blake Blackshear <blakeb@blakeshome.com>
2023-01-18 17:50:06 -06:00
Blake Blackshear
b2a2a9d6c7 only run the latest commit to avoid cache overwrites (#5154) 2023-01-18 17:30:49 -06:00
Felipe Santos
e2239d36c9 Auto discover internal WebRTC candidate for add-on (#5089)
* Auto discover internal WebRTC candidate for add-on

* Write logs to stderr

* Fix port number

* Integrate with newest changes

* Update docs

* Use local variable more

* Use Python to write file, fix JSON->YAML

* Store into variable

* Update docs/docs/configuration/live.md

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>

* Update docs/docs/configuration/live.md

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>

* Update docs/docs/configuration/live.md

* Update docs/docs/configuration/live.md

* Refator s6 scripts to the new format

* Remove unneeded workaround

* Update docker/rootfs/usr/local/go2rtc/create_config.py

* Migrate logging to new s6 format

* Remove more unnecessary s6 variables

* Fix prepare-log and when go2rtc is not present in config

* Restart the whole container if either Frigate or go2rtc fails

* D

* Fix service name in finish

* Fix nginx finish comment

* Restart improvements

* Fix devcontainer

* Fix format

* Update Dockerfile

Co-authored-by: Felipe Santos <felipecassiors@gmail.com>

* Improve scripts logging

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
2023-01-18 17:23:40 -06:00
Nicolas Mowen
6620236bc3 Catch case where go2rtc streams is not defined (#5150) 2023-01-18 17:20:44 -06:00
Felipe Santos
02df2a8bbd Refactor s6 scripts to the new format (#5135)
* Refator s6 scripts to the new format

* Remove unneeded workaround

* Migrate logging to new s6 format

* Remove more unnecessary s6 variables

* Fix prepare-log and when go2rtc is not present in config

* Restart the whole container if either Frigate or go2rtc fails

* D

* Fix service name in finish

* Fix nginx finish comment

* Restart improvements

* Fix devcontainer

* Fix format

* Update Dockerfile

Co-authored-by: Felipe Santos <felipecassiors@gmail.com>

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
2023-01-18 07:53:53 -06:00
Felipe Santos
89513e469a Fix shm size calculation (#5123)
* Fix shm size calculation

* Improve shm examples

* Add note about default shm size for add-ons

* adjust language

Co-authored-by: Blake Blackshear <blakeb@blakeshome.com>
2023-01-18 07:46:57 -06:00
Nicolas Mowen
f5466426df Fix go2rtc error when not set (#5133) 2023-01-17 22:38:17 -06:00
Nicolas Mowen
2631a4c35b Fix not using custom set stream name (#5134) 2023-01-17 22:36:52 -06:00
Nicolas Mowen
ef9338f5af Remove rpi warning about not working hwaccel (#5145) 2023-01-17 22:36:27 -06:00
117 changed files with 1726 additions and 592 deletions

View File

@@ -1,6 +1,6 @@
name: EdgeTpu Support Request name: Detector Support Request
description: Support for setting up EdgeTPU in Frigate description: Support for setting up object detector in Frigate (Coral, OpenVINO, TensorRT, etc.)
title: "[EdgeTPU Support]: " title: "[Detector Support]: "
labels: ["support", "triage"] labels: ["support", "triage"]
assignees: [] assignees: []
body: body:

View File

@@ -6,6 +6,11 @@ on:
- dev - dev
- master - master
# only run the latest commit to avoid cache overwrites
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
env: env:
PYTHON_VERSION: 3.9 PYTHON_VERSION: 3.9
@@ -14,6 +19,15 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Image Build name: Image Build
steps: steps:
- name: Remove unnecessary files
run: |
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc
- id: lowercaseRepo
uses: ASzc/change-string-case-action@v5
with:
string: ${{ github.repository }}
- name: Check out code - name: Check out code
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Set up QEMU - name: Set up QEMU
@@ -38,7 +52,7 @@ jobs:
platforms: linux/amd64,linux/arm64,linux/arm/v7 platforms: linux/amd64,linux/arm64,linux/arm/v7
target: frigate target: frigate
tags: | tags: |
ghcr.io/blakeblackshear/frigate:${{ github.ref_name }}-${{ env.SHORT_SHA }} ghcr.io/${{ steps.lowercaseRepo.outputs.lowercase }}:${{ github.ref_name }}-${{ env.SHORT_SHA }}
cache-from: type=gha cache-from: type=gha
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
- name: Build and push TensorRT - name: Build and push TensorRT
@@ -49,5 +63,5 @@ jobs:
platforms: linux/amd64 platforms: linux/amd64
target: frigate-tensorrt target: frigate-tensorrt
tags: | tags: |
ghcr.io/blakeblackshear/frigate:${{ github.ref_name }}-${{ env.SHORT_SHA }}-tensorrt ghcr.io/${{ steps.lowercaseRepo.outputs.lowercase }}:${{ github.ref_name }}-${{ env.SHORT_SHA }}-tensorrt
cache-from: type=gha cache-from: type=gha

View File

@@ -27,7 +27,7 @@ RUN --mount=type=tmpfs,target=/tmp --mount=type=tmpfs,target=/var/cache/apt \
FROM wget AS go2rtc FROM wget AS go2rtc
ARG TARGETARCH ARG TARGETARCH
WORKDIR /rootfs/usr/local/go2rtc/bin WORKDIR /rootfs/usr/local/go2rtc/bin
RUN wget -qO go2rtc "https://github.com/AlexxIT/go2rtc/releases/download/v0.1-rc.9/go2rtc_linux_${TARGETARCH}" \ RUN wget -qO go2rtc "https://github.com/AlexxIT/go2rtc/releases/download/v1.2.0/go2rtc_linux_${TARGETARCH}" \
&& chmod +x go2rtc && chmod +x go2rtc
@@ -192,22 +192,10 @@ RUN ldconfig
EXPOSE 5000 EXPOSE 5000
EXPOSE 1935 EXPOSE 1935
EXPOSE 8554 EXPOSE 8554
EXPOSE 8555 EXPOSE 8555/tcp 8555/udp
# Fails if cont-init.d fails
ENV S6_BEHAVIOUR_IF_STAGE2_FAILS=2
# Wait indefinitely for cont-init.d to finish before starting services
ENV S6_CMD_WAIT_FOR_SERVICES=1
ENV S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0
# Give services (including Frigate) 30 seconds to stop before killing them
# But this is not working currently because of:
# https://github.com/just-containers/s6-overlay/issues/503
ENV S6_SERVICES_GRACETIME=30000
# Configure logging to prepend timestamps, log to stdout, keep 0 archives and rotate on 10MB # Configure logging to prepend timestamps, log to stdout, keep 0 archives and rotate on 10MB
ENV S6_LOGGING_SCRIPT="T 1 n0 s10000000 T" ENV S6_LOGGING_SCRIPT="T 1 n0 s10000000 T"
# TODO: remove after a new version of s6-overlay is released. See:
# https://github.com/just-containers/s6-overlay/issues/460#issuecomment-1327127006
ENV S6_SERVICES_READYTIME=50
ENTRYPOINT ["/init"] ENTRYPOINT ["/init"]
CMD [] CMD []
@@ -217,7 +205,11 @@ FROM deps AS devcontainer
# Do not start the actual Frigate service on devcontainer as it will be started by VSCode # Do not start the actual Frigate service on devcontainer as it will be started by VSCode
# But start a fake service for simulating the logs # But start a fake service for simulating the logs
COPY docker/fake_frigate_run /etc/services.d/frigate/run COPY docker/fake_frigate_run /etc/s6-overlay/s6-rc.d/frigate/run
# Create symbolic link to the frigate source code, as go2rtc's create_config.sh uses it
RUN mkdir -p /opt/frigate \
&& ln -svf /workspace/frigate/frigate /opt/frigate/frigate
# Install Node 16 # Install Node 16
RUN apt-get update \ RUN apt-get update \

View File

@@ -2,7 +2,12 @@
# shellcheck shell=bash # shellcheck shell=bash
# Start the fake Frigate service # Start the fake Frigate service
set -o errexit -o nounset -o pipefail
# Tell S6-Overlay not to restart this service
s6-svc -O .
while true; do while true; do
echo "The fake Frigate service is running..." echo "[INFO] The fake Frigate service is running..."
sleep 5s sleep 5s
done done

View File

@@ -10,7 +10,9 @@ apt-get -qq install --no-install-recommends -y \
wget \ wget \
procps vainfo \ procps vainfo \
unzip locales tzdata libxml2 xz-utils \ unzip locales tzdata libxml2 xz-utils \
python3-pip python3-pip \
curl \
jq
mkdir -p -m 600 /root/.gnupg mkdir -p -m 600 /root/.gnupg
@@ -62,6 +64,9 @@ if [[ "${TARGETARCH}" == "amd64" ]]; then
apt-get -qq install --no-install-recommends --no-install-suggests -y \ apt-get -qq install --no-install-recommends --no-install-suggests -y \
intel-opencl-icd \ intel-opencl-icd \
mesa-va-drivers libva-drm2 intel-media-va-driver-non-free i965-va-driver libmfx1 radeontop intel-gpu-tools mesa-va-drivers libva-drm2 intel-media-va-driver-non-free i965-va-driver libmfx1 radeontop intel-gpu-tools
# something about this dependency requires it to be installed in a separate call rather than in the line above
apt-get -qq install --no-install-recommends --no-install-suggests -y \
i965-va-driver-shaders
rm -f /etc/apt/sources.list.d/debian-testing.list rm -f /etc/apt/sources.list.d/debian-testing.list
fi fi

View File

@@ -2,7 +2,7 @@
set -euxo pipefail set -euxo pipefail
s6_version="3.1.2.1" s6_version="3.1.4.1"
if [[ "${TARGETARCH}" == "amd64" ]]; then if [[ "${TARGETARCH}" == "amd64" ]]; then
s6_arch="x86_64" s6_arch="x86_64"

View File

@@ -0,0 +1 @@
frigate

View File

@@ -0,0 +1 @@
frigate-pipeline

View File

@@ -0,0 +1 @@
longrun

View File

@@ -0,0 +1,28 @@
#!/command/with-contenv bash
# shellcheck shell=bash
# Take down the S6 supervision tree when the service exits
set -o errexit -o nounset -o pipefail
# Logs should be sent to stdout so that s6 can collect them
declare exit_code_container
exit_code_container=$(cat /run/s6-linux-init-container-results/exitcode)
readonly exit_code_container
readonly exit_code_service="${1}"
readonly exit_code_signal="${2}"
readonly service="Frigate"
echo "[INFO] Service ${service} exited with code ${exit_code_service} (by signal ${exit_code_signal})"
if [[ "${exit_code_service}" -eq 256 ]]; then
if [[ "${exit_code_container}" -eq 0 ]]; then
echo $((128 + exit_code_signal)) >/run/s6-linux-init-container-results/exitcode
fi
elif [[ "${exit_code_service}" -ne 0 ]]; then
if [[ "${exit_code_container}" -eq 0 ]]; then
echo "${exit_code_service}" >/run/s6-linux-init-container-results/exitcode
fi
fi
exec /run/s6/basedir/bin/halt

View File

@@ -0,0 +1 @@
frigate-log

View File

@@ -4,7 +4,14 @@
set -o errexit -o nounset -o pipefail set -o errexit -o nounset -o pipefail
cd /opt/frigate # Logs should be sent to stdout so that s6 can collect them
# Tell S6-Overlay not to restart this service
s6-svc -O .
echo "[INFO] Starting Frigate..."
cd /opt/frigate || echo "[ERROR] Failed to change working directory to /opt/frigate"
# Replace the bash process with the Frigate process, redirecting stderr to stdout # Replace the bash process with the Frigate process, redirecting stderr to stdout
exec 2>&1 exec 2>&1

View File

@@ -0,0 +1 @@
120000

View File

@@ -0,0 +1 @@
longrun

View File

@@ -0,0 +1,12 @@
#!/command/with-contenv bash
# shellcheck shell=bash
set -o errexit -o nounset -o pipefail
# Logs should be sent to stdout so that s6 can collect them
readonly exit_code_service="${1}"
readonly exit_code_signal="${2}"
readonly service="go2rtc-healthcheck"
echo "[INFO] The ${service} service exited with code ${exit_code_service} (by signal ${exit_code_signal})"

View File

@@ -0,0 +1 @@
go2rtc-log

View File

@@ -0,0 +1,22 @@
#!/command/with-contenv bash
# shellcheck shell=bash
# Start the go2rtc-healthcheck service
set -o errexit -o nounset -o pipefail
# Logs should be sent to stdout so that s6 can collect them
# Give some additional time for go2rtc to start before start pinging
sleep 10s
echo "[INFO] Starting go2rtc healthcheck service..."
while sleep 30s; do
# Check if the service is running
if ! curl --connect-timeout 10 --fail --silent --show-error --output /dev/null http://127.0.0.1:1984/api/streams 2>&1; then
echo "[ERROR] The go2rtc service is not responding to ping, restarting..."
# We can also use -r instead of -t to send kill signal rather than term
s6-svc -t /var/run/service/go2rtc 2>&1
# Give some additional time to go2rtc to restart before start pinging again
sleep 10s
fi
done

View File

@@ -0,0 +1 @@
5000

View File

@@ -0,0 +1 @@
longrun

View File

@@ -0,0 +1,2 @@
go2rtc
go2rtc-healthcheck

View File

@@ -0,0 +1 @@
go2rtc-pipeline

View File

@@ -0,0 +1 @@
longrun

View File

@@ -0,0 +1,12 @@
#!/command/with-contenv bash
# shellcheck shell=bash
set -o errexit -o nounset -o pipefail
# Logs should be sent to stdout so that s6 can collect them
readonly exit_code_service="${1}"
readonly exit_code_signal="${2}"
readonly service="go2rtc"
echo "[INFO] The ${service} service exited with code ${exit_code_service} (by signal ${exit_code_signal})"

View File

@@ -0,0 +1 @@
go2rtc-log

View File

@@ -0,0 +1,61 @@
#!/command/with-contenv bash
# shellcheck shell=bash
# Start the go2rtc service
set -o errexit -o nounset -o pipefail
# Logs should be sent to stdout so that s6 can collect them
function get_ip_and_port_from_supervisor() {
local ip_address
# Example: 192.168.1.10/24
local ip_regex='^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})/[0-9]{1,2}$'
if ip_address=$(
curl -fsSL \
-H "Authorization: Bearer ${SUPERVISOR_TOKEN}" \
-H "Content-Type: application/json" \
http://supervisor/network/interface/default/info |
jq --exit-status --raw-output '.data.ipv4.address[0]'
) && [[ "${ip_address}" =~ ${ip_regex} ]]; then
ip_address="${BASH_REMATCH[1]}"
echo "[INFO] Got IP address from supervisor: ${ip_address}"
else
echo "[WARN] Failed to get IP address from supervisor"
return 0
fi
local webrtc_port
local port_regex='^([0-9]{1,5})$'
if webrtc_port=$(
curl -fsSL \
-H "Authorization: Bearer ${SUPERVISOR_TOKEN}" \
-H "Content-Type: application/json" \
http://supervisor/addons/self/info |
jq --exit-status --raw-output '.data.network["8555/tcp"]'
) && [[ "${webrtc_port}" =~ ${port_regex} ]]; then
webrtc_port="${BASH_REMATCH[1]}"
echo "[INFO] Got WebRTC port from supervisor: ${webrtc_port}"
else
echo "[WARN] Failed to get WebRTC port from supervisor"
return 0
fi
export FRIGATE_GO2RTC_WEBRTC_CANDIDATE_INTERNAL="${ip_address}:${webrtc_port}"
}
if [[ ! -f "/dev/shm/go2rtc.yaml" ]]; then
echo "[INFO] Preparing go2rtc config..."
if [[ -n "${SUPERVISOR_TOKEN:-}" ]]; then
# Running as a Home Assistant add-on, infer the IP address and port
get_ip_and_port_from_supervisor
fi
python3 /usr/local/go2rtc/create_config.py
fi
echo "[INFO] Starting go2rtc..."
# Replace the bash process with the go2rtc process, redirecting stderr to stdout
exec 2>&1
exec go2rtc -config=/dev/shm/go2rtc.yaml

View File

@@ -0,0 +1 @@
30000

View File

@@ -0,0 +1 @@
longrun

View File

@@ -0,0 +1 @@
oneshot

View File

@@ -0,0 +1 @@
/etc/s6-overlay/s6-rc.d/log-prepare/run

View File

@@ -0,0 +1 @@
nginx

View File

@@ -0,0 +1 @@
nginx-pipeline

View File

@@ -0,0 +1 @@
longrun

View File

@@ -0,0 +1,30 @@
#!/command/with-contenv bash
# shellcheck shell=bash
# Take down the S6 supervision tree when the service fails
set -o errexit -o nounset -o pipefail
# Logs should be sent to stdout so that s6 can collect them
declare exit_code_container
exit_code_container=$(cat /run/s6-linux-init-container-results/exitcode)
readonly exit_code_container
readonly exit_code_service="${1}"
readonly exit_code_signal="${2}"
readonly service="NGINX"
echo "[INFO] Service ${service} exited with code ${exit_code_service} (by signal ${exit_code_signal})"
if [[ "${exit_code_service}" -eq 256 ]]; then
if [[ "${exit_code_container}" -eq 0 ]]; then
echo $((128 + exit_code_signal)) >/run/s6-linux-init-container-results/exitcode
fi
if [[ "${exit_code_signal}" -eq 15 ]]; then
exec /run/s6/basedir/bin/halt
fi
elif [[ "${exit_code_service}" -ne 0 ]]; then
if [[ "${exit_code_container}" -eq 0 ]]; then
echo "${exit_code_service}" >/run/s6-linux-init-container-results/exitcode
fi
exec /run/s6/basedir/bin/halt
fi

View File

@@ -0,0 +1 @@
nginx-log

View File

@@ -2,6 +2,12 @@
# shellcheck shell=bash # shellcheck shell=bash
# Start the NGINX service # Start the NGINX service
set -o errexit -o nounset -o pipefail
# Logs should be sent to stdout so that s6 can collect them
echo "[INFO] Starting NGINX..."
# Replace the bash process with the NGINX process, redirecting stderr to stdout # Replace the bash process with the NGINX process, redirecting stderr to stdout
exec 2>&1 exec 2>&1
exec nginx exec nginx

View File

@@ -0,0 +1 @@
30000

View File

@@ -0,0 +1 @@
longrun

View File

@@ -1,16 +0,0 @@
#!/command/with-contenv bash
# shellcheck shell=bash
# Take down the S6 supervision tree when the service exits
set -o errexit -o nounset -o pipefail
# Prepare exit code
if [[ "${1}" -eq 256 ]]; then
exit_code="$((128 + ${2}))"
else
exit_code="${1}"
fi
# Make the container exit with the same exit code as the service
echo "${exit_code}" > /run/s6-linux-init-container-results/exitcode
exec /run/s6/basedir/bin/halt

View File

@@ -1,8 +0,0 @@
#!/command/with-contenv bash
# shellcheck shell=bash
# Take down the S6 supervision tree when the service fails, or restart it
# otherwise
if [[ "${1}" -ne 0 && "${1}" -ne 256 ]]; then
exec /run/s6/basedir/bin/halt
fi

View File

@@ -1,11 +0,0 @@
#!/command/with-contenv bash
# shellcheck shell=bash
# Start the go2rtc service
set -o errexit -o nounset -o pipefail
raw_config=$(python3 /usr/local/go2rtc/create_config.py)
# Replace the bash process with the go2rtc process, redirecting stderr to stdout
exec 2>&1
exec go2rtc -config="${raw_config}"

View File

@@ -1,8 +0,0 @@
#!/command/with-contenv bash
# shellcheck shell=bash
# Take down the S6 supervision tree when the service fails, or restart it
# otherwise
if [[ "${1}" -ne 0 && "${1}" -ne 256 ]]; then
exec /run/s6/basedir/bin/halt
fi

View File

@@ -1,5 +0,0 @@
#!/command/with-contenv bash
# shellcheck shell=bash
exec 2>&1
exec python3 -u -m frigate "${@}"

View File

@@ -2,9 +2,17 @@
import json import json
import os import os
import sys
import yaml import yaml
sys.path.insert(0, "/opt/frigate")
from frigate.const import BIRDSEYE_PIPE, BTBN_PATH
from frigate.ffmpeg_presets import parse_preset_hardware_acceleration_encode
sys.path.remove("/opt/frigate")
FRIGATE_ENV_VARS = {k: v for k, v in os.environ.items() if k.startswith("FRIGATE_")}
config_file = os.environ.get("CONFIG_FILE", "/config/config.yml") config_file = os.environ.get("CONFIG_FILE", "/config/config.yml")
# Check if we can use .yaml instead of .yml # Check if we can use .yaml instead of .yml
@@ -16,16 +24,83 @@ with open(config_file) as f:
raw_config = f.read() raw_config = f.read()
if config_file.endswith((".yaml", ".yml")): if config_file.endswith((".yaml", ".yml")):
config = yaml.safe_load(raw_config) config: dict[str, any] = yaml.safe_load(raw_config)
elif config_file.endswith(".json"): elif config_file.endswith(".json"):
config = json.loads(raw_config) config: dict[str, any] = json.loads(raw_config)
go2rtc_config: dict[str, any] = config["go2rtc"] go2rtc_config: dict[str, any] = config.get("go2rtc", {})
if not go2rtc_config.get("log", {}).get("format"): # Need to enable CORS for go2rtc so the frigate integration / card work automatically
if go2rtc_config.get("api") is None:
go2rtc_config["api"] = {"origin": "*"}
elif go2rtc_config["api"].get("origin") is None:
go2rtc_config["api"]["origin"] = "*"
# we want to ensure that logs are easy to read
if go2rtc_config.get("log") is None:
go2rtc_config["log"] = {"format": "text"} go2rtc_config["log"] = {"format": "text"}
elif go2rtc_config["log"].get("format") is None:
go2rtc_config["log"]["format"] = "text"
if not go2rtc_config.get("webrtc", {}).get("candidates", []): if not go2rtc_config.get("webrtc", {}).get("candidates", []):
go2rtc_config["webrtc"] = {"candidates": ["stun:8555"]} default_candidates = []
# use internal candidate if it was discovered when running through the add-on
internal_candidate = os.environ.get(
"FRIGATE_GO2RTC_WEBRTC_CANDIDATE_INTERNAL", None
)
if internal_candidate is not None:
default_candidates.append(internal_candidate)
# should set default stun server so webrtc can work
default_candidates.append("stun:8555")
print(json.dumps(go2rtc_config)) go2rtc_config["webrtc"] = {"candidates": default_candidates}
else:
print(
"[INFO] Not injecting WebRTC candidates into go2rtc config as it has been set manually",
)
# sets default RTSP response to be equivalent to ?video=h264,h265&audio=aac
# this means user does not need to specify audio codec when using restream
# as source for frigate and the integration supports HLS playback
if go2rtc_config.get("rtsp") is None:
go2rtc_config["rtsp"] = {"default_query": "mp4"}
elif go2rtc_config["rtsp"].get("default_query") is None:
go2rtc_config["rtsp"]["default_query"] = "mp4"
# need to replace ffmpeg command when using ffmpeg4
if not os.path.exists(BTBN_PATH):
if go2rtc_config.get("ffmpeg") is None:
go2rtc_config["ffmpeg"] = {
"rtsp": "-fflags nobuffer -flags low_delay -stimeout 5000000 -user_agent go2rtc/ffmpeg -rtsp_transport tcp -i {input}"
}
elif go2rtc_config["ffmpeg"].get("rtsp") is None:
go2rtc_config["ffmpeg"][
"rtsp"
] = "-fflags nobuffer -flags low_delay -stimeout 5000000 -user_agent go2rtc/ffmpeg -rtsp_transport tcp -i {input}"
for name in go2rtc_config.get("streams", {}):
stream = go2rtc_config["streams"][name]
if isinstance(stream, str):
go2rtc_config["streams"][name] = go2rtc_config["streams"][name].format(
**FRIGATE_ENV_VARS
)
elif isinstance(stream, list):
for i, stream in enumerate(stream):
go2rtc_config["streams"][name][i] = stream.format(**FRIGATE_ENV_VARS)
# add birdseye restream stream if enabled
if config.get("birdseye", {}).get("restream", False):
birdseye: dict[str, any] = config.get("birdseye")
input = f"-f rawvideo -pix_fmt yuv420p -video_size {birdseye.get('width', 1280)}x{birdseye.get('height', 720)} -r 10 -i {BIRDSEYE_PIPE}"
ffmpeg_cmd = f"exec:{parse_preset_hardware_acceleration_encode(config.get('ffmpeg', {}).get('hwaccel_args'), input, '-rtsp_transport tcp -f rtsp {output}')}"
if go2rtc_config.get("streams"):
go2rtc_config["streams"]["birdseye"] = ffmpeg_cmd
else:
go2rtc_config["streams"] = {"birdseye": ffmpeg_cmd}
# Write go2rtc_config to /dev/shm/go2rtc.yaml
with open("/dev/shm/go2rtc.yaml", "w") as f:
yaml.dump(go2rtc_config, f)

View File

@@ -106,31 +106,37 @@ If available, recommended settings are:
According to [this discussion](https://github.com/blakeblackshear/frigate/issues/3235#issuecomment-1135876973), the http video streams seem to be the most reliable for Reolink. According to [this discussion](https://github.com/blakeblackshear/frigate/issues/3235#issuecomment-1135876973), the http video streams seem to be the most reliable for Reolink.
```yaml ```yaml
go2rtc:
streams:
reolink:
- http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=username&password=password
- ffmpeg:reolink#audio=opus
reolink_sub:
- http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_ext.bcs&user=username&password=password
cameras: cameras:
reolink: reolink:
ffmpeg: ffmpeg:
input_args: preset-http-reolink
inputs: inputs:
- path: http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=username&password=password - path: rtsp://127.0.0.1:8554/reolink?video=copy&audio=aac
input_args: preset-rtsp-restream
roles: roles:
- record - record
- rtmp - path: rtsp://127.0.0.1:8554/reolink_sub?video=copy
- path: http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_ext.bcs&user=username&password=password input_args: preset-rtsp-restream
roles: roles:
- detect - detect
detect:
width: 896
height: 672
fps: 7
``` ```
### Unifi Protect Cameras ### Unifi Protect Cameras
In the Unifi 2.0 update Unifi Protect Cameras had a change in audio sample rate which causes issues for ffmpeg. The input rate needs to be set for record and rtmp. Unifi protect cameras require the rtspx stream to be used with go2rtc https://github.com/AlexxIT/go2rtc/tree/v1.2.0#source-rtsp
In the Unifi 2.0 update Unifi Protect Cameras had a change in audio sample rate which causes issues for ffmpeg. The input rate needs to be set for record and rtmp if used directly with unifi protect.
```yaml ```yaml
ffmpeg: ffmpeg:
output_args: output_args:
record: preset-record-ubiquiti record: preset-record-ubiquiti
rtmp: preset-rtmp-ubiquiti rtmp: preset-rtmp-ubiquiti # recommend using go2rtc instead
``` ```

View File

@@ -101,7 +101,7 @@ The OpenVINO device to be used is specified using the `"device"` attribute accor
OpenVINO is supported on 6th Gen Intel platforms (Skylake) and newer. A supported Intel platform is required to use the `GPU` device with OpenVINO. The `MYRIAD` device may be run on any platform, including Arm devices. For detailed system requirements, see [OpenVINO System Requirements](https://www.intel.com/content/www/us/en/developer/tools/openvino-toolkit/system-requirements.html) OpenVINO is supported on 6th Gen Intel platforms (Skylake) and newer. A supported Intel platform is required to use the `GPU` device with OpenVINO. The `MYRIAD` device may be run on any platform, including Arm devices. For detailed system requirements, see [OpenVINO System Requirements](https://www.intel.com/content/www/us/en/developer/tools/openvino-toolkit/system-requirements.html)
An OpenVINO model is provided in the container at `/openvino-model/ssdlite_mobilenet_v2.xml` and is used by this detector type by default. The model comes from Intel's Open Model Zoo [SSDLite MobileNet V2](https://github.com/openvinotoolkit/open_model_zoo/tree/master/models/public/ssdlite_mobilenet_v2) and is converted to an FP16 precision IR model. Use the model configuration shown below when using the OpenVINO detector. An OpenVINO model is provided in the container at `/openvino-model/ssdlite_mobilenet_v2.xml` and is used by this detector type by default. The model comes from Intel's Open Model Zoo [SSDLite MobileNet V2](https://github.com/openvinotoolkit/open_model_zoo/tree/master/models/public/ssdlite_mobilenet_v2) and is converted to an FP16 precision IR model. Use the model configuration shown below when using the OpenVINO detector with the default model.
```yaml ```yaml
detectors: detectors:
@@ -119,6 +119,25 @@ model:
labelmap_path: /openvino-model/coco_91cl_bkgr.txt 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/index.md#full-configuration-reference) for a list of possible `model_type` options. Below is an example of how `yolox_tiny` can be used in Frigate:
```yaml
detectors:
ov:
type: openvino
device: AUTO
model:
path: /path/to/yolox_tiny.xml
model:
width: 416
height: 416
input_tensor: nchw
input_pixel_format: bgr
model_type: yolox
labelmap_path: /path/to/coco_80cl.txt
```
### Intel NCS2 VPU and Myriad X Setup ### Intel NCS2 VPU and Myriad X Setup
Intel produces a neural net inference accelleration chip called Myriad X. This chip was sold in their Neural Compute Stick 2 (NCS2) which has been discontinued. If intending to use the MYRIAD device for accelleration, additional setup is required to pass through the USB device. The host needs a udev rule installed to handle the NCS2 device. Intel produces a neural net inference accelleration chip called Myriad X. This chip was sold in their Neural Compute Stick 2 (NCS2) which has been discontinued. If intending to use the MYRIAD device for accelleration, additional setup is required to pass through the USB device. The host needs a udev rule installed to handle the NCS2 device.
@@ -212,6 +231,10 @@ yolov4x-mish-320
yolov4x-mish-640 yolov4x-mish-640
yolov7-tiny-288 yolov7-tiny-288
yolov7-tiny-416 yolov7-tiny-416
yolov7-640
yolov7-320
yolov7x-640
yolov7x-320
``` ```
### Configuration Parameters ### Configuration Parameters

View File

@@ -28,16 +28,17 @@ Input args presets help make the config more readable and handle use cases for d
See [the camera specific docs](/configuration/camera_specific.md) for more info on non-standard cameras and recommendations for using them in Frigate. See [the camera specific docs](/configuration/camera_specific.md) for more info on non-standard cameras and recommendations for using them in Frigate.
| Preset | Usage | Other Notes | | Preset | Usage | Other Notes |
| ------------------------- | ------------------------- | --------------------------------------------------- | | -------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------ |
| preset-http-jpeg-generic | HTTP Live Jpeg | Recommend restreaming live jpeg instead | | preset-http-jpeg-generic | HTTP Live Jpeg | Recommend restreaming live jpeg instead |
| preset-http-mjpeg-generic | HTTP Mjpeg Stream | Recommend restreaming mjpeg stream instead | | preset-http-mjpeg-generic | HTTP Mjpeg Stream | Recommend restreaming mjpeg stream instead |
| preset-http-reolink | Reolink HTTP-FLV Stream | Only for reolink http, not when restreaming as rtsp | | preset-http-reolink | Reolink HTTP-FLV Stream | Only for reolink http, not when restreaming as rtsp |
| preset-rtmp-generic | RTMP Stream | | | preset-rtmp-generic | RTMP Stream | |
| preset-rtsp-generic | RTSP Stream | This is the default when nothing is specified | | preset-rtsp-generic | RTSP Stream | This is the default when nothing is specified |
| preset-rtsp-restream | RTSP Stream from restream | Use when using rtsp restream as source | | preset-rtsp-restream | RTSP Stream from restream | Use for rtsp restream as source for frigate |
| preset-rtsp-udp | RTSP Stream via UDP | Use when camera is UDP only | | preset-rtsp-restream-low-latency | RTSP Stream from restream | Use for rtsp restream as source for frigate to lower latency, may cause issues with some cameras |
| preset-rtsp-blue-iris | Blue Iris RTSP Stream | Use when consuming a stream from Blue Iris | | preset-rtsp-udp | RTSP Stream via UDP | Use when camera is UDP only |
| preset-rtsp-blue-iris | Blue Iris RTSP Stream | Use when consuming a stream from Blue Iris |
:::caution :::caution
@@ -46,21 +47,22 @@ It is important to be mindful of input args when using restream because you can
::: :::
```yaml ```yaml
go2rtc:
streams:
reolink_cam: http://192.168.0.139/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=admin&password=password
cameras: cameras:
reolink_cam: reolink_cam:
ffmpeg: ffmpeg:
inputs: inputs:
- path: http://192.168.0.139/flv?port=1935&app=bcs&stream=channel0_ext.bcs&user=admin&password={FRIGATE_CAM_PASSWORD} - path: http://192.168.0.139/flv?port=1935&app=bcs&stream=channel0_ext.bcs&user=admin&password=password
input_args: preset-http-reolink input_args: preset-http-reolink
roles: roles:
- detect - detect
- path: rtsp://192.168.0.10:8554/garage - path: rtsp://127.0.0.1:8554/reolink_cam
input_args: preset-rtsp-generic input_args: preset-rtsp-generic
roles: roles:
- record - record
- path: http://192.168.0.139/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=admin&password={FRIGATE_CAM_PASSWORD}
roles:
- restream
``` ```
### Output Args Presets ### Output Args Presets

View File

@@ -7,12 +7,6 @@ It is recommended to update your configuration to enable hardware accelerated de
### Raspberry Pi 3/4 ### Raspberry Pi 3/4
:::caution
There is currently a bug in ffmpeg that causes hwaccel to not work for the RPi kernel 5.15.61 and above. For more information see https://github.com/blakeblackshear/frigate/issues/3780
:::
Ensure you increase the allocated RAM for your GPU to at least 128 (raspi-config > Performance Options > GPU Memory). Ensure you increase the allocated RAM for your GPU to at least 128 (raspi-config > Performance Options > GPU Memory).
**NOTICE**: If you are using the addon, you may need to turn off `Protection mode` for hardware acceleration. **NOTICE**: If you are using the addon, you may need to turn off `Protection mode` for hardware acceleration.
@@ -21,23 +15,39 @@ ffmpeg:
hwaccel_args: preset-rpi-64-h264 hwaccel_args: preset-rpi-64-h264
``` ```
### Intel-based CPUs (<10th Generation) via Quicksync ### Intel-based CPUs (<10th Generation) via VAAPI
VAAPI supports automatic profile selection so it will work automatically with both H.264 and H.265 streams. VAAPI is recommended for all generations of Intel-based CPUs if QSV does not work.
```yaml ```yaml
ffmpeg: ffmpeg:
hwaccel_args: preset-vaapi hwaccel_args: preset-vaapi
``` ```
**NOTICE**: With some of the processors, like the J4125, the default driver `iHD` doesn't seem to work correctly for hardware acceleration. You may need to change the driver to `i965` by adding the following environment variable `LIBVA_DRIVER_NAME=i965` to your docker-compose file or [in the frigate.yml for HA OS users](advanced.md#environment_vars). **NOTICE**: With some of the processors, like the J4125, the default driver `iHD` doesn't seem to work correctly for hardware acceleration. You may need to change the driver to `i965` by adding the following environment variable `LIBVA_DRIVER_NAME=i965` to your docker-compose file or [in the frigate.yml for HA OS users](advanced.md#environment_vars).
### Intel-based CPUs (>=10th Generation) via Quicksync ### Intel-based CPUs (>=10th Generation) via Quicksync
QSV must be set specifically based on the video encoding of the stream.
#### H.264 streams
```yaml ```yaml
ffmpeg: ffmpeg:
hwaccel_args: preset-intel-qsv-h264 hwaccel_args: preset-intel-qsv-h264
``` ```
#### H.265 streams
```yaml
ffmpeg:
hwaccel_args: preset-intel-qsv-h265
```
### AMD/ATI GPUs (Radeon HD 2000 and newer GPUs) via libva-mesa-driver ### AMD/ATI GPUs (Radeon HD 2000 and newer GPUs) via libva-mesa-driver
VAAPI supports automatic profile selection so it will work automatically with both H.264 and H.265 streams.
**Note:** You also need to set `LIBVA_DRIVER_NAME=radeonsi` as an environment variable on the container. **Note:** You also need to set `LIBVA_DRIVER_NAME=radeonsi` as an environment variable on the container.
```yaml ```yaml
@@ -45,14 +55,20 @@ ffmpeg:
hwaccel_args: preset-vaapi hwaccel_args: preset-vaapi
``` ```
### NVIDIA GPU ### NVIDIA GPUs
[Supported Nvidia GPUs for Decoding](https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new) While older GPUs may work, it is recommended to use modern, supported GPUs. NVIDIA provides a [matrix of supported GPUs and features](https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new). If your card is on the list and supports CUVID/NVDEC, it will most likely work with Frigate for decoding. However, you must also use [a driver version that will work with FFmpeg](https://github.com/FFmpeg/nv-codec-headers/blob/master/README). Older driver versions may be missing symbols and fail to work, and older cards are not supported by newer driver versions. The only way around this is to [provide your own FFmpeg](/configuration/advanced#custom-ffmpeg-build) that will work with your driver version, but this is unsupported and may not work well if at all.
These instructions are based on the [jellyfin documentation](https://jellyfin.org/docs/general/administration/hardware-acceleration.html#nvidia-hardware-acceleration-on-docker-linux) A more complete list of cards and ther compatible drivers is available in the [driver release readme](https://download.nvidia.com/XFree86/Linux-x86_64/525.85.05/README/supportedchips.html).
If your distribution does not offer NVIDIA driver packages, you can [download them here](https://www.nvidia.com/en-us/drivers/unix/).
#### Docker Configuration
Additional configuration is needed for the Docker container to be able to access the NVIDIA GPU. The supported method for this is to install the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker) and specify the GPU to Docker. How you do this depends on how Docker is being run:
##### Docker Compose
Add `--gpus all` to your docker run command or update your compose file.
If you have multiple Nvidia graphic card, you can add them with their ids obtained via `nvidia-smi` command
```yaml ```yaml
services: services:
frigate: frigate:
@@ -68,11 +84,23 @@ services:
capabilities: [gpu] capabilities: [gpu]
``` ```
##### Docker Run CLI
```bash
docker run -d \
--name frigate \
...
--gpus=all \
ghcr.io/blakeblackshear/frigate:stable
```
#### Setup Decoder
The decoder you need to pass in the `hwaccel_args` will depend on the input video. The decoder you need to pass in the `hwaccel_args` will depend on the input video.
A list of supported codecs (you can use `ffmpeg -decoders | grep cuvid` in the container to get a list) A list of supported codecs (you can use `ffmpeg -decoders | grep cuvid` in the container to get the ones your card supports)
```shell ```
V..... h263_cuvid Nvidia CUVID H263 decoder (codec h263) V..... h263_cuvid Nvidia CUVID H263 decoder (codec h263)
V..... h264_cuvid Nvidia CUVID H264 decoder (codec h264) V..... h264_cuvid Nvidia CUVID H264 decoder (codec h264)
V..... hevc_cuvid Nvidia CUVID HEVC decoder (codec hevc) V..... hevc_cuvid Nvidia CUVID HEVC decoder (codec hevc)
@@ -93,12 +121,12 @@ ffmpeg:
``` ```
If everything is working correctly, you should see a significant improvement in performance. If everything is working correctly, you should see a significant improvement in performance.
Verify that hardware decoding is working by running `nvidia-smi`, which should show the ffmpeg Verify that hardware decoding is working by running `nvidia-smi`, which should show `ffmpeg`
processes: processes:
:::note :::note
nvidia-smi may not show ffmpeg processes when run inside the container [due to docker limitations](https://github.com/NVIDIA/nvidia-docker/issues/179#issuecomment-645579458) `nvidia-smi` may not show `ffmpeg` processes when run inside the container [due to docker limitations](https://github.com/NVIDIA/nvidia-docker/issues/179#issuecomment-645579458).
::: :::
@@ -129,3 +157,7 @@ nvidia-smi may not show ffmpeg processes when run inside the container [due to d
| 0 N/A N/A 12827 C ffmpeg 417MiB | | 0 N/A N/A 12827 C ffmpeg 417MiB |
+-----------------------------------------------------------------------------+ +-----------------------------------------------------------------------------+
``` ```
If you do not see these processes, check the `docker logs` for the container and look for decoding errors.
These instructions were originally based on the [Jellyfin documentation](https://jellyfin.org/docs/general/administration/hardware-acceleration.html#nvidia-hardware-acceleration-on-docker-linux).

View File

@@ -3,7 +3,7 @@ id: index
title: Configuration File title: Configuration File
--- ---
For Home Assistant Addon installations, the config file needs to be in the root of your Home Assistant config directory (same location as `configuration.yaml`) and named `frigate.yml`. For Home Assistant Addon installations, the config file needs to be in the root of your Home Assistant config directory (same location as `configuration.yaml`). It can be named `frigate.yml` or `frigate.yaml`, but if both files exist `frigate.yaml` will be preferred and `frigate.yml` will be ignored.
For all other installation types, the config file should be mapped to `/config/config.yml` inside the container. For all other installation types, the config file should be mapped to `/config/config.yml` inside the container.
@@ -19,7 +19,6 @@ cameras:
- path: rtsp://viewer:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2 - path: rtsp://viewer:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2
roles: roles:
- detect - detect
- restream
detect: detect:
width: 1280 width: 1280
height: 720 height: 720
@@ -37,6 +36,25 @@ It is not recommended to copy this full configuration file. Only specify values
::: :::
**Note:** The following values will be replaced at runtime by using environment variables
- `{FRIGATE_MQTT_USER}`
- `{FRIGATE_MQTT_PASSWORD}`
- `{FRIGATE_RTSP_USER}`
- `{FRIGATE_RTSP_PASSWORD}`
for example:
```yaml
mqtt:
user: "{FRIGATE_MQTT_USER}"
password: "{FRIGATE_MQTT_PASSWORD}"
```
```yaml
- path: rtsp://{FRIGATE_RTSP_USER}:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:8554/unicast
```
```yaml ```yaml
mqtt: mqtt:
# Optional: Enable mqtt server (default: shown below) # Optional: Enable mqtt server (default: shown below)
@@ -105,6 +123,9 @@ model:
# Optional: Object detection model input tensor format # Optional: Object detection model input tensor format
# Valid values are nhwc or nchw (default: shown below) # Valid values are nhwc or nchw (default: shown below)
input_tensor: nhwc 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)
model_type: ssd
# Optional: Label name modifications. These are merged into the standard labelmap. # Optional: Label name modifications. These are merged into the standard labelmap.
labelmap: labelmap:
2: vehicle 2: vehicle
@@ -146,7 +167,7 @@ birdseye:
# More information about presets at https://docs.frigate.video/configuration/ffmpeg_presets # More information about presets at https://docs.frigate.video/configuration/ffmpeg_presets
ffmpeg: ffmpeg:
# Optional: global ffmpeg args (default: shown below) # Optional: global ffmpeg args (default: shown below)
global_args: -hide_banner -loglevel warning global_args: -hide_banner -loglevel warning -threads 2
# Optional: global hwaccel args (default: shown below) # Optional: global hwaccel args (default: shown below)
# NOTE: See hardware acceleration docs for your specific device # NOTE: See hardware acceleration docs for your specific device
hwaccel_args: [] hwaccel_args: []
@@ -155,7 +176,7 @@ ffmpeg:
# Optional: global output args # Optional: global output args
output_args: output_args:
# Optional: output args for detect streams (default: shown below) # Optional: output args for detect streams (default: shown below)
detect: -f rawvideo -pix_fmt yuv420p detect: -threads 2 -f rawvideo -pix_fmt yuv420p
# Optional: output args for record streams (default: shown below) # Optional: output args for record streams (default: shown below)
record: preset-record-generic record: preset-record-generic
# Optional: output args for rtmp streams (default: shown below) # Optional: output args for rtmp streams (default: shown below)
@@ -172,7 +193,6 @@ detect:
# NOTE: Recommended value of 5. Ideally, try and reduce your FPS on the camera. # NOTE: Recommended value of 5. Ideally, try and reduce your FPS on the camera.
fps: 5 fps: 5
# Optional: enables detection for the camera (default: True) # Optional: enables detection for the camera (default: True)
# This value can be set via MQTT and will be updated in startup based on retained value
enabled: True enabled: True
# Optional: Number of frames without a detection before Frigate considers an object to be gone. (default: 5x the frame rate) # Optional: Number of frames without a detection before Frigate considers an object to be gone. (default: 5x the frame rate)
max_disappeared: 25 max_disappeared: 25
@@ -271,11 +291,6 @@ record:
# Optional: Enable recording (default: shown below) # Optional: Enable recording (default: shown below)
# WARNING: If recording is disabled in the config, turning it on via # WARNING: If recording is disabled in the config, turning it on via
# the UI or MQTT later will have no effect. # the UI or MQTT later will have no effect.
# WARNING: Frigate does not currently support limiting recordings based
# on available disk space automatically. If using recordings,
# you must specify retention settings for a number of days that
# will fit within the available disk space of your drive or Frigate
# will crash.
enabled: False enabled: False
# Optional: Number of minutes to wait between cleanup runs (default: shown below) # Optional: Number of minutes to wait between cleanup runs (default: shown below)
# This can be used to reduce the frequency of deleting recording segments from disk if you want to minimize i/o # This can be used to reduce the frequency of deleting recording segments from disk if you want to minimize i/o
@@ -325,7 +340,6 @@ record:
# NOTE: Can be overridden at the camera level # NOTE: Can be overridden at the camera level
snapshots: snapshots:
# Optional: Enable writing jpg snapshot to /media/frigate/clips (default: shown below) # Optional: Enable writing jpg snapshot to /media/frigate/clips (default: shown below)
# This value can be set via MQTT and will be updated in startup based on retained value
enabled: False enabled: False
# Optional: save a clean PNG copy of the snapshot image (default: shown below) # Optional: save a clean PNG copy of the snapshot image (default: shown below)
clean_copy: True clean_copy: True
@@ -355,7 +369,7 @@ rtmp:
enabled: False enabled: False
# Optional: Restream configuration # Optional: Restream configuration
# Uses https://github.com/AlexxIT/go2rtc (v0.1-rc9) # Uses https://github.com/AlexxIT/go2rtc (v1.2.0)
go2rtc: go2rtc:
# Optional: jsmpeg stream configuration for WebUI # Optional: jsmpeg stream configuration for WebUI
@@ -410,12 +424,12 @@ cameras:
# Required: the path to the stream # Required: the path to the stream
# NOTE: path may include environment variables, which must begin with 'FRIGATE_' and be referenced in {} # NOTE: path may include environment variables, which must begin with 'FRIGATE_' and be referenced in {}
- path: rtsp://viewer:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2 - path: rtsp://viewer:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2
# Required: list of roles for this stream. valid values are: detect,record,restream,rtmp # Required: list of roles for this stream. valid values are: detect,record,rtmp
# NOTICE: In addition to assigning the record, restream, and rtmp roles, # NOTICE: In addition to assigning the record and rtmp roles,
# they must also be enabled in the camera config. # they must also be enabled in the camera config.
roles: roles:
- detect - detect
- restream - record
- rtmp - rtmp
# Optional: stream specific global args (default: inherit) # Optional: stream specific global args (default: inherit)
# global_args: # global_args:
@@ -490,5 +504,34 @@ ui:
# Optional: Set a timezone to use in the UI (default: use browser local time) # Optional: Set a timezone to use in the UI (default: use browser local time)
timezone: None timezone: None
# Optional: Use an experimental recordings / camera view UI (default: shown below) # Optional: Use an experimental recordings / camera view UI (default: shown below)
experimental_ui: False use_experimental: False
# Optional: Set the time format used.
# Options are browser, 12hour, or 24hour (default: shown below)
time_format: browser
# Optional: Set the date style for a specified length.
# Options are: full, long, medium, short
# Examples:
# short: 2/11/23
# medium: Feb 11, 2023
# full: Saturday, February 11, 2023
# (default: shown below).
date_style: short
# Optional: Set the time style for a specified length.
# Options are: full, long, medium, short
# Examples:
# short: 8:14 PM
# medium: 8:15:22 PM
# full: 8:15:22 PM Mountain Standard Time
# (default: shown below).
time_style: medium
# Optional: Ability to manually override the date / time styling to use strftime format
# https://www.gnu.org/software/libc/manual/html_node/Formatting-Calendar-Time.html
# possible values are shown above (default: not set)
strftime_fmt: "%Y/%m/%d %H:%M"
# Optional: Telemetry configuration
telemetry:
# Optional: Enable the latest version outbound check (default: shown below)
# NOTE: If you use the HomeAssistant integration, disabling this will prevent it from reporting new versions
version_check: True
``` ```

View File

@@ -3,44 +3,31 @@ id: live
title: Live View title: Live View
--- ---
Frigate has different live view options, some of which require [restream](restream.md) to be enabled. Frigate has different live view options, some of which require the bundled `go2rtc` to be configured as shown in the [step by step guide](/guides/configuring_go2rtc).
## Live View Options ## Live View Options
Live view options can be selected while viewing the live stream. The options are: Live view options can be selected while viewing the live stream. The options are:
| Source | Latency | Frame Rate | Resolution | Audio | Requires Restream | Other Limitations | | Source | Latency | Frame Rate | Resolution | Audio | Requires go2rtc | Other Limitations |
| ------ | ------- | ------------------------------------- | -------------- | ---------------------------- | ----------------- | -------------------------------------------- | | ------ | ------- | ------------------------------------- | -------------- | ---------------------------- | --------------- | -------------------------------------------- |
| jsmpeg | low | same as `detect -> fps`, capped at 10 | same as detect | no | no | none | | jsmpeg | low | same as `detect -> fps`, capped at 10 | same as detect | no | no | none |
| mse | low | native | native | yes (depends on audio codec) | yes | not supported on iOS, Firefox is h.264 only | | mse | low | native | native | yes (depends on audio codec) | yes | not supported on iOS, Firefox is h.264 only |
| webrtc | lowest | native | native | yes (depends on audio codec) | yes | requires extra config, doesn't support h.265 | | webrtc | lowest | native | native | yes (depends on audio codec) | yes | requires extra config, doesn't support h.265 |
### Audio Support ### Audio Support
MSE Requires AAC audio, WebRTC requires PCMU/PCMA, or opus audio. If you want to support both MSE and WebRTC then your restream config needs to use ffmpeg to set both. MSE Requires AAC audio, WebRTC requires PCMU/PCMA, or opus audio. If you want to support both MSE and WebRTC then your restream config needs to make sure both are enabled.
```yaml ```yaml
go2rtc: go2rtc:
streams: streams:
test_cam: ffmpeg:rtsp://192.168.1.5:554/live0#video=copy#audio=aac#audio=opus rtsp_cam: # <- for RTSP streams
``` - rtsp://192.168.1.5:554/live0 # <- stream which supports video & aac audio
- "ffmpeg:rtsp_cam#audio=opus" # <- copy of the stream which transcodes audio to the missing codec (usually will be opus)
However, chances are that your camera already provides at least one usable audio type, so you just need restream to add the missing one. For example, if your camera outputs audio in AAC format: http_cam: # <- for http streams
- http://192.168.50.155/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=user&password=password # <- stream which supports video & aac audio
```yaml - "ffmpeg:http_cam#audio=opus" # <- copy of the stream which transcodes audio to the missing codec (usually will be opus)
go2rtc:
streams:
test_cam: ffmpeg:rtsp://192.168.1.5:554/live0#video=copy#audio=copy#audio=opus
```
Which will reuse your camera AAC audio, while also adding one track in OPUS format.
If your camera uses RTSP and supports the audio type for the live view you want to use, then you can pass the camera stream to go2rtc without ffmpeg.
```yaml
go2rtc:
streams:
test_cam: rtsp://192.168.1.5:554/live0
``` ```
### Setting Stream For Live UI ### Setting Stream For Live UI
@@ -50,8 +37,12 @@ There may be some cameras that you would prefer to use the sub stream for live v
```yaml ```yaml
go2rtc: go2rtc:
streams: streams:
test_cam: ffmpeg:rtsp://192.168.1.5:554/live0#video=copy#audio=aac#audio=opus rtsp_cam:
test_cam_sub: ffmpeg:rtsp://192.168.1.5:554/substream#video=copy#audio=aac#audio=opus - rtsp://192.168.1.5:554/live0 # <- stream which supports video & aac audio.
- "ffmpeg:rtsp_cam#audio=opus" # <- copy of the stream which transcodes audio to opus
rtsp_cam_sub:
- rtsp://192.168.1.5:554/substream # <- stream which supports video & aac audio.
- "ffmpeg:rtsp_cam_sub#audio=opus" # <- copy of the stream which transcodes audio to opus
cameras: cameras:
test_cam: test_cam:
@@ -59,16 +50,16 @@ cameras:
output_args: output_args:
record: preset-record-generic-audio-copy record: preset-record-generic-audio-copy
inputs: inputs:
- path: rtsp://127.0.0.1:8554/test_cam?video=copy&audio=aac # <--- the name here must match the name of the camera in restream - path: rtsp://127.0.0.1:8554/test_cam # <--- the name here must match the name of the camera in restream
input_args: preset-rtsp-restream input_args: preset-rtsp-restream
roles: roles:
- record - record
- path: rtsp://127.0.0.1:8554/test_cam_sub?video=copy # <--- the name here must match the name of the camera_sub in restream - path: rtsp://127.0.0.1:8554/test_cam_sub # <--- the name here must match the name of the camera_sub in restream
input_args: preset-rtsp-restream input_args: preset-rtsp-restream
roles: roles:
- detect - detect
live: live:
stream_name: test_cam_sub stream_name: rtsp_cam_sub
``` ```
### WebRTC extra configuration: ### WebRTC extra configuration:
@@ -76,19 +67,30 @@ cameras:
WebRTC works by creating a TCP or UDP connection on port `8555`. However, it requires additional configuration: WebRTC works by creating a TCP or UDP connection on port `8555`. However, it requires additional configuration:
- For external access, over the internet, setup your router to forward port `8555` to port `8555` on the Frigate device, for both TCP and UDP. - For external access, over the internet, setup your router to forward port `8555` to port `8555` on the Frigate device, for both TCP and UDP.
- For internal/local access, you will need to use a custom go2rtc config: - For internal/local access, unless you are running through the add-on, you will also need to set the WebRTC candidates list in the go2rtc config. For example, if `192.168.1.10` is the local IP of the device running Frigate:
1. Add your internal IP to the list of `candidates`. Here is an example, assuming that `192.168.1.10` is the local IP of the device running Frigate: ```yaml title="/config/frigate.yaml"
go2rtc:
streams:
test_cam: ...
webrtc:
candidates:
- 192.168.1.10:8555
- stun:8555
```
```yaml :::tip
go2rtc:
streams: This extra configuration may not be required if Frigate has been installed as a Home Assistant add-on, as Frigate uses the Supervisor's API to generate a WebRTC candidate.
test_cam: ...
webrtc: However, it is recommended if issues occur to define the candidates manually. You should do this if the Frigate add-on fails to generate a valid candidate. If an error occurs you will see some warnings like the below in the add-on logs page during the initialization:
candidates:
- 192.168.1.10:8555 ```log
- stun:8555 [WARN] Failed to get IP address from supervisor
``` [WARN] Failed to get WebRTC port from supervisor
```
:::
:::note :::note
@@ -99,4 +101,4 @@ If you are having difficulties getting WebRTC to work and you are running Frigat
::: :::
See https://github.com/AlexxIT/go2rtc#module-webrtc for more information about this. See [go2rtc WebRTC docs](https://github.com/AlexxIT/go2rtc/tree/v1.2.0#module-webrtc) for more information about this.

View File

@@ -3,17 +3,38 @@ id: restream
title: Restream title: Restream
--- ---
### RTSP ## RTSP
Frigate can restream your video feed as an RTSP feed for other applications such as Home Assistant to utilize it at `rtsp://<frigate_host>:8554/<camera_name>`. Port 8554 must be open. [This allows you to use a video feed for detection in Frigate and Home Assistant live view at the same time without having to make two separate connections to the camera](#reduce-connections-to-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. Frigate can restream your video feed as an RTSP feed for other applications such as Home Assistant to utilize it at `rtsp://<frigate_host>:8554/<camera_name>`. Port 8554 must be open. [This allows you to use a video feed for detection in Frigate and Home Assistant live view at the same time without having to make two separate connections to the camera](#reduce-connections-to-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.
Frigate uses [go2rtc](https://github.com/AlexxIT/go2rtc) to provide its restream and MSE/WebRTC capabilities. The go2rtc config is hosted at the `go2rtc` in the config, see [go2rtc docs](https://github.com/AlexxIT/go2rtc#configuration) for more advanced configurations and features. Frigate uses [go2rtc](https://github.com/AlexxIT/go2rtc/tree/v1.2.0) to provide its restream and MSE/WebRTC capabilities. The go2rtc config is hosted at the `go2rtc` in the config, see [go2rtc docs](https://github.com/AlexxIT/go2rtc/tree/v1.2.0#configuration) for more advanced configurations and features.
#### Birdseye Restream :::note
You can access the go2rtc webUI at `http://frigate_ip:5000/live/webrtc` which can be helpful to debug as well as provide useful information about your camera streams.
:::
### Birdseye Restream
Birdseye RTSP restream can be enabled at `birdseye -> restream` and accessed at `rtsp://<frigate_host>:8554/birdseye`. Enabling the restream will cause birdseye to run 24/7 which may increase CPU usage somewhat. Birdseye RTSP restream can be enabled at `birdseye -> restream` and accessed at `rtsp://<frigate_host>:8554/birdseye`. Enabling the restream will cause birdseye to run 24/7 which may increase CPU usage somewhat.
### RTMP (Deprecated) ### Securing Restream With Authentication
The go2rtc restream can be secured with RTSP based username / password authentication. Ex:
```yaml
go2rtc:
rtsp:
username: "admin"
password: "pass"
streams:
...
```
**NOTE:** This does not apply to localhost requests, there is no need to provide credentials when using the restream as a source for frigate cameras.
## RTMP (Deprecated)
In previous Frigate versions RTMP was used for re-streaming. RTMP has disadvantages however including being incompatible with H.265, high bitrates, and certain audio codecs. RTMP is deprecated and it is recommended to move to the new restream role. In previous Frigate versions RTMP was used for re-streaming. RTMP has disadvantages however including being incompatible with H.265, high bitrates, and certain audio codecs. RTMP is deprecated and it is recommended to move to the new restream role.
@@ -28,15 +49,30 @@ One connection is made to the camera. One for the restream, `detect` and `record
```yaml ```yaml
go2rtc: go2rtc:
streams: streams:
test_cam: ffmpeg:rtsp://192.168.1.5:554/live0#video=copy#audio=aac#audio=opus rtsp_cam: # <- for RTSP streams
- rtsp://192.168.1.5:554/live0 # <- stream which supports video & aac audio
- "ffmpeg:rtsp_cam#audio=opus" # <- copy of the stream which transcodes audio to the missing codec (usually will be opus)
http_cam: # <- for other streams
- http://192.168.50.155/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=user&password=password # <- stream which supports video & aac audio
- "ffmpeg:http_cam#audio=opus" # <- copy of the stream which transcodes audio to the missing codec (usually will be opus)
cameras: cameras:
test_cam: rtsp_cam:
ffmpeg: ffmpeg:
output_args: output_args:
record: preset-record-generic-audio-copy record: preset-record-generic-audio-copy
inputs: inputs:
- path: rtsp://127.0.0.1:8554/test_cam?video=copy&audio=aac # <--- the name here must match the name of the camera in restream - path: rtsp://127.0.0.1:8554/rtsp_cam # <--- the name here must match the name of the camera in restream
input_args: preset-rtsp-restream
roles:
- record
- detect
http_cam:
ffmpeg:
output_args:
record: preset-record-generic-audio-copy
inputs:
- path: rtsp://127.0.0.1:8554/http_cam # <--- the name here must match the name of the camera in restream
input_args: preset-rtsp-restream input_args: preset-rtsp-restream
roles: roles:
- record - record
@@ -50,21 +86,56 @@ Two connections are made to the camera. One for the sub stream, one for the rest
```yaml ```yaml
go2rtc: go2rtc:
streams: streams:
test_cam: ffmpeg:rtsp://192.168.1.5:554/live0#video=copy#audio=aac#audio=opus rtsp_cam:
test_cam_sub: ffmpeg:rtsp://192.168.1.5:554/substream#video=copy#audio=aac#audio=opus - rtsp://192.168.1.5:554/live0 # <- stream which supports video & aac audio. This is only supported for rtsp streams, http must use ffmpeg
- "ffmpeg:rtsp_cam#audio=opus" # <- copy of the stream which transcodes audio to opus
rtsp_cam_sub:
- rtsp://192.168.1.5:554/substream # <- stream which supports video & aac audio. This is only supported for rtsp streams, http must use ffmpeg
- "ffmpeg:rtsp_cam_sub#audio=opus" # <- copy of the stream which transcodes audio to opus
http_cam:
- http://192.168.50.155/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=user&password=password # <- stream which supports video & aac audio. This is only supported for rtsp streams, http must use ffmpeg
- "ffmpeg:http_cam#audio=opus" # <- copy of the stream which transcodes audio to opus
http_cam_sub:
- http://192.168.50.155/flv?port=1935&app=bcs&stream=channel0_ext.bcs&user=user&password=password # <- stream which supports video & aac audio. This is only supported for rtsp streams, http must use ffmpeg
- "ffmpeg:http_cam_sub#audio=opus" # <- copy of the stream which transcodes audio to opus
cameras: cameras:
test_cam: rtsp_cam:
ffmpeg: ffmpeg:
output_args: output_args:
record: preset-record-generic-audio-copy record: preset-record-generic-audio-copy
inputs: inputs:
- path: rtsp://127.0.0.1:8554/test_cam?video=copy&audio=aac # <--- the name here must match the name of the camera in restream - path: rtsp://127.0.0.1:8554/rtsp_cam # <--- the name here must match the name of the camera in restream
input_args: preset-rtsp-restream input_args: preset-rtsp-restream
roles: roles:
- record - record
- path: rtsp://127.0.0.1:8554/test_cam_sub?video=copy&audio=aac # <--- the name here must match the name of the camera_sub in restream - path: rtsp://127.0.0.1:8554/rtsp_cam_sub # <--- the name here must match the name of the camera_sub in restream
input_args: preset-rtsp-restream
roles:
- detect
http_cam:
ffmpeg:
output_args:
record: preset-record-generic-audio-copy
inputs:
- path: rtsp://127.0.0.1:8554/http_cam # <--- the name here must match the name of the camera in restream
input_args: preset-rtsp-restream
roles:
- record
- path: rtsp://127.0.0.1:8554/http_cam_sub # <--- the name here must match the name of the camera_sub in restream
input_args: preset-rtsp-restream input_args: preset-rtsp-restream
roles: roles:
- detect - detect
``` ```
## Advanced Restream Configurations
The [exec](https://github.com/AlexxIT/go2rtc/tree/v1.2.0#source-exec) source in go2rtc can be used for custom ffmpeg commands. An example is below:
NOTE: The output will need to be passed with two curly braces `{{output}}`
```yaml
go2rtc:
streams:
stream1: exec:ffmpeg -hide_banner -re -stream_loop -1 -i /media/BigBuckBunny.mp4 -c copy -rtsp_transport tcp -f rtsp {{output}}
```

View File

@@ -11,6 +11,24 @@ During testing, enable the Zones option for the debug feed so you can adjust as
To create a zone, follow [the steps for a "Motion mask"](masks.md), but use the section of the web UI for creating a zone instead. To create a zone, follow [the steps for a "Motion mask"](masks.md), but use the section of the web UI for creating a zone instead.
### Restricting events to specific zones
Often you will only want events to be created when an object enters areas of interest. This is done using zones along with setting required_zones. Let's say you only want to be notified when an object enters your entire_yard zone, the config would be:
```yaml
camera:
record:
events:
required_zones:
- entire_yard
snapshots:
required_zones:
- entire_yard
zones:
entire_yard:
coordinates: ...
```
### Restricting zones to specific objects ### Restricting zones to specific objects
Sometimes you want to limit a zone to specific object types to have more granular control of when events/snapshots are saved. The following example will limit one zone to person objects and the other to cars. Sometimes you want to limit a zone to specific object types to have more granular control of when events/snapshots are saved. The following example will limit one zone to person objects and the other to cars.

View File

@@ -3,7 +3,7 @@ id: camera_setup
title: Camera setup title: Camera setup
--- ---
Cameras configured to output H.264 video and AAC audio will offer the most compatibility with all features of Frigate and Home Assistant. H.265 has better compression, but far less compatibility. Safari and Edge are the only browsers able to play H.265. Ideally, cameras should be configured directly for the desired resolutions and frame rates you want to use in Frigate. Reducing frame rates within Frigate will waste CPU resources decoding extra frames that are discarded. There are three different goals that you want to tune your stream configurations around. Cameras configured to output H.264 video and AAC audio will offer the most compatibility with all features of Frigate and Home Assistant. H.265 has better compression, but less compatibility. Chrome 108+, Safari and Edge are the only browsers able to play H.265 and only support a limited number of H.265 profiles. Ideally, cameras should be configured directly for the desired resolutions and frame rates you want to use in Frigate. Reducing frame rates within Frigate will waste CPU resources decoding extra frames that are discarded. There are three different goals that you want to tune your stream configurations around.
- **Detection**: This is the only stream that Frigate will decode for processing. Also, this is the stream where snapshots will be generated from. The resolution for detection should be tuned for the size of the objects you want to detect. See [Choosing a detect resolution](#choosing-a-detect-resolution) for more details. The recommended frame rate is 5fps, but may need to be higher for very fast moving objects. Higher resolutions and frame rates will drive higher CPU usage on your server. - **Detection**: This is the only stream that Frigate will decode for processing. Also, this is the stream where snapshots will be generated from. The resolution for detection should be tuned for the size of the objects you want to detect. See [Choosing a detect resolution](#choosing-a-detect-resolution) for more details. The recommended frame rate is 5fps, but may need to be higher for very fast moving objects. Higher resolutions and frame rates will drive higher CPU usage on your server.

View File

@@ -57,12 +57,21 @@ More information is available [in the detector docs](/configuration/detectors#op
Inference speeds vary greatly depending on the CPU, GPU, or VPU used, some known examples are below: Inference speeds vary greatly depending on the CPU, GPU, or VPU used, some known examples are below:
| Name | Inference Speed | Notes | | Name | Inference Speed | Notes |
| ------------------- | --------------- | --------------------------------------------------------------------- | | -------------------- | --------------- | --------------------------------------------------------------------- |
| Intel Celeron J4105 | ~ 25 ms | Inference speeds on CPU were ~ 150 ms | | Intel NCS2 VPU | 60 - 65 ms | May vary based on host device |
| Intel Celeron N4020 | 50 - 200 ms | Inference speeds on CPU were ~ 800 ms, greatly depends on other loads | | Intel Celeron J4105 | ~ 25 ms | Inference speeds on CPU were 150 - 200 ms |
| Intel NCS2 VPU | 60 - 65 ms | May vary based on host device | | Intel Celeron N3060 | 130 - 150 ms | Inference speeds on CPU were ~ 550 ms |
| Intel i5 1135G7 | 10 - 15 ms | | | Intel Celeron N3205U | ~ 120 ms | Inference speeds on CPU were ~ 380 ms |
| Intel Celeron N4020 | 50 - 200 ms | Inference speeds on CPU were ~ 800 ms, greatly depends on other loads |
| Intel i3 6100T | 15 - 35 ms | Inference speeds on CPU were 60 - 120 ms |
| Intel i3 8100 | ~ 15 ms | Inference speeds on CPU were ~ 65 ms |
| Intel i5 4590 | ~ 20 ms | Inference speeds on CPU were ~ 230 ms |
| Intel i5 6500 | ~ 15 ms | Inference speeds on CPU were ~ 150 ms |
| Intel i5 7200u | 15 - 25 ms | Inference speeds on CPU were ~ 150 ms |
| Intel i5 7500 | ~ 15 ms | Inference speeds on CPU were ~ 260 ms |
| Intel i5 1135G7 | 10 - 15 ms | |
| Intel i5 12600K | ~ 15 ms | Inference speeds on CPU were ~ 35 ms |
### TensorRT ### TensorRT
@@ -71,10 +80,15 @@ The TensortRT detector is able to run on x86 hosts that have an Nvidia GPU which
Inference speeds will vary greatly depending on the GPU and the model used. Inference speeds will vary greatly depending on the GPU and the model used.
`tiny` variants are faster than the equivalent non-tiny model, some known examples are below: `tiny` variants are faster than the equivalent non-tiny model, some known examples are below:
| Name | Model | Inference Speed | | Name | Inference Speed |
| -------- | --------------- | --------------- | | --------------- | ----------------- |
| RTX 3050 | yolov4-tiny-416 | ~ 5 ms | | GTX 1060 6GB | ~ 7 ms |
| RTX 3050 | yolov7-tiny-416 | ~ 6 ms | | GTX 1070 | ~ 6 ms |
| GTX 1660 SUPER | ~ 4 ms |
| RTX 3050 | 5 - 7 ms |
| RTX 3070 Mobile | ~ 5 ms |
| Quadro P400 2GB | 20 - 25 ms |
| Quadro P2000 | ~ 12 ms |
## What does Frigate use the CPU for and what does it use a detector for? (ELI5 Version) ## What does Frigate use the CPU for and what does it use a detector for? (ELI5 Version)

View File

@@ -74,17 +74,29 @@ database:
### Calculating required shm-size ### Calculating required shm-size
Frigate utilizes shared memory to store frames during processing. The default `shm-size` provided by Docker is 64m. Frigate utilizes shared memory to store frames during processing. The default `shm-size` provided by Docker is **64MB**.
The default shm-size of 64m is fine for setups with 2 or less 1080p cameras. If Frigate is exiting with "Bus error" messages, it is likely because you have too many high resolution cameras and you need to specify a higher shm size. The default shm size of **64MB** is fine for setups with **2 cameras** detecting at **720p**. If Frigate is exiting with "Bus error" messages, it is likely because you have too many high resolution cameras and you need to specify a higher shm size.
You can calculate the necessary shm-size for each camera with the following formula using the resolution specified for detect: The Frigate container also stores logs in shm, which can take up to **30MB**, so make sure to take this into account in your math as well.
``` You can calculate the necessary shm size for each camera with the following formula using the resolution specified for detect:
(width * height * 1.5 * 9 + 270480)/1048576 = <shm size in mb>
```console
# Replace <width> and <height>
$ python -c 'print("{:.2f}MB".format((<width> * <height> * 1.5 * 9 + 270480) / 1048576))'
# Example for 1280x720
$ python -c 'print("{:.2f}MB".format((1280 * 720 * 1.5 * 9 + 270480) / 1048576))'
12.12MB
# Example for eight cameras detecting at 1280x720, including logs
$ python -c 'print("{:.2f}MB".format(((1280 * 720 * 1.5 * 9 + 270480) / 1048576) * 8 + 30))'
126.99MB
``` ```
The shm size cannot be set per container for Home Assistant Addons. You must set `default-shm-size` in `/etc/docker/daemon.json` to increase the default shm size. This will increase the shm size for all of your docker containers. This may or may not cause issues with your setup. https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file The shm size cannot be set per container for Home Assistant add-ons. However, this is probably not required since by default Home Assistant Supervisor allocates `/dev/shm` with half the size of your total memory. If your machine has 8GB of memory, chances are that Frigate will have access to up to 4GB without any additional configuration.
### Raspberry Pi 3/4 ### Raspberry Pi 3/4
@@ -151,7 +163,10 @@ docker run -d \
:::caution :::caution
Due to limitations in Home Assistant Operating System, utilizing external storage for recordings or snapshots requires [modifying udev rules manually](https://community.home-assistant.io/t/solved-mount-usb-drive-in-hassio-to-be-used-on-the-media-folder-with-udev-customization/258406/46). There are important limitations in Home Assistant Operating System to be aware of:
- Utilizing external storage for recordings or snapshots requires [modifying udev rules manually](https://community.home-assistant.io/t/solved-mount-usb-drive-in-hassio-to-be-used-on-the-media-folder-with-udev-customization/258406/46).
- AMD GPUs are not supported because HA OS does not include the mesa driver.
- Nvidia GPUs are not supported because addons do not support the nvidia runtime.
::: :::
@@ -182,6 +197,13 @@ There are several versions of the addon available:
## Home Assistant Supervised ## Home Assistant Supervised
:::caution
There are important limitations in Home Assistant Supervised to be aware of:
- Nvidia GPUs are not supported because addons do not support the nvidia runtime.
:::
:::tip :::tip
If possible, it is recommended to run Frigate standalone in Docker and use [Frigate's Proxy Addon](https://github.com/blakeblackshear/frigate-hass-addons/blob/main/frigate_proxy/README.md). If possible, it is recommended to run Frigate standalone in Docker and use [Frigate's Proxy Addon](https://github.com/blakeblackshear/frigate-hass-addons/blob/main/frigate_proxy/README.md).

View File

@@ -0,0 +1,77 @@
---
id: configuring_go2rtc
title: Configuring go2rtc
---
Use of the bundled go2rtc is optional. You can still configure FFmpeg to connect directly to your cameras. However, adding go2rtc to your configuration is required for the following features:
- WebRTC or MSE for live viewing with higher resolutions and frame rates than the jsmpeg stream which is limited to the detect stream
- RTSP (instead of RTMP) relay for use with Home Assistant or other consumers to reduce the number of connections to your camera streams
# Setup a go2rtc stream
First, you will want to configure go2rtc to connect to your camera stream by adding the stream you want to use for live view in your Frigate config file. If you set the stream name under go2rtc to match the name of your camera, it will automatically be mapped and you will get additional live view options for the camera. Avoid changing any other parts of your config at this step. Note that go2rtc supports [many different stream types](https://github.com/AlexxIT/go2rtc/tree/v1.2.0#module-streams), not just rtsp.
```yaml
go2rtc:
streams:
back:
- rtsp://user:password@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2
```
The easiest live view to get working is MSE. After adding this to the config, restart Frigate and try to watch the live stream by selecting MSE in the dropdown after clicking on the camera.
### What if my video doesn't play?
If you are unable to see your video feed, first check the go2rtc logs in the Frigate UI under Logs in the sidebar. If go2rtc is having difficulty connecting to your camera, you should see some error messages in the log. If you do not see any errors, then the video codec of the stream may not be supported in your browser. If your camera stream is set to H265, try switching to H264. You can see more information about [video codec compatibility](https://github.com/AlexxIT/go2rtc/tree/v1.2.0#codecs-madness) in the go2rtc documentation. If you are not able to switch your camera settings from H265 to H264 or your stream is a different format such as MJPEG, you can use go2rtc to re-encode the video using the [FFmpeg parameters](https://github.com/AlexxIT/go2rtc/tree/v1.2.0#source-ffmpeg). It supports rotating and resizing video feeds and hardware acceleration. Keep in mind that transcoding video from one format to another is a resource intensive task and you may be better off using the built-in jsmpeg view. Here is an example of a config that will re-encode the stream to H264 without hardware acceleration:
```yaml
go2rtc:
streams:
back:
- rtsp://user:password@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2
- "ffmpeg:back#video=h264"
```
Some camera streams may need to use the ffmpeg module in go2rtc. This has the downside of slower startup times, but has compatibility with more stream types.
```yaml
go2rtc:
streams:
back:
- ffmpeg:rtsp://user:password@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2
```
If you can see the video but do not have audio, this is most likely because your camera's audio stream is not AAC. If possible, update your camera's audio settings to AAC. If your cameras do not support AAC audio, you will need to tell go2rtc to re-encode the audio to AAC on demand if you want audio. This will use additional CPU and add some latency. To add AAC audio on demand, you can update your go2rtc config as follows:
```yaml
go2rtc:
streams:
back:
- rtsp://user:password@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2
- "ffmpeg:back#audio=aac"
```
If you need to convert **both** the audio and video streams, you can use the following:
```yaml
go2rtc:
streams:
back:
- rtsp://user:password@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2
- "ffmpeg:back#video=h264#audio=aac"
```
When using the ffmpeg module, you would add AAC audio like this:
```yaml
go2rtc:
streams:
back:
- "ffmpeg:rtsp://user:password@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2#video=copy#audio=copy#audio=aac"
```
## Next steps
1. If the stream you added to go2rtc is also used by Frigate for the `record` or `detect` role, you can migrate your config to pull from the RTSP restream to reduce the number of connections to your camera as shown [here](/configuration/restream#reduce-connections-to-camera).
1. You may also prefer to [setup WebRTC](/configuration/live#webrtc-extra-configuration) for slightly lower latency than MSE. Note that WebRTC only supports h264 and specific audio formats.

View File

@@ -1,10 +0,0 @@
---
id: events_setup
title: Setting Up Events
---
[Snapshots](../configuration/snapshots.md) and/or [Recordings](../configuration/record.md) must be enabled for events to be created for detected objects.
## Limiting Events to Areas of Interest
The best way to limit events to areas of interest is to use [zones](../configuration/zones.md) along with `required_zones` for events and snapshots to only have events created in areas of interest.

View File

@@ -1,79 +1,32 @@
--- ---
id: getting_started id: getting_started
title: Creating a config file title: Getting started
--- ---
This guide walks through the steps to build a configuration file for Frigate. It assumes that you already have an environment setup as described in [Installation](../frigate/installation.md). You should also configure your cameras according to the [camera setup guide](/guides/camera_setup) This guide walks through the steps to build a configuration file for Frigate. It assumes that you already have an environment setup as described in [Installation](../frigate/installation.md). You should also configure your cameras according to the [camera setup guide](/frigate/camera_setup). Pay particular attention to the section on choosing a detect resolution.
### Step 1: Configure the MQTT server (Optional) ### Step 1: Add a detect stream
Use of a functioning MQTT server is optional for Frigate, but required for the home assistant integration. Start by adding the mqtt section at the top level in your config: First we will add the detect stream for the camera:
If using mqtt:
```yaml
mqtt:
host: <ip of your mqtt server>
```
If not using mqtt:
```yaml ```yaml
mqtt: mqtt:
enabled: False enabled: False
```
If using the Mosquitto Addon in Home Assistant, a username and password is required. For example:
```yaml
mqtt:
host: <ip of your mqtt server>
user: <username>
password: <password>
```
Frigate supports many configuration options for mqtt. See the [configuration reference](../configuration/index.md#full-configuration-reference) for more info.
### Step 2: Configure detectors
By default, Frigate will use a single CPU detector. If you have a USB Coral, you will need to add a detectors section to your config.
```yaml
mqtt:
host: <ip of your mqtt server>
detectors:
coral:
type: edgetpu
device: usb
```
More details on available detectors can be found [here](../configuration/detectors.md).
### Step 3: Add a minimal camera configuration
Now let's add the first camera:
```yaml
mqtt:
host: <ip of your mqtt server>
detectors:
coral:
type: edgetpu
device: usb
cameras: cameras:
camera_1: # <------ Name the camera camera_1: # <------ Name the camera
ffmpeg: ffmpeg:
inputs: inputs:
- path: rtsp://10.0.10.10:554/rtsp # <----- Update for your camera - path: rtsp://10.0.10.10:554/rtsp # <----- The stream you want to use for detection
roles: roles:
- detect - detect
detect: detect:
enabled: False # <---- disable detection until you have a working camera feed
width: 1280 # <---- update for your camera's resolution width: 1280 # <---- update for your camera's resolution
height: 720 # <---- update for your camera's resolution height: 720 # <---- update for your camera's resolution
``` ```
### Step 4: Start Frigate ### Step 2: Start Frigate
At this point you should be able to start Frigate and see the the video feed in the UI. At this point you should be able to start Frigate and see the the video feed in the UI.
@@ -81,41 +34,48 @@ If you get an error image from the camera, this means ffmpeg was not able to get
FFmpeg arguments for other types of cameras can be found [here](../configuration/camera_specific.md). FFmpeg arguments for other types of cameras can be found [here](../configuration/camera_specific.md).
### Step 5: Configure hardware acceleration (optional) ### Step 3: Configure hardware acceleration (recommended)
Now that you have a working camera configuration, you want to setup hardware acceleration to minimize the CPU required to decode your video streams. See the [hardware acceleration](../configuration/hardware_acceleration.md) config reference for examples applicable to your hardware. Now that you have a working camera configuration, you want to setup hardware acceleration to minimize the CPU required to decode your video streams. See the [hardware acceleration](../configuration/hardware_acceleration.md) config reference for examples applicable to your hardware.
In order to best evaluate the performance impact of hardware acceleration, it is recommended to temporarily disable detection. Here is an example configuration with hardware acceleration configured for Intel processors with an integrated GPU using the [preset](../configuration/ffmpeg_presets.md):
```yaml ```yaml
mqtt: ... mqtt: ...
detectors: ...
cameras:
camera_1:
ffmpeg: ...
detect:
enabled: False
...
```
Here is an example configuration with hardware acceleration configured:
```yaml
mqtt: ...
detectors: ...
cameras: cameras:
camera_1: camera_1:
ffmpeg: ffmpeg:
inputs: ... inputs: ...
hwaccel_args: -c:v h264_v4l2m2m hwaccel_args: preset-vaapi
detect: ... detect: ...
``` ```
### Step 6: Setup motion masks ### Step 4: Configure detectors
By default, Frigate will use a single CPU detector. If you have a USB Coral, you will need to add a detectors section to your config.
```yaml
mqtt: ...
detectors: # <---- add detectors
coral:
type: edgetpu
device: usb
cameras:
camera_1:
ffmpeg: ...
detect:
enabled: True # <---- turn on detection
...
```
More details on available detectors can be found [here](../configuration/detectors.md).
Restart Frigate and you should start seeing detections for `person`. If you want to track other objects, they will need to be added according to the [configuration file reference](../configuration/index.md#full-configuration-reference).
### Step 5: Setup motion masks
Now that you have optimized your configuration for decoding the video stream, you will want to check to see where to implement motion masks. To do this, navigate to the camera in the UI, select "Debug" at the top, and enable "Motion boxes" in the options below the video feed. Watch for areas that continuously trigger unwanted motion to be detected. Common areas to mask include camera timestamps and trees that frequently blow in the wind. The goal is to avoid wasting object detection cycles looking at these areas. Now that you have optimized your configuration for decoding the video stream, you will want to check to see where to implement motion masks. To do this, navigate to the camera in the UI, select "Debug" at the top, and enable "Motion boxes" in the options below the video feed. Watch for areas that continuously trigger unwanted motion to be detected. Common areas to mask include camera timestamps and trees that frequently blow in the wind. The goal is to avoid wasting object detection cycles looking at these areas.
@@ -131,7 +91,7 @@ Your configuration should look similar to this now.
```yaml ```yaml
mqtt: mqtt:
host: mqtt.local enabled: False
detectors: detectors:
coral: coral:
@@ -153,9 +113,13 @@ cameras:
- 0,461,3,0,1919,0,1919,843,1699,492,1344,458,1346,336,973,317,869,375,866,432 - 0,461,3,0,1919,0,1919,843,1699,492,1344,458,1346,336,973,317,869,375,866,432
``` ```
### Step 7: Enable recording (optional) ### Step 6: Enable recording and/or snapshots
To enable recording video, add the `record` role to a stream and enable it in the config. In order to see Events in the Frigate UI, either snapshots or record will need to be enabled.
#### Record
To enable recording video, add the `record` role to a stream and enable it in the config. If record is disabled in the config, turning it on via the UI will not have any effect.
```yaml ```yaml
mqtt: ... mqtt: ...
@@ -169,7 +133,7 @@ cameras:
- path: rtsp://10.0.10.10:554/rtsp - path: rtsp://10.0.10.10:554/rtsp
roles: roles:
- detect - detect
- path: rtsp://10.0.10.10:554/high_res_stream # <----- Add high res stream - path: rtsp://10.0.10.10:554/high_res_stream # <----- Add stream you want to record from
roles: roles:
- record - record
detect: ... detect: ...
@@ -182,9 +146,9 @@ If you don't have separate streams for detect and record, you would just add the
By default, Frigate will retain video of all events for 10 days. The full set of options for recording can be found [here](../configuration/index.md#full-configuration-reference). By default, Frigate will retain video of all events for 10 days. The full set of options for recording can be found [here](../configuration/index.md#full-configuration-reference).
### Step 8: Enable snapshots (optional) #### Snapshots
To enable snapshots of your events, just enable it in the config. To enable snapshots of your events, just enable it in the config. Snapshots are taken from the detect stream because it is the only stream decoded.
```yaml ```yaml
mqtt: ... mqtt: ...
@@ -201,3 +165,10 @@ cameras:
``` ```
By default, Frigate will retain snapshots of all events for 10 days. The full set of options for snapshots can be found [here](../configuration/index.md#full-configuration-reference). By default, Frigate will retain snapshots of all events for 10 days. The full set of options for snapshots can be found [here](../configuration/index.md#full-configuration-reference).
### Step 7: Follow up guides
Now that you have a working install, you can use the following guides for additional features:
1. [Configuring go2rtc](configuring_go2rtc) - Additional live view options and RTSP relay
2. [Home Assistant Integration](../integrations/home-assistant.md) - Integrate with Home Assistant

View File

@@ -1,6 +1,6 @@
--- ---
id: reverse_proxy id: reverse_proxy
title: Setting up a Reverse Proxy title: Setting up a reverse proxy
--- ---
This guide outlines the basic configuration steps needed to expose your Frigate UI to the internet. This guide outlines the basic configuration steps needed to expose your Frigate UI to the internet.
@@ -8,6 +8,7 @@ A common way of accomplishing this is to use a reverse proxy webserver between y
A reverse proxy accepts HTTP requests from the public internet and redirects them transparently to internal webserver(s) on your network. A reverse proxy accepts HTTP requests from the public internet and redirects them transparently to internal webserver(s) on your network.
The suggested steps are: The suggested steps are:
- **Configure** a 'proxy' HTTP webserver (such as [Apache2](https://httpd.apache.org/docs/current/) or [NPM](https://github.com/NginxProxyManager/nginx-proxy-manager)) and only expose ports 80/443 from this webserver to the internet - **Configure** a 'proxy' HTTP webserver (such as [Apache2](https://httpd.apache.org/docs/current/) or [NPM](https://github.com/NginxProxyManager/nginx-proxy-manager)) and only expose ports 80/443 from this webserver to the internet
- **Encrypt** content from the proxy webserver by installing SSL (such as with [Let's Encrypt](https://letsencrypt.org/)). Note that SSL is then not required on your Frigate webserver as the proxy encrypts all requests for you - **Encrypt** content from the proxy webserver by installing SSL (such as with [Let's Encrypt](https://letsencrypt.org/)). Note that SSL is then not required on your Frigate webserver as the proxy encrypts all requests for you
- **Restrict** access to your Frigate instance at the proxy using, for example, password authentication - **Restrict** access to your Frigate instance at the proxy using, for example, password authentication
@@ -31,6 +32,7 @@ On Debian Apache2 the configuration file will be named along the lines of `/etc/
Make life easier for yourself by presenting your Frigate interface as a DNS sub-domain rather than as a sub-folder of your main domain. Make life easier for yourself by presenting your Frigate interface as a DNS sub-domain rather than as a sub-folder of your main domain.
Here we access Frigate via https://cctv.mydomain.co.uk Here we access Frigate via https://cctv.mydomain.co.uk
```xml ```xml
<VirtualHost *:443> <VirtualHost *:443>
ServerName cctv.mydomain.co.uk ServerName cctv.mydomain.co.uk
@@ -38,7 +40,7 @@ Here we access Frigate via https://cctv.mydomain.co.uk
ProxyPreserveHost On ProxyPreserveHost On
ProxyPass "/" "http://frigatepi.local:5000/" ProxyPass "/" "http://frigatepi.local:5000/"
ProxyPassReverse "/" "http://frigatepi.local:5000/" ProxyPassReverse "/" "http://frigatepi.local:5000/"
ProxyPass /ws ws://frigatepi.local:5000/ws ProxyPass /ws ws://frigatepi.local:5000/ws
ProxyPassReverse /ws ws://frigatepi.local:5000/ws ProxyPassReverse /ws ws://frigatepi.local:5000/ws

View File

@@ -16,6 +16,8 @@ See the [MQTT integration
documentation](https://www.home-assistant.io/integrations/mqtt/) for more documentation](https://www.home-assistant.io/integrations/mqtt/) for more
details. details.
In addition, MQTT must be enabled in your Frigate configuration file and Frigate must be connected to the same MQTT server as Home Assistant for many of the entities created by the integration to function.
### Integration installation ### Integration installation
Available via HACS as a default repository. To install: Available via HACS as a default repository. To install:
@@ -30,7 +32,7 @@ Home Assistant > HACS > Integrations > "Explore & Add Integrations" > Frigate
- Then add/configure the integration: - Then add/configure the integration:
``` ```
Home Assistant > Configuration > Integrations > Add Integration > Frigate Home Assistant > Settings > Devices & Services > Add Integration > Frigate
``` ```
Note: You will also need Note: You will also need
@@ -64,13 +66,13 @@ Home Assistant > Configuration > Integrations > Frigate > Options
| Option | Description | | Option | Description |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| RTSP URL Template | A [jinja2](https://jinja.palletsprojects.com/) template that is used to override the standard RTMP stream URL (e.g. for use with reverse proxies). This option is only shown to users who have [advanced mode](https://www.home-assistant.io/blog/2019/07/17/release-96/#advanced-mode) enabled. See [RTSP streams](#streams) below. | | RTSP URL Template | A [jinja2](https://jinja.palletsprojects.com/) template that is used to override the standard RTSP stream URL (e.g. for use with reverse proxies). This option is only shown to users who have [advanced mode](https://www.home-assistant.io/blog/2019/07/17/release-96/#advanced-mode) enabled. See [RTSP streams](#streams) below. |
## Entities Provided ## Entities Provided
| Platform | Description | | Platform | Description |
| --------------- | --------------------------------------------------------------------------------- | | --------------- | --------------------------------------------------------------------------------- |
| `camera` | Live camera stream (requires RTMP), camera for image of the last detected object. | | `camera` | Live camera stream (requires RTSP), camera for image of the last detected object. |
| `sensor` | States to monitor Frigate performance, object counts for all zones and cameras. | | `sensor` | States to monitor Frigate performance, object counts for all zones and cameras. |
| `switch` | Switch entities to toggle detection, recordings and snapshots. | | `switch` | Switch entities to toggle detection, recordings and snapshots. |
| `binary_sensor` | A "motion" binary sensor entity per camera/zone/object. | | `binary_sensor` | A "motion" binary sensor entity per camera/zone/object. |

View File

@@ -39,6 +39,12 @@ You cannot use the `environment_vars` section of your configuration file to set
Once your API key is configured, you can submit examples directly from the events page in Frigate using the `SEND TO FRIGATE+` button. Once your API key is configured, you can submit examples directly from the events page in Frigate using the `SEND TO FRIGATE+` button.
:::note
Snapshots must be enabled to be able to submit examples to Frigate+
:::
![Send To Plus](/img/send-to-plus.png) ![Send To Plus](/img/send-to-plus.png)
### Annotate and verify ### Annotate and verify

View File

@@ -17,16 +17,18 @@ ffmpeg:
record: preset-record-generic-audio-aac record: preset-record-generic-audio-aac
``` ```
### I can't view events or recordings in the Web UI.
Ensure your cameras send h264 encoded video, or [transcode them](/configuration/restream.md).
You can open `chrome://media-internals/` in another tab and then try to playback, the media internals page will give information about why playback is failing.
### My mjpeg stream or snapshots look green and crazy ### My mjpeg stream or snapshots look green and crazy
This almost always means that the width/height defined for your camera are not correct. Double check the resolution with VLC or another player. Also make sure you don't have the width and height values backwards. This almost always means that the width/height defined for your camera are not correct. Double check the resolution with VLC or another player. Also make sure you don't have the width and height values backwards.
![mismatched-resolution](/img/mismatched-resolution-min.jpg) ![mismatched-resolution](/img/mismatched-resolution-min.jpg)
### I can't view events or recordings in the Web UI.
Ensure your cameras send h264 encoded video, or [transcode them](/configuration/restream.md).
### "[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5639eeb6e140] moov atom not found" ### "[mov,mp4,m4a,3gp,3g2,mj2 @ 0x5639eeb6e140] moov atom not found"
These messages in the logs are expected in certain situations. Frigate checks the integrity of the recordings before storing. Occasionally these cached files will be invalid and cleaned up automatically. These messages in the logs are expected in certain situations. Frigate checks the integrity of the recordings before storing. Occasionally these cached files will be invalid and cleaned up automatically.

View File

@@ -4,11 +4,11 @@ module.exports = {
"frigate/index", "frigate/index",
"frigate/hardware", "frigate/hardware",
"frigate/installation", "frigate/installation",
"frigate/camera_setup",
], ],
Guides: [ Guides: [
"guides/camera_setup",
"guides/getting_started", "guides/getting_started",
"guides/events_setup", "guides/configuring_go2rtc",
"guides/false_positives", "guides/false_positives",
"guides/ha_notifications", "guides/ha_notifications",
"guides/stationary_objects", "guides/stationary_objects",

View File

@@ -3,6 +3,7 @@ import multiprocessing as mp
from multiprocessing.queues import Queue from multiprocessing.queues import Queue
from multiprocessing.synchronize import Event as MpEvent from multiprocessing.synchronize import Event as MpEvent
import os import os
import shutil
import signal import signal
import sys import sys
from typing import Optional from typing import Optional
@@ -27,7 +28,6 @@ from frigate.object_processing import TrackedObjectProcessor
from frigate.output import output_frames from frigate.output import output_frames
from frigate.plus import PlusApi from frigate.plus import PlusApi
from frigate.record import RecordingCleanup, RecordingMaintainer from frigate.record import RecordingCleanup, RecordingMaintainer
from frigate.restream import RestreamApi
from frigate.stats import StatsEmitter, stats_init from frigate.stats import StatsEmitter, stats_init
from frigate.storage import StorageMaintainer from frigate.storage import StorageMaintainer
from frigate.version import VERSION from frigate.version import VERSION
@@ -116,6 +116,9 @@ class FrigateApp:
if not "werkzeug" in self.config.logger.logs: if not "werkzeug" in self.config.logger.logs:
logging.getLogger("werkzeug").setLevel("ERROR") logging.getLogger("werkzeug").setLevel("ERROR")
if not "ws4py" in self.config.logger.logs:
logging.getLogger("ws4py").setLevel("ERROR")
def init_queues(self) -> None: def init_queues(self) -> None:
# Queues for clip processing # Queues for clip processing
self.event_queue: Queue = mp.Queue() self.event_queue: Queue = mp.Queue()
@@ -155,7 +158,9 @@ class FrigateApp:
self.db.bind(models) self.db.bind(models)
def init_stats(self) -> None: def init_stats(self) -> None:
self.stats_tracking = stats_init(self.camera_metrics, self.detectors) self.stats_tracking = stats_init(
self.config, self.camera_metrics, self.detectors
)
def init_web_server(self) -> None: def init_web_server(self) -> None:
self.flask_app = create_app( self.flask_app = create_app(
@@ -167,18 +172,13 @@ class FrigateApp:
self.plus_api, self.plus_api,
) )
def init_restream(self) -> None:
self.restream = RestreamApi(self.config)
self.restream.add_cameras()
def init_dispatcher(self) -> None: def init_dispatcher(self) -> None:
comms: list[Communicator] = [] comms: list[Communicator] = []
if self.config.mqtt.enabled: if self.config.mqtt.enabled:
comms.append(MqttClient(self.config)) comms.append(MqttClient(self.config))
self.ws_client = WebSocketClient(self.config) comms.append(WebSocketClient(self.config))
comms.append(self.ws_client)
self.dispatcher = Dispatcher(self.config, self.camera_metrics, comms) self.dispatcher = Dispatcher(self.config, self.camera_metrics, comms)
def start_detectors(self) -> None: def start_detectors(self) -> None:
@@ -327,6 +327,22 @@ class FrigateApp:
self.frigate_watchdog = FrigateWatchdog(self.detectors, self.stop_event) self.frigate_watchdog = FrigateWatchdog(self.detectors, self.stop_event)
self.frigate_watchdog.start() self.frigate_watchdog.start()
def check_shm(self) -> None:
available_shm = round(shutil.disk_usage("/dev/shm").total / 1000000, 1)
min_req_shm = 30
for _, camera in self.config.cameras.items():
min_req_shm += round(
(camera.detect.width * camera.detect.height * 1.5 * 9 + 270480)
/ 1048576,
1,
)
if available_shm < min_req_shm:
logger.warning(
f"The current SHM size of {available_shm}MB is too small, recommend increasing it to at least {min_req_shm}MB."
)
def start(self) -> None: def start(self) -> None:
self.init_logger() self.init_logger()
logger.info(f"Starting Frigate ({VERSION})") logger.info(f"Starting Frigate ({VERSION})")
@@ -360,7 +376,6 @@ class FrigateApp:
print(e) print(e)
self.log_process.terminate() self.log_process.terminate()
sys.exit(1) sys.exit(1)
self.init_restream()
self.start_detectors() self.start_detectors()
self.start_video_output_processor() self.start_video_output_processor()
self.start_detected_frames_processor() self.start_detected_frames_processor()
@@ -375,6 +390,7 @@ class FrigateApp:
self.start_recording_cleanup() self.start_recording_cleanup()
self.start_stats_emitter() self.start_stats_emitter()
self.start_watchdog() self.start_watchdog()
self.check_shm()
# self.zeroconf = broadcast_zeroconf(self.config.mqtt.client_id) # self.zeroconf = broadcast_zeroconf(self.config.mqtt.client_id)
def receiveSignal(signalNumber: int, frame: Optional[FrameType]) -> None: def receiveSignal(signalNumber: int, frame: Optional[FrameType]) -> None:
@@ -394,7 +410,17 @@ class FrigateApp:
logger.info(f"Stopping...") logger.info(f"Stopping...")
self.stop_event.set() self.stop_event.set()
self.ws_client.stop() for detector in self.detectors.values():
detector.stop()
# Empty the detection queue and set the events for all requests
while not self.detection_queue.empty():
connection_id = self.detection_queue.get(timeout=1)
self.detection_out_events[connection_id].set()
self.detection_queue.close()
self.detection_queue.join_thread()
self.dispatcher.stop()
self.detected_frames_processor.join() self.detected_frames_processor.join()
self.event_processor.join() self.event_processor.join()
self.event_cleanup.join() self.event_cleanup.join()
@@ -404,10 +430,20 @@ class FrigateApp:
self.frigate_watchdog.join() self.frigate_watchdog.join()
self.db.stop() self.db.stop()
for detector in self.detectors.values():
detector.stop()
while len(self.detection_shms) > 0: while len(self.detection_shms) > 0:
shm = self.detection_shms.pop() shm = self.detection_shms.pop()
shm.close() shm.close()
shm.unlink() shm.unlink()
for queue in [
self.event_queue,
self.event_processed_queue,
self.video_output_queue,
self.detected_frames_queue,
self.recordings_info_queue,
self.log_queue,
]:
while not queue.empty():
queue.get_nowait()
queue.close()
queue.join_thread()

View File

@@ -27,6 +27,11 @@ class Communicator(ABC):
"""Pass receiver so communicators can pass commands.""" """Pass receiver so communicators can pass commands."""
pass pass
@abstractmethod
def stop(self) -> None:
"""Stop the communicator."""
pass
class Dispatcher: class Dispatcher:
"""Handle communication between Frigate and communicators.""" """Handle communication between Frigate and communicators."""
@@ -72,6 +77,10 @@ class Dispatcher:
for comm in self.comms: for comm in self.comms:
comm.publish(topic, payload, retain) comm.publish(topic, payload, retain)
def stop(self) -> None:
for comm in self.comms:
comm.stop()
def _on_detect_command(self, camera_name: str, payload: str) -> None: def _on_detect_command(self, camera_name: str, payload: str) -> None:
"""Callback for detect topic.""" """Callback for detect topic."""
detect_settings = self.config.cameras[camera_name].detect detect_settings = self.config.cameras[camera_name].detect

View File

@@ -35,6 +35,9 @@ class MqttClient(Communicator): # type: ignore[misc]
f"{self.mqtt_config.topic_prefix}/{topic}", payload, retain=retain f"{self.mqtt_config.topic_prefix}/{topic}", payload, retain=retain
) )
def stop(self) -> None:
self.client.disconnect()
def _set_initial_topics(self) -> None: def _set_initial_topics(self) -> None:
"""Set initial state topics.""" """Set initial state topics."""
for camera_name, camera in self.config.cameras.items(): for camera_name, camera in self.config.cameras.items():

View File

@@ -95,3 +95,4 @@ class WebSocketClient(Communicator): # type: ignore[misc]
self.websocket_server.manager.join() self.websocket_server.manager.join()
self.websocket_server.shutdown() self.websocket_server.shutdown()
self.websocket_thread.join() self.websocket_thread.join()
logger.info("Exiting websocket client...")

View File

@@ -66,12 +66,41 @@ class LiveModeEnum(str, Enum):
webrtc = "webrtc" webrtc = "webrtc"
class TimeFormatEnum(str, Enum):
browser = "browser"
hours12 = "12hour"
hours24 = "24hour"
class DateTimeStyleEnum(str, Enum):
full = "full"
long = "long"
medium = "medium"
short = "short"
class UIConfig(FrigateBaseModel): class UIConfig(FrigateBaseModel):
live_mode: LiveModeEnum = Field( live_mode: LiveModeEnum = Field(
default=LiveModeEnum.mse, title="Default Live Mode." default=LiveModeEnum.mse, title="Default Live Mode."
) )
timezone: Optional[str] = Field(title="Override UI timezone.") timezone: Optional[str] = Field(title="Override UI timezone.")
use_experimental: bool = Field(default=False, title="Experimental UI") use_experimental: bool = Field(default=False, title="Experimental UI")
time_format: TimeFormatEnum = Field(
default=TimeFormatEnum.browser, title="Override UI time format."
)
date_style: DateTimeStyleEnum = Field(
default=DateTimeStyleEnum.short, title="Override UI dateStyle."
)
time_style: DateTimeStyleEnum = Field(
default=DateTimeStyleEnum.medium, title="Override UI timeStyle."
)
strftime_fmt: Optional[str] = Field(
default=None, title="Override date and time format using strftime syntax."
)
class TelemetryConfig(FrigateBaseModel):
version_check: bool = Field(default=True, title="Enable latest version check.")
class MqttConfig(FrigateBaseModel): class MqttConfig(FrigateBaseModel):
@@ -366,9 +395,18 @@ class BirdseyeCameraConfig(BaseModel):
) )
FFMPEG_GLOBAL_ARGS_DEFAULT = ["-hide_banner", "-loglevel", "warning"] # Note: Setting threads to less than 2 caused several issues with recording segments
# https://github.com/blakeblackshear/frigate/issues/5659
FFMPEG_GLOBAL_ARGS_DEFAULT = ["-hide_banner", "-loglevel", "warning", "-threads", "2"]
FFMPEG_INPUT_ARGS_DEFAULT = "preset-rtsp-generic" FFMPEG_INPUT_ARGS_DEFAULT = "preset-rtsp-generic"
DETECT_FFMPEG_OUTPUT_ARGS_DEFAULT = ["-f", "rawvideo", "-pix_fmt", "yuv420p"] DETECT_FFMPEG_OUTPUT_ARGS_DEFAULT = [
"-threads",
"2",
"-f",
"rawvideo",
"-pix_fmt",
"yuv420p",
]
RTMP_FFMPEG_OUTPUT_ARGS_DEFAULT = "preset-rtmp-generic" RTMP_FFMPEG_OUTPUT_ARGS_DEFAULT = "preset-rtmp-generic"
RECORD_FFMPEG_OUTPUT_ARGS_DEFAULT = "preset-record-generic" RECORD_FFMPEG_OUTPUT_ARGS_DEFAULT = "preset-record-generic"
@@ -818,6 +856,9 @@ class FrigateConfig(FrigateBaseModel):
default_factory=dict, title="Frigate environment variables." default_factory=dict, title="Frigate environment variables."
) )
ui: UIConfig = Field(default_factory=UIConfig, title="UI configuration.") ui: UIConfig = Field(default_factory=UIConfig, title="UI configuration.")
telemetry: TelemetryConfig = Field(
default_factory=TelemetryConfig, title="Telemetry configuration."
)
model: ModelConfig = Field( model: ModelConfig = Field(
default_factory=ModelConfig, title="Detection model configuration." default_factory=ModelConfig, title="Detection model configuration."
) )

View File

@@ -23,6 +23,13 @@ class InputTensorEnum(str, Enum):
nhwc = "nhwc" nhwc = "nhwc"
class ModelTypeEnum(str, Enum):
ssd = "ssd"
yolox = "yolox"
yolov5 = "yolov5"
yolov8 = "yolov8"
class ModelConfig(BaseModel): class ModelConfig(BaseModel):
path: Optional[str] = Field(title="Custom Object detection model path.") path: Optional[str] = Field(title="Custom Object detection model path.")
labelmap_path: Optional[str] = Field(title="Label map for custom object detector.") labelmap_path: Optional[str] = Field(title="Label map for custom object detector.")
@@ -37,6 +44,9 @@ class ModelConfig(BaseModel):
input_pixel_format: PixelFormatEnum = Field( input_pixel_format: PixelFormatEnum = Field(
default=PixelFormatEnum.rgb, title="Model Input Pixel Color Format" default=PixelFormatEnum.rgb, title="Model Input Pixel Color Format"
) )
model_type: ModelTypeEnum = Field(
default=ModelTypeEnum.ssd, title="Object Detection Model Type"
)
_merged_labelmap: Optional[Dict[int, str]] = PrivateAttr() _merged_labelmap: Optional[Dict[int, str]] = PrivateAttr()
_colormap: Dict[int, Tuple[int, int, int]] = PrivateAttr() _colormap: Dict[int, Tuple[int, int, int]] = PrivateAttr()

View File

@@ -13,12 +13,19 @@ from .detector_config import BaseDetectorConfig
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
plugin_modules = [
importlib.import_module(name) _included_modules = pkgutil.iter_modules(plugins.__path__, plugins.__name__ + ".")
for finder, name, ispkg in pkgutil.iter_modules(
plugins.__path__, plugins.__name__ + "." plugin_modules = []
)
] for _, name, _ in _included_modules:
try:
# currently openvino may fail when importing
# on an arm device with 64 KiB page size.
plugin_modules.append(importlib.import_module(name))
except ImportError as e:
logger.error(f"Error importing detector runtime: {e}")
api_types = {det.type_key: det for det in DetectionApi.__subclasses__()} api_types = {det.type_key: det for det in DetectionApi.__subclasses__()}

View File

@@ -5,7 +5,11 @@ from frigate.detectors.detection_api import DetectionApi
from frigate.detectors.detector_config import BaseDetectorConfig from frigate.detectors.detector_config import BaseDetectorConfig
from typing import Literal from typing import Literal
from pydantic import Extra, Field from pydantic import Extra, Field
import tflite_runtime.interpreter as tflite
try:
from tflite_runtime.interpreter import Interpreter
except ModuleNotFoundError:
from tensorflow.lite.python.interpreter import Interpreter
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -22,7 +26,7 @@ class CpuTfl(DetectionApi):
type_key = DETECTOR_KEY type_key = DETECTOR_KEY
def __init__(self, detector_config: CpuDetectorConfig): def __init__(self, detector_config: CpuDetectorConfig):
self.interpreter = tflite.Interpreter( self.interpreter = Interpreter(
model_path=detector_config.model.path or "/cpu_model.tflite", model_path=detector_config.model.path or "/cpu_model.tflite",
num_threads=detector_config.num_threads or 3, num_threads=detector_config.num_threads or 3,
) )

View File

@@ -5,8 +5,11 @@ from frigate.detectors.detection_api import DetectionApi
from frigate.detectors.detector_config import BaseDetectorConfig from frigate.detectors.detector_config import BaseDetectorConfig
from typing import Literal from typing import Literal
from pydantic import Extra, Field from pydantic import Extra, Field
import tflite_runtime.interpreter as tflite
from tflite_runtime.interpreter import load_delegate try:
from tflite_runtime.interpreter import Interpreter, load_delegate
except ModuleNotFoundError:
from tensorflow.lite.python.interpreter import Interpreter, load_delegate
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -33,7 +36,7 @@ class EdgeTpuTfl(DetectionApi):
logger.info(f"Attempting to load TPU as {device_config['device']}") logger.info(f"Attempting to load TPU as {device_config['device']}")
edge_tpu_delegate = load_delegate("libedgetpu.so.1.0", device_config) edge_tpu_delegate = load_delegate("libedgetpu.so.1.0", device_config)
logger.info("TPU found") logger.info("TPU found")
self.interpreter = tflite.Interpreter( self.interpreter = Interpreter(
model_path=detector_config.model.path or "/edgetpu_model.tflite", model_path=detector_config.model.path or "/edgetpu_model.tflite",
experimental_delegates=[edge_tpu_delegate], experimental_delegates=[edge_tpu_delegate],
) )

View File

@@ -3,7 +3,7 @@ import numpy as np
import openvino.runtime as ov import openvino.runtime as ov
from frigate.detectors.detection_api import DetectionApi from frigate.detectors.detection_api import DetectionApi
from frigate.detectors.detector_config import BaseDetectorConfig from frigate.detectors.detector_config import BaseDetectorConfig, ModelTypeEnum
from typing import Literal from typing import Literal
from pydantic import Extra, Field from pydantic import Extra, Field
@@ -24,12 +24,18 @@ class OvDetector(DetectionApi):
def __init__(self, detector_config: OvDetectorConfig): def __init__(self, detector_config: OvDetectorConfig):
self.ov_core = ov.Core() self.ov_core = ov.Core()
self.ov_model = self.ov_core.read_model(detector_config.model.path) self.ov_model = self.ov_core.read_model(detector_config.model.path)
self.ov_model_type = detector_config.model.model_type
self.h = detector_config.model.height
self.w = detector_config.model.width
self.interpreter = self.ov_core.compile_model( self.interpreter = self.ov_core.compile_model(
model=self.ov_model, device_name=detector_config.device model=self.ov_model, device_name=detector_config.device
) )
logger.info(f"Model Input Shape: {self.interpreter.input(0).shape}") logger.info(f"Model Input Shape: {self.interpreter.input(0).shape}")
self.output_indexes = 0 self.output_indexes = 0
while True: while True:
try: try:
tensor_shape = self.interpreter.output(self.output_indexes).shape tensor_shape = self.interpreter.output(self.output_indexes).shape
@@ -38,29 +44,131 @@ class OvDetector(DetectionApi):
except: except:
logger.info(f"Model has {self.output_indexes} Output Tensors") logger.info(f"Model has {self.output_indexes} Output Tensors")
break break
if self.ov_model_type == ModelTypeEnum.yolox:
self.num_classes = tensor_shape[2] - 5
logger.info(f"YOLOX model has {self.num_classes} classes")
self.set_strides_grids()
def set_strides_grids(self):
grids = []
expanded_strides = []
strides = [8, 16, 32]
hsizes = [self.h // stride for stride in strides]
wsizes = [self.w // stride for stride in strides]
for hsize, wsize, stride in zip(hsizes, wsizes, strides):
xv, yv = np.meshgrid(np.arange(wsize), np.arange(hsize))
grid = np.stack((xv, yv), 2).reshape(1, -1, 2)
grids.append(grid)
shape = grid.shape[:2]
expanded_strides.append(np.full((*shape, 1), stride))
self.grids = np.concatenate(grids, 1)
self.expanded_strides = np.concatenate(expanded_strides, 1)
## Takes in class ID, confidence score, and array of [x, y, w, h] that describes detection position,
## returns an array that's easily passable back to Frigate.
def process_yolo(self, class_id, conf, pos):
return [
class_id, # class ID
conf, # confidence score
(pos[1] - (pos[3] / 2)) / self.h, # y_min
(pos[0] - (pos[2] / 2)) / self.w, # x_min
(pos[1] + (pos[3] / 2)) / self.h, # y_max
(pos[0] + (pos[2] / 2)) / self.w, # x_max
]
def detect_raw(self, tensor_input): def detect_raw(self, tensor_input):
infer_request = self.interpreter.create_infer_request() infer_request = self.interpreter.create_infer_request()
infer_request.infer([tensor_input]) infer_request.infer([tensor_input])
results = infer_request.get_output_tensor() if self.ov_model_type == ModelTypeEnum.ssd:
results = infer_request.get_output_tensor()
detections = np.zeros((20, 6), np.float32) detections = np.zeros((20, 6), np.float32)
i = 0 i = 0
for object_detected in results.data[0, 0, :]: for object_detected in results.data[0, 0, :]:
if object_detected[0] != -1: if object_detected[0] != -1:
logger.debug(object_detected) logger.debug(object_detected)
if object_detected[2] < 0.1 or i == 20: if object_detected[2] < 0.1 or i == 20:
break break
detections[i] = [ detections[i] = [
object_detected[1], # Label ID object_detected[1], # Label ID
float(object_detected[2]), # Confidence float(object_detected[2]), # Confidence
object_detected[4], # y_min object_detected[4], # y_min
object_detected[3], # x_min object_detected[3], # x_min
object_detected[6], # y_max object_detected[6], # y_max
object_detected[5], # x_max object_detected[5], # x_max
] ]
i += 1 i += 1
return detections
elif self.ov_model_type == ModelTypeEnum.yolox:
out_tensor = infer_request.get_output_tensor()
# [x, y, h, w, box_score, class_no_1, ..., class_no_80],
results = out_tensor.data
results[..., :2] = (results[..., :2] + self.grids) * self.expanded_strides
results[..., 2:4] = np.exp(results[..., 2:4]) * self.expanded_strides
image_pred = results[0, ...]
return detections class_conf = np.max(
image_pred[:, 5 : 5 + self.num_classes], axis=1, keepdims=True
)
class_pred = np.argmax(image_pred[:, 5 : 5 + self.num_classes], axis=1)
class_pred = np.expand_dims(class_pred, axis=1)
conf_mask = (image_pred[:, 4] * class_conf.squeeze() >= 0.3).squeeze()
# Detections ordered as (x1, y1, x2, y2, obj_conf, class_conf, class_pred)
dets = np.concatenate((image_pred[:, :5], class_conf, class_pred), axis=1)
dets = dets[conf_mask]
ordered = dets[dets[:, 5].argsort()[::-1]][:20]
detections = np.zeros((20, 6), np.float32)
for i, object_detected in enumerate(ordered):
detections[i] = self.process_yolo(
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

View File

@@ -67,7 +67,7 @@ class EventProcessor(threading.Thread):
while not self.stop_event.is_set(): while not self.stop_event.is_set():
try: try:
event_type, camera, event_data = self.event_queue.get(timeout=10) event_type, camera, event_data = self.event_queue.get(timeout=1)
except queue.Empty: except queue.Empty:
continue continue

View File

@@ -1,14 +1,52 @@
"""Handles inserting and maintaining ffmpeg presets.""" """Handles inserting and maintaining ffmpeg presets."""
import logging
import os import os
from typing import Any from typing import Any
from frigate.version import VERSION from frigate.version import VERSION
from frigate.const import BTBN_PATH from frigate.const import BTBN_PATH
from frigate.util import vainfo_hwaccel
logger = logging.getLogger(__name__)
class LibvaGpuSelector:
"Automatically selects the correct libva GPU."
_selected_gpu = None
def get_selected_gpu(self) -> str:
"""Get selected libva GPU."""
if not os.path.exists("/dev/dri"):
return ""
if self._selected_gpu:
return self._selected_gpu
devices = list(filter(lambda d: d.startswith("render"), os.listdir("/dev/dri")))
if len(devices) < 2:
self._selected_gpu = "/dev/dri/renderD128"
return self._selected_gpu
for device in devices:
check = vainfo_hwaccel(device_name=device)
logger.debug(f"{device} return vainfo status code: {check.returncode}")
if check.returncode == 0:
self._selected_gpu = f"/dev/dri/{device}"
return self._selected_gpu
return ""
TIMEOUT_PARAM = "-timeout" if os.path.exists(BTBN_PATH) else "-stimeout" TIMEOUT_PARAM = "-timeout" if os.path.exists(BTBN_PATH) else "-stimeout"
_gpu_selector = LibvaGpuSelector()
_user_agent_args = [ _user_agent_args = [
"-user_agent", "-user_agent",
f"FFmpeg Frigate/{VERSION}", f"FFmpeg Frigate/{VERSION}",
@@ -23,7 +61,7 @@ PRESETS_HW_ACCEL_DECODE = {
"-hwaccel", "-hwaccel",
"vaapi", "vaapi",
"-hwaccel_device", "-hwaccel_device",
"/dev/dri/renderD128", _gpu_selector.get_selected_gpu(),
"-hwaccel_output_format", "-hwaccel_output_format",
"vaapi", "vaapi",
], ],
@@ -31,7 +69,7 @@ PRESETS_HW_ACCEL_DECODE = {
"-hwaccel", "-hwaccel",
"qsv", "qsv",
"-qsv_device", "-qsv_device",
"/dev/dri/renderD128", _gpu_selector.get_selected_gpu(),
"-hwaccel_output_format", "-hwaccel_output_format",
"qsv", "qsv",
"-c:v", "-c:v",
@@ -43,7 +81,7 @@ PRESETS_HW_ACCEL_DECODE = {
"-hwaccel", "-hwaccel",
"qsv", "qsv",
"-qsv_device", "-qsv_device",
"/dev/dri/renderD128", _gpu_selector.get_selected_gpu(),
"-hwaccel_output_format", "-hwaccel_output_format",
"qsv", "qsv",
"-c:v", "-c:v",
@@ -54,47 +92,36 @@ PRESETS_HW_ACCEL_DECODE = {
"cuda", "cuda",
"-hwaccel_output_format", "-hwaccel_output_format",
"cuda", "cuda",
"-extra_hw_frames",
"2",
"-c:v",
"h264_cuvid",
], ],
"preset-nvidia-h265": [ "preset-nvidia-h265": [
"-hwaccel", "-hwaccel",
"cuda", "cuda",
"-hwaccel_output_format", "-hwaccel_output_format",
"cuda", "cuda",
"-extra_hw_frames",
"2",
"-c:v",
"hevc_cuvid",
], ],
"preset-nvidia-mjpeg": [ "preset-nvidia-mjpeg": [
"-hwaccel", "-hwaccel",
"cuda", "cuda",
"-hwaccel_output_format", "-hwaccel_output_format",
"cuda", "cuda",
"-extra_hw_frames",
"2",
"-c:v",
"mjpeg_cuvid",
], ],
} }
PRESETS_HW_ACCEL_SCALE = { PRESETS_HW_ACCEL_SCALE = {
"preset-rpi-32-h264": "-r {} -s {}x{} -f rawvideo -pix_fmt yuv420p", "preset-rpi-32-h264": "-r {0} -s {1}x{2}",
"preset-rpi-64-h264": "-r {} -s {}x{} -f rawvideo -pix_fmt yuv420p", "preset-rpi-64-h264": "-r {0} -s {1}x{2}",
"preset-vaapi": "-vf fps={},scale_vaapi=w={}:h={},hwdownload,format=yuv420p -f rawvideo", "preset-vaapi": "-r {0} -vf fps={0},scale_vaapi=w={1}:h={2},hwdownload,format=yuv420p",
"preset-intel-qsv-h264": "-r {} -vf vpp_qsv=w={}:h={}:format=nv12,hwdownload,format=nv12,format=yuv420p -f rawvideo", "preset-intel-qsv-h264": "-r {0} -vf vpp_qsv=framerate={0}:w={1}:h={2}:format=nv12,hwdownload,format=nv12,format=yuv420p",
"preset-intel-qsv-h265": "-r {} -vf vpp_qsv=w={}:h={}:format=nv12,hwdownload,format=nv12,format=yuv420p -f rawvideo", "preset-intel-qsv-h265": "-r {0} -vf vpp_qsv=framerate={0}:w={1}:h={2}:format=nv12,hwdownload,format=nv12,format=yuv420p",
"preset-nvidia-h264": "-vf fps={},scale_cuda=w={}:h={}:format=nv12,hwdownload,format=nv12,format=yuv420p -f rawvideo", "preset-nvidia-h264": "-r {0} -vf fps={0},scale_cuda=w={1}:h={2}:format=nv12,hwdownload,format=nv12,format=yuv420p",
"preset-nvidia-h265": "-vf fps={},scale_cuda=w={}:h={}:format=nv12,hwdownload,format=nv12,format=yuv420p -f rawvideo", "preset-nvidia-h265": "-r {0} -vf fps={0},scale_cuda=w={1}:h={2}:format=nv12,hwdownload,format=nv12,format=yuv420p",
"default": "-r {} -s {}x{}", "default": "-r {0} -s {1}x{2}",
} }
PRESETS_HW_ACCEL_ENCODE = { PRESETS_HW_ACCEL_ENCODE = {
"preset-rpi-32-h264": "ffmpeg -hide_banner {0} -c:v h264_v4l2m2m -g 50 -bf 0 {1}", "preset-rpi-32-h264": "ffmpeg -hide_banner {0} -c:v h264_v4l2m2m {1}",
"preset-rpi-64-h264": "ffmpeg -hide_banner {0} -c:v h264_v4l2m2m -g 50 -bf 0 {1}", "preset-rpi-64-h264": "ffmpeg -hide_banner {0} -c:v h264_v4l2m2m {1}",
"preset-vaapi": "ffmpeg -hide_banner -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device {2} {0} -c:v h264_vaapi -g 50 -bf 0 -profile:v high -level:v 4.1 -sei:v 0 -an -vf format=vaapi|nv12,hwupload {1}",
"preset-intel-qsv-h264": "ffmpeg -hide_banner {0} -c:v h264_qsv -g 50 -bf 0 -profile:v high -level:v 4.1 -async_depth:v 1 {1}", "preset-intel-qsv-h264": "ffmpeg -hide_banner {0} -c:v h264_qsv -g 50 -bf 0 -profile:v high -level:v 4.1 -async_depth:v 1 {1}",
"preset-intel-qsv-h265": "ffmpeg -hide_banner {0} -c:v h264_qsv -g 50 -bf 0 -profile:v high -level:v 4.1 -async_depth:v 1 {1}", "preset-intel-qsv-h265": "ffmpeg -hide_banner {0} -c:v h264_qsv -g 50 -bf 0 -profile:v high -level:v 4.1 -async_depth:v 1 {1}",
"preset-nvidia-h264": "ffmpeg -hide_banner {0} -c:v h264_nvenc -g 50 -profile:v high -level:v auto -preset:v p2 -tune:v ll {1}", "preset-nvidia-h264": "ffmpeg -hide_banner {0} -c:v h264_nvenc -g 50 -profile:v high -level:v auto -preset:v p2 -tune:v ll {1}",
@@ -127,7 +154,9 @@ def parse_preset_hardware_acceleration_scale(
scale = PRESETS_HW_ACCEL_SCALE.get(arg, "") scale = PRESETS_HW_ACCEL_SCALE.get(arg, "")
if scale: if scale:
return scale.format(fps, width, height).split(" ") scale = scale.format(fps, width, height).split(" ")
scale.extend(detect_args)
return scale
else: else:
scale = scale.format(fps, width, height).split(" ") scale = scale.format(fps, width, height).split(" ")
scale.extend(detect_args) scale.extend(detect_args)
@@ -142,6 +171,7 @@ def parse_preset_hardware_acceleration_encode(arg: Any, input: str, output: str)
return PRESETS_HW_ACCEL_ENCODE.get(arg, PRESETS_HW_ACCEL_ENCODE["default"]).format( return PRESETS_HW_ACCEL_ENCODE.get(arg, PRESETS_HW_ACCEL_ENCODE["default"]).format(
input, input,
output, output,
_gpu_selector.get_selected_gpu(),
) )
@@ -237,6 +267,17 @@ PRESETS_INPUT = {
TIMEOUT_PARAM, TIMEOUT_PARAM,
"5000000", "5000000",
], ],
"preset-rtsp-restream-low-latency": _user_agent_args
+ [
"-rtsp_transport",
"tcp",
TIMEOUT_PARAM,
"5000000",
"-fflags",
"nobuffer",
"-flags",
"low_delay",
],
"preset-rtsp-udp": _user_agent_args "preset-rtsp-udp": _user_agent_args
+ [ + [
"-avoid_negative_ts", "-avoid_negative_ts",

View File

@@ -111,6 +111,7 @@ def events_summary():
Event.select( Event.select(
Event.camera, Event.camera,
Event.label, Event.label,
Event.sub_label,
fn.strftime( fn.strftime(
"%Y-%m-%d", "%Y-%m-%d",
fn.datetime( fn.datetime(
@@ -124,6 +125,7 @@ def events_summary():
.group_by( .group_by(
Event.camera, Event.camera,
Event.label, Event.label,
Event.sub_label,
fn.strftime( fn.strftime(
"%Y-%m-%d", "%Y-%m-%d",
fn.datetime( fn.datetime(
@@ -184,6 +186,18 @@ def send_to_plus(id):
logger.error(message) logger.error(message)
return make_response(jsonify({"success": False, "message": message}), 404) return make_response(jsonify({"success": False, "message": message}), 404)
if event.end_time is None:
logger.error(f"Unable to load clean png for in-progress event: {event.id}")
return make_response(
jsonify(
{
"success": False,
"message": "Unable to load clean png for in-progress event",
}
),
400,
)
if event.plus_id: if event.plus_id:
message = "Already submitted to plus" message = "Already submitted to plus"
logger.error(message) logger.error(message)
@@ -202,6 +216,15 @@ def send_to_plus(id):
400, 400,
) )
if image is None or image.size == 0:
logger.error(f"Unable to load clean png for event: {event.id}")
return make_response(
jsonify(
{"success": False, "message": "Unable to load clean png for event"}
),
400,
)
try: try:
plus_id = current_app.plus_api.upload_image(image, event.camera) plus_id = current_app.plus_api.upload_image(image, event.camera)
except Exception as ex: except Exception as ex:
@@ -301,7 +324,9 @@ def get_sub_labels():
sub_labels.remove(None) sub_labels.remove(None)
if split_joined: if split_joined:
for label in sub_labels: original_labels = sub_labels.copy()
for label in original_labels:
if "," in label: if "," in label:
sub_labels.remove(label) sub_labels.remove(label)
parts = label.split(",") parts = label.split(",")
@@ -310,6 +335,7 @@ def get_sub_labels():
if not (part.strip()) in sub_labels: if not (part.strip()) in sub_labels:
sub_labels.append(part.strip()) sub_labels.append(part.strip())
sub_labels.sort()
return jsonify(sub_labels) return jsonify(sub_labels)
@@ -617,7 +643,13 @@ def events():
sub_label_clauses.append((Event.sub_label.is_null())) sub_label_clauses.append((Event.sub_label.is_null()))
for label in filtered_sub_labels: for label in filtered_sub_labels:
sub_label_clauses.append((Event.sub_label.cast("text") % f"*{label}*")) sub_label_clauses.append(
(Event.sub_label.cast("text") == label)
) # include exact matches
# include this label when part of a list
sub_label_clauses.append((Event.sub_label.cast("text") % f"*{label},*"))
sub_label_clauses.append((Event.sub_label.cast("text") % f"*, {label}*"))
sub_label_clause = reduce(operator.or_, sub_label_clauses) sub_label_clause = reduce(operator.or_, sub_label_clauses)
clauses.append((sub_label_clause)) clauses.append((sub_label_clause))
@@ -769,7 +801,10 @@ def config_save():
logging.error(f"Error restarting Frigate: {e}") logging.error(f"Error restarting Frigate: {e}")
return "Config successfully saved, unable to restart Frigate", 200 return "Config successfully saved, unable to restart Frigate", 200
return "Config successfully saved, restarting...", 200 return (
"Config successfully saved, restarting (this can take up to one minute)...",
200,
)
else: else:
return "Config successfully saved.", 200 return "Config successfully saved.", 200
@@ -867,7 +902,7 @@ def latest_frame(camera_name):
response.headers["Content-Type"] = "image/jpeg" response.headers["Content-Type"] = "image/jpeg"
response.headers["Cache-Control"] = "no-store" response.headers["Cache-Control"] = "no-store"
return response return response
elif camera_name == "birdseye" and current_app.frigate_config.restream.birdseye: elif camera_name == "birdseye" and current_app.frigate_config.birdseye.restream:
frame = cv2.cvtColor( frame = cv2.cvtColor(
current_app.detected_frames_processor.get_current_frame(camera_name), current_app.detected_frames_processor.get_current_frame(camera_name),
cv2.COLOR_YUV2BGR_I420, cv2.COLOR_YUV2BGR_I420,
@@ -1272,12 +1307,12 @@ def ffprobe():
output.append( output.append(
{ {
"return_code": ffprobe.returncode, "return_code": ffprobe.returncode,
"stderr": json.loads(ffprobe.stderr.decode("unicode_escape").strip()) "stderr": ffprobe.stderr.decode("unicode_escape").strip()
if ffprobe.stderr.decode() if ffprobe.returncode != 0
else {}, else "",
"stdout": json.loads(ffprobe.stdout.decode("unicode_escape").strip()) "stdout": json.loads(ffprobe.stdout.decode("unicode_escape").strip())
if ffprobe.stdout.decode() if ffprobe.returncode == 0
else {}, else "",
} }
) )

View File

@@ -2,11 +2,16 @@
import logging import logging
import threading import threading
import os import os
import signal
import queue import queue
import multiprocessing as mp
from multiprocessing.queues import Queue from multiprocessing.queues import Queue
from logging import handlers from logging import handlers
from typing import Optional
from types import FrameType
from setproctitle import setproctitle from setproctitle import setproctitle
from typing import Deque from typing import Deque, Optional
from types import FrameType
from collections import deque from collections import deque
from frigate.util import clean_camera_user_pass from frigate.util import clean_camera_user_pass
@@ -34,10 +39,21 @@ def log_process(log_queue: Queue) -> None:
threading.current_thread().name = f"logger" threading.current_thread().name = f"logger"
setproctitle("frigate.logger") setproctitle("frigate.logger")
listener_configurer() listener_configurer()
stop_event = mp.Event()
def receiveSignal(signalNumber: int, frame: Optional[FrameType]) -> None:
stop_event.set()
signal.signal(signal.SIGTERM, receiveSignal)
signal.signal(signal.SIGINT, receiveSignal)
while True: while True:
try: try:
record = log_queue.get(timeout=5) record = log_queue.get(timeout=1)
except (queue.Empty, KeyboardInterrupt): except (queue.Empty, KeyboardInterrupt):
if stop_event.is_set():
break
continue continue
logger = logging.getLogger(record.name) logger = logging.getLogger(record.name)
logger.handle(record) logger.handle(record)

View File

@@ -88,6 +88,7 @@ def run_detector(
stop_event = mp.Event() stop_event = mp.Event()
def receiveSignal(signalNumber, frame): def receiveSignal(signalNumber, frame):
logger.info("Signal to exit detection process...")
stop_event.set() stop_event.set()
signal.signal(signal.SIGTERM, receiveSignal) signal.signal(signal.SIGTERM, receiveSignal)
@@ -104,7 +105,7 @@ def run_detector(
while not stop_event.is_set(): while not stop_event.is_set():
try: try:
connection_id = detection_queue.get(timeout=5) connection_id = detection_queue.get(timeout=1)
except queue.Empty: except queue.Empty:
continue continue
input_frame = frame_manager.get( input_frame = frame_manager.get(
@@ -125,6 +126,8 @@ def run_detector(
avg_speed.value = (avg_speed.value * 9 + duration) / 10 avg_speed.value = (avg_speed.value * 9 + duration) / 10
logger.info("Exited detection process...")
class ObjectDetectProcess: class ObjectDetectProcess:
def __init__( def __init__(
@@ -144,6 +147,9 @@ class ObjectDetectProcess:
self.start_or_restart() self.start_or_restart()
def stop(self): def stop(self):
# if the process has already exited on its own, just return
if self.detect_process and self.detect_process.exitcode:
return
self.detect_process.terminate() self.detect_process.terminate()
logging.info("Waiting for detection process to exit gracefully...") logging.info("Waiting for detection process to exit gracefully...")
self.detect_process.join(timeout=30) self.detect_process.join(timeout=30)
@@ -151,6 +157,7 @@ class ObjectDetectProcess:
logging.info("Detection process didnt exit. Force killing...") logging.info("Detection process didnt exit. Force killing...")
self.detect_process.kill() self.detect_process.kill()
self.detect_process.join() self.detect_process.join()
logging.info("Detection process has exited...")
def start_or_restart(self): def start_or_restart(self):
self.detection_start.value = 0.0 self.detection_start.value = 0.0
@@ -173,12 +180,13 @@ class ObjectDetectProcess:
class RemoteObjectDetector: class RemoteObjectDetector:
def __init__(self, name, labels, detection_queue, event, model_config): def __init__(self, name, labels, detection_queue, event, model_config, stop_event):
self.labels = labels self.labels = labels
self.name = name self.name = name
self.fps = EventsPerSecond() self.fps = EventsPerSecond()
self.detection_queue = detection_queue self.detection_queue = detection_queue
self.event = event self.event = event
self.stop_event = stop_event
self.shm = mp.shared_memory.SharedMemory(name=self.name, create=False) self.shm = mp.shared_memory.SharedMemory(name=self.name, create=False)
self.np_shm = np.ndarray( self.np_shm = np.ndarray(
(1, model_config.height, model_config.width, 3), (1, model_config.height, model_config.width, 3),
@@ -193,11 +201,14 @@ class RemoteObjectDetector:
def detect(self, tensor_input, threshold=0.4): def detect(self, tensor_input, threshold=0.4):
detections = [] detections = []
if self.stop_event.is_set():
return detections
# copy input to shared memory # copy input to shared memory
self.np_shm[:] = tensor_input[:] self.np_shm[:] = tensor_input[:]
self.event.clear() self.event.clear()
self.detection_queue.put(self.name) self.detection_queue.put(self.name)
result = self.event.wait(timeout=10.0) result = self.event.wait(timeout=5.0)
# if it timed out # if it timed out
if result is None: if result is None:

View File

@@ -901,7 +901,7 @@ class TrackedObjectProcessor(threading.Thread):
current_tracked_objects, current_tracked_objects,
motion_boxes, motion_boxes,
regions, regions,
) = self.tracked_objects_queue.get(True, 10) ) = self.tracked_objects_queue.get(True, 1)
except queue.Empty: except queue.Empty:
continue continue

View File

@@ -38,16 +38,10 @@ class FFMpegConverter:
quality: int, quality: int,
birdseye_rtsp: bool = False, birdseye_rtsp: bool = False,
): ):
if birdseye_rtsp: self.bd_pipe = None
if os.path.exists(BIRDSEYE_PIPE):
os.remove(BIRDSEYE_PIPE)
os.mkfifo(BIRDSEYE_PIPE, mode=0o777) if birdseye_rtsp:
stdin = os.open(BIRDSEYE_PIPE, os.O_RDONLY | os.O_NONBLOCK) self.recreate_birdseye_pipe()
self.bd_pipe = os.open(BIRDSEYE_PIPE, os.O_WRONLY)
os.close(stdin)
else:
self.bd_pipe = None
ffmpeg_cmd = [ ffmpeg_cmd = [
"ffmpeg", "ffmpeg",
@@ -80,14 +74,36 @@ class FFMpegConverter:
start_new_session=True, start_new_session=True,
) )
def recreate_birdseye_pipe(self) -> None:
if self.bd_pipe:
os.close(self.bd_pipe)
if os.path.exists(BIRDSEYE_PIPE):
os.remove(BIRDSEYE_PIPE)
os.mkfifo(BIRDSEYE_PIPE, mode=0o777)
stdin = os.open(BIRDSEYE_PIPE, os.O_RDONLY | os.O_NONBLOCK)
self.bd_pipe = os.open(BIRDSEYE_PIPE, os.O_WRONLY)
os.close(stdin)
self.reading_birdseye = False
def write(self, b) -> None: def write(self, b) -> None:
self.process.stdin.write(b) self.process.stdin.write(b)
if self.bd_pipe: if self.bd_pipe:
try: try:
os.write(self.bd_pipe, b) os.write(self.bd_pipe, b)
self.reading_birdseye = True
except BrokenPipeError: except BrokenPipeError:
# catch error when no one is listening if self.reading_birdseye:
# we know the pipe was being read from and now it is not
# so we should recreate the pipe to ensure no partially-read
# frames exist
logger.debug(
"Recreating the birdseye pipe because it was read from and now is not"
)
self.recreate_birdseye_pipe()
return return
def read(self, length): def read(self, length):
@@ -109,14 +125,15 @@ class FFMpegConverter:
class BroadcastThread(threading.Thread): class BroadcastThread(threading.Thread):
def __init__(self, camera, converter, websocket_server): def __init__(self, camera, converter, websocket_server, stop_event):
super(BroadcastThread, self).__init__() super(BroadcastThread, self).__init__()
self.camera = camera self.camera = camera
self.converter = converter self.converter = converter
self.websocket_server = websocket_server self.websocket_server = websocket_server
self.stop_event = stop_event
def run(self): def run(self):
while True: while not self.stop_event.is_set():
buf = self.converter.read(65536) buf = self.converter.read(65536)
if buf: if buf:
manager = self.websocket_server.manager manager = self.websocket_server.manager
@@ -426,7 +443,7 @@ def output_frames(config: FrigateConfig, video_output_queue):
cam_config.live.quality, cam_config.live.quality,
) )
broadcasters[camera] = BroadcastThread( broadcasters[camera] = BroadcastThread(
camera, converters[camera], websocket_server camera, converters[camera], websocket_server, stop_event
) )
if config.birdseye.enabled: if config.birdseye.enabled:
@@ -439,7 +456,7 @@ def output_frames(config: FrigateConfig, video_output_queue):
config.birdseye.restream, config.birdseye.restream,
) )
broadcasters["birdseye"] = BroadcastThread( broadcasters["birdseye"] = BroadcastThread(
"birdseye", converters["birdseye"], websocket_server "birdseye", converters["birdseye"], websocket_server, stop_event
) )
websocket_thread.start() websocket_thread.start()
@@ -463,7 +480,7 @@ def output_frames(config: FrigateConfig, video_output_queue):
current_tracked_objects, current_tracked_objects,
motion_boxes, motion_boxes,
regions, regions,
) = video_output_queue.get(True, 10) ) = video_output_queue.get(True, 1)
except queue.Empty: except queue.Empty:
continue continue

View File

@@ -100,19 +100,12 @@ class RecordingMaintainer(threading.Thread):
for camera in grouped_recordings.keys(): for camera in grouped_recordings.keys():
segment_count = len(grouped_recordings[camera]) segment_count = len(grouped_recordings[camera])
if segment_count > keep_count: if segment_count > keep_count:
#### logger.warning(
# Need to find a way to tell if these are aging out based on retention settings or if the system is overloaded. f"Unable to keep up with recording segments in cache for {camera}. Keeping the {keep_count} most recent segments out of {segment_count} and discarding the rest..."
#### )
# logger.warning(
# f"Too many recording segments in cache for {camera}. Keeping the {keep_count} most recent segments out of {segment_count}, discarding the rest..."
# )
to_remove = grouped_recordings[camera][:-keep_count] to_remove = grouped_recordings[camera][:-keep_count]
for f in to_remove: for f in to_remove:
cache_path = f["cache_path"] cache_path = f["cache_path"]
####
# Need to find a way to tell if these are aging out based on retention settings or if the system is overloaded.
####
# logger.warning(f"Discarding a recording segment: {cache_path}")
Path(cache_path).unlink(missing_ok=True) Path(cache_path).unlink(missing_ok=True)
self.end_time_cache.pop(cache_path, None) self.end_time_cache.pop(cache_path, None)
grouped_recordings[camera] = grouped_recordings[camera][-keep_count:] grouped_recordings[camera] = grouped_recordings[camera][-keep_count:]
@@ -178,10 +171,12 @@ class RecordingMaintainer(threading.Thread):
else: else:
if duration == -1: if duration == -1:
logger.warning( logger.warning(
f"Failed to probe corrupt segment {f}: {p.returncode} - {p.stderr}" f"Failed to probe corrupt segment {cache_path}: {p.returncode} - {p.stderr}"
) )
logger.warning(f"Discarding a corrupt recording segment: {f}") logger.warning(
f"Discarding a corrupt recording segment: {cache_path}"
)
Path(cache_path).unlink(missing_ok=True) Path(cache_path).unlink(missing_ok=True)
continue continue
@@ -227,6 +222,19 @@ class RecordingMaintainer(threading.Thread):
cache_path, cache_path,
record_mode, record_mode,
) )
# if it doesn't overlap with an event, go ahead and drop the segment
# if it ends more than the configured pre_capture for the camera
else:
pre_capture = self.config.cameras[
camera
].record.events.pre_capture
most_recently_processed_frame_time = self.recordings_info[
camera
][-1][0]
retain_cutoff = most_recently_processed_frame_time - pre_capture
if end_time.timestamp() < retain_cutoff:
Path(cache_path).unlink(missing_ok=True)
self.end_time_cache.pop(cache_path, None)
# else retain days includes this segment # else retain days includes this segment
else: else:
record_mode = self.config.cameras[camera].record.retain.mode record_mode = self.config.cameras[camera].record.retain.mode
@@ -411,6 +419,10 @@ class RecordingCleanup(threading.Thread):
logger.debug(f"Checking tmp clip {p}.") logger.debug(f"Checking tmp clip {p}.")
if p.stat().st_mtime < (datetime.datetime.now().timestamp() - 60 * 1): if p.stat().st_mtime < (datetime.datetime.now().timestamp() - 60 * 1):
logger.debug("Deleting tmp clip.") logger.debug("Deleting tmp clip.")
# empty contents of file before unlinking https://github.com/blakeblackshear/frigate/issues/4769
with open(p, "w"):
pass
p.unlink(missing_ok=True) p.unlink(missing_ok=True)
def expire_recordings(self): def expire_recordings(self):

View File

@@ -1,33 +0,0 @@
"""Controls go2rtc restream."""
import logging
import requests
from frigate.config import FrigateConfig
from frigate.const import BIRDSEYE_PIPE
from frigate.ffmpeg_presets import (
parse_preset_hardware_acceleration_encode,
)
logger = logging.getLogger(__name__)
class RestreamApi:
"""Control go2rtc relay API."""
def __init__(self, config: FrigateConfig) -> None:
self.config: FrigateConfig = config
def add_cameras(self) -> None:
"""Add cameras to go2rtc."""
self.relays: dict[str, str] = {}
if self.config.birdseye.restream:
self.relays[
"birdseye"
] = f"exec:{parse_preset_hardware_acceleration_encode(self.config.ffmpeg.hwaccel_args, f'-f rawvideo -pix_fmt yuv420p -video_size {self.config.birdseye.width}x{self.config.birdseye.height} -r 10 -i {BIRDSEYE_PIPE}', '-rtsp_transport tcp -f rtsp {output}')}"
for name, path in self.relays.items():
params = {"src": path, "name": name}
requests.put("http://127.0.0.1:1984/api/streams", params=params)

View File

@@ -22,7 +22,11 @@ from frigate.object_detection import ObjectDetectProcess
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def get_latest_version() -> str: def get_latest_version(config: FrigateConfig) -> str:
if not config.telemetry.version_check:
return "disabled"
try: try:
request = requests.get( request = requests.get(
"https://api.github.com/repos/blakeblackshear/frigate/releases/latest", "https://api.github.com/repos/blakeblackshear/frigate/releases/latest",
@@ -40,6 +44,7 @@ def get_latest_version() -> str:
def stats_init( def stats_init(
config: FrigateConfig,
camera_metrics: dict[str, CameraMetricsTypes], camera_metrics: dict[str, CameraMetricsTypes],
detectors: dict[str, ObjectDetectProcess], detectors: dict[str, ObjectDetectProcess],
) -> StatsTrackingTypes: ) -> StatsTrackingTypes:
@@ -47,7 +52,8 @@ def stats_init(
"camera_metrics": camera_metrics, "camera_metrics": camera_metrics,
"detectors": detectors, "detectors": detectors,
"started": int(time.time()), "started": int(time.time()),
"latest_frigate_version": get_latest_version(), "latest_frigate_version": get_latest_version(config),
"last_updated": int(time.time()),
} }
return stats_tracking return stats_tracking
@@ -239,6 +245,7 @@ def stats_snapshot(
"latest_version": stats_tracking["latest_frigate_version"], "latest_version": stats_tracking["latest_frigate_version"],
"storage": {}, "storage": {},
"temperatures": get_temperatures(), "temperatures": get_temperatures(),
"last_updated": int(time.time()),
} }
for path in [RECORD_DIR, CLIPS_DIR, CACHE_DIR, "/dev/shm"]: for path in [RECORD_DIR, CLIPS_DIR, CACHE_DIR, "/dev/shm"]:
@@ -276,8 +283,10 @@ class StatsEmitter(threading.Thread):
def run(self) -> None: def run(self) -> None:
time.sleep(10) time.sleep(10)
while not self.stop_event.wait(self.config.mqtt.stats_interval): while not self.stop_event.wait(self.config.mqtt.stats_interval):
logger.debug("Starting stats collection")
stats = stats_snapshot( stats = stats_snapshot(
self.config, self.stats_tracking, self.hwaccel_errors self.config, self.stats_tracking, self.hwaccel_errors
) )
self.dispatcher.publish("stats", json.dumps(stats), retain=False) self.dispatcher.publish("stats", json.dumps(stats), retain=False)
logger.info(f"Exiting watchdog...") logger.debug("Finished stats collection")
logger.info(f"Exiting stats emitter...")

View File

@@ -36,3 +36,14 @@ class TestUserPassCleanup(unittest.TestCase):
"""Test that no change is made to path with no special characters.""" """Test that no change is made to path with no special characters."""
escaped = escape_special_characters(self.rtsp_with_pass) escaped = escape_special_characters(self.rtsp_with_pass)
assert escaped == self.rtsp_with_pass assert escaped == self.rtsp_with_pass
class TestUserPassMasking(unittest.TestCase):
def setUp(self) -> None:
self.rtsp_log_message = "Did you mean file:rtsp://user:password@192.168.1.3:554"
def test_rtsp_in_log_message(self):
"""Test that the rtsp url in a log message is espaced."""
escaped = clean_camera_user_pass(self.rtsp_log_message)
print(f"The escaped is {escaped}")
assert escaped == "Did you mean file:rtsp://*:*@192.168.1.3:554"

View File

@@ -29,3 +29,4 @@ class StatsTrackingTypes(TypedDict):
detectors: dict[str, ObjectDetectProcess] detectors: dict[str, ObjectDetectProcess]
started: int started: int
latest_frigate_version: str latest_frigate_version: str
last_updated: int

View File

@@ -14,7 +14,7 @@ from abc import ABC, abstractmethod
from collections import Counter from collections import Counter
from collections.abc import Mapping from collections.abc import Mapping
from multiprocessing import shared_memory from multiprocessing import shared_memory
from typing import Any, AnyStr, Tuple from typing import Any, AnyStr, Optional, Tuple
import cv2 import cv2
import numpy as np import numpy as np
@@ -722,7 +722,7 @@ def load_labels(path, encoding="utf-8"):
def clean_camera_user_pass(line: str) -> str: def clean_camera_user_pass(line: str) -> str:
"""Removes user and password from line.""" """Removes user and password from line."""
if line.startswith("rtsp://"): if "rtsp://" in line:
return re.sub(REGEX_RTSP_CAMERA_USER_PASS, "://*:*@", line) return re.sub(REGEX_RTSP_CAMERA_USER_PASS, "://*:*@", line)
else: else:
return re.sub(REGEX_HTTP_CAMERA_USER_PASS, "user=*&password=*", line) return re.sub(REGEX_HTTP_CAMERA_USER_PASS, "user=*&password=*", line)
@@ -926,6 +926,17 @@ def get_nvidia_gpu_stats() -> dict[str, str]:
"--format=csv", "--format=csv",
] ]
if (
"CUDA_VISIBLE_DEVICES" in os.environ
and os.environ["CUDA_VISIBLE_DEVICES"].isdigit()
):
nvidia_smi_command.extend(["--id", os.environ["CUDA_VISIBLE_DEVICES"]])
elif (
"NVIDIA_VISIBLE_DEVICES" in os.environ
and os.environ["NVIDIA_VISIBLE_DEVICES"].isdigit()
):
nvidia_smi_command.extend(["--id", os.environ["NVIDIA_VISIBLE_DEVICES"]])
p = sp.run( p = sp.run(
nvidia_smi_command, nvidia_smi_command,
encoding="ascii", encoding="ascii",
@@ -965,9 +976,13 @@ def ffprobe_stream(path: str) -> sp.CompletedProcess:
return sp.run(ffprobe_cmd, capture_output=True) return sp.run(ffprobe_cmd, capture_output=True)
def vainfo_hwaccel() -> sp.CompletedProcess: def vainfo_hwaccel(device_name: Optional[str] = None) -> sp.CompletedProcess:
"""Run vainfo.""" """Run vainfo."""
ffprobe_cmd = ["vainfo"] ffprobe_cmd = (
["vainfo"]
if not device_name
else ["vainfo", "--display", "drm", "--device", f"/dev/dri/{device_name}"]
)
return sp.run(ffprobe_cmd, capture_output=True) return sp.run(ffprobe_cmd, capture_output=True)

Some files were not shown because too many files have changed in this diff Show More