mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-08-31 07:27:57 +00:00
Compare commits
No commits in common. "dev" and "v0.16.0-beta1" have entirely different histories.
dev
...
v0.16.0-be
@ -8,7 +8,6 @@ amdgpu
|
|||||||
analyzeduration
|
analyzeduration
|
||||||
Annke
|
Annke
|
||||||
apexcharts
|
apexcharts
|
||||||
Aqara
|
|
||||||
arange
|
arange
|
||||||
argmax
|
argmax
|
||||||
argmin
|
argmin
|
||||||
@ -23,7 +22,6 @@ autotrack
|
|||||||
autotracked
|
autotracked
|
||||||
autotracker
|
autotracker
|
||||||
autotracking
|
autotracking
|
||||||
backchannel
|
|
||||||
balena
|
balena
|
||||||
Beelink
|
Beelink
|
||||||
BGRA
|
BGRA
|
||||||
@ -65,7 +63,6 @@ dsize
|
|||||||
dtype
|
dtype
|
||||||
ECONNRESET
|
ECONNRESET
|
||||||
edgetpu
|
edgetpu
|
||||||
Eufy
|
|
||||||
facenet
|
facenet
|
||||||
fastapi
|
fastapi
|
||||||
faststart
|
faststart
|
||||||
@ -84,7 +81,6 @@ frontdoor
|
|||||||
fstype
|
fstype
|
||||||
fullchain
|
fullchain
|
||||||
fullscreen
|
fullscreen
|
||||||
gatekeep
|
|
||||||
genai
|
genai
|
||||||
generativeai
|
generativeai
|
||||||
genpts
|
genpts
|
||||||
@ -113,7 +109,6 @@ imdecode
|
|||||||
imencode
|
imencode
|
||||||
imread
|
imread
|
||||||
imwrite
|
imwrite
|
||||||
inpoint
|
|
||||||
interp
|
interp
|
||||||
iostat
|
iostat
|
||||||
iotop
|
iotop
|
||||||
@ -165,7 +160,6 @@ mpegts
|
|||||||
mqtt
|
mqtt
|
||||||
mse
|
mse
|
||||||
msenc
|
msenc
|
||||||
muxing
|
|
||||||
namedtuples
|
namedtuples
|
||||||
nbytes
|
nbytes
|
||||||
nchw
|
nchw
|
||||||
@ -196,13 +190,10 @@ ONVIF
|
|||||||
openai
|
openai
|
||||||
opencv
|
opencv
|
||||||
openvino
|
openvino
|
||||||
overfitting
|
|
||||||
OWASP
|
OWASP
|
||||||
paddleocr
|
paddleocr
|
||||||
paho
|
paho
|
||||||
passwordless
|
passwordless
|
||||||
PCMA
|
|
||||||
PCMU
|
|
||||||
popleft
|
popleft
|
||||||
posthog
|
posthog
|
||||||
postprocess
|
postprocess
|
||||||
@ -228,16 +219,13 @@ radeontop
|
|||||||
rawvideo
|
rawvideo
|
||||||
rcond
|
rcond
|
||||||
RDONLY
|
RDONLY
|
||||||
realmonitor
|
|
||||||
rebranded
|
rebranded
|
||||||
recvonly
|
|
||||||
referer
|
referer
|
||||||
reindex
|
reindex
|
||||||
Reolink
|
Reolink
|
||||||
restream
|
restream
|
||||||
restreamed
|
restreamed
|
||||||
restreaming
|
restreaming
|
||||||
RJSF
|
|
||||||
rkmpp
|
rkmpp
|
||||||
rknn
|
rknn
|
||||||
rkrga
|
rkrga
|
||||||
@ -247,11 +235,8 @@ rocminfo
|
|||||||
rootfs
|
rootfs
|
||||||
rtmp
|
rtmp
|
||||||
RTSP
|
RTSP
|
||||||
rtsps
|
|
||||||
rtspx
|
|
||||||
ruamel
|
ruamel
|
||||||
scroller
|
scroller
|
||||||
sendonly
|
|
||||||
setproctitle
|
setproctitle
|
||||||
setpts
|
setpts
|
||||||
shms
|
shms
|
||||||
@ -262,7 +247,6 @@ SNDMORE
|
|||||||
socs
|
socs
|
||||||
sqliteq
|
sqliteq
|
||||||
sqlitevecq
|
sqlitevecq
|
||||||
Srtp
|
|
||||||
ssdlite
|
ssdlite
|
||||||
statm
|
statm
|
||||||
stimeout
|
stimeout
|
||||||
@ -280,7 +264,6 @@ tensorrt
|
|||||||
tflite
|
tflite
|
||||||
thresholded
|
thresholded
|
||||||
timelapse
|
timelapse
|
||||||
titlecase
|
|
||||||
tmpfs
|
tmpfs
|
||||||
tobytes
|
tobytes
|
||||||
toggleable
|
toggleable
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
---
|
|
||||||
globs: ["**/*.ts", "**/*.tsx"]
|
|
||||||
alwaysApply: false
|
|
||||||
---
|
|
||||||
|
|
||||||
Never write strings in the frontend directly, always write to and reference the relevant translations file.
|
|
||||||
134
.github/DISCUSSION_TEMPLATE/beta-support.yml
vendored
134
.github/DISCUSSION_TEMPLATE/beta-support.yml
vendored
@ -1,134 +0,0 @@
|
|||||||
title: "[Beta Support]: "
|
|
||||||
labels: ["support", "triage", "beta"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thank you for testing Frigate beta versions! Use this form for support with beta releases.
|
|
||||||
|
|
||||||
**Note:** Beta versions may have incomplete features, known issues, or unexpected behavior. Please check the [release notes](https://github.com/blakeblackshear/frigate/releases) and [recent discussions][discussions] for known beta issues before submitting.
|
|
||||||
|
|
||||||
Before submitting, read the [beta documentation][docs].
|
|
||||||
|
|
||||||
By posting here you agree to follow our [AI policy][ai-policy]. Posts that appear to be written by an AI on your behalf may be closed without a response.
|
|
||||||
|
|
||||||
[docs]: https://docs-dev.frigate.video/
|
|
||||||
[discussions]: https://github.com/blakeblackshear/frigate/discussions
|
|
||||||
[ai-policy]: https://github.com/blakeblackshear/frigate/blob/dev/AI_POLICY.md
|
|
||||||
- type: textarea
|
|
||||||
id: description
|
|
||||||
attributes:
|
|
||||||
label: Describe the problem you are having
|
|
||||||
description: Please be as detailed as possible. Include what you expected to happen vs what actually happened.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Beta Version
|
|
||||||
description: Visible on the System Metrics page in the Web UI. Please include the full version including the build identifier (eg. 0.18.0-beta1, 0.18.0-8b72c7a, etc.)
|
|
||||||
placeholder: "0.18.0-beta1"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: issue-category
|
|
||||||
attributes:
|
|
||||||
label: Issue Category
|
|
||||||
description: What area is your issue related to? This helps us understand the context.
|
|
||||||
options:
|
|
||||||
- Object Detection / Detectors
|
|
||||||
- Hardware Acceleration
|
|
||||||
- Configuration / Setup
|
|
||||||
- WebUI / Frontend
|
|
||||||
- Recordings / Storage
|
|
||||||
- Notifications / Events
|
|
||||||
- Integration (Home Assistant, etc)
|
|
||||||
- Performance / Stability
|
|
||||||
- Installation / Updates
|
|
||||||
- Other
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: config
|
|
||||||
attributes:
|
|
||||||
label: Frigate config file
|
|
||||||
description: This will be automatically formatted into code, so no need for backticks. Remove any sensitive information like passwords or URLs.
|
|
||||||
render: yaml
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: frigatelogs
|
|
||||||
attributes:
|
|
||||||
label: Relevant Frigate log output
|
|
||||||
description: Please copy and paste any relevant Frigate log output. Include logs before and after your exact error when possible. This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: go2rtclogs
|
|
||||||
attributes:
|
|
||||||
label: Relevant go2rtc log output (if applicable)
|
|
||||||
description: If your issue involves cameras, streams, or playback, please include go2rtc logs. Logs can be viewed via the Frigate UI, Docker, or the go2rtc dashboard. This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
||||||
- type: dropdown
|
|
||||||
id: install-method
|
|
||||||
attributes:
|
|
||||||
label: Install method
|
|
||||||
options:
|
|
||||||
- Home Assistant App
|
|
||||||
- Docker Compose
|
|
||||||
- Docker CLI
|
|
||||||
- Proxmox via Docker
|
|
||||||
- Proxmox via installation script
|
|
||||||
- Proxomox via VM
|
|
||||||
- Windows WSL2
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: docker
|
|
||||||
attributes:
|
|
||||||
label: docker-compose file or Docker CLI command
|
|
||||||
description: This will be automatically formatted into code, so no need for backticks. Include relevant environment variables and device mappings.
|
|
||||||
render: yaml
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: os
|
|
||||||
attributes:
|
|
||||||
label: Operating system
|
|
||||||
options:
|
|
||||||
- Home Assistant OS
|
|
||||||
- Debian
|
|
||||||
- Ubuntu
|
|
||||||
- Other Linux
|
|
||||||
- Proxmox
|
|
||||||
- UNRAID
|
|
||||||
- Windows
|
|
||||||
- Other
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: input
|
|
||||||
id: hardware
|
|
||||||
attributes:
|
|
||||||
label: CPU / GPU / Hardware
|
|
||||||
description: Provide details about your hardware (e.g., Intel i5-9400, NVIDIA RTX 3060, Raspberry Pi 4, etc)
|
|
||||||
placeholder: "Intel i7-10700, NVIDIA GTX 1660"
|
|
||||||
- type: textarea
|
|
||||||
id: screenshots
|
|
||||||
attributes:
|
|
||||||
label: Screenshots
|
|
||||||
description: Screenshots of the issue, System metrics pages, or any relevant UI. Drag and drop or paste images directly.
|
|
||||||
- type: textarea
|
|
||||||
id: steps-to-reproduce
|
|
||||||
attributes:
|
|
||||||
label: Steps to reproduce
|
|
||||||
description: If applicable, provide detailed steps to reproduce the issue
|
|
||||||
placeholder: |
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '...'
|
|
||||||
3. See error
|
|
||||||
- type: textarea
|
|
||||||
id: other
|
|
||||||
attributes:
|
|
||||||
label: Any other information that may be helpful
|
|
||||||
description: Additional context, related issues, when the problem started appearing, etc.
|
|
||||||
@ -8,12 +8,9 @@ body:
|
|||||||
|
|
||||||
Before submitting your support request, please [search the discussions][discussions], read the [official Frigate documentation][docs], and read the [Frigate FAQ][faq] pinned at the Discussion page to see if your question has already been answered by the community.
|
Before submitting your support request, please [search the discussions][discussions], read the [official Frigate documentation][docs], and read the [Frigate FAQ][faq] pinned at the Discussion page to see if your question has already been answered by the community.
|
||||||
|
|
||||||
By posting here you agree to follow our [AI policy][ai-policy]. Posts that appear to be written by an AI on your behalf may be closed without a response.
|
|
||||||
|
|
||||||
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
||||||
[docs]: https://docs.frigate.video
|
[docs]: https://docs.frigate.video
|
||||||
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
||||||
[ai-policy]: https://github.com/blakeblackshear/frigate/blob/dev/AI_POLICY.md
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
@ -90,12 +87,11 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: Install method
|
label: Install method
|
||||||
options:
|
options:
|
||||||
- Home Assistant App
|
- Home Assistant Add-on
|
||||||
- Docker Compose
|
- Docker Compose
|
||||||
- Docker CLI
|
- Docker CLI
|
||||||
- Proxmox via Docker
|
- Proxmox via Docker
|
||||||
- Proxmox via installation script
|
- Proxmox via TTeck Script
|
||||||
- Proxomox via VM
|
|
||||||
- Windows WSL2
|
- Windows WSL2
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@ -8,12 +8,9 @@ body:
|
|||||||
|
|
||||||
Before submitting your support request, please [search the discussions][discussions], read the [official Frigate documentation][docs], and read the [Frigate FAQ][faq] pinned at the Discussion page to see if your question has already been answered by the community.
|
Before submitting your support request, please [search the discussions][discussions], read the [official Frigate documentation][docs], and read the [Frigate FAQ][faq] pinned at the Discussion page to see if your question has already been answered by the community.
|
||||||
|
|
||||||
By posting here you agree to follow our [AI policy][ai-policy]. Posts that appear to be written by an AI on your behalf may be closed without a response.
|
|
||||||
|
|
||||||
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
||||||
[docs]: https://docs.frigate.video
|
[docs]: https://docs.frigate.video
|
||||||
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
||||||
[ai-policy]: https://github.com/blakeblackshear/frigate/blob/dev/AI_POLICY.md
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
@ -76,12 +73,11 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: Install method
|
label: Install method
|
||||||
options:
|
options:
|
||||||
- Home Assistant App
|
- Home Assistant Add-on
|
||||||
- Docker Compose
|
- Docker Compose
|
||||||
- Docker CLI
|
- Docker CLI
|
||||||
- Proxmox via Docker
|
- Proxmox via Docker
|
||||||
- Proxmox via installation script
|
- Proxmox via TTeck Script
|
||||||
- Proxomox via VM
|
|
||||||
- Windows WSL2
|
- Windows WSL2
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@ -8,12 +8,9 @@ body:
|
|||||||
|
|
||||||
Before submitting your support request, please [search the discussions][discussions], read the [official Frigate documentation][docs], and read the [Frigate FAQ][faq] pinned at the Discussion page to see if your question has already been answered by the community.
|
Before submitting your support request, please [search the discussions][discussions], read the [official Frigate documentation][docs], and read the [Frigate FAQ][faq] pinned at the Discussion page to see if your question has already been answered by the community.
|
||||||
|
|
||||||
By posting here you agree to follow our [AI policy][ai-policy]. Posts that appear to be written by an AI on your behalf may be closed without a response.
|
|
||||||
|
|
||||||
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
||||||
[docs]: https://docs.frigate.video
|
[docs]: https://docs.frigate.video
|
||||||
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
||||||
[ai-policy]: https://github.com/blakeblackshear/frigate/blob/dev/AI_POLICY.md
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
@ -56,12 +53,11 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: Install method
|
label: Install method
|
||||||
options:
|
options:
|
||||||
- Home Assistant App
|
- Home Assistant Add-on
|
||||||
- Docker Compose
|
- Docker Compose
|
||||||
- Docker CLI
|
- Docker CLI
|
||||||
- Proxmox via Docker
|
- Proxmox via Docker
|
||||||
- Proxmox via installation script
|
- Proxmox via TTeck Script
|
||||||
- Proxomox via VM
|
|
||||||
- Windows WSL2
|
- Windows WSL2
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@ -8,12 +8,9 @@ body:
|
|||||||
|
|
||||||
Before submitting your support request, please [search the discussions][discussions], read the [official Frigate documentation][docs], and read the [Frigate FAQ][faq] pinned at the Discussion page to see if your question has already been answered by the community.
|
Before submitting your support request, please [search the discussions][discussions], read the [official Frigate documentation][docs], and read the [Frigate FAQ][faq] pinned at the Discussion page to see if your question has already been answered by the community.
|
||||||
|
|
||||||
By posting here you agree to follow our [AI policy][ai-policy]. Posts that appear to be written by an AI on your behalf may be closed without a response.
|
|
||||||
|
|
||||||
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
||||||
[docs]: https://docs.frigate.video
|
[docs]: https://docs.frigate.video
|
||||||
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
||||||
[ai-policy]: https://github.com/blakeblackshear/frigate/blob/dev/AI_POLICY.md
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
@ -76,12 +73,11 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: Install method
|
label: Install method
|
||||||
options:
|
options:
|
||||||
- Home Assistant App
|
- Home Assistant Add-on
|
||||||
- Docker Compose
|
- Docker Compose
|
||||||
- Docker CLI
|
- Docker CLI
|
||||||
- Proxmox via Docker
|
- Proxmox via Docker
|
||||||
- Proxmox via installation script
|
- Proxmox via TTeck Script
|
||||||
- Proxmox via VM
|
|
||||||
- Windows WSL2
|
- Windows WSL2
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@ -8,12 +8,9 @@ body:
|
|||||||
|
|
||||||
Before submitting your support request, please [search the discussions][discussions], read the [official Frigate documentation][docs], and read the [Frigate FAQ][faq] pinned at the Discussion page to see if your question has already been answered by the community.
|
Before submitting your support request, please [search the discussions][discussions], read the [official Frigate documentation][docs], and read the [Frigate FAQ][faq] pinned at the Discussion page to see if your question has already been answered by the community.
|
||||||
|
|
||||||
By posting here you agree to follow our [AI policy][ai-policy]. Posts that appear to be written by an AI on your behalf may be closed without a response.
|
|
||||||
|
|
||||||
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
||||||
[docs]: https://docs.frigate.video
|
[docs]: https://docs.frigate.video
|
||||||
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
||||||
[ai-policy]: https://github.com/blakeblackshear/frigate/blob/dev/AI_POLICY.md
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
@ -72,12 +69,11 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: Install method
|
label: Install method
|
||||||
options:
|
options:
|
||||||
- Home Assistant App
|
- Home Assistant Add-on
|
||||||
- Docker Compose
|
- Docker Compose
|
||||||
- Docker CLI
|
- Docker CLI
|
||||||
- Proxmox via Docker
|
- Proxmox via Docker
|
||||||
- Proxmox via installation script
|
- Proxmox via TTeck Script
|
||||||
- Proxomox via VM
|
|
||||||
- Windows WSL2
|
- Windows WSL2
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
3
.github/DISCUSSION_TEMPLATE/question.yml
vendored
3
.github/DISCUSSION_TEMPLATE/question.yml
vendored
@ -10,12 +10,9 @@ body:
|
|||||||
|
|
||||||
**If you are looking for support, start a new discussion and use a support category.**
|
**If you are looking for support, start a new discussion and use a support category.**
|
||||||
|
|
||||||
By posting here you agree to follow our [AI policy][ai-policy]. Posts that appear to be written by an AI on your behalf may be closed without a response.
|
|
||||||
|
|
||||||
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
||||||
[docs]: https://docs.frigate.video
|
[docs]: https://docs.frigate.video
|
||||||
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
||||||
[ai-policy]: https://github.com/blakeblackshear/frigate/blob/dev/AI_POLICY.md
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
16
.github/DISCUSSION_TEMPLATE/report-a-bug.yml
vendored
16
.github/DISCUSSION_TEMPLATE/report-a-bug.yml
vendored
@ -6,20 +6,14 @@ body:
|
|||||||
value: |
|
value: |
|
||||||
Use this form to submit a reproducible bug in Frigate or Frigate's UI.
|
Use this form to submit a reproducible bug in Frigate or Frigate's UI.
|
||||||
|
|
||||||
**⚠️ If you are running a beta version (0.18.0-beta or similar), please use the [Beta Support template](https://github.com/blakeblackshear/frigate/discussions/new?category=beta-support) instead.**
|
Before submitting your bug report, please [search the discussions][discussions], look at recent open and closed [pull requests][prs], read the [official Frigate documentation][docs], and read the [Frigate FAQ][faq] pinned at the Discussion page to see if your bug has already been fixed by the developers or reported by the community.
|
||||||
|
|
||||||
Before submitting your bug report, please ask the AI with the "Ask AI" button on the [official documentation site][ai] about your issue, [search the discussions][discussions], look at recent open and closed [pull requests][prs], read the [official Frigate documentation][docs], and read the [Frigate FAQ][faq] pinned at the Discussion page to see if your bug has already been fixed by the developers or reported by the community.
|
|
||||||
|
|
||||||
**If you are unsure if your issue is actually a bug or not, please submit a support request first.**
|
**If you are unsure if your issue is actually a bug or not, please submit a support request first.**
|
||||||
|
|
||||||
By posting here you agree to follow our [AI policy][ai-policy]. Posts that appear to be written by an AI on your behalf may be closed without a response.
|
|
||||||
|
|
||||||
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
[discussions]: https://www.github.com/blakeblackshear/frigate/discussions
|
||||||
[prs]: https://www.github.com/blakeblackshear/frigate/pulls
|
[prs]: https://www.github.com/blakeblackshear/frigate/pulls
|
||||||
[docs]: https://docs.frigate.video
|
[docs]: https://docs.frigate.video
|
||||||
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
[faq]: https://github.com/blakeblackshear/frigate/discussions/12724
|
||||||
[ai]: https://docs.frigate.video
|
|
||||||
[ai-policy]: https://github.com/blakeblackshear/frigate/blob/dev/AI_POLICY.md
|
|
||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
attributes:
|
attributes:
|
||||||
label: Checklist
|
label: Checklist
|
||||||
@ -32,8 +26,6 @@ body:
|
|||||||
- label: I have tried a different browser to see if it is related to my browser.
|
- label: I have tried a different browser to see if it is related to my browser.
|
||||||
required: true
|
required: true
|
||||||
- label: I have tried reproducing the issue in [incognito mode](https://www.computerworld.com/article/1719851/how-to-go-incognito-in-chrome-firefox-safari-and-edge.html) to rule out problems with any third party extensions or plugins I have installed.
|
- label: I have tried reproducing the issue in [incognito mode](https://www.computerworld.com/article/1719851/how-to-go-incognito-in-chrome-firefox-safari-and-edge.html) to rule out problems with any third party extensions or plugins I have installed.
|
||||||
- label: I have asked the AI at https://docs.frigate.video about my issue.
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
attributes:
|
attributes:
|
||||||
@ -119,13 +111,9 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: Install method
|
label: Install method
|
||||||
options:
|
options:
|
||||||
- Home Assistant App
|
- Home Assistant Add-on
|
||||||
- Docker Compose
|
- Docker Compose
|
||||||
- Docker CLI
|
- Docker CLI
|
||||||
- Proxmox via Docker
|
|
||||||
- Proxmox via installation script
|
|
||||||
- Proxomox via VM
|
|
||||||
- Windows WSL2
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
|
|||||||
7
.github/ISSUE_TEMPLATE/feature_request.md
vendored
7
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -7,13 +7,6 @@ assignees: ''
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<!--
|
|
||||||
By posting here you agree to follow our AI policy:
|
|
||||||
https://github.com/blakeblackshear/frigate/blob/dev/AI_POLICY.md
|
|
||||||
|
|
||||||
Requests that appear to be written by an AI on your behalf may be closed without a response.
|
|
||||||
-->
|
|
||||||
|
|
||||||
**Describe what you are trying to accomplish and why in non technical terms**
|
**Describe what you are trying to accomplish and why in non technical terms**
|
||||||
I want to be able to ... so that I can ...
|
I want to be able to ... so that I can ...
|
||||||
|
|
||||||
|
|||||||
1
.github/copilot-instructions.md
vendored
1
.github/copilot-instructions.md
vendored
@ -1 +0,0 @@
|
|||||||
AGENTS.md
|
|
||||||
51
.github/pull_request_template.md
vendored
51
.github/pull_request_template.md
vendored
@ -1,18 +1,17 @@
|
|||||||
_Please read the [contributing guidelines](https://github.com/blakeblackshear/frigate/blob/dev/CONTRIBUTING.md) and the [AI policy](https://github.com/blakeblackshear/frigate/blob/dev/AI_POLICY.md) before submitting a PR. Every PR must be read and submitted by a person, and PRs that appear to be unreviewed AI output will be closed without review._
|
|
||||||
|
|
||||||
## Proposed change
|
## Proposed change
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Thank you!
|
Thank you!
|
||||||
|
|
||||||
Describe what this pull request does and how it will benefit users of Frigate.
|
|
||||||
Please describe in detail any considerations, breaking changes, etc.
|
|
||||||
|
|
||||||
If you're introducing a new feature or significantly refactoring existing functionality,
|
If you're introducing a new feature or significantly refactoring existing functionality,
|
||||||
we encourage you to start a discussion first. This helps ensure your idea aligns with
|
we encourage you to start a discussion first. This helps ensure your idea aligns with
|
||||||
Frigate's development goals.
|
Frigate's development goals.
|
||||||
|
|
||||||
|
Describe what this pull request does and how it will benefit users of Frigate.
|
||||||
|
Please describe in detail any considerations, breaking changes, etc. that are
|
||||||
|
made in this pull request.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
|
||||||
## Type of change
|
## Type of change
|
||||||
|
|
||||||
- [ ] Dependency upgrade
|
- [ ] Dependency upgrade
|
||||||
@ -26,45 +25,6 @@ _Please read the [contributing guidelines](https://github.com/blakeblackshear/fr
|
|||||||
|
|
||||||
- This PR fixes or closes issue: fixes #
|
- This PR fixes or closes issue: fixes #
|
||||||
- This PR is related to issue:
|
- This PR is related to issue:
|
||||||
- Link to discussion with maintainers (**required** for any large or "planned" features):
|
|
||||||
|
|
||||||
## For new features
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Every new feature adds scope that maintainers must test, maintain, and support long-term.
|
|
||||||
We try to be thoughtful about what we take on, and sometimes that means saying no to
|
|
||||||
good code if the feature isn't the right fit — or saying yes to something we weren't sure
|
|
||||||
about. These calls are sometimes subjective, and we won't always get them right. We're
|
|
||||||
happy to discuss and reconsider.
|
|
||||||
|
|
||||||
Linking to an existing feature request or discussion with community interest helps us
|
|
||||||
understand demand, but a great idea is a great idea even without a crowd behind it.
|
|
||||||
|
|
||||||
You can delete this section for bugfixes and non-feature changes.
|
|
||||||
-->
|
|
||||||
|
|
||||||
- [ ] There is an existing feature request or discussion with community interest for this change.
|
|
||||||
- Link:
|
|
||||||
|
|
||||||
## AI disclosure
|
|
||||||
|
|
||||||
<!--
|
|
||||||
We welcome contributions that use AI tools, but we need to understand your relationship
|
|
||||||
with the code you're submitting. See our AI usage policy in CONTRIBUTING.md for details.
|
|
||||||
|
|
||||||
Be honest — this won't disqualify your PR. Trust matters more than method.
|
|
||||||
-->
|
|
||||||
|
|
||||||
- [ ] No AI tools were used in this PR.
|
|
||||||
- [ ] AI tools were used in this PR. Details below:
|
|
||||||
|
|
||||||
**AI tool(s) used** (e.g., Claude, Copilot, ChatGPT, Cursor):
|
|
||||||
|
|
||||||
**How AI was used** (e.g., code generation, code review, debugging, documentation):
|
|
||||||
|
|
||||||
**Extent of AI involvement** (e.g., generated entire implementation, assisted with specific functions, suggested fixes):
|
|
||||||
|
|
||||||
**Human oversight**: Describe what manual review, testing, and validation you performed on the AI-generated portions.
|
|
||||||
|
|
||||||
## Checklist
|
## Checklist
|
||||||
|
|
||||||
@ -75,6 +35,5 @@ _Please read the [contributing guidelines](https://github.com/blakeblackshear/fr
|
|||||||
- [ ] The code change is tested and works locally.
|
- [ ] The code change is tested and works locally.
|
||||||
- [ ] Local tests pass. **Your PR cannot be merged unless tests pass**
|
- [ ] Local tests pass. **Your PR cannot be merged unless tests pass**
|
||||||
- [ ] There is no commented out code in this PR.
|
- [ ] There is no commented out code in this PR.
|
||||||
- [ ] I can explain every line of code in this PR if asked.
|
|
||||||
- [ ] UI changes including text have used i18n keys and have been added to the `en` locale.
|
- [ ] UI changes including text have used i18n keys and have been added to the `en` locale.
|
||||||
- [ ] The code has been formatted using Ruff (`ruff format frigate`)
|
- [ ] The code has been formatted using Ruff (`ruff format frigate`)
|
||||||
|
|||||||
91
.github/workflows/ci.yml
vendored
91
.github/workflows/ci.yml
vendored
@ -15,7 +15,7 @@ concurrency:
|
|||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
PYTHON_VERSION: 3.11
|
PYTHON_VERSION: 3.9
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
amd64_build:
|
amd64_build:
|
||||||
@ -23,7 +23,7 @@ jobs:
|
|||||||
name: AMD64 Build
|
name: AMD64 Build
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Set up QEMU and Buildx
|
- name: Set up QEMU and Buildx
|
||||||
@ -32,7 +32,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Build and push amd64 standard build
|
- name: Build and push amd64 standard build
|
||||||
uses: docker/build-push-action@v7
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: docker/main/Dockerfile
|
file: docker/main/Dockerfile
|
||||||
@ -41,13 +41,12 @@ jobs:
|
|||||||
target: frigate
|
target: frigate
|
||||||
tags: ${{ steps.setup.outputs.image-name }}-amd64
|
tags: ${{ steps.setup.outputs.image-name }}-amd64
|
||||||
cache-from: type=registry,ref=${{ steps.setup.outputs.cache-name }}-amd64
|
cache-from: type=registry,ref=${{ steps.setup.outputs.cache-name }}-amd64
|
||||||
cache-to: type=registry,ref=${{ steps.setup.outputs.cache-name }}-amd64,mode=max
|
|
||||||
arm64_build:
|
arm64_build:
|
||||||
runs-on: ubuntu-22.04-arm
|
runs-on: ubuntu-22.04-arm
|
||||||
name: ARM Build
|
name: ARM Build
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Set up QEMU and Buildx
|
- name: Set up QEMU and Buildx
|
||||||
@ -56,7 +55,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Build and push arm64 standard build
|
- name: Build and push arm64 standard build
|
||||||
uses: docker/build-push-action@v7
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: docker/main/Dockerfile
|
file: docker/main/Dockerfile
|
||||||
@ -67,7 +66,7 @@ jobs:
|
|||||||
${{ steps.setup.outputs.image-name }}-standard-arm64
|
${{ steps.setup.outputs.image-name }}-standard-arm64
|
||||||
cache-from: type=registry,ref=${{ steps.setup.outputs.cache-name }}-arm64
|
cache-from: type=registry,ref=${{ steps.setup.outputs.cache-name }}-arm64
|
||||||
- name: Build and push RPi build
|
- name: Build and push RPi build
|
||||||
uses: docker/bake-action@v7
|
uses: docker/bake-action@v6
|
||||||
with:
|
with:
|
||||||
source: .
|
source: .
|
||||||
push: true
|
push: true
|
||||||
@ -77,12 +76,42 @@ jobs:
|
|||||||
rpi.tags=${{ steps.setup.outputs.image-name }}-rpi
|
rpi.tags=${{ steps.setup.outputs.image-name }}-rpi
|
||||||
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-arm64
|
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-arm64
|
||||||
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-arm64,mode=max
|
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-arm64,mode=max
|
||||||
|
jetson_jp5_build:
|
||||||
|
if: false
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
name: Jetson Jetpack 5
|
||||||
|
steps:
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Set up QEMU and Buildx
|
||||||
|
id: setup
|
||||||
|
uses: ./.github/actions/setup
|
||||||
|
with:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Build and push TensorRT (Jetson, Jetpack 5)
|
||||||
|
env:
|
||||||
|
ARCH: arm64
|
||||||
|
BASE_IMAGE: nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime
|
||||||
|
SLIM_BASE: nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime
|
||||||
|
TRT_BASE: nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime
|
||||||
|
uses: docker/bake-action@v6
|
||||||
|
with:
|
||||||
|
source: .
|
||||||
|
push: true
|
||||||
|
targets: tensorrt
|
||||||
|
files: docker/tensorrt/trt.hcl
|
||||||
|
set: |
|
||||||
|
tensorrt.tags=${{ steps.setup.outputs.image-name }}-tensorrt-jp5
|
||||||
|
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-jp5
|
||||||
|
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-jp5,mode=max
|
||||||
jetson_jp6_build:
|
jetson_jp6_build:
|
||||||
runs-on: ubuntu-22.04-arm
|
runs-on: ubuntu-22.04-arm
|
||||||
name: Jetson Jetpack 6
|
name: Jetson Jetpack 6
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Set up QEMU and Buildx
|
- name: Set up QEMU and Buildx
|
||||||
@ -96,7 +125,7 @@ jobs:
|
|||||||
BASE_IMAGE: nvcr.io/nvidia/tensorrt:23.12-py3-igpu
|
BASE_IMAGE: nvcr.io/nvidia/tensorrt:23.12-py3-igpu
|
||||||
SLIM_BASE: nvcr.io/nvidia/tensorrt:23.12-py3-igpu
|
SLIM_BASE: nvcr.io/nvidia/tensorrt:23.12-py3-igpu
|
||||||
TRT_BASE: nvcr.io/nvidia/tensorrt:23.12-py3-igpu
|
TRT_BASE: nvcr.io/nvidia/tensorrt:23.12-py3-igpu
|
||||||
uses: docker/bake-action@v7
|
uses: docker/bake-action@v6
|
||||||
with:
|
with:
|
||||||
source: .
|
source: .
|
||||||
push: true
|
push: true
|
||||||
@ -113,7 +142,7 @@ jobs:
|
|||||||
- amd64_build
|
- amd64_build
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Set up QEMU and Buildx
|
- name: Set up QEMU and Buildx
|
||||||
@ -124,7 +153,7 @@ jobs:
|
|||||||
- name: Build and push TensorRT (x86 GPU)
|
- name: Build and push TensorRT (x86 GPU)
|
||||||
env:
|
env:
|
||||||
COMPUTE_LEVEL: "50 60 70 80 90"
|
COMPUTE_LEVEL: "50 60 70 80 90"
|
||||||
uses: docker/bake-action@v7
|
uses: docker/bake-action@v6
|
||||||
with:
|
with:
|
||||||
source: .
|
source: .
|
||||||
push: true
|
push: true
|
||||||
@ -132,12 +161,13 @@ jobs:
|
|||||||
files: docker/tensorrt/trt.hcl
|
files: docker/tensorrt/trt.hcl
|
||||||
set: |
|
set: |
|
||||||
tensorrt.tags=${{ steps.setup.outputs.image-name }}-tensorrt
|
tensorrt.tags=${{ steps.setup.outputs.image-name }}-tensorrt
|
||||||
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-tensorrt
|
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-amd64
|
||||||
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-tensorrt,mode=max
|
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-amd64,mode=max
|
||||||
- name: AMD/ROCm general build
|
- name: AMD/ROCm general build
|
||||||
env:
|
env:
|
||||||
|
AMDGPU: gfx
|
||||||
HSA_OVERRIDE: 0
|
HSA_OVERRIDE: 0
|
||||||
uses: docker/bake-action@v7
|
uses: docker/bake-action@v6
|
||||||
with:
|
with:
|
||||||
source: .
|
source: .
|
||||||
push: true
|
push: true
|
||||||
@ -146,7 +176,7 @@ jobs:
|
|||||||
set: |
|
set: |
|
||||||
rocm.tags=${{ steps.setup.outputs.image-name }}-rocm
|
rocm.tags=${{ steps.setup.outputs.image-name }}-rocm
|
||||||
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-rocm,mode=max
|
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-rocm,mode=max
|
||||||
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-rocm
|
*.cache-from=type=gha
|
||||||
arm64_extra_builds:
|
arm64_extra_builds:
|
||||||
runs-on: ubuntu-22.04-arm
|
runs-on: ubuntu-22.04-arm
|
||||||
name: ARM Extra Build
|
name: ARM Extra Build
|
||||||
@ -154,7 +184,7 @@ jobs:
|
|||||||
- arm64_build
|
- arm64_build
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Set up QEMU and Buildx
|
- name: Set up QEMU and Buildx
|
||||||
@ -163,7 +193,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Build and push Rockchip build
|
- name: Build and push Rockchip build
|
||||||
uses: docker/bake-action@v7
|
uses: docker/bake-action@v6
|
||||||
with:
|
with:
|
||||||
source: .
|
source: .
|
||||||
push: true
|
push: true
|
||||||
@ -172,31 +202,6 @@ jobs:
|
|||||||
set: |
|
set: |
|
||||||
rk.tags=${{ steps.setup.outputs.image-name }}-rk
|
rk.tags=${{ steps.setup.outputs.image-name }}-rk
|
||||||
*.cache-from=type=gha
|
*.cache-from=type=gha
|
||||||
synaptics_build:
|
|
||||||
runs-on: ubuntu-22.04-arm
|
|
||||||
name: Synaptics Build
|
|
||||||
needs:
|
|
||||||
- arm64_build
|
|
||||||
steps:
|
|
||||||
- name: Check out code
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
- name: Set up QEMU and Buildx
|
|
||||||
id: setup
|
|
||||||
uses: ./.github/actions/setup
|
|
||||||
with:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Build and push Synaptics build
|
|
||||||
uses: docker/bake-action@v7
|
|
||||||
with:
|
|
||||||
source: .
|
|
||||||
push: true
|
|
||||||
targets: synaptics
|
|
||||||
files: docker/synaptics/synaptics.hcl
|
|
||||||
set: |
|
|
||||||
synaptics.tags=${{ steps.setup.outputs.image-name }}-synaptics
|
|
||||||
*.cache-from=type=gha
|
|
||||||
# The majority of users running arm64 are rpi users, so the rpi
|
# The majority of users running arm64 are rpi users, so the rpi
|
||||||
# build should be the primary arm64 image
|
# build should be the primary arm64 image
|
||||||
assemble_default_build:
|
assemble_default_build:
|
||||||
@ -211,7 +216,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
string: ${{ github.repository }}
|
string: ${{ github.repository }}
|
||||||
- name: Log in to the Container registry
|
- name: Log in to the Container registry
|
||||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1
|
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
|
|||||||
120
.github/workflows/pr_template_check.yml
vendored
120
.github/workflows/pr_template_check.yml
vendored
@ -1,120 +0,0 @@
|
|||||||
name: PR template check
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened, edited]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check_template:
|
|
||||||
name: Validate PR description
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Check PR description against template
|
|
||||||
uses: actions/github-script@v9
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const maintainers = ['blakeblackshear', 'NickM-27', 'hawkeye217', 'dependabot[bot]', 'weblate'];
|
|
||||||
const author = context.payload.pull_request.user.login;
|
|
||||||
|
|
||||||
if (maintainers.includes(author)) {
|
|
||||||
console.log(`Skipping template check for maintainer: ${author}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = context.payload.pull_request.body || '';
|
|
||||||
const errors = [];
|
|
||||||
|
|
||||||
// Check that key template sections exist
|
|
||||||
const requiredSections = [
|
|
||||||
'## Proposed change',
|
|
||||||
'## Type of change',
|
|
||||||
'## AI disclosure',
|
|
||||||
'## Checklist',
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const section of requiredSections) {
|
|
||||||
if (!body.includes(section)) {
|
|
||||||
errors.push(`Missing section: **${section}**`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that "Proposed change" has content beyond the default HTML comment
|
|
||||||
const proposedChangeMatch = body.match(
|
|
||||||
/## Proposed change\s*(?:<!--[\s\S]*?-->\s*)?([\s\S]*?)(?=\n## )/
|
|
||||||
);
|
|
||||||
const proposedContent = proposedChangeMatch
|
|
||||||
? proposedChangeMatch[1].trim()
|
|
||||||
: '';
|
|
||||||
if (!proposedContent) {
|
|
||||||
errors.push(
|
|
||||||
'The **Proposed change** section is empty. Please describe what this PR does.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that at least one "Type of change" checkbox is checked
|
|
||||||
const typeSection = body.match(
|
|
||||||
/## Type of change\s*([\s\S]*?)(?=\n## )/
|
|
||||||
);
|
|
||||||
if (typeSection && !/- \[x\]/i.test(typeSection[1])) {
|
|
||||||
errors.push(
|
|
||||||
'No **Type of change** selected. Please check at least one option.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that at least one AI disclosure checkbox is checked
|
|
||||||
const aiSection = body.match(
|
|
||||||
/## AI disclosure\s*([\s\S]*?)(?=\n## )/
|
|
||||||
);
|
|
||||||
if (aiSection && !/- \[x\]/i.test(aiSection[1])) {
|
|
||||||
errors.push(
|
|
||||||
'No **AI disclosure** option selected. Please indicate whether AI tools were used.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that at least one checklist item is checked
|
|
||||||
const checklistSection = body.match(
|
|
||||||
/## Checklist\s*([\s\S]*?)$/
|
|
||||||
);
|
|
||||||
if (checklistSection && !/- \[x\]/i.test(checklistSection[1])) {
|
|
||||||
errors.push(
|
|
||||||
'No **Checklist** items checked. Please review and check the items that apply.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errors.length === 0) {
|
|
||||||
console.log('PR description passes template validation.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const prNumber = context.payload.pull_request.number;
|
|
||||||
const message = [
|
|
||||||
'## PR template validation failed',
|
|
||||||
'',
|
|
||||||
'This PR was automatically closed because the description does not follow the [pull request template](https://github.com/blakeblackshear/frigate/blob/dev/.github/pull_request_template.md).',
|
|
||||||
'',
|
|
||||||
'**Issues found:**',
|
|
||||||
...errors.map((e) => `- ${e}`),
|
|
||||||
'',
|
|
||||||
'Please update your PR description to include all required sections from the template, then reopen this PR.',
|
|
||||||
'',
|
|
||||||
'> If you used an AI tool to generate this PR, please see our [contributing guidelines](https://github.com/blakeblackshear/frigate/blob/dev/CONTRIBUTING.md) for details.',
|
|
||||||
].join('\n');
|
|
||||||
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: prNumber,
|
|
||||||
body: message,
|
|
||||||
});
|
|
||||||
|
|
||||||
await github.rest.pulls.update({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
pull_number: prNumber,
|
|
||||||
state: 'closed',
|
|
||||||
});
|
|
||||||
|
|
||||||
core.setFailed('PR description does not follow the template.');
|
|
||||||
105
.github/workflows/pull_request.yml
vendored
105
.github/workflows/pull_request.yml
vendored
@ -4,41 +4,62 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- "docs/**"
|
- "docs/**"
|
||||||
- ".github/*.yml"
|
- ".github/**"
|
||||||
- ".github/DISCUSSION_TEMPLATE/**"
|
|
||||||
- ".github/ISSUE_TEMPLATE/**"
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DEFAULT_PYTHON: 3.11
|
DEFAULT_PYTHON: 3.11
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
build_devcontainer:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Build Devcontainer
|
||||||
|
# The Dockerfile contains features that requires buildkit, and since the
|
||||||
|
# devcontainer cli uses docker-compose to build the image, the only way to
|
||||||
|
# ensure docker-compose uses buildkit is to explicitly enable it.
|
||||||
|
env:
|
||||||
|
DOCKER_BUILDKIT: "1"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- uses: actions/setup-node@master
|
||||||
|
with:
|
||||||
|
node-version: 20.x
|
||||||
|
- name: Install devcontainer cli
|
||||||
|
run: npm install --global @devcontainers/cli
|
||||||
|
- name: Build devcontainer
|
||||||
|
run: devcontainer build --workspace-folder .
|
||||||
|
# It would be nice to also test the following commands, but for some
|
||||||
|
# reason they don't work even though in VS Code devcontainer works.
|
||||||
|
# - name: Start devcontainer
|
||||||
|
# run: devcontainer up --workspace-folder .
|
||||||
|
# - name: Run devcontainer scripts
|
||||||
|
# run: devcontainer run-user-commands --workspace-folder .
|
||||||
|
|
||||||
web_lint:
|
web_lint:
|
||||||
name: Web - Lint
|
name: Web - Lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@master
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version: 16.x
|
||||||
- run: npm install
|
- run: npm install
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: npm run lint
|
run: npm run lint
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
- name: Check i18n keys
|
|
||||||
run: npm run i18n:extract:ci
|
|
||||||
working-directory: ./web
|
|
||||||
|
|
||||||
web_test:
|
web_test:
|
||||||
name: Web - Test
|
name: Web - Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@master
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version: 20.x
|
||||||
- run: npm install
|
- run: npm install
|
||||||
@ -50,43 +71,12 @@ jobs:
|
|||||||
# run: npm run test
|
# run: npm run test
|
||||||
# working-directory: ./web
|
# working-directory: ./web
|
||||||
|
|
||||||
web_e2e:
|
|
||||||
name: Web - E2E Tests
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
- uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: 20.x
|
|
||||||
- run: npm install
|
|
||||||
working-directory: ./web
|
|
||||||
- name: Install Playwright Chromium
|
|
||||||
run: npx playwright install chromium --with-deps
|
|
||||||
working-directory: ./web
|
|
||||||
- name: Build web for E2E
|
|
||||||
run: npm run e2e:build
|
|
||||||
working-directory: ./web
|
|
||||||
- name: Run E2E tests
|
|
||||||
run: npm run e2e
|
|
||||||
working-directory: ./web
|
|
||||||
- name: Upload test artifacts
|
|
||||||
uses: actions/upload-artifact@v7
|
|
||||||
if: failure()
|
|
||||||
with:
|
|
||||||
name: playwright-report
|
|
||||||
path: |
|
|
||||||
web/test-results/
|
|
||||||
web/playwright-report/
|
|
||||||
retention-days: 7
|
|
||||||
|
|
||||||
python_checks:
|
python_checks:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
name: Python Checks
|
name: Python Checks
|
||||||
steps:
|
steps:
|
||||||
- name: Check out the repository
|
- name: Check out the repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||||
@ -109,23 +99,16 @@ jobs:
|
|||||||
name: Python Tests
|
name: Python Tests
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- uses: actions/setup-node@v6
|
- name: Set up QEMU
|
||||||
with:
|
uses: docker/setup-qemu-action@v3
|
||||||
node-version: 20.x
|
- name: Set up Docker Buildx
|
||||||
- name: Install devcontainer cli
|
uses: docker/setup-buildx-action@v3
|
||||||
run: npm install --global @devcontainers/cli
|
- name: Build
|
||||||
- name: Build devcontainer
|
run: make
|
||||||
env:
|
- name: Run mypy
|
||||||
DOCKER_BUILDKIT: "1"
|
run: docker run --rm --entrypoint=python3 frigate:latest -u -m mypy --config-file frigate/mypy.ini frigate
|
||||||
run: devcontainer build --workspace-folder .
|
- name: Run tests
|
||||||
- name: Start devcontainer
|
run: docker run --rm --entrypoint=python3 frigate:latest -u -m unittest
|
||||||
run: devcontainer up --workspace-folder .
|
|
||||||
- name: Run mypy in devcontainer
|
|
||||||
run: devcontainer exec --workspace-folder . bash -lc "python3 -u -m mypy --config-file frigate/mypy.ini frigate"
|
|
||||||
- name: Check API spec is up to date
|
|
||||||
run: devcontainer exec --workspace-folder . bash -lc "python3 generate_api_auth_spec.py --check"
|
|
||||||
- name: Run unit tests in devcontainer
|
|
||||||
run: devcontainer exec --workspace-folder . bash -lc "python3 -u -m unittest"
|
|
||||||
|
|||||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- id: lowercaseRepo
|
- id: lowercaseRepo
|
||||||
@ -18,7 +18,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
string: ${{ github.repository }}
|
string: ${{ github.repository }}
|
||||||
- name: Log in to the Container registry
|
- name: Log in to the Container registry
|
||||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1
|
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
@ -39,14 +39,14 @@ jobs:
|
|||||||
STABLE_TAG=${BASE}:stable
|
STABLE_TAG=${BASE}:stable
|
||||||
PULL_TAG=${BASE}:${BUILD_TAG}
|
PULL_TAG=${BASE}:${BUILD_TAG}
|
||||||
docker run --rm -v $HOME/.docker/config.json:/config.json quay.io/skopeo/stable:latest copy --authfile /config.json --multi-arch all docker://${PULL_TAG} docker://${VERSION_TAG}
|
docker run --rm -v $HOME/.docker/config.json:/config.json quay.io/skopeo/stable:latest copy --authfile /config.json --multi-arch all docker://${PULL_TAG} docker://${VERSION_TAG}
|
||||||
for variant in standard-arm64 tensorrt tensorrt-jp6 rk rocm synaptics; do
|
for variant in standard-arm64 tensorrt tensorrt-jp5 tensorrt-jp6 rk h8l rocm; do
|
||||||
docker run --rm -v $HOME/.docker/config.json:/config.json quay.io/skopeo/stable:latest copy --authfile /config.json --multi-arch all docker://${PULL_TAG}-${variant} docker://${VERSION_TAG}-${variant}
|
docker run --rm -v $HOME/.docker/config.json:/config.json quay.io/skopeo/stable:latest copy --authfile /config.json --multi-arch all docker://${PULL_TAG}-${variant} docker://${VERSION_TAG}-${variant}
|
||||||
done
|
done
|
||||||
|
|
||||||
# stable tag
|
# stable tag
|
||||||
if [[ "${BUILD_TYPE}" == "stable" ]]; then
|
if [[ "${BUILD_TYPE}" == "stable" ]]; then
|
||||||
docker run --rm -v $HOME/.docker/config.json:/config.json quay.io/skopeo/stable:latest copy --authfile /config.json --multi-arch all docker://${PULL_TAG} docker://${STABLE_TAG}
|
docker run --rm -v $HOME/.docker/config.json:/config.json quay.io/skopeo/stable:latest copy --authfile /config.json --multi-arch all docker://${PULL_TAG} docker://${STABLE_TAG}
|
||||||
for variant in standard-arm64 tensorrt tensorrt-jp6 rk rocm synaptics; do
|
for variant in standard-arm64 tensorrt tensorrt-jp5 tensorrt-jp6 rk h8l rocm; do
|
||||||
docker run --rm -v $HOME/.docker/config.json:/config.json quay.io/skopeo/stable:latest copy --authfile /config.json --multi-arch all docker://${PULL_TAG}-${variant} docker://${STABLE_TAG}-${variant}
|
docker run --rm -v $HOME/.docker/config.json:/config.json quay.io/skopeo/stable:latest copy --authfile /config.json --multi-arch all docker://${PULL_TAG}-${variant} docker://${STABLE_TAG}-${variant}
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|||||||
6
.github/workflows/stale.yml
vendored
6
.github/workflows/stale.yml
vendored
@ -18,9 +18,9 @@ jobs:
|
|||||||
close-issue-message: ""
|
close-issue-message: ""
|
||||||
days-before-stale: 30
|
days-before-stale: 30
|
||||||
days-before-close: 3
|
days-before-close: 3
|
||||||
exempt-draft-pr: false
|
exempt-draft-pr: true
|
||||||
exempt-issue-labels: "planned,security"
|
exempt-issue-labels: "pinned,security"
|
||||||
exempt-pr-labels: "planned,security,dependencies"
|
exempt-pr-labels: "pinned,security,dependencies"
|
||||||
operations-per-run: 120
|
operations-per-run: 120
|
||||||
- name: Print outputs
|
- name: Print outputs
|
||||||
env:
|
env:
|
||||||
|
|||||||
9
.gitignore
vendored
9
.gitignore
vendored
@ -3,8 +3,6 @@ __pycache__
|
|||||||
.mypy_cache
|
.mypy_cache
|
||||||
*.swp
|
*.swp
|
||||||
debug
|
debug
|
||||||
.claude/*
|
|
||||||
.mcp.json
|
|
||||||
.vscode/*
|
.vscode/*
|
||||||
!.vscode/launch.json
|
!.vscode/launch.json
|
||||||
config/*
|
config/*
|
||||||
@ -12,19 +10,12 @@ config/*
|
|||||||
models
|
models
|
||||||
*.mp4
|
*.mp4
|
||||||
*.db
|
*.db
|
||||||
*.db-*
|
|
||||||
*.csv
|
*.csv
|
||||||
frigate/version.py
|
frigate/version.py
|
||||||
web/build
|
web/build
|
||||||
web/node_modules
|
web/node_modules
|
||||||
web/coverage
|
web/coverage
|
||||||
web/.env
|
|
||||||
core
|
core
|
||||||
!/web/**/*.ts
|
!/web/**/*.ts
|
||||||
.idea/*
|
.idea/*
|
||||||
.ipynb_checkpoints
|
.ipynb_checkpoints
|
||||||
|
|
||||||
# Auto-generated Docker Compose Generator config files
|
|
||||||
docs/src/components/DockerComposeGenerator/config/devices.ts
|
|
||||||
docs/src/components/DockerComposeGenerator/config/hardware.ts
|
|
||||||
docs/src/components/DockerComposeGenerator/config/ports.ts
|
|
||||||
|
|||||||
17
.vscode/launch.json
vendored
17
.vscode/launch.json
vendored
@ -6,23 +6,6 @@
|
|||||||
"type": "debugpy",
|
"type": "debugpy",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"module": "frigate"
|
"module": "frigate"
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "editor-browser",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "Vite: Launch in integrated browser",
|
|
||||||
"url": "http://localhost:5173"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "editor-browser",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "Nginx: Launch in integrated browser",
|
|
||||||
"url": "http://localhost:5000"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "editor-browser",
|
|
||||||
"request": "attach",
|
|
||||||
"name": "Attach to integrated browser"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
450
AGENTS.md
450
AGENTS.md
@ -1,450 +0,0 @@
|
|||||||
# Agent Instructions for Frigate NVR
|
|
||||||
|
|
||||||
This document provides coding guidelines and best practices for contributing to Frigate NVR, a complete and local NVR designed for Home Assistant with AI object detection.
|
|
||||||
|
|
||||||
## Project Overview
|
|
||||||
|
|
||||||
Frigate NVR is a realtime object detection system for IP cameras that uses:
|
|
||||||
|
|
||||||
- **Backend**: Python 3.13+ with FastAPI, OpenCV, TensorFlow/ONNX
|
|
||||||
- **Frontend**: React with TypeScript, Vite, TailwindCSS
|
|
||||||
- **Architecture**: Multiprocessing design with ZMQ and MQTT communication
|
|
||||||
- **Focus**: Minimal resource usage with maximum performance
|
|
||||||
|
|
||||||
## Code Review Guidelines
|
|
||||||
|
|
||||||
When reviewing code, do NOT comment on:
|
|
||||||
|
|
||||||
- Missing imports - Static analysis tooling catches these
|
|
||||||
- Code formatting - Ruff (Python) and Prettier (TypeScript/React) handle formatting
|
|
||||||
- Minor style inconsistencies already enforced by linters
|
|
||||||
|
|
||||||
## Python Backend Standards
|
|
||||||
|
|
||||||
### Python Requirements
|
|
||||||
|
|
||||||
- **Compatibility**: Python 3.13+
|
|
||||||
- **Language Features**: Use modern Python features:
|
|
||||||
- Pattern matching
|
|
||||||
- Type hints (comprehensive typing preferred)
|
|
||||||
- f-strings (preferred over `%` or `.format()`)
|
|
||||||
- Dataclasses
|
|
||||||
- Async/await patterns
|
|
||||||
|
|
||||||
### Code Quality Standards
|
|
||||||
|
|
||||||
- **Formatting**: Ruff (configured in `pyproject.toml`)
|
|
||||||
- **Linting**: Ruff with rules defined in project config
|
|
||||||
- **Type Checking**: Use type hints consistently
|
|
||||||
- **Testing**: unittest framework - use `python3 -u -m unittest` to run tests
|
|
||||||
- **Language**: American English for all code, comments, and documentation
|
|
||||||
- **Punctuation**: Do not use em dashes in documentation, comments, or strings; reword with standard punctuation (commas, colons, parentheses, or separate sentences)
|
|
||||||
|
|
||||||
### Logging Standards
|
|
||||||
|
|
||||||
- **Logger Pattern**: Use module-level logger
|
|
||||||
|
|
||||||
```python
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Format Guidelines**:
|
|
||||||
- No periods at end of log messages
|
|
||||||
- No sensitive data (keys, tokens, passwords)
|
|
||||||
- Use lazy logging: `logger.debug("Message with %s", variable)`
|
|
||||||
- **Log Levels**:
|
|
||||||
- `debug`: Development and troubleshooting information
|
|
||||||
- `info`: Important runtime events (startup, shutdown, state changes)
|
|
||||||
- `warning`: Recoverable issues that should be addressed
|
|
||||||
- `error`: Errors that affect functionality but don't crash the app
|
|
||||||
- `exception`: Use in except blocks to include traceback
|
|
||||||
|
|
||||||
### Error Handling
|
|
||||||
|
|
||||||
- **Exception Types**: Choose most specific exception available
|
|
||||||
- **Try/Catch Best Practices**:
|
|
||||||
- Only wrap code that can throw exceptions
|
|
||||||
- Keep try blocks minimal - process data after the try/except
|
|
||||||
- Avoid bare exceptions except in background tasks
|
|
||||||
|
|
||||||
Bad pattern:
|
|
||||||
|
|
||||||
```python
|
|
||||||
try:
|
|
||||||
data = await device.get_data() # Can throw
|
|
||||||
# ❌ Don't process data inside try block
|
|
||||||
processed = data.get("value", 0) * 100
|
|
||||||
result = processed
|
|
||||||
except DeviceError:
|
|
||||||
logger.error("Failed to get data")
|
|
||||||
```
|
|
||||||
|
|
||||||
Good pattern:
|
|
||||||
|
|
||||||
```python
|
|
||||||
try:
|
|
||||||
data = await device.get_data() # Can throw
|
|
||||||
except DeviceError:
|
|
||||||
logger.error("Failed to get data")
|
|
||||||
return
|
|
||||||
|
|
||||||
# ✅ Process data outside try block
|
|
||||||
processed = data.get("value", 0) * 100
|
|
||||||
result = processed
|
|
||||||
```
|
|
||||||
|
|
||||||
### Async Programming
|
|
||||||
|
|
||||||
- **External I/O**: All external I/O operations must be async
|
|
||||||
- **Best Practices**:
|
|
||||||
- Avoid sleeping in loops - use `asyncio.sleep()` not `time.sleep()`
|
|
||||||
- Avoid awaiting in loops - use `asyncio.gather()` instead
|
|
||||||
- No blocking calls in async functions
|
|
||||||
- Use `asyncio.create_task()` for background operations
|
|
||||||
- **Thread Safety**: Use proper synchronization for shared state
|
|
||||||
|
|
||||||
### Documentation Standards
|
|
||||||
|
|
||||||
- **Module Docstrings**: Concise descriptions at top of files
|
|
||||||
```python
|
|
||||||
"""Utilities for motion detection and analysis."""
|
|
||||||
```
|
|
||||||
- **Function Docstrings**: Required for public functions and methods
|
|
||||||
|
|
||||||
```python
|
|
||||||
async def process_frame(frame: ndarray, config: Config) -> Detection:
|
|
||||||
"""Process a video frame for object detection.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
frame: The video frame as numpy array
|
|
||||||
config: Detection configuration
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Detection results with bounding boxes
|
|
||||||
"""
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Comment Style**:
|
|
||||||
- Explain the "why" not just the "what"
|
|
||||||
- Keep lines under 88 characters when possible
|
|
||||||
- Use clear, descriptive comments
|
|
||||||
|
|
||||||
### File Organization
|
|
||||||
|
|
||||||
- **API Endpoints**: `frigate/api/` - FastAPI route handlers
|
|
||||||
- **Configuration**: `frigate/config/` - Configuration parsing and validation
|
|
||||||
- **Detectors**: `frigate/detectors/` - Object detection backends
|
|
||||||
- **Events**: `frigate/events/` - Event management and storage
|
|
||||||
- **Utilities**: `frigate/util/` - Shared utility functions
|
|
||||||
|
|
||||||
## Frontend (React/TypeScript) Standards
|
|
||||||
|
|
||||||
### Internationalization (i18n)
|
|
||||||
|
|
||||||
- **CRITICAL**: Never write user-facing strings directly in components
|
|
||||||
- **Always use react-i18next**: Import and use the `t()` function
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
function MyComponent() {
|
|
||||||
const { t } = useTranslation(["views/live"]);
|
|
||||||
return <div>{t("camera_not_found")}</div>;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Translation Files**: Add English strings to the appropriate json files in `web/public/locales/en`
|
|
||||||
- **Namespaces**: Organize translations by feature/view (e.g., `views/live`, `common`, `views/system`)
|
|
||||||
|
|
||||||
### Code Quality
|
|
||||||
|
|
||||||
- **Linting**: ESLint (see `web/.eslintrc.cjs`)
|
|
||||||
- **Formatting**: Prettier with Tailwind CSS plugin
|
|
||||||
- **Type Safety**: TypeScript strict mode enabled
|
|
||||||
|
|
||||||
### Component Patterns
|
|
||||||
|
|
||||||
- **UI Components**: Use Radix UI primitives (in `web/src/components/ui/`)
|
|
||||||
- **Styling**: TailwindCSS with `cn()` utility for class merging
|
|
||||||
- **State Management**: React hooks (useState, useEffect, useCallback, useMemo)
|
|
||||||
- **Data Fetching**: Custom hooks with proper loading and error states
|
|
||||||
|
|
||||||
### ESLint Rules
|
|
||||||
|
|
||||||
Key rules enforced:
|
|
||||||
|
|
||||||
- `react-hooks/rules-of-hooks`: error
|
|
||||||
- `react-hooks/exhaustive-deps`: error
|
|
||||||
- `no-console`: error (use proper logging or remove)
|
|
||||||
- `@typescript-eslint/no-explicit-any`: warn (always use proper types instead of `any`)
|
|
||||||
- Unused variables must be prefixed with `_`
|
|
||||||
- Comma dangles required for multiline objects/arrays
|
|
||||||
|
|
||||||
### File Organization
|
|
||||||
|
|
||||||
- **Pages**: `web/src/pages/` - Route components
|
|
||||||
- **Views**: `web/src/views/` - Complex view components
|
|
||||||
- **Components**: `web/src/components/` - Reusable components
|
|
||||||
- **Hooks**: `web/src/hooks/` - Custom React hooks
|
|
||||||
- **API**: `web/src/api/` - API client functions
|
|
||||||
- **Types**: `web/src/types/` - TypeScript type definitions
|
|
||||||
|
|
||||||
## Testing Requirements
|
|
||||||
|
|
||||||
### Backend Testing
|
|
||||||
|
|
||||||
- **Framework**: Python unittest
|
|
||||||
- **Run Command**: `python3 -u -m unittest`
|
|
||||||
- **Location**: `frigate/test/`
|
|
||||||
- **Coverage**: Aim for comprehensive test coverage of core functionality
|
|
||||||
- **Pattern**: Use `TestCase` classes with descriptive test method names
|
|
||||||
```python
|
|
||||||
class TestMotionDetection(unittest.TestCase):
|
|
||||||
def test_detects_motion_above_threshold(self):
|
|
||||||
# Test implementation
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Best Practices
|
|
||||||
|
|
||||||
- Always have a way to test your work and confirm your changes
|
|
||||||
- Write tests for bug fixes to prevent regressions
|
|
||||||
- Test edge cases and error conditions
|
|
||||||
- Mock external dependencies (cameras, APIs, hardware)
|
|
||||||
- Use fixtures for test data
|
|
||||||
|
|
||||||
## Development Commands
|
|
||||||
|
|
||||||
### Python Backend
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run all tests
|
|
||||||
python3 -u -m unittest
|
|
||||||
|
|
||||||
# Run specific test file
|
|
||||||
python3 -u -m unittest frigate.test.test_ffmpeg_presets
|
|
||||||
|
|
||||||
# Check formatting (Ruff)
|
|
||||||
ruff format --check frigate/
|
|
||||||
|
|
||||||
# Apply formatting
|
|
||||||
ruff format frigate/
|
|
||||||
|
|
||||||
# Run linter
|
|
||||||
ruff check frigate/
|
|
||||||
|
|
||||||
# Type check
|
|
||||||
python3 -u -m mypy --config-file frigate/mypy.ini frigate
|
|
||||||
|
|
||||||
# Regenerate the OpenAPI spec after adding, changing, or removing an API
|
|
||||||
# endpoint or its auth dependency — outputs docs/static/frigate-api.yaml,
|
|
||||||
# annotated with each endpoint's auth requirement (admin / any / camera /
|
|
||||||
# public). NEVER edit that file by hand. CI runs the --check variant and fails
|
|
||||||
# if it is out of date. (from repo root)
|
|
||||||
python3 generate_api_auth_spec.py
|
|
||||||
python3 generate_api_auth_spec.py --check
|
|
||||||
```
|
|
||||||
|
|
||||||
### Frontend (from web/ directory)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Start dev server (AI agents should never run this directly unless asked)
|
|
||||||
npm run dev
|
|
||||||
|
|
||||||
# Build for production
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
# Run linter
|
|
||||||
npm run lint
|
|
||||||
|
|
||||||
# Fix linting issues
|
|
||||||
npm run lint:fix
|
|
||||||
|
|
||||||
# Format code
|
|
||||||
npm run prettier:write
|
|
||||||
|
|
||||||
# E2E: first-time setup
|
|
||||||
npm install
|
|
||||||
npx playwright install chromium
|
|
||||||
|
|
||||||
# E2E: build the app and run all tests
|
|
||||||
npm run e2e:build && npm run e2e
|
|
||||||
|
|
||||||
# E2E: interactive UI for debugging
|
|
||||||
npm run e2e:ui
|
|
||||||
|
|
||||||
# E2E: run a specific spec
|
|
||||||
npx playwright test --config e2e/playwright.config.ts e2e/specs/live.spec.ts
|
|
||||||
|
|
||||||
# E2E: filter by name, or run only desktop/mobile
|
|
||||||
npx playwright test --config e2e/playwright.config.ts --grep="severity tab"
|
|
||||||
npx playwright test --config e2e/playwright.config.ts --project=desktop
|
|
||||||
|
|
||||||
# E2E: regenerate mock data after backend model changes (from repo root)
|
|
||||||
PYTHONPATH=. python3 web/e2e/fixtures/mock-data/generate-mock-data.py
|
|
||||||
|
|
||||||
# Regenerate config translations from Pydantic models — outputs to
|
|
||||||
# web/public/locales/en/config/{global,cameras}.json. NEVER edit those
|
|
||||||
# JSON files by hand; change the Pydantic field title/description and
|
|
||||||
# re-run this script. (from repo root)
|
|
||||||
python3 generate_config_translations.py
|
|
||||||
|
|
||||||
# Extract i18n keys from source into the locale files after adding
|
|
||||||
# new t() calls. Use the :ci variant to verify the locale files are
|
|
||||||
# in sync with source (fails if extraction would change anything).
|
|
||||||
npm run i18n:extract
|
|
||||||
npm run i18n:extract:ci
|
|
||||||
```
|
|
||||||
|
|
||||||
### Docker Development
|
|
||||||
|
|
||||||
AI agents should never run these commands directly unless instructed.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Build local image
|
|
||||||
make local
|
|
||||||
|
|
||||||
# Build debug image
|
|
||||||
make debug
|
|
||||||
```
|
|
||||||
|
|
||||||
## Common Patterns
|
|
||||||
|
|
||||||
### API Endpoint Pattern
|
|
||||||
|
|
||||||
```python
|
|
||||||
from fastapi import APIRouter, Request
|
|
||||||
from frigate.api.defs.tags import Tags
|
|
||||||
|
|
||||||
router = APIRouter(tags=[Tags.Events])
|
|
||||||
|
|
||||||
@router.get("/events")
|
|
||||||
async def get_events(request: Request, limit: int = 100):
|
|
||||||
"""Retrieve events from the database."""
|
|
||||||
# Implementation
|
|
||||||
```
|
|
||||||
|
|
||||||
After adding, changing, or removing an endpoint (or its auth dependency), regenerate the OpenAPI spec with `python3 generate_api_auth_spec.py` so `docs/static/frigate-api.yaml` stays in sync and the endpoint's auth requirement is documented. CI enforces this via the `--check` variant; never edit that file by hand.
|
|
||||||
|
|
||||||
### Configuration Access
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Access Frigate configuration
|
|
||||||
config: FrigateConfig = request.app.frigate_config
|
|
||||||
camera_config = config.cameras["front_door"]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Database Queries
|
|
||||||
|
|
||||||
```python
|
|
||||||
from frigate.models import Event
|
|
||||||
|
|
||||||
# Use Peewee ORM for database access
|
|
||||||
events = (
|
|
||||||
Event.select()
|
|
||||||
.where(Event.camera == camera_name)
|
|
||||||
.order_by(Event.start_time.desc())
|
|
||||||
.limit(limit)
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Common Anti-Patterns to Avoid
|
|
||||||
|
|
||||||
### ❌ Avoid These
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Blocking operations in async functions
|
|
||||||
data = requests.get(url) # ❌ Use async HTTP client
|
|
||||||
time.sleep(5) # ❌ Use asyncio.sleep()
|
|
||||||
|
|
||||||
# Hardcoded strings in React components
|
|
||||||
<div>Camera not found</div> # ❌ Use t("camera_not_found")
|
|
||||||
|
|
||||||
# Missing error handling
|
|
||||||
data = await api.get_data() # ❌ No exception handling
|
|
||||||
|
|
||||||
# Bare exceptions in regular code
|
|
||||||
try:
|
|
||||||
value = await sensor.read()
|
|
||||||
except Exception: # ❌ Too broad
|
|
||||||
logger.error("Failed")
|
|
||||||
|
|
||||||
# Returning exceptions in JSON responses
|
|
||||||
except ValueError as e:
|
|
||||||
return JSONResponse(
|
|
||||||
content={"success": False, "message": str(e)},
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### ✅ Use These Instead
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Async operations
|
|
||||||
import aiohttp
|
|
||||||
async with aiohttp.ClientSession() as session:
|
|
||||||
async with session.get(url) as response:
|
|
||||||
data = await response.json()
|
|
||||||
|
|
||||||
await asyncio.sleep(5) # ✅ Non-blocking
|
|
||||||
|
|
||||||
# Translatable strings in React
|
|
||||||
const { t } = useTranslation();
|
|
||||||
<div>{t("camera_not_found")}</div> # ✅ Translatable
|
|
||||||
|
|
||||||
# Proper error handling
|
|
||||||
try:
|
|
||||||
data = await api.get_data()
|
|
||||||
except ApiException as err:
|
|
||||||
logger.error("API error: %s", err)
|
|
||||||
raise
|
|
||||||
|
|
||||||
# Specific exceptions
|
|
||||||
try:
|
|
||||||
value = await sensor.read()
|
|
||||||
except SensorException as err: # ✅ Specific
|
|
||||||
logger.exception("Failed to read sensor")
|
|
||||||
|
|
||||||
# Safe error responses
|
|
||||||
except ValueError:
|
|
||||||
logger.exception("Invalid parameters for API request")
|
|
||||||
return JSONResponse(
|
|
||||||
content={
|
|
||||||
"success": False,
|
|
||||||
"message": "Invalid request parameters",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
## WebSocket Broadcasts
|
|
||||||
|
|
||||||
Outbound WebSocket broadcasts go through a per-recipient classifier in `frigate/comms/ws.py` that enforces camera-level access. **The classifier is fail-closed: any topic it doesn't recognize is dropped for every client.** New outbound topics must be classified there or they'll silently disappear.
|
|
||||||
|
|
||||||
## Project-Specific Conventions
|
|
||||||
|
|
||||||
### Configuration Files
|
|
||||||
|
|
||||||
- Main config: `config/config.yml`
|
|
||||||
|
|
||||||
### Directory Structure
|
|
||||||
|
|
||||||
- Backend code: `frigate/`
|
|
||||||
- Frontend code: `web/`
|
|
||||||
- Docker files: `docker/`
|
|
||||||
- Documentation: `docs/`
|
|
||||||
- Database migrations: `migrations/`
|
|
||||||
|
|
||||||
### Code Style Conformance
|
|
||||||
|
|
||||||
Always conform new and refactored code to the existing coding style in the project:
|
|
||||||
|
|
||||||
- Follow established patterns in similar files
|
|
||||||
- Match indentation and formatting of surrounding code
|
|
||||||
- Use consistent naming conventions (snake_case for Python, camelCase for TypeScript)
|
|
||||||
- Maintain the same level of verbosity in comments and docstrings
|
|
||||||
|
|
||||||
## Additional Resources
|
|
||||||
|
|
||||||
- Documentation: https://docs.frigate.video
|
|
||||||
- Main Repository: https://github.com/blakeblackshear/frigate
|
|
||||||
- Home Assistant Integration: https://github.com/blakeblackshear/frigate-hass-integration
|
|
||||||
126
AI_POLICY.md
126
AI_POLICY.md
@ -1,126 +0,0 @@
|
|||||||
# Frigate AI Policy
|
|
||||||
|
|
||||||
## TL;DR
|
|
||||||
|
|
||||||
- **Use AI tools if they help you.** We do too. This is about what you post, not which tools you use to write it.
|
|
||||||
- **A person has to read it and send it.** Don't wire a bot or an agent up to post on your behalf.
|
|
||||||
- **Write your posts yourself.** Your own words, the template filled in, and you answering maintainers rather than your assistant.
|
|
||||||
- **Don't paste an AI's guess at the cause as though it were a diagnosis.** Tell us what you actually observed.
|
|
||||||
- **Read your code before you submit it.** Disclose that AI was used, and be ready to explain every line.
|
|
||||||
- **If we misjudge something you wrote, just say so.** We'll take you at your word.
|
|
||||||
|
|
||||||
The rest of this document explains each of these, and why.
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
AI tools are a reality of modern development and we're not opposed to their use. You are responsible for anything you submit, however it was produced, and we are responsible for anything we merge and release. We hold a high bar for both.
|
|
||||||
|
|
||||||
This policy applies everywhere this project is discussed: issues, discussions, pull requests, code reviews, and commit comments.
|
|
||||||
|
|
||||||
## Why this exists
|
|
||||||
|
|
||||||
Frigate is built and supported by a small group of maintainers and a community of volunteers who read every post and review every pull request. Nobody here is paid to do it, and time spent reading a post is time not spent fixing bugs or building features.
|
|
||||||
|
|
||||||
We're not opposed to AI tools. We use them too. But content generated by an AI and submitted without review costs a real person real time, and usually gives them less to work with than a few honest sentences would have. That is the problem this policy addresses.
|
|
||||||
|
|
||||||
## A person has to be in the loop
|
|
||||||
|
|
||||||
Every issue, discussion, comment, and pull request here must be read and submitted by a person. Using an AI tool to help you write is fine. Wiring one up to post on your behalf is not.
|
|
||||||
|
|
||||||
Specifically, do not:
|
|
||||||
|
|
||||||
- Connect a bot or agent to GitHub that opens issues, discussions, or pull requests without you reading them first
|
|
||||||
- Post output from a tool you have not read
|
|
||||||
- Use tooling to file bulk or drive-by contributions across the repository
|
|
||||||
|
|
||||||
We will close anything we believe was posted without a person reading it, and we may mark it as spam. Posts that skip the templates are the most common sign of this.
|
|
||||||
|
|
||||||
## Issues, discussions, and comments
|
|
||||||
|
|
||||||
We do not mind if you use AI tools to help you write. Do not have tools post unreviewed content on your behalf. We may hide any comment we believe to be unreviewed AI output.
|
|
||||||
|
|
||||||
Keep posts to what is needed to communicate your point. A long, confidently written, AI-padded post is harder to help with than a short direct one, not easier, and it is usually obvious.
|
|
||||||
|
|
||||||
**Describe your actual problem in your own words.** Tell us what you did, what you expected, and what actually happened. That is the information we need, and only you have it.
|
|
||||||
|
|
||||||
**Do not paste an AI's guess at the cause as though it were a diagnosis.** It is frequently wrong in ways that send everyone down the wrong path, and it buries the details that would have led to the real answer. We would rather see what you observed than what a model inferred.
|
|
||||||
|
|
||||||
**Fill in the template completely.** The templates ask for logs, config, version, and hardware because those are the things needed to help you. An AI cannot supply them for you, and a post missing them cannot be acted on.
|
|
||||||
|
|
||||||
**Answer maintainers yourself.** If we ask you a question, we are asking _you_, not your AI assistant. These are the spaces where we build trust and understanding with the community, and that only works if we're talking to each other. Using AI to fix your grammar or clarity is fine, but the substance has to be yours.
|
|
||||||
|
|
||||||
This applies to pull request descriptions and review replies as much as it does to bug reports and discussions.
|
|
||||||
|
|
||||||
### Quoting AI output
|
|
||||||
|
|
||||||
If you want to include something an AI told you, it must be:
|
|
||||||
|
|
||||||
- In a quote block, using `>`
|
|
||||||
- Disclosed as AI output, saying which tool it came from
|
|
||||||
- Accompanied by your own comment explaining why you think it is relevant
|
|
||||||
|
|
||||||
Keep the excerpt short. Do not paste long transcripts.
|
|
||||||
|
|
||||||
### Non-native English speakers
|
|
||||||
|
|
||||||
AI is genuinely useful for participating in a project that operates in English, and we would rather hear from you through a translation tool than not hear from you at all. Using AI to improve the grammar or clarity of something you wrote yourself is fine.
|
|
||||||
|
|
||||||
If you are translating your posts, make sure the translation says what you meant. Including your original text in a `<details>` block helps us verify the translation if something reads oddly, and keeps the thread readable.
|
|
||||||
|
|
||||||
## Code contributions
|
|
||||||
|
|
||||||
We need to understand your relationship with the code you're submitting. The more AI was involved, the more important it is that you've genuinely reviewed, tested, and understood what it produced.
|
|
||||||
|
|
||||||
Because of the long-term maintenance burden every merged change creates, we require a human in the loop who understands the work the AI produced. Pull requests that appear to be unreviewed AI output will be closed without review.
|
|
||||||
|
|
||||||
### Requirements when AI is used
|
|
||||||
|
|
||||||
If AI is used to generate any portion of the code, contributors must adhere to the following requirements:
|
|
||||||
|
|
||||||
1. **Explicitly disclose the manner in which AI was employed.** The PR template asks for this. Be honest, this won't automatically disqualify your PR. We'd rather have an honest disclosure than find out later. Trust matters more than method.
|
|
||||||
2. **Perform a comprehensive manual review prior to submitting the pull request.** Don't submit code you haven't read carefully and tested locally.
|
|
||||||
3. **Be prepared to explain every line of code you submitted when asked about it by a maintainer.** If you can't explain why something works the way it does, you're not ready to submit it.
|
|
||||||
4. **Check for an existing pull request addressing the same change.** If one exists, comment there and work with its author instead of opening a duplicate.
|
|
||||||
5. **It is strictly prohibited to use AI to write your posts for you** (bug reports, feature requests, pull request descriptions, GitHub discussions, responding to humans, etc.). We need to hear from _you_, not your AI assistant. These are the spaces where we build trust and understanding with contributors, and that only works if we're talking to each other.
|
|
||||||
|
|
||||||
### Established contributors
|
|
||||||
|
|
||||||
Contributors with a long history of thoughtful, quality contributions to Frigate have earned trust through that track record. The level of scrutiny we apply to AI usage naturally reflects that trust. This isn't a formal exemption, it's just how trust works. If you've been around, we know how you think and how you work. If you're new, we're still getting to know you, and clear disclosure helps build that relationship.
|
|
||||||
|
|
||||||
### What this means in practice
|
|
||||||
|
|
||||||
We're not trying to gatekeep how you write code. Use whatever tools make you productive. But there's a difference between using AI as a tool to implement something you understand and handing a feature request to an AI and submitting whatever comes back. The former is fine. The latter creates maintenance risk for the project.
|
|
||||||
|
|
||||||
Some honest context: when we review a PR, we're not just evaluating whether the code works today. We're evaluating whether we can maintain it, debug it, and extend it long-term, often without the original author's involvement. Code that the author doesn't deeply understand is code that nobody understands, and that's a liability.
|
|
||||||
|
|
||||||
One more thing worth saying directly: most maintainers already have access to the same AI tools you do. A PR that's entirely AI-generated, where the author can't explain the design, debug issues independently, or engage substantively in design discussions, doesn't offer something we couldn't produce ourselves. What makes a contribution genuinely valuable is the human judgment and domain understanding behind it, as well as the engagement during review that shapes it into something we can confidently take on long-term.
|
|
||||||
|
|
||||||
## Our use of AI
|
|
||||||
|
|
||||||
The Frigate documentation site has an "Ask AI" search that answers questions from the docs, and we may use AI tooling to help with triage and project management. Like any automated tooling, it is not always right.
|
|
||||||
|
|
||||||
If an AI tool leaves a comment on your contribution, treat it the way you would any other comment. If you think it is wrong, say so, and a brief explanation is enough. Maintainers always have the final say.
|
|
||||||
|
|
||||||
## Enforcement
|
|
||||||
|
|
||||||
Contributions and posts that do not follow this policy will be closed. Depending on the situation, maintainers may also:
|
|
||||||
|
|
||||||
- Hide or delete comments that appear to be unreviewed AI output
|
|
||||||
- Mark automated content as spam
|
|
||||||
- Close an issue, discussion, or pull request without further review
|
|
||||||
- Lock a conversation
|
|
||||||
- Temporarily or permanently block an account from participating in the project
|
|
||||||
|
|
||||||
Repeated violations may result in being blocked from contributing to Frigate.
|
|
||||||
|
|
||||||
### When we get it wrong
|
|
||||||
|
|
||||||
There is no reliable way to detect this, and we're not going to pretend otherwise. Whether something reads as unreviewed AI output is a judgment call, usually made quickly, by a volunteer with limited time and no way to know for certain. These calls are subjective and we won't always get them right.
|
|
||||||
|
|
||||||
If it happens to you, just say so. A short reply telling us you wrote it yourself is enough, and we'll take you at your word and pick the conversation back up. We would much rather occasionally reopen something we misjudged than treat everyone who posts here as a suspect.
|
|
||||||
|
|
||||||
We'd ask for some understanding in return. These calls get made quickly because the volume is real, and time spent second-guessing them is time not spent helping the person in the next thread.
|
|
||||||
|
|
||||||
## Attribution
|
|
||||||
|
|
||||||
Portions of this policy are adapted from the [Open Home Foundation AI Policy](https://developers.home-assistant.io/docs/ai_policy/).
|
|
||||||
135
CONTRIBUTING.md
135
CONTRIBUTING.md
@ -1,135 +0,0 @@
|
|||||||
# Contributing to Frigate
|
|
||||||
|
|
||||||
Thank you for your interest in contributing to Frigate. This document covers the expectations and guidelines for contributions. Please read it before submitting a pull request.
|
|
||||||
|
|
||||||
All participation in this project, including pull requests, issues, and discussions, is covered by our [AI policy](AI_POLICY.md).
|
|
||||||
|
|
||||||
## Before you start
|
|
||||||
|
|
||||||
### Bugfixes
|
|
||||||
|
|
||||||
If you've found a bug and want to fix it, go for it. Link to the relevant issue in your PR if one exists, or describe the bug in the PR description.
|
|
||||||
|
|
||||||
### New features
|
|
||||||
|
|
||||||
A pull request is more than just code — it's a request for the maintainers to review, integrate, and support the change long-term. We're selective about what we take on, and prioritize changes that align with the project's direction and can be responsibly maintained in the long term.
|
|
||||||
|
|
||||||
**Large or highly-requested features** raise the bar even higher. Popularity signals demand, but it doesn't pre-approve any particular implementation. The bigger the change, the higher the long-term cost, and the more important it is that we're aligned on scope and approach before any code is written. A large PR that lands without prior discussion is unlikely to be merged as-is, no matter how well it's implemented.
|
|
||||||
|
|
||||||
Before writing code for a new feature:
|
|
||||||
|
|
||||||
1. **Check for existing discussion.** Search [feature requests](https://github.com/blakeblackshear/frigate/issues) and [discussions](https://github.com/blakeblackshear/frigate/discussions) to see if it's been proposed or discussed. Feature requests tagged with "planned" are on our radar — we plan to get to them, but we don't maintain a public roadmap or timeline. Check in with us first if you have interest in contributing to one.
|
|
||||||
2. **Start a discussion or feature request first.** This helps ensure your idea aligns with Frigate's direction before you invest time building it. Community interest in a feature request helps us gauge demand, though a great idea is a great idea even without a crowd behind it.
|
|
||||||
|
|
||||||
## AI usage policy
|
|
||||||
|
|
||||||
AI tools are a reality of modern development and we're not opposed to their use. But we need to understand your relationship with the code you're submitting, and we need to hear from you rather than from your AI assistant.
|
|
||||||
|
|
||||||
**Read the [AI policy](AI_POLICY.md) before you open a pull request.** It is short, and it applies to everything you post here. The parts that most often catch people out:
|
|
||||||
|
|
||||||
- A person has to be in the loop. Don't wire a bot or agent up to open pull requests, issues, or discussions on your behalf.
|
|
||||||
- Disclose how AI was used. The PR template asks for this. Be honest, it won't automatically disqualify your PR.
|
|
||||||
- Review and test everything you submit, and be prepared to explain every line when asked.
|
|
||||||
- Don't use AI to write your PR description or your replies to maintainers.
|
|
||||||
|
|
||||||
Pull requests that appear to be unreviewed AI output will be closed without review.
|
|
||||||
|
|
||||||
## Pull request guidelines
|
|
||||||
|
|
||||||
### Before submitting
|
|
||||||
|
|
||||||
- **Search for existing PRs** to avoid duplicating effort.
|
|
||||||
- **Test your changes locally.** Your PR cannot be merged unless tests pass.
|
|
||||||
- **Format your code.** Run `ruff format frigate` for Python and `npm run prettier:write` from the `web/` directory for frontend changes.
|
|
||||||
- **Run the linter.** Run `ruff check frigate` for Python and `npm run lint` from `web/` for frontend.
|
|
||||||
- **One concern per PR.** Don't combine unrelated changes. A bugfix and a new feature should be separate PRs.
|
|
||||||
|
|
||||||
### What we look for in review
|
|
||||||
|
|
||||||
- **Does it work?** Tested locally, tests pass, no regressions.
|
|
||||||
- **Is it maintainable?** Clear code, appropriate complexity, good separation of concerns.
|
|
||||||
- **Does it fit?** Consistent with Frigate's architecture and design philosophy.
|
|
||||||
- **Is it scoped well?** Solves the stated problem without unnecessary additions.
|
|
||||||
|
|
||||||
### After submitting
|
|
||||||
|
|
||||||
- Be responsive to review feedback. We may ask for changes.
|
|
||||||
- Expect honest, direct feedback. We try to be respectful but we also try to be efficient.
|
|
||||||
- If your PR goes stale, rebase it on the latest `dev` branch.
|
|
||||||
|
|
||||||
## Coding standards
|
|
||||||
|
|
||||||
### Python (backend)
|
|
||||||
|
|
||||||
- **Python** — use modern language features (type hints, pattern matching, f-strings, dataclasses)
|
|
||||||
- **Formatting**: Ruff (configured in `pyproject.toml`)
|
|
||||||
- **Linting**: Ruff
|
|
||||||
- **Testing**: `python3 -u -m unittest`
|
|
||||||
- **Logging**: Use module-level `logger = logging.getLogger(__name__)` with lazy formatting
|
|
||||||
- **Async**: All external I/O must be async. No blocking calls in async functions.
|
|
||||||
- **Error handling**: Use specific exception types. Keep try blocks minimal.
|
|
||||||
- **Language**: American English for all code, comments, and documentation
|
|
||||||
|
|
||||||
### TypeScript/React (frontend)
|
|
||||||
|
|
||||||
- **Linting**: ESLint (`npm run lint` from `web/`)
|
|
||||||
- **Formatting**: Prettier (`npm run prettier:write` from `web/`)
|
|
||||||
- **Type safety**: TypeScript strict mode. Avoid `any`.
|
|
||||||
- **i18n**: All user-facing strings must use `react-i18next`. Never hardcode display text in components. Add English strings to the appropriate files in `web/public/locales/en/`.
|
|
||||||
- **Components**: Use Radix UI/shadcn primitives and TailwindCSS with the `cn()` utility.
|
|
||||||
|
|
||||||
### Development commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Python
|
|
||||||
python3 -u -m unittest # Run all tests
|
|
||||||
python3 -u -m unittest frigate.test.test_ffmpeg_presets # Run specific test
|
|
||||||
ruff format frigate # Format
|
|
||||||
ruff check frigate # Lint
|
|
||||||
|
|
||||||
# Frontend (from web/ directory)
|
|
||||||
npm run build # Build
|
|
||||||
npm run lint # Lint
|
|
||||||
npm run lint:fix # Lint + fix
|
|
||||||
npm run prettier:write # Format
|
|
||||||
```
|
|
||||||
|
|
||||||
## Project structure
|
|
||||||
|
|
||||||
```
|
|
||||||
frigate/ # Python backend
|
|
||||||
api/ # FastAPI route handlers
|
|
||||||
config/ # Configuration parsing and validation
|
|
||||||
detectors/ # Object detection backends
|
|
||||||
events/ # Event management and storage
|
|
||||||
test/ # Backend tests
|
|
||||||
util/ # Shared utilities
|
|
||||||
web/ # React/TypeScript frontend
|
|
||||||
src/
|
|
||||||
api/ # API client functions
|
|
||||||
components/ # Reusable components
|
|
||||||
hooks/ # Custom React hooks
|
|
||||||
pages/ # Route components
|
|
||||||
types/ # TypeScript type definitions
|
|
||||||
views/ # Complex view components
|
|
||||||
docker/ # Docker build files
|
|
||||||
docs/ # Documentation site
|
|
||||||
migrations/ # Database migrations
|
|
||||||
```
|
|
||||||
|
|
||||||
## Translations
|
|
||||||
|
|
||||||
Frigate uses [Weblate](https://hosted.weblate.org/projects/frigate-nvr/) for managing language translations. If you'd like to help translate Frigate into your language:
|
|
||||||
|
|
||||||
1. Visit the [Frigate project on Weblate](https://hosted.weblate.org/projects/frigate-nvr/).
|
|
||||||
2. Create an account or log in.
|
|
||||||
3. Browse the available languages and select the one you'd like to contribute to, or request a new language.
|
|
||||||
4. Translate strings directly in the Weblate interface — no code changes or pull requests needed.
|
|
||||||
|
|
||||||
Translation contributions through Weblate are automatically synced to the repository. Please do not submit pull requests for translation changes — use Weblate instead so that translations are properly tracked and coordinated.
|
|
||||||
|
|
||||||
## Resources
|
|
||||||
|
|
||||||
- [Documentation](https://docs.frigate.video)
|
|
||||||
- [Discussions, Support, and Bug Reports](https://github.com/blakeblackshear/frigate/discussions)
|
|
||||||
- [Feature Requests](https://github.com/blakeblackshear/frigate/issues)
|
|
||||||
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
|||||||
The MIT License
|
The MIT License
|
||||||
|
|
||||||
Copyright (c) 2026 Frigate, Inc. (Frigate™)
|
Copyright (c) 2020 Blake Blackshear
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
12
Makefile
12
Makefile
@ -1,7 +1,7 @@
|
|||||||
default_target: local
|
default_target: local
|
||||||
|
|
||||||
COMMIT_HASH := $(shell git log -1 --pretty=format:"%h"|tail -1)
|
COMMIT_HASH := $(shell git log -1 --pretty=format:"%h"|tail -1)
|
||||||
VERSION = 0.18.0
|
VERSION = 0.16.0
|
||||||
IMAGE_REPO ?= ghcr.io/blakeblackshear/frigate
|
IMAGE_REPO ?= ghcr.io/blakeblackshear/frigate
|
||||||
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||||
BOARDS= #Initialized empty
|
BOARDS= #Initialized empty
|
||||||
@ -14,19 +14,12 @@ push-boards: $(BOARDS:%=push-%)
|
|||||||
|
|
||||||
version:
|
version:
|
||||||
echo 'VERSION = "$(VERSION)-$(COMMIT_HASH)"' > frigate/version.py
|
echo 'VERSION = "$(VERSION)-$(COMMIT_HASH)"' > frigate/version.py
|
||||||
echo 'VITE_GIT_COMMIT_HASH=$(COMMIT_HASH)' > web/.env
|
|
||||||
|
|
||||||
local: version
|
local: version
|
||||||
docker buildx build --target=frigate --file docker/main/Dockerfile . \
|
docker buildx build --target=frigate --file docker/main/Dockerfile . \
|
||||||
--tag frigate:latest \
|
--tag frigate:latest \
|
||||||
--load
|
--load
|
||||||
|
|
||||||
debug: version
|
|
||||||
docker buildx build --target=frigate --file docker/main/Dockerfile . \
|
|
||||||
--build-arg DEBUG=true \
|
|
||||||
--tag frigate:latest \
|
|
||||||
--load
|
|
||||||
|
|
||||||
amd64:
|
amd64:
|
||||||
docker buildx build --target=frigate --file docker/main/Dockerfile . \
|
docker buildx build --target=frigate --file docker/main/Dockerfile . \
|
||||||
--tag $(IMAGE_REPO):$(VERSION)-$(COMMIT_HASH) \
|
--tag $(IMAGE_REPO):$(VERSION)-$(COMMIT_HASH) \
|
||||||
@ -49,8 +42,7 @@ push: push-boards
|
|||||||
--push
|
--push
|
||||||
|
|
||||||
run: local
|
run: local
|
||||||
docker run --rm --publish=5000:5000 --publish=8971:8971 \
|
docker run --rm --publish=5000:5000 --volume=${PWD}/config:/config frigate:latest
|
||||||
--volume=${PWD}/config:/config frigate:latest
|
|
||||||
|
|
||||||
run_tests: local
|
run_tests: local
|
||||||
docker run --rm --workdir=/opt/frigate --entrypoint= frigate:latest \
|
docker run --rm --workdir=/opt/frigate --entrypoint= frigate:latest \
|
||||||
|
|||||||
23
README.md
23
README.md
@ -1,10 +1,8 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img align="center" alt="logo" src="docs/static/img/branding/frigate.png">
|
<img align="center" alt="logo" src="docs/static/img/frigate.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
# Frigate NVR™ - Realtime Object Detection for IP Cameras
|
# Frigate - NVR With Realtime Object Detection for IP Cameras
|
||||||
|
|
||||||
[](https://opensource.org/licenses/MIT)
|
|
||||||
|
|
||||||
<a href="https://hosted.weblate.org/engage/frigate-nvr/">
|
<a href="https://hosted.weblate.org/engage/frigate-nvr/">
|
||||||
<img src="https://hosted.weblate.org/widget/frigate-nvr/language-badge.svg" alt="Translation status" />
|
<img src="https://hosted.weblate.org/widget/frigate-nvr/language-badge.svg" alt="Translation status" />
|
||||||
@ -14,7 +12,7 @@
|
|||||||
|
|
||||||
A complete and local NVR designed for [Home Assistant](https://www.home-assistant.io) with AI object detection. Uses OpenCV and Tensorflow to perform realtime object detection locally for IP cameras.
|
A complete and local NVR designed for [Home Assistant](https://www.home-assistant.io) with AI object detection. Uses OpenCV and Tensorflow to perform realtime object detection locally for IP cameras.
|
||||||
|
|
||||||
Use of a GPU or AI accelerator is highly recommended. AI accelerators will outperform even the best CPUs with very little overhead. See Frigate's supported [object detectors](https://docs.frigate.video/configuration/object_detectors/).
|
Use of a GPU or AI accelerator such as a [Google Coral](https://coral.ai/products/) or [Hailo](https://hailo.ai/) is highly recommended. AI accelerators will outperform even the best CPUs with very little overhead.
|
||||||
|
|
||||||
- Tight integration with Home Assistant via a [custom component](https://github.com/blakeblackshear/frigate-hass-integration)
|
- Tight integration with Home Assistant via a [custom component](https://github.com/blakeblackshear/frigate-hass-integration)
|
||||||
- Designed to minimize resource use and maximize performance by only looking for objects when and where it is necessary
|
- Designed to minimize resource use and maximize performance by only looking for objects when and where it is necessary
|
||||||
@ -35,15 +33,6 @@ View the documentation at https://docs.frigate.video
|
|||||||
|
|
||||||
If you would like to make a donation to support development, please use [Github Sponsors](https://github.com/sponsors/blakeblackshear).
|
If you would like to make a donation to support development, please use [Github Sponsors](https://github.com/sponsors/blakeblackshear).
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This project is licensed under the **MIT License**.
|
|
||||||
|
|
||||||
- **Code:** The source code, configuration files, and documentation in this repository are available under the [MIT License](LICENSE). You are free to use, modify, and distribute the code as long as you include the original copyright notice.
|
|
||||||
- **Trademarks:** The "Frigate" name, the "Frigate NVR" brand, and the Frigate logo are **trademarks of Frigate, Inc.** and are **not** covered by the MIT License.
|
|
||||||
|
|
||||||
Please see our [Trademark Policy](TRADEMARK.md) for details on acceptable use of our brand assets.
|
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
### Live dashboard
|
### Live dashboard
|
||||||
@ -67,7 +56,7 @@ Please see our [Trademark Policy](TRADEMARK.md) for details on acceptable use of
|
|||||||
### Built-in mask and zone editor
|
### Built-in mask and zone editor
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<img width="800" alt="Built-in mask and zone editor" src="https://github.com/blakeblackshear/frigate/assets/569905/d7885fc3-bfe6-452f-b7d0-d957cb3e31f5">
|
<img width="800" alt="Multi-camera scrubbing" src="https://github.com/blakeblackshear/frigate/assets/569905/d7885fc3-bfe6-452f-b7d0-d957cb3e31f5">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## Translations
|
## Translations
|
||||||
@ -77,7 +66,3 @@ We use [Weblate](https://hosted.weblate.org/projects/frigate-nvr/) to support la
|
|||||||
<a href="https://hosted.weblate.org/engage/frigate-nvr/">
|
<a href="https://hosted.weblate.org/engage/frigate-nvr/">
|
||||||
<img src="https://hosted.weblate.org/widget/frigate-nvr/multi-auto.svg" alt="Translation status" />
|
<img src="https://hosted.weblate.org/widget/frigate-nvr/multi-auto.svg" alt="Translation status" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Copyright © 2026 Frigate, Inc.**
|
|
||||||
|
|||||||
70
README_CN.md
70
README_CN.md
@ -1,90 +1,64 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img align="center" alt="logo" src="docs/static/img/branding/frigate.png">
|
<img align="center" alt="logo" src="docs/static/img/frigate.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
# Frigate NVR™ - 一个具有实时目标检测的本地 NVR
|
# Frigate - 一个具有实时目标检测的本地NVR
|
||||||
|
|
||||||
|
[English](https://github.com/blakeblackshear/frigate) | \[简体中文\]
|
||||||
|
|
||||||
<a href="https://hosted.weblate.org/engage/frigate-nvr/-/zh_Hans/">
|
<a href="https://hosted.weblate.org/engage/frigate-nvr/-/zh_Hans/">
|
||||||
<img src="https://hosted.weblate.org/widget/frigate-nvr/-/zh_Hans/svg-badge.svg" alt="翻译状态" />
|
<img src="https://hosted.weblate.org/widget/frigate-nvr/-/zh_Hans/svg-badge.svg" alt="翻译状态" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
[English](https://github.com/blakeblackshear/frigate) | \[简体中文\]
|
一个完整的本地网络视频录像机(NVR),专为[Home Assistant](https://www.home-assistant.io)设计,具备AI物体检测功能。使用OpenCV和TensorFlow在本地为IP摄像头执行实时物体检测。
|
||||||
|
|
||||||
[](https://opensource.org/licenses/MIT)
|
强烈推荐使用GPU或者AI加速器(例如[Google Coral加速器](https://coral.ai/products/) 或者 [Hailo](https://hailo.ai/))。它们的性能甚至超过目前的顶级CPU,并且可以以极低的耗电实现更优的性能。
|
||||||
|
- 通过[自定义组件](https://github.com/blakeblackshear/frigate-hass-integration)与Home Assistant紧密集成
|
||||||
一个完整的本地网络视频录像机(NVR),专为[Home Assistant](https://www.home-assistant.io)设计,具备 AI 目标/物体检测功能。使用 OpenCV 和 TensorFlow 在本地为 IP 摄像头执行实时物体检测。
|
- 设计上通过仅在必要时和必要地点寻找物体,最大限度地减少资源使用并最大化性能
|
||||||
|
|
||||||
强烈推荐使用 GPU 或者 AI 加速器(例如[Google Coral 加速器](https://coral.ai/products/) 或者 [Hailo](https://hailo.ai/)等)。它们的运行效率远远高于现在的顶级 CPU,并且功耗也极低。
|
|
||||||
|
|
||||||
- 通过[自定义组件](https://github.com/blakeblackshear/frigate-hass-integration)与 Home Assistant 紧密集成
|
|
||||||
- 设计上通过仅在必要时和必要地点寻找目标,最大限度地减少资源使用并最大化性能
|
|
||||||
- 大量利用多进程处理,强调实时性而非处理每一帧
|
- 大量利用多进程处理,强调实时性而非处理每一帧
|
||||||
- 使用非常低开销的画面变动检测(也叫运动检测)来确定运行目标检测的位置
|
- 使用非常低开销的运动检测来确定运行物体检测的位置
|
||||||
- 使用 TensorFlow 进行目标检测,并运行在单独的进程中以达到最大 FPS
|
- 使用TensorFlow进行物体检测,运行在单独的进程中以达到最大FPS
|
||||||
- 通过 MQTT 进行通信,便于集成到其他系统中
|
- 通过MQTT进行通信,便于集成到其他系统中
|
||||||
- 根据检测到的物体设置保留时间进行视频录制
|
- 根据检测到的物体设置保留时间进行视频录制
|
||||||
- 24/7 全天候录制
|
- 24/7全天候录制
|
||||||
- 通过 RTSP 重新流传输以减少摄像头的连接数
|
- 通过RTSP重新流传输以减少摄像头的连接数
|
||||||
- 支持 WebRTC 和 MSE,实现低延迟的实时观看
|
- 支持WebRTC和MSE,实现低延迟的实时观看
|
||||||
|
|
||||||
## 社区中文翻译文档
|
## 文档(英文)
|
||||||
|
|
||||||
你可以在这里查看文档 https://docs.frigate-cn.video
|
你可以在这里查看文档 https://docs.frigate.video
|
||||||
|
|
||||||
|
文档还暂时没有提供翻译,将会在未来提供。
|
||||||
|
|
||||||
## 赞助
|
## 赞助
|
||||||
|
|
||||||
如果您想通过捐赠支持开发,请使用 [Github Sponsors](https://github.com/sponsors/blakeblackshear)。
|
如果您想通过捐赠支持开发,请使用 [Github Sponsors](https://github.com/sponsors/blakeblackshear)。
|
||||||
|
|
||||||
## 协议
|
|
||||||
|
|
||||||
本项目采用 **MIT 许可证**授权。
|
|
||||||
|
|
||||||
**代码部分**:本代码库中的源代码、配置文件和文档均遵循 [MIT 许可证](LICENSE)。您可以自由使用、修改和分发这些代码,但必须保留原始版权声明。
|
|
||||||
|
|
||||||
**商标部分**:“Frigate”名称、“Frigate NVR”品牌以及 Frigate 的 Logo 为 **Frigate, Inc. 的商标**,**不在** MIT 许可证覆盖范围内。
|
|
||||||
有关品牌资产的规范使用详情,请参阅我们的[《商标政策》](TRADEMARK.md)。
|
|
||||||
|
|
||||||
## 截图
|
## 截图
|
||||||
|
|
||||||
### 实时监控面板
|
### 实时监控面板
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<img width="800" alt="实时监控面板" src="https://github.com/blakeblackshear/frigate/assets/569905/5e713cb9-9db5-41dc-947a-6937c3bc376e">
|
<img width="800" alt="实时监控面板" src="https://github.com/blakeblackshear/frigate/assets/569905/5e713cb9-9db5-41dc-947a-6937c3bc376e">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### 简单的核查工作流程
|
### 简单的审查工作流程
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<img width="800" alt="简单的审查工作流程" src="https://github.com/blakeblackshear/frigate/assets/569905/6fed96e8-3b18-40e5-9ddc-31e6f3c9f2ff">
|
<img width="800" alt="简单的审查工作流程" src="https://github.com/blakeblackshear/frigate/assets/569905/6fed96e8-3b18-40e5-9ddc-31e6f3c9f2ff">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### 多摄像头可按时间轴查看
|
### 多摄像头可按时间轴查看
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<img width="800" alt="多摄像头可按时间轴查看" src="https://github.com/blakeblackshear/frigate/assets/569905/d6788a15-0eeb-4427-a8d4-80b93cae3d74">
|
<img width="800" alt="多摄像头可按时间轴查看" src="https://github.com/blakeblackshear/frigate/assets/569905/d6788a15-0eeb-4427-a8d4-80b93cae3d74">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### 内置遮罩和区域编辑器
|
### 内置遮罩和区域编辑器
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<img width="800" alt="内置遮罩和区域编辑器" src="https://github.com/blakeblackshear/frigate/assets/569905/d7885fc3-bfe6-452f-b7d0-d957cb3e31f5">
|
<img width="800" alt="内置遮罩和区域编辑器" src="https://github.com/blakeblackshear/frigate/assets/569905/d7885fc3-bfe6-452f-b7d0-d957cb3e31f5">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## 翻译
|
|
||||||
|
|
||||||
|
## 翻译
|
||||||
我们使用 [Weblate](https://hosted.weblate.org/projects/frigate-nvr/) 平台提供翻译支持,欢迎参与进来一起完善。
|
我们使用 [Weblate](https://hosted.weblate.org/projects/frigate-nvr/) 平台提供翻译支持,欢迎参与进来一起完善。
|
||||||
|
|
||||||
## 非官方中文讨论社区
|
## 中文讨论社区
|
||||||
|
欢迎加入非官方中文讨论QQ群:1043861059
|
||||||
欢迎加入中文讨论 QQ 群:[1043861059](https://qm.qq.com/q/7vQKsTmSz)
|
|
||||||
|
|
||||||
Bilibili:https://space.bilibili.com/3546894915602564
|
|
||||||
|
|
||||||
## 中文社区赞助商
|
|
||||||
|
|
||||||
[](https://edgeone.ai/zh?from=github)
|
|
||||||
本项目 CDN 加速及安全防护由 Tencent EdgeOne 赞助
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Copyright © 2026 Frigate, Inc.**
|
|
||||||
|
|||||||
58
TRADEMARK.md
58
TRADEMARK.md
@ -1,58 +0,0 @@
|
|||||||
# Trademark Policy
|
|
||||||
|
|
||||||
**Last Updated:** November 2025
|
|
||||||
|
|
||||||
This document outlines the policy regarding the use of the trademarks associated with the Frigate NVR project.
|
|
||||||
|
|
||||||
## 1. Our Trademarks
|
|
||||||
|
|
||||||
The following terms and visual assets are trademarks (the "Marks") of **Frigate, Inc.**:
|
|
||||||
|
|
||||||
- **Frigate™**
|
|
||||||
- **Frigate NVR™**
|
|
||||||
- **Frigate+™**
|
|
||||||
- **The Frigate Logo**
|
|
||||||
|
|
||||||
**Note on Common Law Rights:**
|
|
||||||
Frigate, Inc. asserts all common law rights in these Marks. The absence of a federal registration symbol (®) does not constitute a waiver of our intellectual property rights.
|
|
||||||
|
|
||||||
## 2. Interaction with the MIT License
|
|
||||||
|
|
||||||
The software in this repository is licensed under the [MIT License](LICENSE).
|
|
||||||
|
|
||||||
**Crucial Distinction:**
|
|
||||||
|
|
||||||
- The **Code** is free to use, modify, and distribute under the MIT terms.
|
|
||||||
- The **Brand (Trademarks)** is **NOT** licensed under MIT.
|
|
||||||
|
|
||||||
You may not use the Marks in any way that is not explicitly permitted by this policy or by written agreement with Frigate, Inc.
|
|
||||||
|
|
||||||
## 3. Acceptable Use
|
|
||||||
|
|
||||||
You may use the Marks without prior written permission in the following specific contexts:
|
|
||||||
|
|
||||||
- **Referential Use:** To truthfully refer to the software (e.g., _"I use Frigate NVR for my home security"_).
|
|
||||||
- **Compatibility:** To indicate that your product or project works with the software (e.g., _"MyPlugin for Frigate NVR"_ or _"Compatible with Frigate"_).
|
|
||||||
- **Commentary:** In news articles, blog posts, or tutorials discussing the software.
|
|
||||||
|
|
||||||
## 4. Prohibited Use
|
|
||||||
|
|
||||||
You may **NOT** use the Marks in the following ways:
|
|
||||||
|
|
||||||
- **Commercial Products:** You may not use "Frigate" in the name of a commercial product, service, or app (e.g., selling an app named _"Frigate Viewer"_ is prohibited).
|
|
||||||
- **Implying Affiliation:** You may not use the Marks in a way that suggests your project is official, sponsored by, or endorsed by Frigate, Inc.
|
|
||||||
- **Confusing Forks:** If you fork this repository to create a derivative work, you **must** remove the Frigate logo and rename your project to avoid user confusion. You cannot distribute a modified version of the software under the name "Frigate".
|
|
||||||
- **Domain Names:** You may not register domain names containing "Frigate" that are likely to confuse users (e.g., `frigate-official-support.com`).
|
|
||||||
|
|
||||||
## 5. The Logo
|
|
||||||
|
|
||||||
The Frigate logo (the bird icon) is a visual trademark.
|
|
||||||
|
|
||||||
- You generally **cannot** use the logo on your own website or product packaging without permission.
|
|
||||||
- If you are building a dashboard or integration that interfaces with Frigate, you may use the logo only to represent the Frigate node/service, provided it does not imply you _are_ Frigate.
|
|
||||||
|
|
||||||
## 6. Questions & Permissions
|
|
||||||
|
|
||||||
If you are unsure if your intended use violates this policy, or if you wish to request a specific license to use the Marks (e.g., for a partnership), please contact us at:
|
|
||||||
|
|
||||||
**help@frigate.video**
|
|
||||||
@ -24,7 +24,7 @@ yell
|
|||||||
sigh
|
sigh
|
||||||
singing
|
singing
|
||||||
choir
|
choir
|
||||||
yodeling
|
sodeling
|
||||||
chant
|
chant
|
||||||
mantra
|
mantra
|
||||||
child_singing
|
child_singing
|
||||||
|
|||||||
@ -4,13 +4,13 @@ from statistics import mean
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
import frigate.util as util
|
||||||
from frigate.config import DetectorTypeEnum
|
from frigate.config import DetectorTypeEnum
|
||||||
from frigate.object_detection.base import (
|
from frigate.object_detection.base import (
|
||||||
ObjectDetectProcess,
|
ObjectDetectProcess,
|
||||||
RemoteObjectDetector,
|
RemoteObjectDetector,
|
||||||
load_labels,
|
load_labels,
|
||||||
)
|
)
|
||||||
from frigate.util.process import FrigateProcess
|
|
||||||
|
|
||||||
my_frame = np.expand_dims(np.full((300, 300, 3), 1, np.uint8), axis=0)
|
my_frame = np.expand_dims(np.full((300, 300, 3), 1, np.uint8), axis=0)
|
||||||
labels = load_labels("/labelmap.txt")
|
labels = load_labels("/labelmap.txt")
|
||||||
@ -91,7 +91,7 @@ edgetpu_process_2 = ObjectDetectProcess(
|
|||||||
)
|
)
|
||||||
|
|
||||||
for x in range(0, 10):
|
for x in range(0, 10):
|
||||||
camera_process = FrigateProcess(
|
camera_process = util.Process(
|
||||||
target=start, args=(x, 300, detection_queue, events[str(x)])
|
target=start, args=(x, 300, detection_queue, events[str(x)])
|
||||||
)
|
)
|
||||||
camera_process.daemon = True
|
camera_process.daemon = True
|
||||||
@ -14,8 +14,6 @@ services:
|
|||||||
dockerfile: docker/main/Dockerfile
|
dockerfile: docker/main/Dockerfile
|
||||||
# Use target devcontainer-trt for TensorRT dev
|
# Use target devcontainer-trt for TensorRT dev
|
||||||
target: devcontainer
|
target: devcontainer
|
||||||
cache_from:
|
|
||||||
- ghcr.io/blakeblackshear/frigate:cache-amd64
|
|
||||||
## Uncomment this block for nvidia gpu support
|
## Uncomment this block for nvidia gpu support
|
||||||
# deploy:
|
# deploy:
|
||||||
# resources:
|
# resources:
|
||||||
|
|||||||
@ -2,19 +2,15 @@
|
|||||||
|
|
||||||
# Update package list and install dependencies
|
# Update package list and install dependencies
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y build-essential cmake git wget linux-headers-$(uname -r)
|
sudo apt-get install -y build-essential cmake git wget
|
||||||
|
|
||||||
hailo_version="4.21.0"
|
hailo_version="4.20.1"
|
||||||
arch=$(uname -m)
|
arch=$(uname -m)
|
||||||
|
|
||||||
if [[ $arch == "aarch64" ]]; then
|
if [[ $arch == "x86_64" ]]; then
|
||||||
source /etc/os-release
|
sudo apt install -y linux-headers-$(uname -r);
|
||||||
os_codename=$VERSION_CODENAME
|
else
|
||||||
echo "Detected OS codename: $os_codename"
|
sudo apt install -y linux-modules-extra-$(uname -r);
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$os_codename" = "trixie" ]; then
|
|
||||||
sudo apt install -y dkms
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Clone the HailoRT driver repository
|
# Clone the HailoRT driver repository
|
||||||
@ -51,4 +47,3 @@ sudo udevadm control --reload-rules && sudo udevadm trigger
|
|||||||
|
|
||||||
echo "HailoRT driver installation complete."
|
echo "HailoRT driver installation complete."
|
||||||
echo "reboot your system to load the firmware!"
|
echo "reboot your system to load the firmware!"
|
||||||
echo "Driver version: $(modinfo -F version hailo_pci)"
|
|
||||||
|
|||||||
@ -52,18 +52,10 @@ RUN --mount=type=tmpfs,target=/tmp --mount=type=tmpfs,target=/var/cache/apt \
|
|||||||
--mount=type=cache,target=/root/.ccache \
|
--mount=type=cache,target=/root/.ccache \
|
||||||
/deps/build_sqlite_vec.sh
|
/deps/build_sqlite_vec.sh
|
||||||
|
|
||||||
# Build intel-media-driver from source against bookworm's system libva so it
|
|
||||||
# works with Debian 12's glibc/libstdc++ (pre-built noble/trixie packages
|
|
||||||
# require glibc 2.38 which is not available on bookworm).
|
|
||||||
FROM base AS intel-media-driver
|
|
||||||
ARG DEBIAN_FRONTEND
|
|
||||||
RUN --mount=type=bind,source=docker/main/build_intel_media_driver.sh,target=/deps/build_intel_media_driver.sh \
|
|
||||||
/deps/build_intel_media_driver.sh
|
|
||||||
|
|
||||||
FROM scratch AS go2rtc
|
FROM scratch AS go2rtc
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
WORKDIR /rootfs/usr/local/go2rtc/bin
|
WORKDIR /rootfs/usr/local/go2rtc/bin
|
||||||
ADD --link --chmod=755 "https://github.com/AlexxIT/go2rtc/releases/download/v1.9.14/go2rtc_linux_${TARGETARCH}" go2rtc
|
ADD --link --chmod=755 "https://github.com/AlexxIT/go2rtc/releases/download/v1.9.9/go2rtc_linux_${TARGETARCH}" go2rtc
|
||||||
|
|
||||||
FROM wget AS tempio
|
FROM wget AS tempio
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
@ -81,10 +73,10 @@ RUN --mount=type=bind,source=docker/main/install_tempio.sh,target=/deps/install_
|
|||||||
FROM base_host AS ov-converter
|
FROM base_host AS ov-converter
|
||||||
ARG DEBIAN_FRONTEND
|
ARG DEBIAN_FRONTEND
|
||||||
|
|
||||||
# Install OpenVINO for model conversion
|
# Install OpenVino Runtime and Dev library
|
||||||
COPY docker/main/requirements-ov.txt /requirements-ov.txt
|
COPY docker/main/requirements-ov.txt /requirements-ov.txt
|
||||||
RUN apt-get -qq update \
|
RUN apt-get -qq update \
|
||||||
&& apt-get -qq install -y wget python3 python3-distutils \
|
&& apt-get -qq install -y wget python3 python3-dev python3-distutils gcc pkg-config libhdf5-dev \
|
||||||
&& wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
&& wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
||||||
&& sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' get-pip.py \
|
&& sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' get-pip.py \
|
||||||
&& python3 get-pip.py "pip" \
|
&& python3 get-pip.py "pip" \
|
||||||
@ -156,12 +148,11 @@ RUN --mount=type=bind,source=docker/main/install_s6_overlay.sh,target=/deps/inst
|
|||||||
FROM base AS wheels
|
FROM base AS wheels
|
||||||
ARG DEBIAN_FRONTEND
|
ARG DEBIAN_FRONTEND
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
ARG DEBUG=false
|
|
||||||
|
|
||||||
# Use a separate container to build wheels to prevent build dependencies in final image
|
# Use a separate container to build wheels to prevent build dependencies in final image
|
||||||
RUN apt-get -qq update \
|
RUN apt-get -qq update \
|
||||||
&& apt-get -qq install -y \
|
&& apt-get -qq install -y \
|
||||||
apt-transport-https wget unzip \
|
apt-transport-https wget \
|
||||||
&& apt-get -qq update \
|
&& apt-get -qq update \
|
||||||
&& apt-get -qq install -y \
|
&& apt-get -qq install -y \
|
||||||
python3.11 \
|
python3.11 \
|
||||||
@ -186,8 +177,6 @@ RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
|||||||
&& python3 get-pip.py "pip"
|
&& python3 get-pip.py "pip"
|
||||||
|
|
||||||
COPY docker/main/requirements.txt /requirements.txt
|
COPY docker/main/requirements.txt /requirements.txt
|
||||||
COPY docker/main/requirements-dev.txt /requirements-dev.txt
|
|
||||||
|
|
||||||
RUN pip3 install -r /requirements.txt
|
RUN pip3 install -r /requirements.txt
|
||||||
|
|
||||||
# Build pysqlite3 from source
|
# Build pysqlite3 from source
|
||||||
@ -195,10 +184,7 @@ COPY docker/main/build_pysqlite3.sh /build_pysqlite3.sh
|
|||||||
RUN /build_pysqlite3.sh
|
RUN /build_pysqlite3.sh
|
||||||
|
|
||||||
COPY docker/main/requirements-wheels.txt /requirements-wheels.txt
|
COPY docker/main/requirements-wheels.txt /requirements-wheels.txt
|
||||||
RUN pip3 wheel --wheel-dir=/wheels -r /requirements-wheels.txt && \
|
RUN pip3 wheel --wheel-dir=/wheels -r /requirements-wheels.txt
|
||||||
if [ "$DEBUG" = "true" ]; then \
|
|
||||||
pip3 wheel --wheel-dir=/wheels -r /requirements-dev.txt; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install HailoRT & Wheels
|
# Install HailoRT & Wheels
|
||||||
RUN --mount=type=bind,source=docker/main/install_hailort.sh,target=/deps/install_hailort.sh \
|
RUN --mount=type=bind,source=docker/main/install_hailort.sh,target=/deps/install_hailort.sh \
|
||||||
@ -208,7 +194,6 @@ RUN --mount=type=bind,source=docker/main/install_hailort.sh,target=/deps/install
|
|||||||
FROM scratch AS deps-rootfs
|
FROM scratch AS deps-rootfs
|
||||||
COPY --from=nginx /usr/local/nginx/ /usr/local/nginx/
|
COPY --from=nginx /usr/local/nginx/ /usr/local/nginx/
|
||||||
COPY --from=sqlite-vec /usr/local/lib/ /usr/local/lib/
|
COPY --from=sqlite-vec /usr/local/lib/ /usr/local/lib/
|
||||||
COPY --from=intel-media-driver /rootfs/ /
|
|
||||||
COPY --from=go2rtc /rootfs/ /
|
COPY --from=go2rtc /rootfs/ /
|
||||||
COPY --from=libusb-build /usr/local/lib /usr/local/lib
|
COPY --from=libusb-build /usr/local/lib /usr/local/lib
|
||||||
COPY --from=tempio /rootfs/ /
|
COPY --from=tempio /rootfs/ /
|
||||||
@ -221,7 +206,6 @@ COPY docker/main/rootfs/ /
|
|||||||
# Frigate deps (ffmpeg, python, nginx, go2rtc, s6-overlay, etc)
|
# Frigate deps (ffmpeg, python, nginx, go2rtc, s6-overlay, etc)
|
||||||
FROM slim-base AS deps
|
FROM slim-base AS deps
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
ARG BASE_IMAGE
|
|
||||||
|
|
||||||
ARG DEBIAN_FRONTEND
|
ARG DEBIAN_FRONTEND
|
||||||
# http://stackoverflow.com/questions/48162574/ddg#49462622
|
# http://stackoverflow.com/questions/48162574/ddg#49462622
|
||||||
@ -240,33 +224,17 @@ ENV TRANSFORMERS_NO_ADVISORY_WARNINGS=1
|
|||||||
# Set OpenCV ffmpeg loglevel to fatal: https://ffmpeg.org/doxygen/trunk/log_8h.html
|
# Set OpenCV ffmpeg loglevel to fatal: https://ffmpeg.org/doxygen/trunk/log_8h.html
|
||||||
ENV OPENCV_FFMPEG_LOGLEVEL=8
|
ENV OPENCV_FFMPEG_LOGLEVEL=8
|
||||||
|
|
||||||
# Set NumPy to ignore getlimits warning
|
|
||||||
ENV PYTHONWARNINGS="ignore:::numpy.core.getlimits"
|
|
||||||
|
|
||||||
# Set HailoRT to disable logging
|
# Set HailoRT to disable logging
|
||||||
ENV HAILORT_LOGGER_PATH=NONE
|
ENV HAILORT_LOGGER_PATH=NONE
|
||||||
|
|
||||||
# TensorFlow C++ logging suppression (must be set before import)
|
|
||||||
# TF_CPP_MIN_LOG_LEVEL: 0=all, 1=INFO+, 2=WARNING+, 3=ERROR+ (we use 3 for errors only)
|
|
||||||
ENV TF_CPP_MIN_LOG_LEVEL=3
|
|
||||||
# Suppress verbose logging from TensorFlow C++ code
|
|
||||||
ENV TF_CPP_MIN_VLOG_LEVEL=3
|
|
||||||
# Disable oneDNN optimization messages ("optimized with oneDNN...")
|
|
||||||
ENV TF_ENABLE_ONEDNN_OPTS=0
|
|
||||||
# Suppress AutoGraph verbosity during conversion
|
|
||||||
ENV AUTOGRAPH_VERBOSITY=0
|
|
||||||
# Google Logging (GLOG) suppression for TensorFlow components
|
|
||||||
ENV GLOG_minloglevel=3
|
|
||||||
ENV GLOG_logtostderr=0
|
|
||||||
|
|
||||||
ENV PATH="/usr/local/go2rtc/bin:/usr/local/tempio/bin:/usr/local/nginx/sbin:${PATH}"
|
ENV PATH="/usr/local/go2rtc/bin:/usr/local/tempio/bin:/usr/local/nginx/sbin:${PATH}"
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
RUN --mount=type=bind,source=docker/main/install_deps.sh,target=/deps/install_deps.sh \
|
RUN --mount=type=bind,source=docker/main/install_deps.sh,target=/deps/install_deps.sh \
|
||||||
/deps/install_deps.sh
|
/deps/install_deps.sh
|
||||||
|
|
||||||
ENV DEFAULT_FFMPEG_VERSION="8.0"
|
ENV DEFAULT_FFMPEG_VERSION="7.0"
|
||||||
ENV INCLUDED_FFMPEG_VERSIONS="${DEFAULT_FFMPEG_VERSION}:7.0:5.0"
|
ENV INCLUDED_FFMPEG_VERSIONS="${DEFAULT_FFMPEG_VERSION}:5.0"
|
||||||
|
|
||||||
RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
||||||
&& sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' get-pip.py \
|
&& sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' get-pip.py \
|
||||||
@ -275,16 +243,6 @@ RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
|||||||
RUN --mount=type=bind,from=wheels,source=/wheels,target=/deps/wheels \
|
RUN --mount=type=bind,from=wheels,source=/wheels,target=/deps/wheels \
|
||||||
pip3 install -U /deps/wheels/*.whl
|
pip3 install -U /deps/wheels/*.whl
|
||||||
|
|
||||||
# Install Axera Engine
|
|
||||||
RUN pip3 install https://github.com/AXERA-TECH/pyaxengine/releases/download/0.1.3-frigate/axengine-0.1.3-py3-none-any.whl
|
|
||||||
|
|
||||||
ENV PATH="${PATH}:/usr/bin/axcl"
|
|
||||||
ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/usr/lib/axcl"
|
|
||||||
|
|
||||||
# Install MemryX runtime (requires libgomp (OpenMP) in the final docker image)
|
|
||||||
RUN --mount=type=bind,source=docker/main/install_memryx.sh,target=/deps/install_memryx.sh \
|
|
||||||
bash -c "bash /deps/install_memryx.sh"
|
|
||||||
|
|
||||||
COPY --from=deps-rootfs / /
|
COPY --from=deps-rootfs / /
|
||||||
|
|
||||||
RUN ldconfig
|
RUN ldconfig
|
||||||
@ -302,7 +260,7 @@ ENTRYPOINT ["/init"]
|
|||||||
CMD []
|
CMD []
|
||||||
|
|
||||||
HEALTHCHECK --start-period=300s --start-interval=5s --interval=15s --timeout=5s --retries=3 \
|
HEALTHCHECK --start-period=300s --start-interval=5s --interval=15s --timeout=5s --retries=3 \
|
||||||
CMD test -f /dev/shm/.frigate-is-stopping && exit 0; curl --fail --silent --show-error http://127.0.0.1:5000/api/version || exit 1
|
CMD curl --fail --silent --show-error http://127.0.0.1:5000/api/version || exit 1
|
||||||
|
|
||||||
# Frigate deps with Node.js and NPM for devcontainer
|
# Frigate deps with Node.js and NPM for devcontainer
|
||||||
FROM deps AS devcontainer
|
FROM deps AS devcontainer
|
||||||
|
|||||||
@ -1,48 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -euxo pipefail
|
|
||||||
|
|
||||||
# Intel media driver is x86_64-only. Create empty rootfs on other arches so
|
|
||||||
# the downstream COPY --from has a valid source.
|
|
||||||
if [ "$(uname -m)" != "x86_64" ]; then
|
|
||||||
mkdir -p /rootfs
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
MEDIA_DRIVER_VERSION="intel-media-25.2.6"
|
|
||||||
GMMLIB_VERSION="intel-gmmlib-22.7.2"
|
|
||||||
|
|
||||||
apt-get -qq update
|
|
||||||
apt-get -qq install -y wget gnupg ca-certificates cmake g++ make pkg-config
|
|
||||||
|
|
||||||
# Use Intel's jammy repo for newer libva-dev (2.22) which provides the
|
|
||||||
# VVC/VVC-decode headers required by media-driver 25.x
|
|
||||||
wget -qO - https://repositories.intel.com/gpu/intel-graphics.key | gpg --yes --dearmor --output /usr/share/keyrings/intel-graphics.gpg
|
|
||||||
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/intel-graphics.gpg] https://repositories.intel.com/gpu/ubuntu jammy client" > /etc/apt/sources.list.d/intel-gpu-jammy.list
|
|
||||||
apt-get -qq update
|
|
||||||
apt-get -qq install -y libva-dev
|
|
||||||
|
|
||||||
# Build gmmlib (required by media-driver)
|
|
||||||
wget -qO gmmlib.tar.gz "https://github.com/intel/gmmlib/archive/refs/tags/${GMMLIB_VERSION}.tar.gz"
|
|
||||||
mkdir /tmp/gmmlib
|
|
||||||
tar -xf gmmlib.tar.gz -C /tmp/gmmlib --strip-components 1
|
|
||||||
cmake -S /tmp/gmmlib -B /tmp/gmmlib/build -DCMAKE_BUILD_TYPE=Release
|
|
||||||
make -C /tmp/gmmlib/build -j"$(nproc)"
|
|
||||||
make -C /tmp/gmmlib/build install
|
|
||||||
|
|
||||||
# Build intel-media-driver
|
|
||||||
wget -qO media-driver.tar.gz "https://github.com/intel/media-driver/archive/refs/tags/${MEDIA_DRIVER_VERSION}.tar.gz"
|
|
||||||
mkdir /tmp/media-driver
|
|
||||||
tar -xf media-driver.tar.gz -C /tmp/media-driver --strip-components 1
|
|
||||||
cmake -S /tmp/media-driver -B /tmp/media-driver/build \
|
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
|
||||||
-DENABLE_KERNELS=ON \
|
|
||||||
-DENABLE_NONFREE_KERNELS=ON \
|
|
||||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
|
||||||
-DCMAKE_INSTALL_LIBDIR=/usr/lib/x86_64-linux-gnu \
|
|
||||||
-DCMAKE_C_FLAGS="-Wno-error" \
|
|
||||||
-DCMAKE_CXX_FLAGS="-Wno-error"
|
|
||||||
make -C /tmp/media-driver/build -j"$(nproc)"
|
|
||||||
|
|
||||||
# Install driver to rootfs for COPY --from
|
|
||||||
make -C /tmp/media-driver/build install DESTDIR=/rootfs
|
|
||||||
@ -73,7 +73,6 @@ cd /tmp/nginx
|
|||||||
--with-file-aio \
|
--with-file-aio \
|
||||||
--with-http_sub_module \
|
--with-http_sub_module \
|
||||||
--with-http_ssl_module \
|
--with-http_ssl_module \
|
||||||
--with-http_v2_module \
|
|
||||||
--with-http_auth_request_module \
|
--with-http_auth_request_module \
|
||||||
--with-http_realip_module \
|
--with-http_realip_module \
|
||||||
--with-threads \
|
--with-threads \
|
||||||
|
|||||||
@ -1,106 +1,11 @@
|
|||||||
"""Convert the default SSDLite MobileNet v2 model to OpenVINO IR.
|
|
||||||
|
|
||||||
Replaces the legacy openvino-dev Model Optimizer conversion. The TensorFlow
|
|
||||||
frontend translates the Object Detection API pre and post processors literally,
|
|
||||||
producing per-class NonMaxSuppression, NonZero ops and map loops with data
|
|
||||||
dependent shapes that the GPU plugin handles very badly. Both are cut out the
|
|
||||||
way ssd_v2_support.json used to do it: the preprocessor is an identity at the
|
|
||||||
native 300x300 input, and the postprocessor becomes a single fused
|
|
||||||
DetectionOutput. The result is the [1, 1, 100, 7] tensor that Frigate's
|
|
||||||
OpenVINO detector expects, with the input flipped to BGR to match the legacy
|
|
||||||
reverse_input_channels behavior.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
import openvino as ov
|
import openvino as ov
|
||||||
from openvino import opset8 as ops
|
from openvino.tools import mo
|
||||||
from openvino.preprocess import PrePostProcessor
|
|
||||||
|
|
||||||
MODEL_DIR = "/models/ssdlite_mobilenet_v2_coco_2018_05_09"
|
ov_model = mo.convert_model(
|
||||||
OUTPUT_PATH = "/models/ssdlite_mobilenet_v2.xml"
|
"/models/ssdlite_mobilenet_v2_coco_2018_05_09/frozen_inference_graph.pb",
|
||||||
INPUT_SHAPE = [1, 300, 300, 3]
|
compress_to_fp16=True,
|
||||||
|
transformations_config="/usr/local/lib/python3.11/dist-packages/openvino/tools/mo/front/tf/ssd_v2_support.json",
|
||||||
# faster_rcnn_box_coder divides the deltas by pipeline.config's y/x/height/width
|
tensorflow_object_detection_api_pipeline_config="/models/ssdlite_mobilenet_v2_coco_2018_05_09/pipeline.config",
|
||||||
# scales of 10/10/5/5, which DetectionOutput expresses as per-prior variances.
|
reverse_input_channels=True,
|
||||||
BOX_VARIANCES = np.float32([0.1, 0.1, 0.2, 0.2])
|
|
||||||
|
|
||||||
model = ov.convert_model(
|
|
||||||
f"{MODEL_DIR}/frozen_inference_graph.pb",
|
|
||||||
input=[("image_tensor:0", INPUT_SHAPE)],
|
|
||||||
)
|
)
|
||||||
|
ov.save_model(ov_model, "/models/ssdlite_mobilenet_v2.xml")
|
||||||
nodes = {op.get_friendly_name(): op for op in model.get_ordered_ops()}
|
|
||||||
parameter = model.get_parameters()[0]
|
|
||||||
|
|
||||||
preprocessor = nodes["Preprocessor/map/TensorArrayStack/TensorArrayGatherV3"]
|
|
||||||
box_deltas = nodes["Postprocessor/Reshape_1"].output(0)
|
|
||||||
class_scores = nodes["Postprocessor/convert_scores"].output(0)
|
|
||||||
anchors_output = nodes["Postprocessor/Reshape"].output(0)
|
|
||||||
|
|
||||||
# The anchors only depend on the static input shape, so fold them into a
|
|
||||||
# constant and drop the generator subgraph with the rest of the postprocessor.
|
|
||||||
probe = ov.Core().compile_model(
|
|
||||||
ov.Model([anchors_output, preprocessor.output(0)], [parameter], "probe"), "CPU"
|
|
||||||
)
|
|
||||||
probe_input = np.random.default_rng(0).integers(0, 255, INPUT_SHAPE, dtype=np.uint8)
|
|
||||||
anchors, resized = (out.copy() for out in probe([probe_input]).values())
|
|
||||||
|
|
||||||
assert np.allclose(resized, probe_input, atol=1e-3), (
|
|
||||||
"preprocessor is not an identity at 300x300, it cannot be bypassed"
|
|
||||||
)
|
|
||||||
|
|
||||||
image = ops.convert(parameter, "f32")
|
|
||||||
|
|
||||||
for consumer in list(preprocessor.output(0).get_target_inputs()):
|
|
||||||
consumer.replace_source_output(image.output(0))
|
|
||||||
|
|
||||||
# (ymin, xmin, ymax, xmax) -> (xmin, ymin, xmax, ymax)
|
|
||||||
priors = anchors[:, [1, 0, 3, 2]].astype(np.float32).reshape(-1)
|
|
||||||
variances = np.tile(BOX_VARIANCES, len(anchors))
|
|
||||||
proposals = ops.constant(np.stack([priors, variances])[np.newaxis])
|
|
||||||
|
|
||||||
# (ty, tx, th, tw) -> (dx, dy, dw, dh) for the CENTER_SIZE decode
|
|
||||||
box_logits = ops.reshape(ops.gather(box_deltas, [1, 0, 3, 2], 1), [1, -1], False)
|
|
||||||
class_preds = ops.reshape(class_scores, [1, -1], False)
|
|
||||||
|
|
||||||
detections = ops.detection_output(
|
|
||||||
box_logits,
|
|
||||||
class_preds,
|
|
||||||
proposals,
|
|
||||||
{
|
|
||||||
"background_label_id": 0,
|
|
||||||
"top_k": 100,
|
|
||||||
"keep_top_k": [100],
|
|
||||||
"nms_threshold": 0.6,
|
|
||||||
"confidence_threshold": 0.3,
|
|
||||||
"code_type": "caffe.PriorBoxParameter.CENTER_SIZE",
|
|
||||||
"share_location": True,
|
|
||||||
"variance_encoded_in_target": False,
|
|
||||||
"normalized": True,
|
|
||||||
"clip_before_nms": False,
|
|
||||||
"clip_after_nms": True,
|
|
||||||
"decrease_label_id": False,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
detections.output(0).get_tensor().set_names({"detection_out"})
|
|
||||||
|
|
||||||
model = ov.Model([detections], [parameter], "ssdlite_mobilenet_v2")
|
|
||||||
|
|
||||||
ppp = PrePostProcessor(model)
|
|
||||||
ppp.input().tensor().set_layout(ov.Layout("NHWC"))
|
|
||||||
ppp.input().preprocess().reverse_channels()
|
|
||||||
model = ppp.build()
|
|
||||||
|
|
||||||
# Fail the build rather than silently ship the dynamically shaped graph again.
|
|
||||||
op_types = [op.get_type_name() for op in model.get_ordered_ops()]
|
|
||||||
assert op_types.count("DetectionOutput") == 1, "postprocessor was not fused"
|
|
||||||
|
|
||||||
for dynamic_op in ("NonMaxSuppression", "NonZero", "Loop", "TensorIterator"):
|
|
||||||
assert dynamic_op not in op_types, f"{dynamic_op} left in the graph"
|
|
||||||
|
|
||||||
output_shape = model.outputs[0].get_partial_shape()
|
|
||||||
assert output_shape.is_static and list(output_shape) == [1, 1, 100, 7], (
|
|
||||||
f"unexpected detector output shape {output_shape}"
|
|
||||||
)
|
|
||||||
|
|
||||||
ov.save_model(model, OUTPUT_PATH, compress_to_fp16=True)
|
|
||||||
|
|||||||
@ -2,31 +2,18 @@
|
|||||||
|
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
|
|
||||||
SQLITE3_VERSION="3.46.1"
|
SQLITE3_VERSION="96c92aba00c8375bc32fafcdf12429c58bd8aabfcadab6683e35bbb9cdebf19e" # 3.46.0
|
||||||
PYSQLITE3_VERSION="0.5.3"
|
PYSQLITE3_VERSION="0.5.3"
|
||||||
|
|
||||||
# Install libsqlite3-dev if not present (needed for some base images like NVIDIA TensorRT)
|
# Fetch the source code for the latest release of Sqlite.
|
||||||
if ! dpkg -l | grep -q libsqlite3-dev; then
|
|
||||||
echo "Installing libsqlite3-dev for compilation..."
|
|
||||||
apt-get update && apt-get install -y libsqlite3-dev && rm -rf /var/lib/apt/lists/*
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Fetch the pre-built sqlite amalgamation instead of building from source
|
|
||||||
if [[ ! -d "sqlite" ]]; then
|
if [[ ! -d "sqlite" ]]; then
|
||||||
mkdir sqlite
|
wget https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=${SQLITE3_VERSION} -O sqlite.tar.gz
|
||||||
cd sqlite
|
tar xzf sqlite.tar.gz
|
||||||
|
cd sqlite/
|
||||||
# Download the pre-built amalgamation from sqlite.org
|
LIBS="-lm" ./configure --disable-tcl --enable-tempstore=always
|
||||||
# For SQLite 3.46.1, the amalgamation version is 3460100
|
make sqlite3.c
|
||||||
SQLITE_AMALGAMATION_VERSION="3460100"
|
|
||||||
|
|
||||||
wget https://www.sqlite.org/2024/sqlite-amalgamation-${SQLITE_AMALGAMATION_VERSION}.zip -O sqlite-amalgamation.zip
|
|
||||||
unzip sqlite-amalgamation.zip
|
|
||||||
mv sqlite-amalgamation-${SQLITE_AMALGAMATION_VERSION}/* .
|
|
||||||
rmdir sqlite-amalgamation-${SQLITE_AMALGAMATION_VERSION}
|
|
||||||
rm sqlite-amalgamation.zip
|
|
||||||
|
|
||||||
cd ../
|
cd ../
|
||||||
|
rm sqlite.tar.gz
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Grab the pysqlite3 source code.
|
# Grab the pysqlite3 source code.
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
|
|
||||||
SQLITE_VEC_VERSION="0.1.9"
|
SQLITE_VEC_VERSION="0.1.3"
|
||||||
|
|
||||||
source /etc/os-release
|
source /etc/os-release
|
||||||
|
|
||||||
|
|||||||
@ -19,9 +19,7 @@ apt-get -qq install --no-install-recommends -y \
|
|||||||
nethogs \
|
nethogs \
|
||||||
libgl1 \
|
libgl1 \
|
||||||
libglib2.0-0 \
|
libglib2.0-0 \
|
||||||
libusb-1.0.0 \
|
libusb-1.0.0
|
||||||
python3-h2 \
|
|
||||||
libgomp1 # memryx detector
|
|
||||||
|
|
||||||
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1
|
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1
|
||||||
|
|
||||||
@ -33,18 +31,6 @@ unset DEBIAN_FRONTEND
|
|||||||
yes | dpkg -i /tmp/libedgetpu1-max.deb && export DEBIAN_FRONTEND=noninteractive
|
yes | dpkg -i /tmp/libedgetpu1-max.deb && export DEBIAN_FRONTEND=noninteractive
|
||||||
rm /tmp/libedgetpu1-max.deb
|
rm /tmp/libedgetpu1-max.deb
|
||||||
|
|
||||||
# install mesa-teflon-delegate from bookworm-backports
|
|
||||||
# Only available for arm64 at the moment
|
|
||||||
if [[ "${TARGETARCH}" == "arm64" ]]; then
|
|
||||||
if [[ "${BASE_IMAGE}" == *"nvcr.io/nvidia/tensorrt"* ]]; then
|
|
||||||
echo "Info: Skipping apt-get commands because BASE_IMAGE includes 'nvcr.io/nvidia/tensorrt' for arm64."
|
|
||||||
else
|
|
||||||
echo "deb http://deb.debian.org/debian bookworm-backports main" | tee /etc/apt/sources.list.d/bookworm-backbacks.list
|
|
||||||
apt-get -qq update
|
|
||||||
apt-get -qq install --no-install-recommends --no-install-suggests -y mesa-teflon-delegate/bookworm-backports
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ffmpeg -> amd64
|
# ffmpeg -> amd64
|
||||||
if [[ "${TARGETARCH}" == "amd64" ]]; then
|
if [[ "${TARGETARCH}" == "amd64" ]]; then
|
||||||
mkdir -p /usr/lib/ffmpeg/5.0
|
mkdir -p /usr/lib/ffmpeg/5.0
|
||||||
@ -55,10 +41,6 @@ if [[ "${TARGETARCH}" == "amd64" ]]; then
|
|||||||
wget -qO ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2024-09-19-12-51/ffmpeg-n7.0.2-18-g3e6cec1286-linux64-gpl-7.0.tar.xz"
|
wget -qO ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2024-09-19-12-51/ffmpeg-n7.0.2-18-g3e6cec1286-linux64-gpl-7.0.tar.xz"
|
||||||
tar -xf ffmpeg.tar.xz -C /usr/lib/ffmpeg/7.0 --strip-components 1 amd64/bin/ffmpeg amd64/bin/ffprobe
|
tar -xf ffmpeg.tar.xz -C /usr/lib/ffmpeg/7.0 --strip-components 1 amd64/bin/ffmpeg amd64/bin/ffprobe
|
||||||
rm -rf ffmpeg.tar.xz
|
rm -rf ffmpeg.tar.xz
|
||||||
mkdir -p /usr/lib/ffmpeg/8.0
|
|
||||||
wget -qO ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2026-06-02-14-20/ffmpeg-n8.1.1-9-g58d4114d36-linux64-gpl-8.1.tar.xz"
|
|
||||||
tar -xf ffmpeg.tar.xz -C /usr/lib/ffmpeg/8.0 --strip-components 1 amd64/bin/ffmpeg amd64/bin/ffprobe
|
|
||||||
rm -rf ffmpeg.tar.xz
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ffmpeg -> arm64
|
# ffmpeg -> arm64
|
||||||
@ -71,84 +53,29 @@ if [[ "${TARGETARCH}" == "arm64" ]]; then
|
|||||||
wget -qO ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2024-09-19-12-51/ffmpeg-n7.0.2-18-g3e6cec1286-linuxarm64-gpl-7.0.tar.xz"
|
wget -qO ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2024-09-19-12-51/ffmpeg-n7.0.2-18-g3e6cec1286-linuxarm64-gpl-7.0.tar.xz"
|
||||||
tar -xf ffmpeg.tar.xz -C /usr/lib/ffmpeg/7.0 --strip-components 1 arm64/bin/ffmpeg arm64/bin/ffprobe
|
tar -xf ffmpeg.tar.xz -C /usr/lib/ffmpeg/7.0 --strip-components 1 arm64/bin/ffmpeg arm64/bin/ffprobe
|
||||||
rm -f ffmpeg.tar.xz
|
rm -f ffmpeg.tar.xz
|
||||||
mkdir -p /usr/lib/ffmpeg/8.0
|
|
||||||
wget -qO ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2026-06-02-14-20/ffmpeg-n8.1.1-9-g58d4114d36-linuxarm64-gpl-8.1.tar.xz"
|
|
||||||
tar -xf ffmpeg.tar.xz -C /usr/lib/ffmpeg/8.0 --strip-components 1 arm64/bin/ffmpeg arm64/bin/ffprobe
|
|
||||||
rm -f ffmpeg.tar.xz
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# arch specific packages
|
# arch specific packages
|
||||||
if [[ "${TARGETARCH}" == "amd64" ]]; then
|
if [[ "${TARGETARCH}" == "amd64" ]]; then
|
||||||
# Install non-free version of i965 driver
|
|
||||||
sed -i -E "/^Components: main$/s/main/main contrib non-free non-free-firmware/" "/etc/apt/sources.list.d/debian.sources" \
|
|
||||||
&& apt-get -qq update \
|
|
||||||
&& apt-get install --no-install-recommends --no-install-suggests -y i965-va-driver-shaders \
|
|
||||||
&& sed -i -E "/^Components: main contrib non-free non-free-firmware$/s/main contrib non-free non-free-firmware/main/" "/etc/apt/sources.list.d/debian.sources" \
|
|
||||||
&& apt-get update
|
|
||||||
|
|
||||||
# install amd / intel-i965 driver packages
|
# install amd / intel-i965 driver packages
|
||||||
apt-get -qq install --no-install-recommends --no-install-suggests -y \
|
apt-get -qq install --no-install-recommends --no-install-suggests -y \
|
||||||
intel-gpu-tools onevpl-tools \
|
i965-va-driver intel-gpu-tools onevpl-tools \
|
||||||
libva-drm2 \
|
libva-drm2 \
|
||||||
mesa-va-drivers radeontop
|
mesa-va-drivers radeontop
|
||||||
|
|
||||||
# intel packages use zst compression so we need to update dpkg
|
# intel packages use zst compression so we need to update dpkg
|
||||||
apt-get install -y dpkg
|
apt-get install -y dpkg
|
||||||
|
|
||||||
# use intel apt repo for libmfx1 (legacy QSV, pre-Gen12)
|
# use intel apt intel packages
|
||||||
wget -qO - https://repositories.intel.com/gpu/intel-graphics.key | gpg --yes --dearmor --output /usr/share/keyrings/intel-graphics.gpg
|
wget -qO - https://repositories.intel.com/gpu/intel-graphics.key | gpg --yes --dearmor --output /usr/share/keyrings/intel-graphics.gpg
|
||||||
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/intel-graphics.gpg] https://repositories.intel.com/gpu/ubuntu jammy client" | tee /etc/apt/sources.list.d/intel-gpu-jammy.list
|
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/intel-graphics.gpg] https://repositories.intel.com/gpu/ubuntu jammy client" | tee /etc/apt/sources.list.d/intel-gpu-jammy.list
|
||||||
apt-get -qq update
|
apt-get -qq update
|
||||||
|
|
||||||
# intel-media-va-driver-non-free is built from source in the
|
|
||||||
# intel-media-driver Dockerfile stage for Battlemage (Xe2) support
|
|
||||||
apt-get -qq install --no-install-recommends --no-install-suggests -y \
|
apt-get -qq install --no-install-recommends --no-install-suggests -y \
|
||||||
libmfx1
|
intel-opencl-icd=24.35.30872.31-996~22.04 intel-level-zero-gpu=1.3.29735.27-914~22.04 intel-media-va-driver-non-free=24.3.3-996~22.04 \
|
||||||
|
libmfx1=23.2.2-880~22.04 libmfxgen1=24.2.4-914~22.04 libvpl2=1:2.13.0.0-996~22.04
|
||||||
|
|
||||||
rm -f /usr/share/keyrings/intel-graphics.gpg
|
rm -f /usr/share/keyrings/intel-graphics.gpg
|
||||||
rm -f /etc/apt/sources.list.d/intel-gpu-jammy.list
|
rm -f /etc/apt/sources.list.d/intel-gpu-jammy.list
|
||||||
|
|
||||||
# upgrade libva2, oneVPL runtime, and libvpl2 from trixie for Battlemage support
|
|
||||||
echo "deb http://deb.debian.org/debian trixie main" > /etc/apt/sources.list.d/trixie.list
|
|
||||||
apt-get -qq update
|
|
||||||
apt-get -qq install -y -t trixie libva2 libva-drm2 libzstd1
|
|
||||||
apt-get -qq install -y -t trixie libmfx-gen1.2 libvpl2
|
|
||||||
rm -f /etc/apt/sources.list.d/trixie.list
|
|
||||||
apt-get -qq update
|
|
||||||
apt-get -qq install -y ocl-icd-libopencl1
|
|
||||||
|
|
||||||
# install libtbb12 for NPU support
|
|
||||||
apt-get -qq install -y libtbb12
|
|
||||||
|
|
||||||
# install legacy and standard intel compute packages
|
|
||||||
# see https://github.com/intel/compute-runtime/blob/master/LEGACY_PLATFORMS.md for more info
|
|
||||||
# needed core package
|
|
||||||
wget https://github.com/intel/compute-runtime/releases/download/26.14.37833.4/libigdgmm12_22.9.0_amd64.deb
|
|
||||||
dpkg -i libigdgmm12_22.9.0_amd64.deb
|
|
||||||
rm libigdgmm12_22.9.0_amd64.deb
|
|
||||||
|
|
||||||
# legacy compute-runtime packages
|
|
||||||
wget https://github.com/intel/compute-runtime/releases/download/24.35.30872.36/intel-opencl-icd-legacy1_24.35.30872.36_amd64.deb
|
|
||||||
wget https://github.com/intel/compute-runtime/releases/download/24.35.30872.36/intel-level-zero-gpu-legacy1_1.5.30872.36_amd64.deb
|
|
||||||
wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.17537.24/intel-igc-opencl_1.0.17537.24_amd64.deb
|
|
||||||
wget https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.17537.24/intel-igc-core_1.0.17537.24_amd64.deb
|
|
||||||
# standard compute-runtime packages
|
|
||||||
wget https://github.com/intel/compute-runtime/releases/download/26.14.37833.4/intel-opencl-icd_26.14.37833.4-0_amd64.deb
|
|
||||||
wget https://github.com/intel/compute-runtime/releases/download/26.14.37833.4/libze-intel-gpu1_26.14.37833.4-0_amd64.deb
|
|
||||||
wget https://github.com/intel/intel-graphics-compiler/releases/download/v2.32.7/intel-igc-opencl-2_2.32.7+21184_amd64.deb
|
|
||||||
wget https://github.com/intel/intel-graphics-compiler/releases/download/v2.32.7/intel-igc-core-2_2.32.7+21184_amd64.deb
|
|
||||||
# npu packages
|
|
||||||
wget https://github.com/oneapi-src/level-zero/releases/download/v1.28.2/level-zero_1.28.2+u22.04_amd64.deb
|
|
||||||
wget https://github.com/intel/linux-npu-driver/releases/download/v1.19.0/intel-driver-compiler-npu_1.19.0.20250707-16111289554_ubuntu22.04_amd64.deb
|
|
||||||
wget https://github.com/intel/linux-npu-driver/releases/download/v1.19.0/intel-fw-npu_1.19.0.20250707-16111289554_ubuntu22.04_amd64.deb
|
|
||||||
wget https://github.com/intel/linux-npu-driver/releases/download/v1.19.0/intel-level-zero-npu_1.19.0.20250707-16111289554_ubuntu22.04_amd64.deb
|
|
||||||
|
|
||||||
dpkg -i *.deb
|
|
||||||
rm *.deb
|
|
||||||
apt-get -qq install -f -y
|
|
||||||
|
|
||||||
# Battlemage uses the xe kernel driver, but the VA-API driver is still iHD.
|
|
||||||
# The oneVPL runtime may look for a driver named after the kernel module.
|
|
||||||
ln -sf /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so /usr/lib/x86_64-linux-gnu/dri/xe_drv_video.so
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${TARGETARCH}" == "arm64" ]]; then
|
if [[ "${TARGETARCH}" == "arm64" ]]; then
|
||||||
@ -167,6 +94,6 @@ rm -rf /var/lib/apt/lists/*
|
|||||||
|
|
||||||
# Install yq, for frigate-prepare and go2rtc echo source
|
# Install yq, for frigate-prepare and go2rtc echo source
|
||||||
curl -fsSL \
|
curl -fsSL \
|
||||||
"https://github.com/mikefarah/yq/releases/download/v4.48.2/yq_linux_$(dpkg --print-architecture)" \
|
"https://github.com/mikefarah/yq/releases/download/v4.33.3/yq_linux_$(dpkg --print-architecture)" \
|
||||||
--output /usr/local/bin/yq
|
--output /usr/local/bin/yq
|
||||||
chmod +x /usr/local/bin/yq
|
chmod +x /usr/local/bin/yq
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
|
|
||||||
hailo_version="4.21.0"
|
hailo_version="4.20.1"
|
||||||
|
|
||||||
if [[ "${TARGETARCH}" == "amd64" ]]; then
|
if [[ "${TARGETARCH}" == "amd64" ]]; then
|
||||||
arch="x86_64"
|
arch="x86_64"
|
||||||
|
|||||||
@ -1,31 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Download the MxAccl for Frigate github release
|
|
||||||
wget https://github.com/memryx/mx_accl_frigate/archive/refs/tags/v2.1.0.zip -O /tmp/mxaccl.zip
|
|
||||||
unzip /tmp/mxaccl.zip -d /tmp
|
|
||||||
mv /tmp/mx_accl_frigate-2.1.0 /opt/mx_accl_frigate
|
|
||||||
rm /tmp/mxaccl.zip
|
|
||||||
|
|
||||||
# Install Python dependencies
|
|
||||||
pip3 install -r /opt/mx_accl_frigate/freeze
|
|
||||||
|
|
||||||
# Link the Python package dynamically
|
|
||||||
SITE_PACKAGES=$(python3 -c "import site; print(site.getsitepackages()[0])")
|
|
||||||
ln -s /opt/mx_accl_frigate/memryx "$SITE_PACKAGES/memryx"
|
|
||||||
|
|
||||||
# Copy architecture-specific shared libraries
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
if [[ "$ARCH" == "x86_64" ]]; then
|
|
||||||
cp /opt/mx_accl_frigate/memryx/x86/libmemx.so* /usr/lib/x86_64-linux-gnu/
|
|
||||||
cp /opt/mx_accl_frigate/memryx/x86/libmx_accl.so* /usr/lib/x86_64-linux-gnu/
|
|
||||||
elif [[ "$ARCH" == "aarch64" ]]; then
|
|
||||||
cp /opt/mx_accl_frigate/memryx/arm/libmemx.so* /usr/lib/aarch64-linux-gnu/
|
|
||||||
cp /opt/mx_accl_frigate/memryx/arm/libmx_accl.so* /usr/lib/aarch64-linux-gnu/
|
|
||||||
else
|
|
||||||
echo "Unsupported architecture: $ARCH"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Refresh linker cache
|
|
||||||
ldconfig
|
|
||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
|
|
||||||
s6_version="3.2.1.0"
|
s6_version="3.1.5.0"
|
||||||
|
|
||||||
if [[ "${TARGETARCH}" == "amd64" ]]; then
|
if [[ "${TARGETARCH}" == "amd64" ]]; then
|
||||||
s6_arch="x86_64"
|
s6_arch="x86_64"
|
||||||
|
|||||||
@ -1,4 +1 @@
|
|||||||
ruff == 0.15.20
|
ruff
|
||||||
|
|
||||||
# types
|
|
||||||
types-peewee == 3.17.*
|
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
numpy
|
numpy
|
||||||
openvino >= 2026.2.0
|
tensorflow
|
||||||
|
openvino-dev>=2024.0.0
|
||||||
@ -1,28 +1,24 @@
|
|||||||
aiofiles == 24.1.*
|
aiofiles == 24.1.*
|
||||||
click == 8.1.*
|
click == 8.1.*
|
||||||
# FastAPI
|
# FastAPI
|
||||||
aiohttp == 3.12.*
|
aiohttp == 3.11.3
|
||||||
starlette == 0.47.*
|
starlette == 0.41.2
|
||||||
starlette-context == 0.4.*
|
starlette-context == 0.3.6
|
||||||
fastapi[standard-no-fastapi-cloud-cli] == 0.116.*
|
fastapi == 0.115.*
|
||||||
uvicorn == 0.35.*
|
uvicorn == 0.30.*
|
||||||
slowapi == 0.1.*
|
slowapi == 0.1.*
|
||||||
joserfc == 1.2.*
|
joserfc == 1.0.*
|
||||||
cryptography == 44.0.*
|
pathvalidate == 3.2.*
|
||||||
pathvalidate == 3.3.*
|
|
||||||
markupsafe == 3.0.*
|
markupsafe == 3.0.*
|
||||||
python-multipart == 0.0.26
|
python-multipart == 0.0.12
|
||||||
# Classification Model Training
|
|
||||||
tensorflow == 2.19.* ; platform_machine == 'aarch64'
|
|
||||||
tensorflow-cpu == 2.19.* ; platform_machine == 'x86_64'
|
|
||||||
# General
|
# General
|
||||||
mypy == 1.6.1
|
mypy == 1.6.1
|
||||||
onvif-zeep-async == 4.0.*
|
onvif-zeep-async == 3.1.*
|
||||||
paho-mqtt == 2.1.*
|
paho-mqtt == 2.1.*
|
||||||
pandas == 2.2.*
|
pandas == 2.2.*
|
||||||
peewee == 3.17.*
|
peewee == 3.17.*
|
||||||
peewee_migrate == 1.14.*
|
peewee_migrate == 1.13.*
|
||||||
psutil == 7.1.*
|
psutil == 6.1.*
|
||||||
pydantic == 2.10.*
|
pydantic == 2.10.*
|
||||||
git+https://github.com/fbcotter/py3nvml#egg=py3nvml
|
git+https://github.com/fbcotter/py3nvml#egg=py3nvml
|
||||||
pytz == 2025.*
|
pytz == 2025.*
|
||||||
@ -31,24 +27,24 @@ ruamel.yaml == 0.18.*
|
|||||||
tzlocal == 5.2
|
tzlocal == 5.2
|
||||||
requests == 2.32.*
|
requests == 2.32.*
|
||||||
types-requests == 2.32.*
|
types-requests == 2.32.*
|
||||||
norfair == 2.3.*
|
norfair == 2.2.*
|
||||||
setproctitle == 1.3.*
|
setproctitle == 1.3.*
|
||||||
ws4py == 0.5.*
|
ws4py == 0.5.*
|
||||||
unidecode == 1.3.*
|
unidecode == 1.3.*
|
||||||
titlecase == 2.4.*
|
|
||||||
# Image Manipulation
|
# Image Manipulation
|
||||||
numpy == 1.26.*
|
numpy == 1.26.*
|
||||||
opencv-python-headless == 4.11.0.*
|
opencv-python-headless == 4.11.0.*
|
||||||
opencv-contrib-python == 4.11.0.*
|
opencv-contrib-python == 4.11.0.*
|
||||||
scipy == 1.16.*
|
scipy == 1.14.*
|
||||||
# OpenVino & ONNX
|
# OpenVino & ONNX
|
||||||
openvino == 2025.4.*
|
openvino == 2024.4.*
|
||||||
onnxruntime == 1.22.*
|
onnxruntime-openvino == 1.20.* ; platform_machine == 'x86_64'
|
||||||
|
onnxruntime == 1.20.* ; platform_machine == 'aarch64'
|
||||||
# Embeddings
|
# Embeddings
|
||||||
transformers == 4.45.*
|
transformers == 4.45.*
|
||||||
# Generative AI
|
# Generative AI
|
||||||
google-genai == 1.58.*
|
google-generativeai == 0.8.*
|
||||||
ollama == 0.6.*
|
ollama == 0.3.*
|
||||||
openai == 1.65.*
|
openai == 1.65.*
|
||||||
# push notifications
|
# push notifications
|
||||||
py-vapid == 1.9.*
|
py-vapid == 1.9.*
|
||||||
@ -56,7 +52,7 @@ pywebpush == 2.0.*
|
|||||||
# alpr
|
# alpr
|
||||||
pyclipper == 1.3.*
|
pyclipper == 1.3.*
|
||||||
shapely == 2.0.*
|
shapely == 2.0.*
|
||||||
rapidfuzz==3.12.*
|
Levenshtein==0.26.*
|
||||||
# HailoRT Wheels
|
# HailoRT Wheels
|
||||||
appdirs==1.4.*
|
appdirs==1.4.*
|
||||||
argcomplete==2.0.*
|
argcomplete==2.0.*
|
||||||
@ -74,10 +70,3 @@ prometheus-client == 0.21.*
|
|||||||
# TFLite
|
# TFLite
|
||||||
tflite_runtime @ https://github.com/frigate-nvr/TFlite-builds/releases/download/v2.17.1/tflite_runtime-2.17.1-cp311-cp311-linux_x86_64.whl; platform_machine == 'x86_64'
|
tflite_runtime @ https://github.com/frigate-nvr/TFlite-builds/releases/download/v2.17.1/tflite_runtime-2.17.1-cp311-cp311-linux_x86_64.whl; platform_machine == 'x86_64'
|
||||||
tflite_runtime @ https://github.com/feranick/TFlite-builds/releases/download/v2.17.1/tflite_runtime-2.17.1-cp311-cp311-linux_aarch64.whl; platform_machine == 'aarch64'
|
tflite_runtime @ https://github.com/feranick/TFlite-builds/releases/download/v2.17.1/tflite_runtime-2.17.1-cp311-cp311-linux_aarch64.whl; platform_machine == 'aarch64'
|
||||||
# audio transcription
|
|
||||||
sherpa-onnx==1.12.*
|
|
||||||
faster-whisper==1.1.*
|
|
||||||
librosa==0.11.*
|
|
||||||
soundfile==0.13.*
|
|
||||||
# Memory profiling
|
|
||||||
memray == 1.15.*
|
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
scikit-build == 0.18.*
|
scikit-build == 0.18.*
|
||||||
|
nvidia-pyindex
|
||||||
|
|||||||
@ -10,8 +10,7 @@ echo "[INFO] Starting certsync..."
|
|||||||
|
|
||||||
lefile="/etc/letsencrypt/live/frigate/fullchain.pem"
|
lefile="/etc/letsencrypt/live/frigate/fullchain.pem"
|
||||||
|
|
||||||
tls_enabled=`python3 /usr/local/nginx/get_nginx_settings.py | jq -r .tls.enabled`
|
tls_enabled=`python3 /usr/local/nginx/get_tls_settings.py | jq -r .enabled`
|
||||||
listen_external_port=`python3 /usr/local/nginx/get_nginx_settings.py | jq -r .listen.external_port`
|
|
||||||
|
|
||||||
while true
|
while true
|
||||||
do
|
do
|
||||||
@ -35,7 +34,7 @@ do
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
liveprint=`echo | openssl s_client -showcerts -connect 127.0.0.1:$listen_external_port 2>&1 | openssl x509 -fingerprint 2>&1 | grep -i fingerprint || echo 'failed'`
|
liveprint=`echo | openssl s_client -showcerts -connect 127.0.0.1:8971 2>&1 | openssl x509 -fingerprint 2>&1 | grep -i fingerprint || echo 'failed'`
|
||||||
|
|
||||||
case "$liveprint" in
|
case "$liveprint" in
|
||||||
*Fingerprint*)
|
*Fingerprint*)
|
||||||
|
|||||||
@ -4,11 +4,6 @@
|
|||||||
|
|
||||||
set -o errexit -o nounset -o pipefail
|
set -o errexit -o nounset -o pipefail
|
||||||
|
|
||||||
# opt out of openvino telemetry
|
|
||||||
if [ -e /usr/local/bin/opt_in_out ]; then
|
|
||||||
/usr/local/bin/opt_in_out --opt_out > /dev/null 2>&1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Logs should be sent to stdout so that s6 can collect them
|
# Logs should be sent to stdout so that s6 can collect them
|
||||||
|
|
||||||
# Tell S6-Overlay not to restart this service
|
# Tell S6-Overlay not to restart this service
|
||||||
|
|||||||
@ -50,42 +50,6 @@ function set_libva_version() {
|
|||||||
export LIBAVFORMAT_VERSION_MAJOR
|
export LIBAVFORMAT_VERSION_MAJOR
|
||||||
}
|
}
|
||||||
|
|
||||||
function setup_homekit_config() {
|
|
||||||
local config_path="$1"
|
|
||||||
|
|
||||||
if [[ ! -f "${config_path}" ]]; then
|
|
||||||
echo "[INFO] Creating empty config file for HomeKit..."
|
|
||||||
: > "${config_path}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Convert YAML to JSON for jq processing
|
|
||||||
local temp_json="/tmp/cache/homekit_config.json"
|
|
||||||
yq eval -o=json "${config_path}" > "${temp_json}" 2>/dev/null || {
|
|
||||||
echo "[WARNING] Failed to convert HomeKit config to JSON, skipping cleanup"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# Use jq to extract the homekit section, if it exists
|
|
||||||
local homekit_json
|
|
||||||
homekit_json=$(jq '
|
|
||||||
if has("homekit") then {homekit: .homekit} else null end
|
|
||||||
' "${temp_json}" 2>/dev/null) || homekit_json="null"
|
|
||||||
|
|
||||||
# If no homekit section, write an empty config file
|
|
||||||
if [[ "${homekit_json}" == "null" ]]; then
|
|
||||||
: > "${config_path}"
|
|
||||||
else
|
|
||||||
# Convert homekit JSON back to YAML and write to the config file
|
|
||||||
echo "${homekit_json}" | yq eval -P - > "${config_path}" 2>/dev/null || {
|
|
||||||
echo "[WARNING] Failed to convert cleaned config to YAML, creating minimal config"
|
|
||||||
: > "${config_path}"
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Clean up temp files
|
|
||||||
rm -f "${temp_json}"
|
|
||||||
}
|
|
||||||
|
|
||||||
set_libva_version
|
set_libva_version
|
||||||
|
|
||||||
if [[ -f "/dev/shm/go2rtc.yaml" ]]; then
|
if [[ -f "/dev/shm/go2rtc.yaml" ]]; then
|
||||||
@ -106,10 +70,6 @@ else
|
|||||||
echo "[WARNING] Unable to remove existing go2rtc config. Changes made to your frigate config file may not be recognized. Please remove the /dev/shm/go2rtc.yaml from your docker host manually."
|
echo "[WARNING] Unable to remove existing go2rtc config. Changes made to your frigate config file may not be recognized. Please remove the /dev/shm/go2rtc.yaml from your docker host manually."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# HomeKit configuration persistence setup
|
|
||||||
readonly homekit_config_path="/config/go2rtc_homekit.yml"
|
|
||||||
setup_homekit_config "${homekit_config_path}"
|
|
||||||
|
|
||||||
readonly config_path="/config"
|
readonly config_path="/config"
|
||||||
|
|
||||||
if [[ -x "${config_path}/go2rtc" ]]; then
|
if [[ -x "${config_path}/go2rtc" ]]; then
|
||||||
@ -122,7 +82,5 @@ fi
|
|||||||
echo "[INFO] Starting go2rtc..."
|
echo "[INFO] Starting go2rtc..."
|
||||||
|
|
||||||
# Replace the bash process with the go2rtc process, redirecting stderr to stdout
|
# Replace the bash process with the go2rtc process, redirecting stderr to stdout
|
||||||
# Use HomeKit config as the primary config so writebacks go there
|
|
||||||
# The main config from Frigate will be loaded as a secondary config
|
|
||||||
exec 2>&1
|
exec 2>&1
|
||||||
exec "${binary_path}" -config="${homekit_config_path}" -config=/dev/shm/go2rtc.yaml
|
exec "${binary_path}" -config=/dev/shm/go2rtc.yaml
|
||||||
|
|||||||
@ -80,14 +80,14 @@ if [ ! \( -f "$letsencrypt_path/privkey.pem" -a -f "$letsencrypt_path/fullchain.
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# build templates for optional FRIGATE_BASE_PATH environment variable
|
# build templates for optional FRIGATE_BASE_PATH environment variable
|
||||||
python3 /usr/local/nginx/get_nginx_settings.py | \
|
python3 /usr/local/nginx/get_base_path.py | \
|
||||||
tempio -template /usr/local/nginx/templates/base_path.gotmpl \
|
tempio -template /usr/local/nginx/templates/base_path.gotmpl \
|
||||||
-out /usr/local/nginx/conf/base_path.conf
|
-out /usr/local/nginx/conf/base_path.conf
|
||||||
|
|
||||||
# build templates for additional network settings
|
# build templates for optional TLS support
|
||||||
python3 /usr/local/nginx/get_nginx_settings.py | \
|
python3 /usr/local/nginx/get_tls_settings.py | \
|
||||||
tempio -template /usr/local/nginx/templates/listen.gotmpl \
|
tempio -template /usr/local/nginx/templates/listen.gotmpl \
|
||||||
-out /usr/local/nginx/conf/listen.conf
|
-out /usr/local/nginx/conf/listen.conf
|
||||||
|
|
||||||
# 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
|
||||||
|
|||||||
@ -138,9 +138,5 @@ function migrate_db_from_media_to_config() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# remove leftover from last run, not normally needed, but just in case
|
|
||||||
# used by the docker healthcheck
|
|
||||||
rm -f /dev/shm/.frigate-is-stopping
|
|
||||||
|
|
||||||
migrate_addon_config_dir
|
migrate_addon_config_dir
|
||||||
migrate_db_from_media_to_config
|
migrate_db_from_media_to_config
|
||||||
|
|||||||
@ -1,11 +1,14 @@
|
|||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from ruamel.yaml import YAML
|
from ruamel.yaml import YAML
|
||||||
|
|
||||||
sys.path.insert(0, "/opt/frigate")
|
sys.path.insert(0, "/opt/frigate")
|
||||||
from frigate.util.config import find_config_file, resolve_ffmpeg_path
|
from frigate.const import (
|
||||||
|
DEFAULT_FFMPEG_VERSION,
|
||||||
|
INCLUDED_FFMPEG_VERSIONS,
|
||||||
|
)
|
||||||
|
from frigate.util.config import find_config_file
|
||||||
|
|
||||||
sys.path.remove("/opt/frigate")
|
sys.path.remove("/opt/frigate")
|
||||||
|
|
||||||
@ -18,11 +21,16 @@ try:
|
|||||||
raw_config = f.read()
|
raw_config = f.read()
|
||||||
|
|
||||||
if config_file.endswith((".yaml", ".yml")):
|
if config_file.endswith((".yaml", ".yml")):
|
||||||
config: dict[str, Any] = yaml.load(raw_config)
|
config: dict[str, any] = yaml.load(raw_config)
|
||||||
elif config_file.endswith(".json"):
|
elif config_file.endswith(".json"):
|
||||||
config: dict[str, Any] = json.loads(raw_config)
|
config: dict[str, any] = json.loads(raw_config)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
config: dict[str, Any] = {}
|
config: dict[str, any] = {}
|
||||||
|
|
||||||
path = config.get("ffmpeg", {}).get("path", "default")
|
path = config.get("ffmpeg", {}).get("path", "default")
|
||||||
print(resolve_ffmpeg_path(path, "ffmpeg"))
|
if path == "default":
|
||||||
|
print(f"/usr/lib/ffmpeg/{DEFAULT_FFMPEG_VERSION}/bin/ffmpeg")
|
||||||
|
elif path in INCLUDED_FFMPEG_VERSIONS:
|
||||||
|
print(f"/usr/lib/ffmpeg/{path}/bin/ffmpeg")
|
||||||
|
else:
|
||||||
|
print(f"{path}/bin/ffmpeg")
|
||||||
|
|||||||
@ -4,22 +4,18 @@ import json
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from ruamel.yaml import YAML
|
from ruamel.yaml import YAML
|
||||||
|
|
||||||
sys.path.insert(0, "/opt/frigate")
|
sys.path.insert(0, "/opt/frigate")
|
||||||
from frigate.config.env import substitute_frigate_vars
|
|
||||||
from frigate.const import (
|
from frigate.const import (
|
||||||
BIRDSEYE_PIPE,
|
BIRDSEYE_PIPE,
|
||||||
|
DEFAULT_FFMPEG_VERSION,
|
||||||
|
INCLUDED_FFMPEG_VERSIONS,
|
||||||
LIBAVFORMAT_VERSION_MAJOR,
|
LIBAVFORMAT_VERSION_MAJOR,
|
||||||
)
|
)
|
||||||
from frigate.ffmpeg_presets import parse_preset_hardware_acceleration_encode
|
from frigate.ffmpeg_presets import parse_preset_hardware_acceleration_encode
|
||||||
from frigate.util.config import find_config_file, resolve_ffmpeg_path
|
from frigate.util.config import find_config_file
|
||||||
from frigate.util.services import (
|
|
||||||
is_go2rtc_arbitrary_exec_allowed,
|
|
||||||
is_restricted_go2rtc_source,
|
|
||||||
)
|
|
||||||
|
|
||||||
sys.path.remove("/opt/frigate")
|
sys.path.remove("/opt/frigate")
|
||||||
|
|
||||||
@ -41,13 +37,13 @@ try:
|
|||||||
raw_config = f.read()
|
raw_config = f.read()
|
||||||
|
|
||||||
if config_file.endswith((".yaml", ".yml")):
|
if config_file.endswith((".yaml", ".yml")):
|
||||||
config: dict[str, Any] = yaml.load(raw_config)
|
config: dict[str, any] = yaml.load(raw_config)
|
||||||
elif config_file.endswith(".json"):
|
elif config_file.endswith(".json"):
|
||||||
config: dict[str, Any] = json.loads(raw_config)
|
config: dict[str, any] = json.loads(raw_config)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
config: dict[str, Any] = {}
|
config: dict[str, any] = {}
|
||||||
|
|
||||||
go2rtc_config: dict[str, Any] = config.get("go2rtc", {})
|
go2rtc_config: dict[str, any] = config.get("go2rtc", {})
|
||||||
|
|
||||||
# Need to enable CORS for go2rtc so the frigate integration / card work automatically
|
# Need to enable CORS for go2rtc so the frigate integration / card work automatically
|
||||||
if go2rtc_config.get("api") is None:
|
if go2rtc_config.get("api") is None:
|
||||||
@ -57,7 +53,7 @@ elif go2rtc_config["api"].get("origin") is None:
|
|||||||
|
|
||||||
# Need to set default location for HA config
|
# Need to set default location for HA config
|
||||||
if go2rtc_config.get("hass") is None:
|
if go2rtc_config.get("hass") is None:
|
||||||
go2rtc_config["hass"] = {"config": "/homeassistant"}
|
go2rtc_config["hass"] = {"config": "/config"}
|
||||||
|
|
||||||
# we want to ensure that logs are easy to read
|
# we want to ensure that logs are easy to read
|
||||||
if go2rtc_config.get("log") is None:
|
if go2rtc_config.get("log") is None:
|
||||||
@ -81,18 +77,23 @@ if go2rtc_config["webrtc"].get("candidates") is None:
|
|||||||
go2rtc_config["webrtc"]["candidates"] = default_candidates
|
go2rtc_config["webrtc"]["candidates"] = default_candidates
|
||||||
|
|
||||||
if go2rtc_config.get("rtsp", {}).get("username") is not None:
|
if go2rtc_config.get("rtsp", {}).get("username") is not None:
|
||||||
go2rtc_config["rtsp"]["username"] = substitute_frigate_vars(
|
go2rtc_config["rtsp"]["username"] = go2rtc_config["rtsp"]["username"].format(
|
||||||
go2rtc_config["rtsp"]["username"]
|
**FRIGATE_ENV_VARS
|
||||||
)
|
)
|
||||||
|
|
||||||
if go2rtc_config.get("rtsp", {}).get("password") is not None:
|
if go2rtc_config.get("rtsp", {}).get("password") is not None:
|
||||||
go2rtc_config["rtsp"]["password"] = substitute_frigate_vars(
|
go2rtc_config["rtsp"]["password"] = go2rtc_config["rtsp"]["password"].format(
|
||||||
go2rtc_config["rtsp"]["password"]
|
**FRIGATE_ENV_VARS
|
||||||
)
|
)
|
||||||
|
|
||||||
# ensure ffmpeg path is set correctly
|
# ensure ffmpeg path is set correctly
|
||||||
path = config.get("ffmpeg", {}).get("path", "default")
|
path = config.get("ffmpeg", {}).get("path", "default")
|
||||||
ffmpeg_path = resolve_ffmpeg_path(path, "ffmpeg")
|
if path == "default":
|
||||||
|
ffmpeg_path = f"/usr/lib/ffmpeg/{DEFAULT_FFMPEG_VERSION}/bin/ffmpeg"
|
||||||
|
elif path in INCLUDED_FFMPEG_VERSIONS:
|
||||||
|
ffmpeg_path = f"/usr/lib/ffmpeg/{path}/bin/ffmpeg"
|
||||||
|
else:
|
||||||
|
ffmpeg_path = f"{path}/bin/ffmpeg"
|
||||||
|
|
||||||
if go2rtc_config.get("ffmpeg") is None:
|
if go2rtc_config.get("ffmpeg") is None:
|
||||||
go2rtc_config["ffmpeg"] = {"bin": ffmpeg_path}
|
go2rtc_config["ffmpeg"] = {"bin": ffmpeg_path}
|
||||||
@ -107,21 +108,14 @@ if LIBAVFORMAT_VERSION_MAJOR < 59:
|
|||||||
elif go2rtc_config["ffmpeg"].get("rtsp") is None:
|
elif go2rtc_config["ffmpeg"].get("rtsp") is None:
|
||||||
go2rtc_config["ffmpeg"]["rtsp"] = rtsp_args
|
go2rtc_config["ffmpeg"]["rtsp"] = rtsp_args
|
||||||
|
|
||||||
|
for name in go2rtc_config.get("streams", {}):
|
||||||
for name in list(go2rtc_config.get("streams", {})):
|
|
||||||
stream = go2rtc_config["streams"][name]
|
stream = go2rtc_config["streams"][name]
|
||||||
|
|
||||||
if isinstance(stream, str):
|
if isinstance(stream, str):
|
||||||
try:
|
try:
|
||||||
formatted_stream = stream.format(**FRIGATE_ENV_VARS)
|
go2rtc_config["streams"][name] = go2rtc_config["streams"][name].format(
|
||||||
if is_restricted_go2rtc_source(formatted_stream):
|
**FRIGATE_ENV_VARS
|
||||||
print(
|
)
|
||||||
f"[ERROR] Stream '{name}' uses a restricted source (echo/expr/exec) which is disabled by default for security. "
|
|
||||||
f"Set GO2RTC_ALLOW_ARBITRARY_EXEC=true to enable arbitrary exec sources."
|
|
||||||
)
|
|
||||||
del go2rtc_config["streams"][name]
|
|
||||||
continue
|
|
||||||
go2rtc_config["streams"][name] = formatted_stream
|
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
print(
|
print(
|
||||||
"[ERROR] Invalid substitution found, see https://docs.frigate.video/configuration/restream#advanced-restream-configurations for more info."
|
"[ERROR] Invalid substitution found, see https://docs.frigate.video/configuration/restream#advanced-restream-configurations for more info."
|
||||||
@ -129,50 +123,18 @@ for name in list(go2rtc_config.get("streams", {})):
|
|||||||
sys.exit(e)
|
sys.exit(e)
|
||||||
|
|
||||||
elif isinstance(stream, list):
|
elif isinstance(stream, list):
|
||||||
filtered_streams = []
|
for i, stream in enumerate(stream):
|
||||||
for i, stream_item in enumerate(stream):
|
|
||||||
try:
|
try:
|
||||||
formatted_stream = stream_item.format(**FRIGATE_ENV_VARS)
|
go2rtc_config["streams"][name][i] = stream.format(**FRIGATE_ENV_VARS)
|
||||||
if is_restricted_go2rtc_source(formatted_stream):
|
|
||||||
print(
|
|
||||||
f"[ERROR] Stream '{name}' item {i + 1} uses a restricted source (echo/expr/exec) which is disabled by default for security. "
|
|
||||||
f"Set GO2RTC_ALLOW_ARBITRARY_EXEC=true to enable arbitrary exec sources."
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
|
|
||||||
filtered_streams.append(formatted_stream)
|
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
print(
|
print(
|
||||||
"[ERROR] Invalid substitution found, see https://docs.frigate.video/configuration/restream#advanced-restream-configurations for more info."
|
"[ERROR] Invalid substitution found, see https://docs.frigate.video/configuration/restream#advanced-restream-configurations for more info."
|
||||||
)
|
)
|
||||||
sys.exit(e)
|
sys.exit(e)
|
||||||
|
|
||||||
if filtered_streams:
|
|
||||||
go2rtc_config["streams"][name] = filtered_streams
|
|
||||||
else:
|
|
||||||
print(
|
|
||||||
f"[ERROR] Stream '{name}' was removed because all sources were restricted (echo/expr/exec). "
|
|
||||||
f"Set GO2RTC_ALLOW_ARBITRARY_EXEC=true to enable arbitrary exec sources."
|
|
||||||
)
|
|
||||||
del go2rtc_config["streams"][name]
|
|
||||||
|
|
||||||
elif isinstance(stream, dict):
|
|
||||||
# The map form ({"url": ...}) lets go2rtc resolve the source
|
|
||||||
# recursively, so it is effectively a dynamic way to generate the URL
|
|
||||||
# for a stream. That can only be backed by an exec source, so it cannot
|
|
||||||
# be allowed unless arbitrary exec is explicitly enabled. When it is
|
|
||||||
# enabled, leave the map untouched for go2rtc to resolve.
|
|
||||||
if not is_go2rtc_arbitrary_exec_allowed():
|
|
||||||
print(
|
|
||||||
f"[ERROR] Stream '{name}' uses a dynamic source format which is disabled by default for security. "
|
|
||||||
f"Set GO2RTC_ALLOW_ARBITRARY_EXEC=true to enable arbitrary exec sources."
|
|
||||||
)
|
|
||||||
del go2rtc_config["streams"][name]
|
|
||||||
continue
|
|
||||||
|
|
||||||
# add birdseye restream stream if enabled
|
# add birdseye restream stream if enabled
|
||||||
if config.get("birdseye", {}).get("restream", False):
|
if config.get("birdseye", {}).get("restream", False):
|
||||||
birdseye: dict[str, Any] = config.get("birdseye")
|
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}"
|
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(ffmpeg_path, config.get('ffmpeg', {}).get('hwaccel_args', ''), input, '-rtsp_transport tcp -f rtsp {output}')}"
|
ffmpeg_cmd = f"exec:{parse_preset_hardware_acceleration_encode(ffmpeg_path, config.get('ffmpeg', {}).get('hwaccel_args', ''), input, '-rtsp_transport tcp -f rtsp {output}')}"
|
||||||
|
|||||||
@ -17,9 +17,7 @@ http {
|
|||||||
|
|
||||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
'$status $body_bytes_sent "$http_referer" '
|
'$status $body_bytes_sent "$http_referer" '
|
||||||
'"$http_user_agent" "$http_x_forwarded_for" '
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
'request_time="$request_time" upstream_response_time="$upstream_response_time"';
|
|
||||||
|
|
||||||
|
|
||||||
access_log /dev/stdout main;
|
access_log /dev/stdout main;
|
||||||
|
|
||||||
@ -63,9 +61,6 @@ http {
|
|||||||
server {
|
server {
|
||||||
include listen.conf;
|
include listen.conf;
|
||||||
|
|
||||||
# enable HTTP/2 for TLS connections to eliminate browser 6-connection limit
|
|
||||||
http2 on;
|
|
||||||
|
|
||||||
# vod settings
|
# vod settings
|
||||||
vod_base_url '';
|
vod_base_url '';
|
||||||
vod_segments_base_url '';
|
vod_segments_base_url '';
|
||||||
@ -76,8 +71,6 @@ http {
|
|||||||
vod_manifest_segment_durations_mode accurate;
|
vod_manifest_segment_durations_mode accurate;
|
||||||
vod_ignore_edit_list on;
|
vod_ignore_edit_list on;
|
||||||
vod_segment_duration 10000;
|
vod_segment_duration 10000;
|
||||||
|
|
||||||
# MPEG-TS settings (not used when fMP4 is enabled, kept for reference)
|
|
||||||
vod_hls_mpegts_align_frames off;
|
vod_hls_mpegts_align_frames off;
|
||||||
vod_hls_mpegts_interleave_frames on;
|
vod_hls_mpegts_interleave_frames on;
|
||||||
|
|
||||||
@ -110,10 +103,6 @@ http {
|
|||||||
aio threads;
|
aio threads;
|
||||||
vod hls;
|
vod hls;
|
||||||
|
|
||||||
# Use fMP4 (fragmented MP4) instead of MPEG-TS for better performance
|
|
||||||
# Smaller segments, faster generation, better browser compatibility
|
|
||||||
vod_hls_container_format fmp4;
|
|
||||||
|
|
||||||
secure_token $args;
|
secure_token $args;
|
||||||
secure_token_types application/vnd.apple.mpegurl;
|
secure_token_types application/vnd.apple.mpegurl;
|
||||||
|
|
||||||
@ -227,6 +216,16 @@ http {
|
|||||||
include proxy.conf;
|
include proxy.conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# frontend uses this to fetch the version
|
||||||
|
location /api/go2rtc/api {
|
||||||
|
include auth_request.conf;
|
||||||
|
limit_except GET {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
proxy_pass http://go2rtc/api;
|
||||||
|
include proxy.conf;
|
||||||
|
}
|
||||||
|
|
||||||
# integration uses this to add webrtc candidate
|
# integration uses this to add webrtc candidate
|
||||||
location /api/go2rtc/webrtc {
|
location /api/go2rtc/webrtc {
|
||||||
include auth_request.conf;
|
include auth_request.conf;
|
||||||
@ -252,7 +251,6 @@ http {
|
|||||||
include proxy.conf;
|
include proxy.conf;
|
||||||
|
|
||||||
proxy_cache api_cache;
|
proxy_cache api_cache;
|
||||||
proxy_cache_key "$scheme$proxy_host$request_uri|$role|$groups|$user";
|
|
||||||
proxy_cache_lock on;
|
proxy_cache_lock on;
|
||||||
proxy_cache_use_stale updating;
|
proxy_cache_use_stale updating;
|
||||||
proxy_cache_valid 200 5s;
|
proxy_cache_valid 200 5s;
|
||||||
@ -274,25 +272,6 @@ http {
|
|||||||
include proxy.conf;
|
include proxy.conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
location /api/logout {
|
|
||||||
auth_request off;
|
|
||||||
rewrite ^/api(/.*)$ $1 break;
|
|
||||||
proxy_pass http://frigate_api;
|
|
||||||
include proxy.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Allow unauthenticated access to the first_time_login endpoint
|
|
||||||
# so the login page can load help text before authentication.
|
|
||||||
location /api/auth/first_time_login {
|
|
||||||
auth_request off;
|
|
||||||
limit_except GET {
|
|
||||||
deny all;
|
|
||||||
}
|
|
||||||
rewrite ^/api(/.*)$ $1 break;
|
|
||||||
proxy_pass http://frigate_api;
|
|
||||||
include proxy.conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /api/stats {
|
location /api/stats {
|
||||||
include auth_request.conf;
|
include auth_request.conf;
|
||||||
access_log off;
|
access_log off;
|
||||||
@ -321,12 +300,6 @@ http {
|
|||||||
add_header Cache-Control "public";
|
add_header Cache-Control "public";
|
||||||
}
|
}
|
||||||
|
|
||||||
location /fonts/ {
|
|
||||||
access_log off;
|
|
||||||
expires 1y;
|
|
||||||
add_header Cache-Control "public";
|
|
||||||
}
|
|
||||||
|
|
||||||
location /locales/ {
|
location /locales/ {
|
||||||
access_log off;
|
access_log off;
|
||||||
add_header Cache-Control "public";
|
add_header Cache-Control "public";
|
||||||
|
|||||||
@ -18,10 +18,6 @@ proxy_set_header X-Forwarded-User $http_x_forwarded_user;
|
|||||||
proxy_set_header X-Forwarded-Groups $http_x_forwarded_groups;
|
proxy_set_header X-Forwarded-Groups $http_x_forwarded_groups;
|
||||||
proxy_set_header X-Forwarded-Email $http_x_forwarded_email;
|
proxy_set_header X-Forwarded-Email $http_x_forwarded_email;
|
||||||
proxy_set_header X-Forwarded-Preferred-Username $http_x_forwarded_preferred_username;
|
proxy_set_header X-Forwarded-Preferred-Username $http_x_forwarded_preferred_username;
|
||||||
proxy_set_header X-Auth-Request-User $http_x_auth_request_user;
|
|
||||||
proxy_set_header X-Auth-Request-Groups $http_x_auth_request_groups;
|
|
||||||
proxy_set_header X-Auth-Request-Email $http_x_auth_request_email;
|
|
||||||
proxy_set_header X-Auth-Request-Preferred-Username $http_x_auth_request_preferred_username;
|
|
||||||
proxy_set_header X-authentik-username $http_x_authentik_username;
|
proxy_set_header X-authentik-username $http_x_authentik_username;
|
||||||
proxy_set_header X-authentik-groups $http_x_authentik_groups;
|
proxy_set_header X-authentik-groups $http_x_authentik_groups;
|
||||||
proxy_set_header X-authentik-email $http_x_authentik_email;
|
proxy_set_header X-authentik-email $http_x_authentik_email;
|
||||||
|
|||||||
10
docker/main/rootfs/usr/local/nginx/get_base_path.py
Normal file
10
docker/main/rootfs/usr/local/nginx/get_base_path.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
"""Prints the base path as json to stdout."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
base_path = os.environ.get("FRIGATE_BASE_PATH", "")
|
||||||
|
|
||||||
|
result: dict[str, any] = {"base_path": base_path}
|
||||||
|
|
||||||
|
print(json.dumps(result))
|
||||||
@ -1,62 +0,0 @@
|
|||||||
"""Prints the nginx settings as json to stdout."""
|
|
||||||
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from ruamel.yaml import YAML
|
|
||||||
|
|
||||||
sys.path.insert(0, "/opt/frigate")
|
|
||||||
from frigate.util.config import find_config_file
|
|
||||||
|
|
||||||
sys.path.remove("/opt/frigate")
|
|
||||||
|
|
||||||
yaml = YAML()
|
|
||||||
|
|
||||||
config_file = find_config_file()
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(config_file) as f:
|
|
||||||
raw_config = f.read()
|
|
||||||
|
|
||||||
if config_file.endswith((".yaml", ".yml")):
|
|
||||||
config: dict[str, Any] = yaml.load(raw_config)
|
|
||||||
elif config_file.endswith(".json"):
|
|
||||||
config: dict[str, Any] = json.loads(raw_config)
|
|
||||||
except FileNotFoundError:
|
|
||||||
config: dict[str, Any] = {}
|
|
||||||
|
|
||||||
tls_config: dict[str, Any] = config.get("tls", {})
|
|
||||||
tls_config.setdefault("enabled", True)
|
|
||||||
|
|
||||||
networking_config: dict[str, Any] = config.get("networking", {})
|
|
||||||
ipv6_config: dict[str, Any] = networking_config.get("ipv6", {})
|
|
||||||
ipv6_config.setdefault("enabled", False)
|
|
||||||
|
|
||||||
listen_config: dict[str, Any] = networking_config.get("listen", {})
|
|
||||||
listen_config.setdefault("internal", 5000)
|
|
||||||
listen_config.setdefault("external", 8971)
|
|
||||||
|
|
||||||
# handle case where internal port is a string with ip:port
|
|
||||||
internal_port = listen_config["internal"]
|
|
||||||
if type(internal_port) is str:
|
|
||||||
internal_port = int(internal_port.split(":")[-1])
|
|
||||||
listen_config["internal_port"] = internal_port
|
|
||||||
|
|
||||||
# handle case where external port is a string with ip:port
|
|
||||||
external_port = listen_config["external"]
|
|
||||||
if type(external_port) is str:
|
|
||||||
external_port = int(external_port.split(":")[-1])
|
|
||||||
listen_config["external_port"] = external_port
|
|
||||||
|
|
||||||
base_path = os.environ.get("FRIGATE_BASE_PATH", "")
|
|
||||||
|
|
||||||
result: dict[str, Any] = {
|
|
||||||
"tls": tls_config,
|
|
||||||
"ipv6": ipv6_config,
|
|
||||||
"listen": listen_config,
|
|
||||||
"base_path": base_path,
|
|
||||||
}
|
|
||||||
|
|
||||||
print(json.dumps(result))
|
|
||||||
30
docker/main/rootfs/usr/local/nginx/get_tls_settings.py
Normal file
30
docker/main/rootfs/usr/local/nginx/get_tls_settings.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
"""Prints the tls config as json to stdout."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from ruamel.yaml import YAML
|
||||||
|
|
||||||
|
sys.path.insert(0, "/opt/frigate")
|
||||||
|
from frigate.util.config import find_config_file
|
||||||
|
|
||||||
|
sys.path.remove("/opt/frigate")
|
||||||
|
|
||||||
|
yaml = YAML()
|
||||||
|
|
||||||
|
config_file = find_config_file()
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(config_file) as f:
|
||||||
|
raw_config = f.read()
|
||||||
|
|
||||||
|
if config_file.endswith((".yaml", ".yml")):
|
||||||
|
config: dict[str, any] = yaml.load(raw_config)
|
||||||
|
elif config_file.endswith(".json"):
|
||||||
|
config: dict[str, any] = json.loads(raw_config)
|
||||||
|
except FileNotFoundError:
|
||||||
|
config: dict[str, any] = {}
|
||||||
|
|
||||||
|
tls_config: dict[str, any] = config.get("tls", {"enabled": True})
|
||||||
|
|
||||||
|
print(json.dumps(tls_config))
|
||||||
@ -7,7 +7,7 @@ location ^~ {{ .base_path }}/ {
|
|||||||
# remove base_url from the path before passing upstream
|
# remove base_url from the path before passing upstream
|
||||||
rewrite ^{{ .base_path }}/(.*) /$1 break;
|
rewrite ^{{ .base_path }}/(.*) /$1 break;
|
||||||
|
|
||||||
proxy_pass $scheme://127.0.0.1:{{ .listen.external_port }};
|
proxy_pass $scheme://127.0.0.1:8971;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
proxy_set_header Connection "upgrade";
|
proxy_set_header Connection "upgrade";
|
||||||
|
|||||||
@ -1,36 +1,33 @@
|
|||||||
# Internal (IPv4 always; IPv6 optional)
|
# intended for internal traffic, not protected by auth
|
||||||
listen {{ .listen.internal }};
|
listen 5000;
|
||||||
{{ if .ipv6.enabled }}listen [::]:{{ .listen.internal_port }};{{ end }}
|
|
||||||
|
|
||||||
|
{{ if not .enabled }}
|
||||||
# intended for external traffic, protected by auth
|
# intended for external traffic, protected by auth
|
||||||
{{ if .tls.enabled }}
|
listen 8971;
|
||||||
# external HTTPS (IPv4 always; IPv6 optional)
|
|
||||||
listen {{ .listen.external }} ssl;
|
|
||||||
{{ if .ipv6.enabled }}listen [::]:{{ .listen.external_port }} ssl;{{ end }}
|
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/frigate/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/frigate/privkey.pem;
|
|
||||||
|
|
||||||
# generated 2024-06-01, Mozilla Guideline v5.7, nginx 1.25.3, OpenSSL 1.1.1w, modern configuration, no OCSP
|
|
||||||
# https://ssl-config.mozilla.org/#server=nginx&version=1.25.3&config=modern&openssl=1.1.1w&ocsp=false&guideline=5.7
|
|
||||||
ssl_session_timeout 1d;
|
|
||||||
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
|
|
||||||
ssl_session_tickets off;
|
|
||||||
|
|
||||||
# modern configuration
|
|
||||||
ssl_protocols TLSv1.3;
|
|
||||||
ssl_prefer_server_ciphers off;
|
|
||||||
|
|
||||||
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
|
|
||||||
add_header Strict-Transport-Security "max-age=63072000" always;
|
|
||||||
|
|
||||||
# ACME challenge location
|
|
||||||
location /.well-known/acme-challenge/ {
|
|
||||||
default_type "text/plain";
|
|
||||||
root /etc/letsencrypt/www;
|
|
||||||
}
|
|
||||||
{{ else }}
|
{{ else }}
|
||||||
# (No tls) default to HTTP (IPv4 always; IPv6 optional)
|
# intended for external traffic, protected by auth
|
||||||
listen {{ .listen.external }};
|
listen 8971 ssl;
|
||||||
{{ if .ipv6.enabled }}listen [::]:{{ .listen.external_port }};{{ end }}
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/frigate/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/frigate/privkey.pem;
|
||||||
|
|
||||||
|
# generated 2024-06-01, Mozilla Guideline v5.7, nginx 1.25.3, OpenSSL 1.1.1w, modern configuration, no OCSP
|
||||||
|
# https://ssl-config.mozilla.org/#server=nginx&version=1.25.3&config=modern&openssl=1.1.1w&ocsp=false&guideline=5.7
|
||||||
|
ssl_session_timeout 1d;
|
||||||
|
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
|
||||||
|
ssl_session_tickets off;
|
||||||
|
|
||||||
|
# modern configuration
|
||||||
|
ssl_protocols TLSv1.3;
|
||||||
|
ssl_prefer_server_ciphers off;
|
||||||
|
|
||||||
|
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
|
||||||
|
add_header Strict-Transport-Security "max-age=63072000" always;
|
||||||
|
|
||||||
|
# ACME challenge location
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
default_type "text/plain";
|
||||||
|
root /etc/letsencrypt/www;
|
||||||
|
}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
|||||||
@ -1,44 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e # Exit immediately if any command fails
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
echo "Starting MemryX driver and runtime installation..."
|
|
||||||
|
|
||||||
# Detect architecture
|
|
||||||
arch=$(uname -m)
|
|
||||||
|
|
||||||
# Purge existing packages and repo
|
|
||||||
echo "Removing old MemryX installations..."
|
|
||||||
# Remove any holds on MemryX packages (if they exist)
|
|
||||||
sudo apt-mark unhold memx-* mxa-manager || true
|
|
||||||
sudo apt purge -y memx-* mxa-manager || true
|
|
||||||
sudo rm -f /etc/apt/sources.list.d/memryx.list /etc/apt/trusted.gpg.d/memryx.asc
|
|
||||||
|
|
||||||
# Install kernel headers
|
|
||||||
echo "Installing kernel headers for: $(uname -r)"
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install -y dkms linux-headers-$(uname -r)
|
|
||||||
|
|
||||||
# Add MemryX key and repo
|
|
||||||
echo "Adding MemryX GPG key and repository..."
|
|
||||||
wget -qO- https://developer.memryx.com/deb/memryx.asc | sudo tee /etc/apt/trusted.gpg.d/memryx.asc >/dev/null
|
|
||||||
echo 'deb https://developer.memryx.com/deb stable main' | sudo tee /etc/apt/sources.list.d/memryx.list >/dev/null
|
|
||||||
|
|
||||||
# Update and install specific SDK 2.1 packages
|
|
||||||
echo "Installing MemryX SDK 2.1 packages..."
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install -y memx-drivers=2.1.* memx-accl=2.1.* mxa-manager=2.1.*
|
|
||||||
|
|
||||||
# Hold packages to prevent automatic upgrades
|
|
||||||
sudo apt-mark hold memx-drivers memx-accl mxa-manager
|
|
||||||
|
|
||||||
# ARM-specific board setup
|
|
||||||
if [[ "$arch" == "aarch64" || "$arch" == "arm64" ]]; then
|
|
||||||
echo "Running ARM board setup..."
|
|
||||||
sudo mx_arm_setup
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "\n\n\033[1;31mYOU MUST RESTART YOUR COMPUTER NOW\033[0m\n\n"
|
|
||||||
|
|
||||||
echo "MemryX SDK 2.1 installation complete!"
|
|
||||||
|
|
||||||
@ -11,10 +11,8 @@ COPY docker/main/requirements-wheels.txt /requirements-wheels.txt
|
|||||||
COPY docker/rockchip/requirements-wheels-rk.txt /requirements-wheels-rk.txt
|
COPY docker/rockchip/requirements-wheels-rk.txt /requirements-wheels-rk.txt
|
||||||
RUN sed -i "/https:\/\//d" /requirements-wheels.txt
|
RUN sed -i "/https:\/\//d" /requirements-wheels.txt
|
||||||
RUN sed -i "/onnxruntime/d" /requirements-wheels.txt
|
RUN sed -i "/onnxruntime/d" /requirements-wheels.txt
|
||||||
RUN sed -i '/\[.*\]/d' /requirements-wheels.txt \
|
RUN pip3 wheel --wheel-dir=/rk-wheels -c /requirements-wheels.txt -r /requirements-wheels-rk.txt
|
||||||
&& pip3 wheel --wheel-dir=/rk-wheels -c /requirements-wheels.txt -r /requirements-wheels-rk.txt
|
|
||||||
RUN rm -rf /rk-wheels/opencv_python-*
|
RUN rm -rf /rk-wheels/opencv_python-*
|
||||||
RUN rm -rf /rk-wheels/torch-*
|
|
||||||
|
|
||||||
FROM deps AS rk-frigate
|
FROM deps AS rk-frigate
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
@ -30,9 +28,7 @@ COPY docker/rockchip/conv2rknn.py /opt/conv2rknn.py
|
|||||||
|
|
||||||
ADD https://github.com/MarcA711/rknn-toolkit2/releases/download/v2.3.2/librknnrt.so /usr/lib/
|
ADD https://github.com/MarcA711/rknn-toolkit2/releases/download/v2.3.2/librknnrt.so /usr/lib/
|
||||||
|
|
||||||
ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/6.1-11/ffmpeg /usr/lib/ffmpeg/6.0/bin/
|
ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/6.1-7/ffmpeg /usr/lib/ffmpeg/6.0/bin/
|
||||||
ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/6.1-11/ffprobe /usr/lib/ffmpeg/6.0/bin/
|
ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/6.1-7/ffprobe /usr/lib/ffmpeg/6.0/bin/
|
||||||
ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/7.1-1/ffmpeg /usr/lib/ffmpeg/7.0/bin/
|
|
||||||
ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/7.1-1/ffprobe /usr/lib/ffmpeg/7.0/bin/
|
|
||||||
ENV DEFAULT_FFMPEG_VERSION="6.0"
|
ENV DEFAULT_FFMPEG_VERSION="6.0"
|
||||||
ENV INCLUDED_FFMPEG_VERSIONS="${DEFAULT_FFMPEG_VERSION}:${INCLUDED_FFMPEG_VERSIONS}"
|
ENV INCLUDED_FFMPEG_VERSIONS="${DEFAULT_FFMPEG_VERSION}:${INCLUDED_FFMPEG_VERSIONS}"
|
||||||
|
|||||||
@ -11,10 +11,10 @@ except FileNotFoundError:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open("/config/conv2rknn.yaml") as config_file:
|
with open("/config/conv2rknn.yaml", "r") as config_file:
|
||||||
configuration = yaml.safe_load(config_file)
|
configuration = yaml.safe_load(config_file)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
raise Exception("Please place a config file at /config/conv2rknn.yaml") from None
|
raise Exception("Please place a config file at /config/conv2rknn.yaml")
|
||||||
|
|
||||||
if configuration["config"] != None:
|
if configuration["config"] != None:
|
||||||
rknn_config = configuration["config"]
|
rknn_config = configuration["config"]
|
||||||
@ -31,7 +31,7 @@ if "soc" not in configuration:
|
|||||||
with open("/proc/device-tree/compatible") as file:
|
with open("/proc/device-tree/compatible") as file:
|
||||||
soc = file.read().split(",")[-1].strip("\x00")
|
soc = file.read().split(",")[-1].strip("\x00")
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
raise Exception("Make sure to run docker in privileged mode.") from None
|
raise Exception("Make sure to run docker in privileged mode.")
|
||||||
|
|
||||||
configuration["soc"] = [
|
configuration["soc"] = [
|
||||||
soc,
|
soc,
|
||||||
|
|||||||
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
ARG ROCM=1
|
ARG ROCM=6.3.3
|
||||||
|
ARG AMDGPU=gfx900
|
||||||
ARG HSA_OVERRIDE_GFX_VERSION
|
ARG HSA_OVERRIDE_GFX_VERSION
|
||||||
ARG HSA_OVERRIDE
|
ARG HSA_OVERRIDE
|
||||||
|
|
||||||
@ -10,17 +11,18 @@ ARG HSA_OVERRIDE
|
|||||||
FROM wget AS rocm
|
FROM wget AS rocm
|
||||||
|
|
||||||
ARG ROCM
|
ARG ROCM
|
||||||
|
ARG AMDGPU
|
||||||
|
|
||||||
RUN apt update -qq && \
|
RUN apt update && \
|
||||||
apt install -y wget gpg && \
|
apt install -y wget gpg && \
|
||||||
wget -O rocm.deb https://repo.radeon.com/amdgpu-install/7.2.3/ubuntu/jammy/amdgpu-install_7.2.3.70203-1_all.deb && \
|
wget -O rocm.deb https://repo.radeon.com/amdgpu-install/$ROCM/ubuntu/jammy/amdgpu-install_6.3.60303-1_all.deb && \
|
||||||
apt install -y ./rocm.deb && \
|
apt install -y ./rocm.deb && \
|
||||||
apt update && \
|
apt update && \
|
||||||
apt install -qq -y rocm
|
apt install -y rocm
|
||||||
|
|
||||||
RUN mkdir -p /opt/rocm-dist/opt/rocm-$ROCM/lib
|
RUN mkdir -p /opt/rocm-dist/opt/rocm-$ROCM/lib
|
||||||
RUN cd /opt/rocm-$ROCM/lib && \
|
RUN cd /opt/rocm-$ROCM/lib && \
|
||||||
cp -dpr libMIOpen*.so* libamd*.so* libhip*.so* libhsa*.so* libmigraphx*.so* librocm*.so* librocblas*.so* libroctracer*.so* librocsolver*.so* librocfft*.so* librocprofiler*.so* libroctx*.so* librocroller.so* /opt/rocm-dist/opt/rocm-$ROCM/lib/ && \
|
cp -dpr libMIOpen*.so* libamd*.so* libhip*.so* libhsa*.so* libmigraphx*.so* librocm*.so* librocblas*.so* libroctracer*.so* librocfft*.so* librocprofiler*.so* libroctx*.so* /opt/rocm-dist/opt/rocm-$ROCM/lib/ && \
|
||||||
mkdir -p /opt/rocm-dist/opt/rocm-$ROCM/lib/migraphx/lib && \
|
mkdir -p /opt/rocm-dist/opt/rocm-$ROCM/lib/migraphx/lib && \
|
||||||
cp -dpr migraphx/lib/* /opt/rocm-dist/opt/rocm-$ROCM/lib/migraphx/lib
|
cp -dpr migraphx/lib/* /opt/rocm-dist/opt/rocm-$ROCM/lib/migraphx/lib
|
||||||
RUN cd /opt/rocm-dist/opt/ && ln -s rocm-$ROCM rocm
|
RUN cd /opt/rocm-dist/opt/ && ln -s rocm-$ROCM rocm
|
||||||
@ -31,16 +33,7 @@ RUN echo /opt/rocm/lib|tee /opt/rocm-dist/etc/ld.so.conf.d/rocm.conf
|
|||||||
#######################################################################
|
#######################################################################
|
||||||
FROM deps AS deps-prelim
|
FROM deps AS deps-prelim
|
||||||
|
|
||||||
COPY docker/rocm/debian-backports.sources /etc/apt/sources.list.d/debian-backports.sources
|
RUN apt-get update && apt-get install -y libnuma1
|
||||||
# install_deps.sh upgraded libstdc++6 from trixie for Battlemage; the matching
|
|
||||||
# -dev package must also come from trixie or apt refuses to satisfy it.
|
|
||||||
RUN echo "deb http://deb.debian.org/debian trixie main" > /etc/apt/sources.list.d/trixie.list && \
|
|
||||||
apt-get update && \
|
|
||||||
apt-get install -y libnuma1 && \
|
|
||||||
apt-get install -qq -y -t bookworm-backports mesa-va-drivers mesa-vulkan-drivers && \
|
|
||||||
apt-get install -qq -y -t trixie libstdc++-14-dev && \
|
|
||||||
rm -f /etc/apt/sources.list.d/trixie.list && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
WORKDIR /opt/frigate
|
WORKDIR /opt/frigate
|
||||||
COPY --from=rootfs / /
|
COPY --from=rootfs / /
|
||||||
@ -51,37 +44,25 @@ RUN wget -q https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
|
|||||||
RUN python3 -m pip config set global.break-system-packages true
|
RUN python3 -m pip config set global.break-system-packages true
|
||||||
|
|
||||||
COPY docker/rocm/requirements-wheels-rocm.txt /requirements.txt
|
COPY docker/rocm/requirements-wheels-rocm.txt /requirements.txt
|
||||||
RUN pip3 uninstall -y onnxruntime \
|
RUN pip3 uninstall -y onnxruntime-openvino \
|
||||||
&& pip3 install -r /requirements.txt
|
&& pip3 install -r /requirements.txt
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
FROM scratch AS rocm-dist
|
FROM scratch AS rocm-dist
|
||||||
|
|
||||||
ARG ROCM
|
ARG ROCM
|
||||||
|
ARG AMDGPU
|
||||||
|
|
||||||
# Copy HIP headers required for MIOpen JIT (BuildHip) / HIPRTC at runtime
|
|
||||||
COPY --from=rocm /opt/rocm-${ROCM}/include/ /opt/rocm-${ROCM}/include/
|
|
||||||
COPY --from=rocm /opt/rocm-$ROCM/bin/rocminfo /opt/rocm-$ROCM/bin/migraphx-driver /opt/rocm-$ROCM/bin/
|
COPY --from=rocm /opt/rocm-$ROCM/bin/rocminfo /opt/rocm-$ROCM/bin/migraphx-driver /opt/rocm-$ROCM/bin/
|
||||||
# Copy MIOpen database files for gfx10xx, gfx11xx, and gfx12xx only (RDNA2/RDNA3/RDNA4)
|
COPY --from=rocm /opt/rocm-$ROCM/share/miopen/db/*$AMDGPU* /opt/rocm-$ROCM/share/miopen/db/
|
||||||
COPY --from=rocm /opt/rocm-$ROCM/share/miopen/db/*gfx10* /opt/rocm-$ROCM/share/miopen/db/
|
COPY --from=rocm /opt/rocm-$ROCM/share/miopen/db/*gfx908* /opt/rocm-$ROCM/share/miopen/db/
|
||||||
COPY --from=rocm /opt/rocm-$ROCM/share/miopen/db/*gfx11* /opt/rocm-$ROCM/share/miopen/db/
|
COPY --from=rocm /opt/rocm-$ROCM/lib/rocblas/library/*$AMDGPU* /opt/rocm-$ROCM/lib/rocblas/library/
|
||||||
COPY --from=rocm /opt/rocm-$ROCM/share/miopen/db/*gfx12* /opt/rocm-$ROCM/share/miopen/db/
|
|
||||||
# Copy rocBLAS library files for gfx10xx, gfx11xx, and gfx12xx only
|
|
||||||
COPY --from=rocm /opt/rocm-$ROCM/lib/rocblas/library/*gfx10* /opt/rocm-$ROCM/lib/rocblas/library/
|
|
||||||
COPY --from=rocm /opt/rocm-$ROCM/lib/rocblas/library/*gfx11* /opt/rocm-$ROCM/lib/rocblas/library/
|
|
||||||
COPY --from=rocm /opt/rocm-$ROCM/lib/rocblas/library/*gfx12* /opt/rocm-$ROCM/lib/rocblas/library/
|
|
||||||
COPY --from=rocm /opt/rocm-dist/ /
|
COPY --from=rocm /opt/rocm-dist/ /
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
FROM deps-prelim AS rocm-prelim-hsa-override0
|
FROM deps-prelim AS rocm-prelim-hsa-override0
|
||||||
ENV MIGRAPHX_DISABLE_MIOPEN_FUSION=1
|
ENV HSA_ENABLE_SDMA=0
|
||||||
ENV MIGRAPHX_DISABLE_SCHEDULE_PASS=1
|
ENV MIGRAPHX_ENABLE_NHWC=1
|
||||||
ENV MIGRAPHX_DISABLE_REDUCE_FUSION=1
|
|
||||||
ENV MIGRAPHX_ENABLE_HIPRTC_WORKAROUNDS=1
|
|
||||||
ENV MIOPEN_CUSTOM_CACHE_DIR=/config/model_cache/migraphx
|
|
||||||
ENV MIOPEN_USER_DB_PATH=/config/model_cache/migraphx
|
|
||||||
ENV AMD_COMGR_CACHE=1
|
|
||||||
ENV AMD_COMGR_CACHE_DIR=/config/model_cache/migraphx
|
|
||||||
|
|
||||||
COPY --from=rocm-dist / /
|
COPY --from=rocm-dist / /
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
Types: deb
|
|
||||||
URIs: http://deb.debian.org/debian
|
|
||||||
Suites: bookworm-backports
|
|
||||||
Components: main
|
|
||||||
Enabled: yes
|
|
||||||
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
|
|
||||||
@ -1 +1 @@
|
|||||||
onnxruntime-migraphx @ https://github.com/NickM-27/frigate-onnxruntime-rocm/releases/download/v7.2.3-1/onnxruntime_migraphx-1.24.4-cp311-cp311-linux_x86_64.whl
|
onnxruntime-rocm @ https://github.com/NickM-27/frigate-onnxruntime-rocm/releases/download/v6.3.3/onnxruntime_rocm-1.20.1-cp311-cp311-linux_x86_64.whl
|
||||||
@ -1,5 +1,8 @@
|
|||||||
|
variable "AMDGPU" {
|
||||||
|
default = "gfx900"
|
||||||
|
}
|
||||||
variable "ROCM" {
|
variable "ROCM" {
|
||||||
default = "7.2.3"
|
default = "6.3.3"
|
||||||
}
|
}
|
||||||
variable "HSA_OVERRIDE_GFX_VERSION" {
|
variable "HSA_OVERRIDE_GFX_VERSION" {
|
||||||
default = ""
|
default = ""
|
||||||
@ -35,6 +38,7 @@ target rocm {
|
|||||||
}
|
}
|
||||||
platforms = ["linux/amd64"]
|
platforms = ["linux/amd64"]
|
||||||
args = {
|
args = {
|
||||||
|
AMDGPU = AMDGPU,
|
||||||
ROCM = ROCM,
|
ROCM = ROCM,
|
||||||
HSA_OVERRIDE_GFX_VERSION = HSA_OVERRIDE_GFX_VERSION,
|
HSA_OVERRIDE_GFX_VERSION = HSA_OVERRIDE_GFX_VERSION,
|
||||||
HSA_OVERRIDE = HSA_OVERRIDE
|
HSA_OVERRIDE = HSA_OVERRIDE
|
||||||
|
|||||||
@ -1,15 +1,53 @@
|
|||||||
BOARDS += rocm
|
BOARDS += rocm
|
||||||
|
|
||||||
|
# AMD/ROCm is chunky so we build couple of smaller images for specific chipsets
|
||||||
|
ROCM_CHIPSETS:=gfx900:9.0.0 gfx1030:10.3.0 gfx1100:11.0.0
|
||||||
|
|
||||||
local-rocm: version
|
local-rocm: version
|
||||||
|
$(foreach chipset,$(ROCM_CHIPSETS), \
|
||||||
|
AMDGPU=$(word 1,$(subst :, ,$(chipset))) \
|
||||||
|
HSA_OVERRIDE_GFX_VERSION=$(word 2,$(subst :, ,$(chipset))) \
|
||||||
|
HSA_OVERRIDE=1 \
|
||||||
|
docker buildx bake --file=docker/rocm/rocm.hcl rocm \
|
||||||
|
--set rocm.tags=frigate:latest-rocm-$(word 1,$(subst :, ,$(chipset))) \
|
||||||
|
--load \
|
||||||
|
&&) true
|
||||||
|
|
||||||
|
unset HSA_OVERRIDE_GFX_VERSION && \
|
||||||
|
HSA_OVERRIDE=0 \
|
||||||
|
AMDGPU=gfx \
|
||||||
docker buildx bake --file=docker/rocm/rocm.hcl rocm \
|
docker buildx bake --file=docker/rocm/rocm.hcl rocm \
|
||||||
--set rocm.tags=frigate:latest-rocm \
|
--set rocm.tags=frigate:latest-rocm \
|
||||||
--load
|
--load
|
||||||
|
|
||||||
build-rocm: version
|
build-rocm: version
|
||||||
|
$(foreach chipset,$(ROCM_CHIPSETS), \
|
||||||
|
AMDGPU=$(word 1,$(subst :, ,$(chipset))) \
|
||||||
|
HSA_OVERRIDE_GFX_VERSION=$(word 2,$(subst :, ,$(chipset))) \
|
||||||
|
HSA_OVERRIDE=1 \
|
||||||
|
docker buildx bake --file=docker/rocm/rocm.hcl rocm \
|
||||||
|
--set rocm.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-rocm-$(chipset) \
|
||||||
|
&&) true
|
||||||
|
|
||||||
|
unset HSA_OVERRIDE_GFX_VERSION && \
|
||||||
|
HSA_OVERRIDE=0 \
|
||||||
|
AMDGPU=gfx \
|
||||||
docker buildx bake --file=docker/rocm/rocm.hcl rocm \
|
docker buildx bake --file=docker/rocm/rocm.hcl rocm \
|
||||||
--set rocm.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-rocm
|
--set rocm.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-rocm
|
||||||
|
|
||||||
push-rocm: build-rocm
|
push-rocm: build-rocm
|
||||||
|
$(foreach chipset,$(ROCM_CHIPSETS), \
|
||||||
|
AMDGPU=$(word 1,$(subst :, ,$(chipset))) \
|
||||||
|
HSA_OVERRIDE_GFX_VERSION=$(word 2,$(subst :, ,$(chipset))) \
|
||||||
|
HSA_OVERRIDE=1 \
|
||||||
|
docker buildx bake --file=docker/rocm/rocm.hcl rocm \
|
||||||
|
--set rocm.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-rocm-$(chipset) \
|
||||||
|
--push \
|
||||||
|
&&) true
|
||||||
|
|
||||||
|
unset HSA_OVERRIDE_GFX_VERSION && \
|
||||||
|
HSA_OVERRIDE=0 \
|
||||||
|
AMDGPU=gfx \
|
||||||
docker buildx bake --file=docker/rocm/rocm.hcl rocm \
|
docker buildx bake --file=docker/rocm/rocm.hcl rocm \
|
||||||
--set rocm.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-rocm \
|
--set rocm.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-rocm \
|
||||||
--push
|
--push
|
||||||
|
|||||||
@ -1,28 +0,0 @@
|
|||||||
# syntax=docker/dockerfile:1.6
|
|
||||||
|
|
||||||
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
|
||||||
|
|
||||||
# Globally set pip break-system-packages option to avoid having to specify it every time
|
|
||||||
ARG PIP_BREAK_SYSTEM_PACKAGES=1
|
|
||||||
|
|
||||||
FROM wheels AS synap1680-wheels
|
|
||||||
ARG TARGETARCH
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
RUN wget -qO- "https://github.com/GaryHuang-ASUS/synaptics_astra_sdk/releases/download/v1.5.0/Synaptics-SL1680-v1.5.0-rt.tar" | tar -C / -xzf -
|
|
||||||
RUN wget -P /wheels/ "https://github.com/synaptics-synap/synap-python/releases/download/v0.0.4-preview/synap_python-0.0.4-cp311-cp311-manylinux_2_35_aarch64.whl"
|
|
||||||
|
|
||||||
FROM deps AS synap1680-deps
|
|
||||||
ARG TARGETARCH
|
|
||||||
ARG PIP_BREAK_SYSTEM_PACKAGES
|
|
||||||
|
|
||||||
RUN --mount=type=bind,from=synap1680-wheels,source=/wheels,target=/deps/synap-wheels \
|
|
||||||
pip3 install --no-deps -U /deps/synap-wheels/*.whl
|
|
||||||
|
|
||||||
WORKDIR /opt/frigate/
|
|
||||||
COPY --from=rootfs / /
|
|
||||||
|
|
||||||
COPY --from=synap1680-wheels /rootfs/usr/local/lib/*.so /usr/lib
|
|
||||||
|
|
||||||
ADD https://raw.githubusercontent.com/synaptics-astra/synap-release/v1.5.0/models/dolphin/object_detection/coco/model/mobilenet224_full80/model.synap /synaptics/mobilenet.synap
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
target wheels {
|
|
||||||
dockerfile = "docker/main/Dockerfile"
|
|
||||||
platforms = ["linux/arm64"]
|
|
||||||
target = "wheels"
|
|
||||||
}
|
|
||||||
|
|
||||||
target deps {
|
|
||||||
dockerfile = "docker/main/Dockerfile"
|
|
||||||
platforms = ["linux/arm64"]
|
|
||||||
target = "deps"
|
|
||||||
}
|
|
||||||
|
|
||||||
target rootfs {
|
|
||||||
dockerfile = "docker/main/Dockerfile"
|
|
||||||
platforms = ["linux/arm64"]
|
|
||||||
target = "rootfs"
|
|
||||||
}
|
|
||||||
|
|
||||||
target synaptics {
|
|
||||||
dockerfile = "docker/synaptics/Dockerfile"
|
|
||||||
contexts = {
|
|
||||||
wheels = "target:wheels",
|
|
||||||
deps = "target:deps",
|
|
||||||
rootfs = "target:rootfs"
|
|
||||||
}
|
|
||||||
platforms = ["linux/arm64"]
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
BOARDS += synaptics
|
|
||||||
|
|
||||||
local-synaptics: version
|
|
||||||
docker buildx bake --file=docker/synaptics/synaptics.hcl synaptics \
|
|
||||||
--set synaptics.tags=frigate:latest-synaptics \
|
|
||||||
--load
|
|
||||||
|
|
||||||
build-synaptics: version
|
|
||||||
docker buildx bake --file=docker/synaptics/synaptics.hcl synaptics \
|
|
||||||
--set synaptics.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-synaptics
|
|
||||||
|
|
||||||
push-synaptics: build-synaptics
|
|
||||||
docker buildx bake --file=docker/synaptics/synaptics.hcl synaptics \
|
|
||||||
--set synaptics.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-synaptics \
|
|
||||||
--push
|
|
||||||
@ -6,32 +6,24 @@ ARG DEBIAN_FRONTEND=noninteractive
|
|||||||
# Globally set pip break-system-packages option to avoid having to specify it every time
|
# Globally set pip break-system-packages option to avoid having to specify it every time
|
||||||
ARG PIP_BREAK_SYSTEM_PACKAGES=1
|
ARG PIP_BREAK_SYSTEM_PACKAGES=1
|
||||||
|
|
||||||
FROM wheels AS trt-wheels
|
FROM tensorrt-base AS frigate-tensorrt
|
||||||
ARG PIP_BREAK_SYSTEM_PACKAGES
|
ARG PIP_BREAK_SYSTEM_PACKAGES
|
||||||
|
ENV TRT_VER=8.6.1
|
||||||
|
|
||||||
# Install TensorRT wheels
|
# Install TensorRT wheels
|
||||||
COPY docker/tensorrt/requirements-amd64.txt /requirements-tensorrt.txt
|
COPY docker/tensorrt/requirements-amd64.txt /requirements-tensorrt.txt
|
||||||
COPY docker/main/requirements-wheels.txt /requirements-wheels.txt
|
RUN pip3 install -U -r /requirements-tensorrt.txt && ldconfig
|
||||||
|
|
||||||
# remove dependencies from the requirements that have type constraints
|
|
||||||
RUN sed -i '/\[.*\]/d' /requirements-wheels.txt \
|
|
||||||
&& pip3 wheel --wheel-dir=/trt-wheels -c /requirements-wheels.txt -r /requirements-tensorrt.txt
|
|
||||||
|
|
||||||
FROM deps AS frigate-tensorrt
|
|
||||||
ARG PIP_BREAK_SYSTEM_PACKAGES
|
|
||||||
|
|
||||||
RUN --mount=type=bind,from=trt-wheels,source=/trt-wheels,target=/deps/trt-wheels \
|
|
||||||
pip3 uninstall -y onnxruntime \
|
|
||||||
&& pip3 install -U /deps/trt-wheels/*.whl
|
|
||||||
|
|
||||||
COPY --from=rootfs / /
|
|
||||||
COPY docker/tensorrt/detector/rootfs/etc/ld.so.conf.d /etc/ld.so.conf.d
|
|
||||||
RUN ldconfig
|
|
||||||
|
|
||||||
WORKDIR /opt/frigate/
|
WORKDIR /opt/frigate/
|
||||||
|
COPY --from=rootfs / /
|
||||||
|
|
||||||
# Dev Container w/ TRT
|
# Dev Container w/ TRT
|
||||||
FROM devcontainer AS devcontainer-trt
|
FROM devcontainer AS devcontainer-trt
|
||||||
|
|
||||||
|
COPY --from=trt-deps /usr/local/lib/libyolo_layer.so /usr/local/lib/libyolo_layer.so
|
||||||
|
COPY --from=trt-deps /usr/local/src/tensorrt_demos /usr/local/src/tensorrt_demos
|
||||||
|
COPY --from=trt-deps /usr/local/cuda-12.1 /usr/local/cuda
|
||||||
|
COPY docker/tensorrt/detector/rootfs/ /
|
||||||
|
COPY --from=trt-deps /usr/local/lib/libyolo_layer.so /usr/local/lib/libyolo_layer.so
|
||||||
RUN --mount=type=bind,from=trt-wheels,source=/trt-wheels,target=/deps/trt-wheels \
|
RUN --mount=type=bind,from=trt-wheels,source=/trt-wheels,target=/deps/trt-wheels \
|
||||||
pip3 install -U /deps/trt-wheels/*.whl
|
pip3 install -U /deps/trt-wheels/*.whl
|
||||||
|
|||||||
@ -1,61 +1,9 @@
|
|||||||
# syntax=docker/dockerfile:1.6
|
# syntax=docker/dockerfile:1.4
|
||||||
|
|
||||||
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
ARG BASE_IMAGE
|
ARG BASE_IMAGE
|
||||||
ARG TRT_BASE=nvcr.io/nvidia/tensorrt:23.12-py3
|
|
||||||
|
|
||||||
# Build TensorRT-specific library
|
|
||||||
FROM ${TRT_BASE} AS trt-deps
|
|
||||||
|
|
||||||
ARG TARGETARCH
|
|
||||||
ARG COMPUTE_LEVEL
|
|
||||||
|
|
||||||
RUN apt-get update \
|
|
||||||
&& apt-get install -y git build-essential cuda-nvcc-* cuda-nvtx-* libnvinfer-dev libnvinfer-plugin-dev libnvparsers-dev libnvonnxparsers-dev \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
RUN --mount=type=bind,source=docker/tensorrt/detector/tensorrt_libyolo.sh,target=/tensorrt_libyolo.sh \
|
|
||||||
/tensorrt_libyolo.sh
|
|
||||||
|
|
||||||
# COPY required individual CUDA deps
|
|
||||||
RUN mkdir -p /usr/local/cuda-deps
|
|
||||||
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
|
||||||
cp /usr/local/cuda-12.3/targets/x86_64-linux/lib/libcurand.so.* /usr/local/cuda-deps/ && \
|
|
||||||
cp /usr/local/cuda-12.3/targets/x86_64-linux/lib/libnvrtc.so.* /usr/local/cuda-deps/ && \
|
|
||||||
cd /usr/local/cuda-deps/ && \
|
|
||||||
for lib in libnvrtc.so.*; do \
|
|
||||||
if [[ "$lib" =~ libnvrtc.so\.([0-9]+\.[0-9]+\.[0-9]+) ]]; then \
|
|
||||||
version="${BASH_REMATCH[1]}"; \
|
|
||||||
ln -sf "libnvrtc.so.$version" libnvrtc.so; \
|
|
||||||
fi; \
|
|
||||||
done && \
|
|
||||||
for lib in libcurand.so.*; do \
|
|
||||||
if [[ "$lib" =~ libcurand.so\.([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) ]]; then \
|
|
||||||
version="${BASH_REMATCH[1]}"; \
|
|
||||||
ln -sf "libcurand.so.$version" libcurand.so; \
|
|
||||||
fi; \
|
|
||||||
done; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Frigate w/ TensorRT Support as separate image
|
|
||||||
FROM deps AS tensorrt-base
|
|
||||||
|
|
||||||
#Disable S6 Global timeout
|
|
||||||
ENV S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0
|
|
||||||
|
|
||||||
# COPY TensorRT Model Generation Deps
|
|
||||||
COPY --from=trt-deps /usr/local/lib/libyolo_layer.so /usr/local/lib/libyolo_layer.so
|
|
||||||
COPY --from=trt-deps /usr/local/src/tensorrt_demos /usr/local/src/tensorrt_demos
|
|
||||||
|
|
||||||
# COPY Individual CUDA deps folder
|
|
||||||
COPY --from=trt-deps /usr/local/cuda-deps /usr/local/cuda
|
|
||||||
|
|
||||||
COPY docker/tensorrt/detector/rootfs/ /
|
|
||||||
ENV YOLO_MODELS=""
|
|
||||||
|
|
||||||
HEALTHCHECK --start-period=600s --start-interval=5s --interval=15s --timeout=5s --retries=3 \
|
|
||||||
CMD curl --fail --silent --show-error http://127.0.0.1:5000/api/version || exit 1
|
|
||||||
|
|
||||||
FROM ${BASE_IMAGE} AS build-wheels
|
FROM ${BASE_IMAGE} AS build-wheels
|
||||||
ARG DEBIAN_FRONTEND
|
ARG DEBIAN_FRONTEND
|
||||||
|
|
||||||
@ -99,11 +47,12 @@ RUN --mount=type=bind,source=docker/tensorrt/detector/build_python_tensorrt.sh,t
|
|||||||
&& TENSORRT_VER=$(cat /etc/TENSORRT_VER) /deps/build_python_tensorrt.sh
|
&& TENSORRT_VER=$(cat /etc/TENSORRT_VER) /deps/build_python_tensorrt.sh
|
||||||
|
|
||||||
COPY docker/tensorrt/requirements-arm64.txt /requirements-tensorrt.txt
|
COPY docker/tensorrt/requirements-arm64.txt /requirements-tensorrt.txt
|
||||||
|
|
||||||
RUN pip3 wheel --wheel-dir=/trt-wheels -r /requirements-tensorrt.txt
|
|
||||||
|
|
||||||
# See https://elinux.org/Jetson_Zoo#ONNX_Runtime
|
# See https://elinux.org/Jetson_Zoo#ONNX_Runtime
|
||||||
ADD https://nvidia.box.com/shared/static/9yvw05k6u343qfnkhdv2x6xhygze0aq1.whl /trt-wheels/onnxruntime_gpu-1.19.0-cp311-cp311-linux_aarch64.whl
|
ADD https://nvidia.box.com/shared/static/9yvw05k6u343qfnkhdv2x6xhygze0aq1.whl /tmp/onnxruntime_gpu-1.19.0-cp311-cp311-linux_aarch64.whl
|
||||||
|
|
||||||
|
RUN pip3 uninstall -y onnxruntime-openvino \
|
||||||
|
&& pip3 wheel --wheel-dir=/trt-wheels -r /requirements-tensorrt.txt \
|
||||||
|
&& pip3 install --no-deps /tmp/onnxruntime_gpu-1.19.0-cp311-cp311-linux_aarch64.whl
|
||||||
|
|
||||||
FROM build-wheels AS trt-model-wheels
|
FROM build-wheels AS trt-model-wheels
|
||||||
ARG DEBIAN_FRONTEND
|
ARG DEBIAN_FRONTEND
|
||||||
@ -112,7 +61,7 @@ RUN apt-get update \
|
|||||||
&& apt-get install -y protobuf-compiler libprotobuf-dev \
|
&& apt-get install -y protobuf-compiler libprotobuf-dev \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
RUN --mount=type=bind,source=docker/tensorrt/requirements-models-arm64.txt,target=/requirements-tensorrt-models.txt \
|
RUN --mount=type=bind,source=docker/tensorrt/requirements-models-arm64.txt,target=/requirements-tensorrt-models.txt \
|
||||||
pip3 wheel --wheel-dir=/trt-model-wheels --no-deps -r /requirements-tensorrt-models.txt
|
pip3 wheel --wheel-dir=/trt-model-wheels -r /requirements-tensorrt-models.txt
|
||||||
|
|
||||||
FROM wget AS jetson-ffmpeg
|
FROM wget AS jetson-ffmpeg
|
||||||
ARG DEBIAN_FRONTEND
|
ARG DEBIAN_FRONTEND
|
||||||
@ -144,9 +93,7 @@ RUN mkdir -p /etc/ld.so.conf.d && echo /usr/lib/ffmpeg/jetson/lib/ > /etc/ld.so.
|
|||||||
COPY --from=trt-wheels /etc/TENSORRT_VER /etc/TENSORRT_VER
|
COPY --from=trt-wheels /etc/TENSORRT_VER /etc/TENSORRT_VER
|
||||||
RUN --mount=type=bind,from=trt-wheels,source=/trt-wheels,target=/deps/trt-wheels \
|
RUN --mount=type=bind,from=trt-wheels,source=/trt-wheels,target=/deps/trt-wheels \
|
||||||
--mount=type=bind,from=trt-model-wheels,source=/trt-model-wheels,target=/deps/trt-model-wheels \
|
--mount=type=bind,from=trt-model-wheels,source=/trt-model-wheels,target=/deps/trt-model-wheels \
|
||||||
pip3 uninstall -y onnxruntime \
|
pip3 install -U /deps/trt-wheels/*.whl /deps/trt-model-wheels/*.whl \
|
||||||
&& pip3 install -U /deps/trt-wheels/*.whl \
|
|
||||||
&& pip3 install -U /deps/trt-model-wheels/*.whl \
|
|
||||||
&& ldconfig
|
&& ldconfig
|
||||||
|
|
||||||
WORKDIR /opt/frigate/
|
WORKDIR /opt/frigate/
|
||||||
|
|||||||
57
docker/tensorrt/Dockerfile.base
Normal file
57
docker/tensorrt/Dockerfile.base
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
# syntax=docker/dockerfile:1.6
|
||||||
|
|
||||||
|
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||||
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
ARG TRT_BASE=nvcr.io/nvidia/tensorrt:23.12-py3
|
||||||
|
|
||||||
|
# Build TensorRT-specific library
|
||||||
|
FROM ${TRT_BASE} AS trt-deps
|
||||||
|
|
||||||
|
ARG TARGETARCH
|
||||||
|
ARG COMPUTE_LEVEL
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y git build-essential cuda-nvcc-* cuda-nvtx-* libnvinfer-dev libnvinfer-plugin-dev libnvparsers-dev libnvonnxparsers-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
RUN --mount=type=bind,source=docker/tensorrt/detector/tensorrt_libyolo.sh,target=/tensorrt_libyolo.sh \
|
||||||
|
/tensorrt_libyolo.sh
|
||||||
|
|
||||||
|
# COPY required individual CUDA deps
|
||||||
|
RUN mkdir -p /usr/local/cuda-deps
|
||||||
|
RUN if [ "$TARGETARCH" = "amd64" ]; then \
|
||||||
|
cp /usr/local/cuda-12.3/targets/x86_64-linux/lib/libcurand.so.* /usr/local/cuda-deps/ && \
|
||||||
|
cp /usr/local/cuda-12.3/targets/x86_64-linux/lib/libnvrtc.so.* /usr/local/cuda-deps/ && \
|
||||||
|
cd /usr/local/cuda-deps/ && \
|
||||||
|
for lib in libnvrtc.so.*; do \
|
||||||
|
if [[ "$lib" =~ libnvrtc.so\.([0-9]+\.[0-9]+\.[0-9]+) ]]; then \
|
||||||
|
version="${BASH_REMATCH[1]}"; \
|
||||||
|
ln -sf "libnvrtc.so.$version" libnvrtc.so; \
|
||||||
|
fi; \
|
||||||
|
done && \
|
||||||
|
for lib in libcurand.so.*; do \
|
||||||
|
if [[ "$lib" =~ libcurand.so\.([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) ]]; then \
|
||||||
|
version="${BASH_REMATCH[1]}"; \
|
||||||
|
ln -sf "libcurand.so.$version" libcurand.so; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Frigate w/ TensorRT Support as separate image
|
||||||
|
FROM deps AS tensorrt-base
|
||||||
|
|
||||||
|
#Disable S6 Global timeout
|
||||||
|
ENV S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0
|
||||||
|
|
||||||
|
# COPY TensorRT Model Generation Deps
|
||||||
|
COPY --from=trt-deps /usr/local/lib/libyolo_layer.so /usr/local/lib/libyolo_layer.so
|
||||||
|
COPY --from=trt-deps /usr/local/src/tensorrt_demos /usr/local/src/tensorrt_demos
|
||||||
|
|
||||||
|
# COPY Individual CUDA deps folder
|
||||||
|
COPY --from=trt-deps /usr/local/cuda-deps /usr/local/cuda
|
||||||
|
|
||||||
|
COPY docker/tensorrt/detector/rootfs/ /
|
||||||
|
ENV YOLO_MODELS=""
|
||||||
|
|
||||||
|
HEALTHCHECK --start-period=600s --start-interval=5s --interval=15s --timeout=5s --retries=3 \
|
||||||
|
CMD curl --fail --silent --show-error http://127.0.0.1:5000/api/version || exit 1
|
||||||
@ -1,6 +1,7 @@
|
|||||||
|
/usr/local/lib
|
||||||
|
/usr/local/cuda
|
||||||
|
/usr/local/lib/python3.11/dist-packages/tensorrt
|
||||||
/usr/local/lib/python3.11/dist-packages/nvidia/cudnn/lib
|
/usr/local/lib/python3.11/dist-packages/nvidia/cudnn/lib
|
||||||
/usr/local/lib/python3.11/dist-packages/nvidia/cuda_runtime/lib
|
/usr/local/lib/python3.11/dist-packages/nvidia/cuda_runtime/lib
|
||||||
/usr/local/lib/python3.11/dist-packages/nvidia/cublas/lib
|
/usr/local/lib/python3.11/dist-packages/nvidia/cublas/lib
|
||||||
/usr/local/lib/python3.11/dist-packages/nvidia/cufft/lib
|
/usr/local/lib/python3.11/dist-packages/nvidia/cufft/lib
|
||||||
/usr/local/lib/python3.11/dist-packages/nvidia/curand/lib/
|
|
||||||
/usr/local/lib/python3.11/dist-packages/nvidia/cuda_nvrtc/lib/
|
|
||||||
@ -1,18 +1,17 @@
|
|||||||
# Nvidia ONNX Runtime GPU Support
|
# NVidia TensorRT Support (amd64 only)
|
||||||
--extra-index-url 'https://pypi.nvidia.com'
|
--extra-index-url 'https://pypi.nvidia.com'
|
||||||
cython==3.0.*; platform_machine == 'x86_64'
|
numpy < 1.24; platform_machine == 'x86_64'
|
||||||
nvidia-cuda-cupti-cu12==12.8.90; platform_machine == 'x86_64'
|
tensorrt == 8.6.1; platform_machine == 'x86_64'
|
||||||
nvidia-cublas-cu12==12.8.4.1; platform_machine == 'x86_64'
|
tensorrt_bindings == 8.6.1; platform_machine == 'x86_64'
|
||||||
nvidia-cudnn-cu12==9.8.0.87; platform_machine == 'x86_64'
|
cuda-python == 11.8.*; platform_machine == 'x86_64'
|
||||||
nvidia-cufft-cu12==11.3.3.83; platform_machine == 'x86_64'
|
cython == 3.0.*; platform_machine == 'x86_64'
|
||||||
nvidia-curand-cu12==10.3.9.90; platform_machine == 'x86_64'
|
nvidia-cuda-runtime-cu12 == 12.1.*; platform_machine == 'x86_64'
|
||||||
nvidia-cuda-nvcc-cu12==12.8.93; platform_machine == 'x86_64'
|
nvidia-cuda-runtime-cu11 == 11.8.*; platform_machine == 'x86_64'
|
||||||
nvidia-cuda-nvrtc-cu12==12.8.93; platform_machine == 'x86_64'
|
nvidia-cublas-cu11 == 11.11.3.6; platform_machine == 'x86_64'
|
||||||
nvidia-cuda-runtime-cu12==12.8.90; platform_machine == 'x86_64'
|
nvidia-cudnn-cu11 == 8.6.0.*; platform_machine == 'x86_64'
|
||||||
nvidia-cusolver-cu12==11.7.3.90; platform_machine == 'x86_64'
|
nvidia-cudnn-cu12 == 9.5.0.*; platform_machine == 'x86_64'
|
||||||
nvidia-cusparse-cu12==12.5.8.93; platform_machine == 'x86_64'
|
nvidia-cufft-cu11==10.*; platform_machine == 'x86_64'
|
||||||
nvidia-nccl-cu12==2.26.2.post1; platform_machine == 'x86_64'
|
nvidia-cufft-cu12==11.*; platform_machine == 'x86_64'
|
||||||
nvidia-nvjitlink-cu12==12.8.93; platform_machine == 'x86_64'
|
|
||||||
onnx==1.16.*; platform_machine == 'x86_64'
|
onnx==1.16.*; platform_machine == 'x86_64'
|
||||||
onnxruntime-gpu==1.24.*; platform_machine == 'x86_64'
|
onnxruntime-gpu==1.20.*; platform_machine == 'x86_64'
|
||||||
protobuf==3.20.3; platform_machine == 'x86_64'
|
protobuf==3.20.3; platform_machine == 'x86_64'
|
||||||
|
|||||||
@ -1,2 +1 @@
|
|||||||
cuda-python == 12.6.*; platform_machine == 'aarch64'
|
cuda-python == 12.6.*; platform_machine == 'aarch64'
|
||||||
numpy == 1.26.*; platform_machine == 'aarch64'
|
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
onnx == 1.14.0; platform_machine == 'aarch64'
|
onnx == 1.14.0; platform_machine == 'aarch64'
|
||||||
protobuf == 3.20.3; platform_machine == 'aarch64'
|
protobuf == 3.20.3; platform_machine == 'aarch64'
|
||||||
|
numpy == 1.23.*; platform_machine == 'aarch64' # required by python-tensorrt 8.2.1 (Jetpack 4.6)
|
||||||
|
|||||||
@ -79,13 +79,21 @@ target "trt-deps" {
|
|||||||
inherits = ["_build_args"]
|
inherits = ["_build_args"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
target "tensorrt-base" {
|
||||||
|
dockerfile = "docker/tensorrt/Dockerfile.base"
|
||||||
|
context = "."
|
||||||
|
contexts = {
|
||||||
|
deps = "target:deps",
|
||||||
|
}
|
||||||
|
inherits = ["_build_args"]
|
||||||
|
}
|
||||||
|
|
||||||
target "tensorrt" {
|
target "tensorrt" {
|
||||||
dockerfile = "docker/tensorrt/Dockerfile.${ARCH}"
|
dockerfile = "docker/tensorrt/Dockerfile.${ARCH}"
|
||||||
context = "."
|
context = "."
|
||||||
contexts = {
|
contexts = {
|
||||||
wget = "target:wget",
|
wget = "target:wget",
|
||||||
wheels = "target:wheels",
|
tensorrt-base = "target:tensorrt-base",
|
||||||
deps = "target:deps",
|
|
||||||
rootfs = "target:rootfs"
|
rootfs = "target:rootfs"
|
||||||
}
|
}
|
||||||
target = "frigate-tensorrt"
|
target = "frigate-tensorrt"
|
||||||
|
|||||||
1
docs/.gitignore
vendored
1
docs/.gitignore
vendored
@ -7,7 +7,6 @@
|
|||||||
# Generated files
|
# Generated files
|
||||||
.docusaurus
|
.docusaurus
|
||||||
.cache-loader
|
.cache-loader
|
||||||
docs/integrations/api/
|
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
259
docs/docs/configuration/advanced.md
Normal file
259
docs/docs/configuration/advanced.md
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
---
|
||||||
|
id: advanced
|
||||||
|
title: Advanced Options
|
||||||
|
sidebar_label: Advanced Options
|
||||||
|
---
|
||||||
|
|
||||||
|
### Logging
|
||||||
|
|
||||||
|
#### Frigate `logger`
|
||||||
|
|
||||||
|
Change the default log level for troubleshooting purposes.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
logger:
|
||||||
|
# Optional: default log level (default: shown below)
|
||||||
|
default: info
|
||||||
|
# Optional: module by module log level configuration
|
||||||
|
logs:
|
||||||
|
frigate.mqtt: error
|
||||||
|
```
|
||||||
|
|
||||||
|
Available log levels are: `debug`, `info`, `warning`, `error`, `critical`
|
||||||
|
|
||||||
|
Examples of available modules are:
|
||||||
|
|
||||||
|
- `frigate.app`
|
||||||
|
- `frigate.mqtt`
|
||||||
|
- `frigate.object_detection`
|
||||||
|
- `detector.<detector_name>`
|
||||||
|
- `watchdog.<camera_name>`
|
||||||
|
- `ffmpeg.<camera_name>.<sorted_roles>` NOTE: All FFmpeg logs are sent as `error` level.
|
||||||
|
|
||||||
|
#### Go2RTC Logging
|
||||||
|
|
||||||
|
See [the go2rtc docs](https://github.com/AlexxIT/go2rtc?tab=readme-ov-file#module-log) for logging configuration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
go2rtc:
|
||||||
|
streams:
|
||||||
|
# ...
|
||||||
|
log:
|
||||||
|
exec: trace
|
||||||
|
```
|
||||||
|
|
||||||
|
### `environment_vars`
|
||||||
|
|
||||||
|
This section can be used to set environment variables for those unable to modify the environment of the container, like within Home Assistant OS.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
environment_vars:
|
||||||
|
VARIABLE_NAME: variable_value
|
||||||
|
```
|
||||||
|
|
||||||
|
### `database`
|
||||||
|
|
||||||
|
Tracked object and recording information is managed in a sqlite database at `/config/frigate.db`. If that database is deleted, recordings will be orphaned and will need to be cleaned up manually. They also won't show up in the Media Browser within Home Assistant.
|
||||||
|
|
||||||
|
If you are storing your database on a network share (SMB, NFS, etc), you may get a `database is locked` error message on startup. You can customize the location of the database in the config if necessary.
|
||||||
|
|
||||||
|
This may need to be in a custom location if network storage is used for the media folder.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
database:
|
||||||
|
path: /path/to/frigate.db
|
||||||
|
```
|
||||||
|
|
||||||
|
### `model`
|
||||||
|
|
||||||
|
If using a custom model, the width and height will need to be specified.
|
||||||
|
|
||||||
|
Custom models may also require different input tensor formats. The colorspace conversion supports RGB, BGR, or YUV frames to be sent to the object detector. The input tensor shape parameter is an enumeration to match what specified by the model.
|
||||||
|
|
||||||
|
| Tensor Dimension | Description |
|
||||||
|
| :--------------: | -------------- |
|
||||||
|
| N | Batch Size |
|
||||||
|
| H | Model Height |
|
||||||
|
| W | Model Width |
|
||||||
|
| C | Color Channels |
|
||||||
|
|
||||||
|
| Available Input Tensor Shapes |
|
||||||
|
| :---------------------------: |
|
||||||
|
| "nhwc" |
|
||||||
|
| "nchw" |
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Optional: model config
|
||||||
|
model:
|
||||||
|
path: /path/to/model
|
||||||
|
width: 320
|
||||||
|
height: 320
|
||||||
|
input_tensor: "nhwc"
|
||||||
|
input_pixel_format: "bgr"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `labelmap`
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
|
||||||
|
If the labelmap is customized then the labels used for alerts will need to be adjusted as well. See [alert labels](../configuration/review.md#restricting-alerts-to-specific-labels) for more info.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
The labelmap can be customized to your needs. A common reason to do this is to combine multiple object types that are easily confused when you don't need to be as granular such as car/truck. By default, truck is renamed to car because they are often confused. You cannot add new object types, but you can change the names of existing objects in the model.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
model:
|
||||||
|
labelmap:
|
||||||
|
2: vehicle
|
||||||
|
3: vehicle
|
||||||
|
5: vehicle
|
||||||
|
7: vehicle
|
||||||
|
15: animal
|
||||||
|
16: animal
|
||||||
|
17: animal
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that if you rename objects in the labelmap, you will also need to update your `objects -> track` list as well.
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
|
||||||
|
Some labels have special handling and modifications can disable functionality.
|
||||||
|
|
||||||
|
`person` objects are associated with `face` and `amazon`
|
||||||
|
|
||||||
|
`car` objects are associated with `license_plate`, `ups`, `fedex`, `amazon`
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Network Configuration
|
||||||
|
|
||||||
|
Changes to Frigate's internal network configuration can be made by bind mounting nginx.conf into the container. For example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
frigate:
|
||||||
|
container_name: frigate
|
||||||
|
...
|
||||||
|
volumes:
|
||||||
|
...
|
||||||
|
- /path/to/your/nginx.conf:/usr/local/nginx/conf/nginx.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Enabling IPv6
|
||||||
|
|
||||||
|
IPv6 is disabled by default, to enable IPv6 listen.gotmpl needs to be bind mounted with IPv6 enabled. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
{{ if not .enabled }}
|
||||||
|
# intended for external traffic, protected by auth
|
||||||
|
listen 8971;
|
||||||
|
{{ else }}
|
||||||
|
# intended for external traffic, protected by auth
|
||||||
|
listen 8971 ssl;
|
||||||
|
|
||||||
|
# intended for internal traffic, not protected by auth
|
||||||
|
listen 5000;
|
||||||
|
```
|
||||||
|
|
||||||
|
becomes
|
||||||
|
|
||||||
|
```
|
||||||
|
{{ if not .enabled }}
|
||||||
|
# intended for external traffic, protected by auth
|
||||||
|
listen [::]:8971 ipv6only=off;
|
||||||
|
{{ else }}
|
||||||
|
# intended for external traffic, protected by auth
|
||||||
|
listen [::]:8971 ipv6only=off ssl;
|
||||||
|
|
||||||
|
# intended for internal traffic, not protected by auth
|
||||||
|
listen [::]:5000 ipv6only=off;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Base path
|
||||||
|
|
||||||
|
By default, Frigate runs at the root path (`/`). However some setups require to run Frigate under a custom path prefix (e.g. `/frigate`), especially when Frigate is located behind a reverse proxy that requires path-based routing.
|
||||||
|
|
||||||
|
### Set Base Path via HTTP Header
|
||||||
|
The preferred way to configure the base path is through the `X-Ingress-Path` HTTP header, which needs to be set to the desired base path in an upstream reverse proxy.
|
||||||
|
|
||||||
|
For example, in Nginx:
|
||||||
|
```
|
||||||
|
location /frigate {
|
||||||
|
proxy_set_header X-Ingress-Path /frigate;
|
||||||
|
proxy_pass http://frigate_backend;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set Base Path via Environment Variable
|
||||||
|
When it is not feasible to set the base path via a HTTP header, it can also be set via the `FRIGATE_BASE_PATH` environment variable in the Docker Compose file.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
```
|
||||||
|
services:
|
||||||
|
frigate:
|
||||||
|
image: blakeblackshear/frigate:latest
|
||||||
|
environment:
|
||||||
|
- FRIGATE_BASE_PATH=/frigate
|
||||||
|
```
|
||||||
|
|
||||||
|
This can be used for example to access Frigate via a Tailscale agent (https), by simply forwarding all requests to the base path (http):
|
||||||
|
```
|
||||||
|
tailscale serve --https=443 --bg --set-path /frigate http://localhost:5000/frigate
|
||||||
|
```
|
||||||
|
|
||||||
|
## Custom Dependencies
|
||||||
|
|
||||||
|
### Custom ffmpeg build
|
||||||
|
|
||||||
|
Included with Frigate is a build of ffmpeg that works for the vast majority of users. However, there exists some hardware setups which have incompatibilities with the included build. In this case, statically built `ffmpeg` and `ffprobe` binaries can be placed in `/config/custom-ffmpeg/bin` for Frigate to use.
|
||||||
|
|
||||||
|
To do this:
|
||||||
|
|
||||||
|
1. Download your ffmpeg build and uncompress it to the `/config/custom-ffmpeg` folder. Verify that both the `ffmpeg` and `ffprobe` binaries are located in `/config/custom-ffmpeg/bin`.
|
||||||
|
2. Update the `ffmpeg.path` in your Frigate config to `/config/custom-ffmpeg`.
|
||||||
|
3. Restart Frigate and the custom version will be used if the steps above were done correctly.
|
||||||
|
|
||||||
|
### Custom go2rtc version
|
||||||
|
|
||||||
|
Frigate currently includes go2rtc v1.9.9, there may be certain cases where you want to run a different version of go2rtc.
|
||||||
|
|
||||||
|
To do this:
|
||||||
|
|
||||||
|
1. Download the go2rtc build to the `/config` folder.
|
||||||
|
2. Rename the build to `go2rtc`.
|
||||||
|
3. Give `go2rtc` execute permission.
|
||||||
|
4. Restart Frigate and the custom version will be used, you can verify by checking go2rtc logs.
|
||||||
|
|
||||||
|
## Validating your config.yml file updates
|
||||||
|
|
||||||
|
When frigate starts up, it checks whether your config file is valid, and if it is not, the process exits. To minimize interruptions when updating your config, you have three options -- you can edit the config via the WebUI which has built in validation, use the config API, or you can validate on the command line using the frigate docker container.
|
||||||
|
|
||||||
|
### Via API
|
||||||
|
|
||||||
|
Frigate can accept a new configuration file as JSON at the `/api/config/save` endpoint. When updating the config this way, Frigate will validate the config before saving it, and return a `400` if the config is not valid.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://frigate_host:5000/api/config/save -d @config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
if you'd like you can use your yaml config directly by using [`yq`](https://github.com/mikefarah/yq) to convert it to json:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yq r -j config.yml | curl -X POST http://frigate_host:5000/api/config/save -d @-
|
||||||
|
```
|
||||||
|
|
||||||
|
### Via Command Line
|
||||||
|
|
||||||
|
You can also validate your config at the command line by using the docker container itself. In CI/CD, you leverage the return code to determine if your config is valid, Frigate will return `1` if the config is invalid, or `0` if it's valid.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run \
|
||||||
|
-v $(pwd)/config.yml:/config/config.yml \
|
||||||
|
--entrypoint python3 \
|
||||||
|
ghcr.io/blakeblackshear/frigate:stable \
|
||||||
|
-u -m frigate \
|
||||||
|
--validate-config
|
||||||
|
```
|
||||||
@ -1,405 +0,0 @@
|
|||||||
---
|
|
||||||
id: system
|
|
||||||
title: System
|
|
||||||
---
|
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
|
|
||||||
### Logging
|
|
||||||
|
|
||||||
#### Frigate `logger`
|
|
||||||
|
|
||||||
Change the default log level for troubleshooting purposes.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Logging" />.
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ------------------------- | ------------------------------------------------------- |
|
|
||||||
| **Logging level** | The default log level for all modules (default: `info`) |
|
|
||||||
| **Per-process log level** | Override the log level for specific modules |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
logger:
|
|
||||||
# Optional: default log level (default: shown below)
|
|
||||||
default: info
|
|
||||||
# Optional: module by module log level configuration
|
|
||||||
logs:
|
|
||||||
frigate.mqtt: error
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
Available log levels are: `debug`, `info`, `warning`, `error`, `critical`
|
|
||||||
|
|
||||||
Examples of available modules are:
|
|
||||||
|
|
||||||
- `frigate.app`
|
|
||||||
- `frigate.mqtt`
|
|
||||||
- `frigate.object_detection.base`
|
|
||||||
- `detector.<detector_name>`
|
|
||||||
- `watchdog.<camera_name>`
|
|
||||||
- `ffmpeg.<camera_name>.<sorted_roles>` NOTE: All FFmpeg logs are sent as `error` level.
|
|
||||||
|
|
||||||
#### Go2RTC Logging
|
|
||||||
|
|
||||||
See [the go2rtc docs](https://github.com/AlexxIT/go2rtc?tab=readme-ov-file#module-log) for logging configuration
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
go2rtc:
|
|
||||||
streams:
|
|
||||||
# ...
|
|
||||||
log:
|
|
||||||
exec: trace
|
|
||||||
```
|
|
||||||
|
|
||||||
### `environment_vars`
|
|
||||||
|
|
||||||
This section can be used to set environment variables for those unable to modify the environment of the container, like within Home Assistant OS. Docker users should set environment variables in their `docker run` command (`-e FRIGATE_MQTT_PASSWORD=secret`) or `docker-compose.yml` file (`environment:` section) instead. Note that values set here are stored in plain text in your config file, so if the goal is to keep credentials out of your configuration, use Docker environment variables or Docker secrets instead.
|
|
||||||
|
|
||||||
Variables prefixed with `FRIGATE_` can be referenced in config fields that support environment variable substitution (such as MQTT host and credentials, camera stream URLs, and ONVIF host and credentials) using the `{FRIGATE_VARIABLE_NAME}` syntax.
|
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
The `go2rtc` section is an exception. go2rtc runs as a separate process, so its stream definitions can only be substituted with variables that exist in the container's environment (set via Docker `-e`, the `environment:` section of `docker-compose.yml`, or Docker secrets). Variables defined in the `environment_vars` block above are not available to go2rtc streams. Home Assistant app users, who cannot set container environment variables, must instead put credentials directly in their go2rtc stream URLs.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Environment variables" /> to add or edit environment variables.
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ----------------- | --------------------------------------------------------- |
|
|
||||||
| **Variable name** | The environment variable name (e.g., `FRIGATE_MQTT_USER`) |
|
|
||||||
| **Value** | The value for the variable |
|
|
||||||
|
|
||||||
Variables defined here can be referenced elsewhere in your configuration using the `{FRIGATE_VARIABLE_NAME}` syntax.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
environment_vars:
|
|
||||||
FRIGATE_MQTT_USER: my_mqtt_user
|
|
||||||
FRIGATE_MQTT_PASSWORD: my_mqtt_password
|
|
||||||
|
|
||||||
mqtt:
|
|
||||||
host: "{FRIGATE_MQTT_HOST}"
|
|
||||||
user: "{FRIGATE_MQTT_USER}"
|
|
||||||
password: "{FRIGATE_MQTT_PASSWORD}"
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
#### TensorFlow Thread Configuration
|
|
||||||
|
|
||||||
If you encounter thread creation errors during classification model training, you can limit TensorFlow's thread usage:
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Environment variables" /> and add the following variables:
|
|
||||||
|
|
||||||
| Variable | Description |
|
|
||||||
| --------------------------------- | ---------------------------------------------- |
|
|
||||||
| `TF_INTRA_OP_PARALLELISM_THREADS` | Threads within operations (`0` = use default) |
|
|
||||||
| `TF_INTER_OP_PARALLELISM_THREADS` | Threads between operations (`0` = use default) |
|
|
||||||
| `TF_DATASET_THREAD_POOL_SIZE` | Data pipeline threads (`0` = use default) |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
environment_vars:
|
|
||||||
TF_INTRA_OP_PARALLELISM_THREADS: "2" # Threads within operations (0 = use default)
|
|
||||||
TF_INTER_OP_PARALLELISM_THREADS: "2" # Threads between operations (0 = use default)
|
|
||||||
TF_DATASET_THREAD_POOL_SIZE: "2" # Data pipeline threads (0 = use default)
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### `database`
|
|
||||||
|
|
||||||
Tracked object and recording information is managed in a sqlite database at `/config/frigate.db`. If that database is deleted, recordings will be orphaned and will need to be cleaned up manually. They also won't show up in the Media Browser within Home Assistant.
|
|
||||||
|
|
||||||
If you are storing your database on a network share (SMB, NFS, etc), you may get a `database is locked` error message on startup. You can customize the location of the database if necessary.
|
|
||||||
|
|
||||||
This may need to be in a custom location if network storage is used for the media folder.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Database" />.
|
|
||||||
|
|
||||||
- Set **Database path** to the custom path for the Frigate database file (default: `/config/frigate.db`)
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
database:
|
|
||||||
path: /path/to/frigate.db
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### `model`
|
|
||||||
|
|
||||||
If using a custom model, the width and height will need to be specified.
|
|
||||||
|
|
||||||
Custom models may also require different input tensor formats. The colorspace conversion supports RGB, BGR, or YUV frames to be sent to the object detector. The input tensor shape parameter is an enumeration to match what specified by the model.
|
|
||||||
|
|
||||||
| Tensor Dimension | Description |
|
|
||||||
| :--------------: | -------------- |
|
|
||||||
| N | Batch Size |
|
|
||||||
| H | Model Height |
|
|
||||||
| W | Model Width |
|
|
||||||
| C | Color Channels |
|
|
||||||
|
|
||||||
| Available Input Tensor Shapes |
|
|
||||||
| :---------------------------: |
|
|
||||||
| "nhwc" |
|
|
||||||
| "nchw" |
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Detectors and model" /> and open the **Custom Model** tab to configure the model path, dimensions, and input format.
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| --------------------------------------------- | ------------------------------------ |
|
|
||||||
| **Custom object detector model path** | Path to the custom model file |
|
|
||||||
| **Object detection model input width** | Model input width (default: 320) |
|
|
||||||
| **Object detection model input height** | Model input height (default: 320) |
|
|
||||||
| **Advanced > Model Input Tensor Shape** | Input tensor shape: `nhwc` or `nchw` |
|
|
||||||
| **Advanced > Model Input Pixel Color Format** | Pixel format: `rgb`, `bgr`, or `yuv` |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# Optional: model config
|
|
||||||
model:
|
|
||||||
path: /path/to/model
|
|
||||||
width: 320
|
|
||||||
height: 320
|
|
||||||
input_tensor: "nhwc"
|
|
||||||
input_pixel_format: "bgr"
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
#### `labelmap`
|
|
||||||
|
|
||||||
:::warning
|
|
||||||
|
|
||||||
If the labelmap is customized then the labels used for alerts will need to be adjusted as well. See [alert labels](../review.md#restricting-alerts-to-specific-labels) for more info.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
The labelmap can be customized to your needs. A common reason to do this is to combine multiple object types that are easily confused when you don't need to be as granular such as car/truck. By default, truck is renamed to car because they are often confused. You cannot add new object types, but you can change the names of existing objects in the model.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
model:
|
|
||||||
labelmap:
|
|
||||||
2: vehicle
|
|
||||||
3: vehicle
|
|
||||||
5: vehicle
|
|
||||||
7: vehicle
|
|
||||||
15: animal
|
|
||||||
16: animal
|
|
||||||
17: animal
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that if you rename objects in the labelmap, you will also need to update your `objects -> track` list as well.
|
|
||||||
|
|
||||||
:::warning
|
|
||||||
|
|
||||||
Some labels have special handling and modifications can disable functionality.
|
|
||||||
|
|
||||||
`person` objects are associated with `face` and `amazon`
|
|
||||||
|
|
||||||
`car` objects are associated with `license_plate`, `ups`, `fedex`, `amazon`
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Network Configuration
|
|
||||||
|
|
||||||
Frigate exposes a few networking options. IPv6 and the listen ports are set in the `networking` configuration (or from the Settings UI); more advanced changes require [customizing the bundled Nginx configuration](#customizing-the-nginx-configuration).
|
|
||||||
|
|
||||||
### Enabling IPv6
|
|
||||||
|
|
||||||
By default Frigate listens on IPv4 only. To also listen on IPv6 (on port `5000`, and on `8971` when TLS is configured), enable it in the `networking` configuration.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Networking" /> and enable **IPv6**.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
networking:
|
|
||||||
ipv6:
|
|
||||||
enabled: true
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### Listen on different ports
|
|
||||||
|
|
||||||
You can change the ports Nginx uses for listening. The internal port (unauthenticated) and external port (authenticated) can be changed independently. You can also specify an IP address using the format `ip:port` if you wish to bind the port to a specific interface. This may be useful for example to prevent exposing the internal port outside the container.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Networking" /> to configure the listen ports.
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ----------------- | --------------------------------------------------------- |
|
|
||||||
| **Internal port** | The unauthenticated listen address/port (default: `5000`) |
|
|
||||||
| **External port** | The authenticated listen address/port (default: `8971`) |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
networking:
|
|
||||||
listen:
|
|
||||||
internal: 127.0.0.1:5000
|
|
||||||
external: 8971
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
:::warning
|
|
||||||
|
|
||||||
This setting is for advanced users. For the majority of use cases it's recommended to change the `ports` section of your Docker compose file or use the Docker `run` `--publish` option instead, e.g. `-p 443:8971`. Changing Frigate's ports may break some integrations.
|
|
||||||
|
|
||||||
The internal and external ports must be different port numbers, and Frigate will refuse to start otherwise. Requests arriving on the internal port are treated as authenticated admins, so pointing both at the same port would remove authentication from the external one.
|
|
||||||
|
|
||||||
Nginx binds these ports when it starts, so port changes only take effect after Frigate restarts.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Customizing the Nginx configuration
|
|
||||||
|
|
||||||
More advanced changes to Frigate's internal network configuration can be made by bind mounting your own `nginx.conf` into the container. For example:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
services:
|
|
||||||
frigate:
|
|
||||||
container_name: frigate
|
|
||||||
...
|
|
||||||
volumes:
|
|
||||||
...
|
|
||||||
- /path/to/your/nginx.conf:/usr/local/nginx/conf/nginx.conf
|
|
||||||
```
|
|
||||||
|
|
||||||
## Base path
|
|
||||||
|
|
||||||
By default, Frigate runs at the root path (`/`). However some setups require to run Frigate under a custom path prefix (e.g. `/frigate`), especially when Frigate is located behind a reverse proxy that requires path-based routing.
|
|
||||||
|
|
||||||
### Set Base Path via HTTP Header
|
|
||||||
|
|
||||||
The preferred way to configure the base path is through the `X-Ingress-Path` HTTP header, which needs to be set to the desired base path in an upstream reverse proxy.
|
|
||||||
|
|
||||||
For example, in Nginx:
|
|
||||||
|
|
||||||
```
|
|
||||||
location /frigate {
|
|
||||||
proxy_set_header X-Ingress-Path /frigate;
|
|
||||||
proxy_pass http://frigate_backend;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Set Base Path via Environment Variable
|
|
||||||
|
|
||||||
When it is not feasible to set the base path via a HTTP header, it can also be set via the `FRIGATE_BASE_PATH` environment variable in the Docker Compose file.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```
|
|
||||||
services:
|
|
||||||
frigate:
|
|
||||||
image: ghcr.io/blakeblackshear/frigate:stable
|
|
||||||
environment:
|
|
||||||
- FRIGATE_BASE_PATH=/frigate
|
|
||||||
```
|
|
||||||
|
|
||||||
This can be used for example to access Frigate via a Tailscale agent (https), by simply forwarding all requests to the base path (http):
|
|
||||||
|
|
||||||
```
|
|
||||||
tailscale serve --https=443 --bg --set-path /frigate http://localhost:5000/frigate
|
|
||||||
```
|
|
||||||
|
|
||||||
## Custom Dependencies
|
|
||||||
|
|
||||||
### Custom ffmpeg build
|
|
||||||
|
|
||||||
Included with Frigate is a build of ffmpeg that works for the vast majority of users. However, there exists some hardware setups which have incompatibilities with the included build. In this case, statically built `ffmpeg` and `ffprobe` binaries can be placed in `/config/custom-ffmpeg/bin` for Frigate to use.
|
|
||||||
|
|
||||||
To do this:
|
|
||||||
|
|
||||||
1. Download your ffmpeg build and uncompress it to the `/config/custom-ffmpeg` folder. Verify that both the `ffmpeg` and `ffprobe` binaries are located in `/config/custom-ffmpeg/bin`.
|
|
||||||
2. Update the `ffmpeg.path` in your Frigate config to `/config/custom-ffmpeg`.
|
|
||||||
3. Restart Frigate and the custom version will be used if the steps above were done correctly.
|
|
||||||
|
|
||||||
### Custom go2rtc version
|
|
||||||
|
|
||||||
Frigate currently includes go2rtc v1.9.14, there may be certain cases where you want to run a different version of go2rtc.
|
|
||||||
|
|
||||||
To do this:
|
|
||||||
|
|
||||||
1. Download the go2rtc build to the `/config` folder.
|
|
||||||
2. Rename the build to `go2rtc`.
|
|
||||||
3. Give `go2rtc` execute permission.
|
|
||||||
4. Restart Frigate and the custom version will be used, you can verify by checking go2rtc logs.
|
|
||||||
|
|
||||||
## Validating your config.yml file updates
|
|
||||||
|
|
||||||
When frigate starts up, it checks whether your config file is valid, and if it is not, the process exits. To minimize interruptions when updating your config, you have three options -- you can edit the config via the WebUI which has built in validation, use the config API, or you can validate on the command line using the frigate docker container.
|
|
||||||
|
|
||||||
### Via API
|
|
||||||
|
|
||||||
Frigate can accept a new configuration file as JSON at the `/api/config/save` endpoint. When updating the config this way, Frigate will validate the config before saving it, and return a `400` if the config is not valid.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -X POST http://frigate_host:5000/api/config/save -d @config.json
|
|
||||||
```
|
|
||||||
|
|
||||||
if you'd like you can use your yaml config directly by using [`yq`](https://github.com/mikefarah/yq) to convert it to json:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yq -o=json '.' config.yaml | curl -X POST 'http://frigate_host:5000/api/config/save?save_option=saveonly' --data-binary @-
|
|
||||||
```
|
|
||||||
|
|
||||||
### Via Command Line
|
|
||||||
|
|
||||||
You can also validate your config at the command line by using the docker container itself. In CI/CD, you leverage the return code to determine if your config is valid, Frigate will return `1` if the config is invalid, or `0` if it's valid.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run \
|
|
||||||
-v $(pwd)/config.yml:/config/config.yml \
|
|
||||||
--entrypoint python3 \
|
|
||||||
ghcr.io/blakeblackshear/frigate:stable \
|
|
||||||
-u -m frigate \
|
|
||||||
--validate-config
|
|
||||||
```
|
|
||||||
@ -3,10 +3,6 @@ id: audio_detectors
|
|||||||
title: Audio Detectors
|
title: Audio Detectors
|
||||||
---
|
---
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
|
|
||||||
Frigate provides a builtin audio detector which runs on the CPU. Compared to object detection in images, audio detection is a relatively lightweight operation so the only option is to run the detection on a CPU.
|
Frigate provides a builtin audio detector which runs on the CPU. Compared to object detection in images, audio detection is a relatively lightweight operation so the only option is to run the detection on a CPU.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
@ -15,17 +11,7 @@ Audio events work by detecting a type of audio and creating an event, the event
|
|||||||
|
|
||||||
### Enabling Audio Events
|
### Enabling Audio Events
|
||||||
|
|
||||||
Audio events can be enabled globally or for specific cameras.
|
Audio events can be enabled for all cameras or only for specific cameras.
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
**Global:** Navigate to <NavPath path="Settings > Global configuration > Audio events" /> and set **Enable audio detection** to on.
|
|
||||||
|
|
||||||
**Per-camera:** Navigate to <NavPath path="Settings > Camera configuration > Audio events" /> and set **Enable audio detection** to on for the desired camera.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
|
||||||
@ -40,9 +26,6 @@ cameras:
|
|||||||
enabled: True # <- enable audio events for the front_camera
|
enabled: True # <- enable audio events for the front_camera
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
If you are using multiple streams then you must set the `audio` role on the stream that is going to be used for audio detection, this can be any stream but the stream must have audio included.
|
If you are using multiple streams then you must set the `audio` role on the stream that is going to be used for audio detection, this can be any stream but the stream must have audio included.
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
@ -51,14 +34,6 @@ The ffmpeg process for capturing audio will be a separate connection to the came
|
|||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > Camera configuration > Streams (FFmpeg)" /> and add an input with the `audio` role pointing to a stream that includes audio.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
cameras:
|
cameras:
|
||||||
front_camera:
|
front_camera:
|
||||||
@ -73,12 +48,9 @@ cameras:
|
|||||||
- detect
|
- detect
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### Configuring Minimum Volume
|
### Configuring Minimum Volume
|
||||||
|
|
||||||
The audio detector uses volume levels in the same way that motion in a camera feed is used for object detection. This means that Frigate will not run audio detection unless the audio volume is above the configured level in order to reduce resource usage. Audio levels can vary widely between camera models so it is important to run tests to see what volume levels are. The [Debug view](/usage/live#the-single-camera-view) in the Frigate UI has an Audio tab for cameras that have the `audio` role assigned where a graph and the current levels are displayed. The `min_volume` parameter should be set to the minimum the `RMS` level required to run audio detection.
|
The audio detector uses volume levels in the same way that motion in a camera feed is used for object detection. This means that frigate will not run audio detection unless the audio volume is above the configured level in order to reduce resource usage. Audio levels can vary widely between camera models so it is important to run tests to see what volume levels are. MQTT explorer can be used on the audio topic to see what volume level is being detected.
|
||||||
|
|
||||||
:::tip
|
:::tip
|
||||||
|
|
||||||
@ -88,18 +60,7 @@ Volume is considered motion for recordings, this means when the `record -> retai
|
|||||||
|
|
||||||
### Configuring Audio Events
|
### Configuring Audio Events
|
||||||
|
|
||||||
The included audio model has over [500 different types](https://github.com/blakeblackshear/frigate/blob/dev/audio-labelmap.txt) of audio that can be detected, many of which are not practical. By default `bark`, `fire_alarm`, `speech`, and `yell` are enabled but these can be customized.
|
The included audio model has over [500 different types](https://github.com/blakeblackshear/frigate/blob/dev/audio-labelmap.txt) of audio that can be detected, many of which are not practical. By default `bark`, `fire_alarm`, `scream`, `speech`, and `yell` are enabled but these can be customized.
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > Global configuration > Audio events" />.
|
|
||||||
|
|
||||||
- Set **Enable audio detection** to on
|
|
||||||
- Set **Listen types** to include the audio types you want to detect
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
audio:
|
audio:
|
||||||
@ -107,199 +68,7 @@ audio:
|
|||||||
listen:
|
listen:
|
||||||
- bark
|
- bark
|
||||||
- fire_alarm
|
- fire_alarm
|
||||||
|
- scream
|
||||||
- speech
|
- speech
|
||||||
- yell
|
- yell
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### Common Audio Labels
|
|
||||||
|
|
||||||
The labelmap includes hundreds of sound types. The labels below are the ones most users may find practical, grouped by what they're typically used for. Use the exact label string from the left column in your `listen` config, or search for the label in the Frigate UI directly.
|
|
||||||
|
|
||||||
Some labels cover several related sounds: `yell` is triggered by shouting, yelling, children shouting, and screaming; `crying` covers baby cries, sobbing, and whimpering; and `speech` covers ordinary talking and conversation.
|
|
||||||
|
|
||||||
**Safety and security**
|
|
||||||
|
|
||||||
| Label | Detects |
|
|
||||||
| ---------------- | ---------------------------------- |
|
|
||||||
| `yell` | Shouting, yelling, screaming |
|
|
||||||
| `fire_alarm` | Fire and smoke alarm sirens |
|
|
||||||
| `smoke_detector` | Smoke detector beeps |
|
|
||||||
| `alarm` | General alarm sounds |
|
|
||||||
| `car_alarm` | Car alarms |
|
|
||||||
| `siren` | Emergency vehicle and civil sirens |
|
|
||||||
| `glass` | Glass clinking |
|
|
||||||
| `shatter` | Breaking glass |
|
|
||||||
| `breaking` | Something breaking |
|
|
||||||
| `gunshot` | Gunshots |
|
|
||||||
| `explosion` | Explosions |
|
|
||||||
|
|
||||||
**People and activity**
|
|
||||||
|
|
||||||
| Label | Detects |
|
|
||||||
| ----------- | ------------------------ |
|
|
||||||
| `speech` | Talking and conversation |
|
|
||||||
| `laughter` | Laughing |
|
|
||||||
| `crying` | Baby crying and sobbing |
|
|
||||||
| `cough` | Coughing |
|
|
||||||
| `footsteps` | Footsteps and walking |
|
|
||||||
| `knock` | Knocking on a door |
|
|
||||||
| `doorbell` | Doorbell |
|
|
||||||
| `ding-dong` | Doorbell chime |
|
|
||||||
|
|
||||||
**Pets and animals**
|
|
||||||
|
|
||||||
| Label | Detects |
|
|
||||||
| ---------- | ---------------- |
|
|
||||||
| `bark` | Dog barking |
|
|
||||||
| `dog` | Other dog sounds |
|
|
||||||
| `howl` | Howling |
|
|
||||||
| `growling` | Growling |
|
|
||||||
| `meow` | Cat meowing |
|
|
||||||
| `cat` | Other cat sounds |
|
|
||||||
| `hiss` | Hissing |
|
|
||||||
|
|
||||||
**Vehicles and driveway**
|
|
||||||
|
|
||||||
| Label | Detects |
|
|
||||||
| ----------------- | -------------------- |
|
|
||||||
| `car` | Passing cars |
|
|
||||||
| `honk` | Car horns |
|
|
||||||
| `truck` | Trucks |
|
|
||||||
| `reversing_beeps` | Vehicle backup beeps |
|
|
||||||
| `motorcycle` | Motorcycles |
|
|
||||||
| `engine_starting` | Engines starting |
|
|
||||||
|
|
||||||
:::tip
|
|
||||||
|
|
||||||
Frequently-heard labels like `speech` can generate a lot of events, and each event could save a snapshot and recording based on your configuration, so start with a focused set and expand from there. The defaults (`bark`, `fire_alarm`, `speech`, `yell`) plus a few of the safety labels above cover most needs. See the [full audio labelmap](https://github.com/blakeblackshear/frigate/blob/dev/audio-labelmap.txt) or the Frigate UI for every available type.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Audio Transcription
|
|
||||||
|
|
||||||
Frigate supports fully local audio transcription using either `sherpa-onnx` or OpenAI's open-source Whisper models via `faster-whisper`. The goal of this feature is to support Semantic Search for `speech` audio events. Frigate is not intended to act as a continuous, fully-automatic speech transcription service. Automatically transcribing all speech (or queuing many audio events for transcription) requires substantial CPU (or GPU) resources and is impractical on most systems. For this reason, transcriptions for events are initiated manually from the UI or the API rather than being run continuously in the background.
|
|
||||||
|
|
||||||
:::info
|
|
||||||
|
|
||||||
Audio transcription requires a one-time internet connection to download the Whisper or Sherpa-ONNX model on first use. Once cached, transcription runs fully offline. See [Network Requirements](/frigate/network_requirements#one-time-model-downloads) for details.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
Transcription accuracy also depends heavily on the quality of your camera's microphone and recording conditions. Many cameras use inexpensive microphones, and distance to the speaker, low audio bitrate, or background noise can significantly reduce transcription quality. If you need higher accuracy, more robust long-running queues, or large-scale automatic transcription, consider using the HTTP API in combination with an automation platform and a cloud transcription service.
|
|
||||||
|
|
||||||
#### Configuration
|
|
||||||
|
|
||||||
To enable transcription, configure it globally and optionally disable for specific cameras. Audio detection must also be enabled as described above.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
**Global:** Navigate to <NavPath path="Settings > Enrichments > Audio transcription" />.
|
|
||||||
|
|
||||||
- Set **Enable audio transcription** to on
|
|
||||||
- Set **Transcription device** to the desired device
|
|
||||||
- Set **Model size** to the desired size
|
|
||||||
|
|
||||||
**Per-camera:** Navigate to <NavPath path="Settings > Camera configuration > Audio transcription" /> to enable or disable transcription for a specific camera.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
audio_transcription:
|
|
||||||
enabled: True
|
|
||||||
device: ...
|
|
||||||
model_size: ...
|
|
||||||
```
|
|
||||||
|
|
||||||
Disable audio transcription for select cameras at the camera level:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
cameras:
|
|
||||||
back_yard:
|
|
||||||
...
|
|
||||||
audio_transcription:
|
|
||||||
enabled: False
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
Audio detection must be enabled and configured as described above in order to use audio transcription features.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
The optional config parameters that can be set at the global level include:
|
|
||||||
|
|
||||||
- **`enabled`**: Enable or disable the audio transcription feature.
|
|
||||||
- Default: `False`
|
|
||||||
- It is recommended to only configure the features at the global level, and enable it at the individual camera level.
|
|
||||||
- **`device`**: Device to use to run transcription and translation models.
|
|
||||||
- Default: `CPU`
|
|
||||||
- This can be `CPU` or `GPU`. The `sherpa-onnx` models are lightweight and run on the CPU only. The `whisper` models can run on GPU but are only supported on CUDA hardware.
|
|
||||||
- **`model_size`**: The size of the model used for live transcription.
|
|
||||||
- Default: `small`
|
|
||||||
- This can be `small` or `large`. The `small` setting uses `sherpa-onnx` models that are fast, lightweight, and always run on the CPU but are not as accurate as the `whisper` model.
|
|
||||||
- This config option applies to **live transcription only**. Recorded `speech` events will always use a different `whisper` model (and can be accelerated for CUDA hardware if available with `device: GPU`).
|
|
||||||
- **`language`**: Defines the language used by `whisper` to translate `speech` audio events (and live audio only if using the `large` model).
|
|
||||||
- Default: `en`
|
|
||||||
- You must use a valid [language code](https://github.com/openai/whisper/blob/main/whisper/tokenizer.py#L10).
|
|
||||||
- Transcriptions for `speech` events are translated.
|
|
||||||
- Live audio is translated only if you are using the `large` model. The `small` `sherpa-onnx` model is English-only.
|
|
||||||
|
|
||||||
The only field that is valid at the camera level is `enabled`.
|
|
||||||
|
|
||||||
#### Live transcription
|
|
||||||
|
|
||||||
The single camera Live view in the Frigate UI supports live transcription of audio for streams defined with the `audio` role. Use the Enable/Disable Live Audio Transcription button/switch to toggle transcription processing, or toggle it outside of the UI with the [`frigate/<camera_name>/audio_transcription/set`](/integrations/mqtt#frigatecamera_nameaudio_transcriptionset) MQTT topic or the HTTP API. When speech is heard, the UI will display a black box over the top of the camera stream with text. The MQTT topic `frigate/<camera_name>/audio/transcription` will also be updated in real-time with transcribed text.
|
|
||||||
|
|
||||||
Results can be error-prone due to a number of factors, including:
|
|
||||||
|
|
||||||
- Poor quality camera microphone
|
|
||||||
- Distance of the audio source to the camera microphone
|
|
||||||
- Low audio bitrate setting in the camera
|
|
||||||
- Background noise
|
|
||||||
- Using the `small` model - it's fast, but not accurate for poor quality audio
|
|
||||||
|
|
||||||
For speech sources close to the camera with minimal background noise, use the `small` model.
|
|
||||||
|
|
||||||
If you have CUDA hardware, you can experiment with the `large` `whisper` model on GPU. Performance is not quite as fast as the `sherpa-onnx` `small` model, but live transcription is far more accurate. Using the `large` model with CPU will likely be too slow for real-time transcription.
|
|
||||||
|
|
||||||
#### Transcription and translation of `speech` audio events
|
|
||||||
|
|
||||||
Any `speech` events in Explore can be transcribed and/or translated through the Transcribe button (the microphone icon) in the Tracked Object Details pane.
|
|
||||||
|
|
||||||
In order to use transcription and translation for past events, you must enable audio detection and define `speech` as an audio type to listen for. To have `speech` events translated into the language of your choice, set the `language` config parameter with the correct [language code](https://github.com/openai/whisper/blob/main/whisper/tokenizer.py#L10).
|
|
||||||
|
|
||||||
The transcribed/translated speech will appear in the description box in the Tracked Object Details pane. If Semantic Search is enabled, embeddings are generated for the transcription text and are fully searchable using the description search type.
|
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
Only one `speech` event may be transcribed at a time. Frigate does not automatically transcribe `speech` events or implement a queue for long-running transcription model inference.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
Recorded `speech` events will always use a `whisper` model, regardless of the `model_size` config setting. Without a supported Nvidia GPU, generating transcriptions for longer `speech` events may take a fair amount of time, so be patient.
|
|
||||||
|
|
||||||
#### FAQ
|
|
||||||
|
|
||||||
1. Why doesn't Frigate automatically transcribe all `speech` events?
|
|
||||||
|
|
||||||
Frigate does not implement a queue mechanism for speech transcription, and adding one is not trivial. A proper queue would need backpressure, prioritization, memory/disk buffering, retry logic, crash recovery, and safeguards to prevent unbounded growth when events outpace processing. That's a significant amount of complexity for a feature that, in most real-world environments, would mostly just churn through low-value noise.
|
|
||||||
|
|
||||||
Because transcription is **serialized (one event at a time)** and speech events can be generated far faster than they can be processed, an auto-transcribe toggle would very quickly create an ever-growing backlog and degrade core functionality. For the amount of engineering and risk involved, it adds **very little practical value** for the majority of deployments, which are often on low-powered, edge hardware.
|
|
||||||
|
|
||||||
If you hear speech that's actually important and worth saving/indexing for the future, **just press the transcribe button (the microphone icon) in Explore** on that specific `speech` event - that keeps things explicit, reliable, and under your control.
|
|
||||||
|
|
||||||
Other options are being considered for future versions of Frigate to add transcription options that support external `whisper` Docker containers. A single transcription service could then be shared by Frigate and other applications (for example, Home Assistant Voice), and run on more powerful machines when available.
|
|
||||||
|
|
||||||
2. Why don't you save live transcription text and use that for `speech` events?
|
|
||||||
|
|
||||||
There's no guarantee that a `speech` event is even created from the exact audio that went through the transcription model. Live transcription and `speech` event creation are **separate, asynchronous processes**. Even when both are correctly configured, trying to align the **precise start and end time of a speech event** with whatever audio the model happened to be processing at that moment is unreliable.
|
|
||||||
|
|
||||||
Automatically persisting that data would often result in **misaligned, partial, or irrelevant transcripts**, while still incurring all of the CPU, storage, and privacy costs of transcription. That's why Frigate treats transcription as an **explicit, user-initiated action** rather than an automatic side-effect of every `speech` event.
|
|
||||||
|
|||||||
@ -3,10 +3,6 @@ id: authentication
|
|||||||
title: Authentication
|
title: Authentication
|
||||||
---
|
---
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
|
|
||||||
# Authentication
|
# Authentication
|
||||||
|
|
||||||
Frigate stores user information in its database. Password hashes are generated using industry standard PBKDF2-SHA256 with 600,000 iterations. Upon successful login, a JWT token is issued with an expiration date and set as a cookie. The cookie is refreshed as needed automatically. This JWT token can also be passed in the Authorization header as a bearer token.
|
Frigate stores user information in its database. Password hashes are generated using industry standard PBKDF2-SHA256 with 600,000 iterations. Upon successful login, a JWT token is issued with an expiration date and set as a cookie. The cookie is refreshed as needed automatically. This JWT token can also be passed in the Authorization header as a bearer token.
|
||||||
@ -26,30 +22,13 @@ On startup, an admin user and password are generated and printed in the logs. It
|
|||||||
|
|
||||||
## Resetting admin password
|
## Resetting admin password
|
||||||
|
|
||||||
In the event that you are locked out of your instance, you can tell Frigate to reset the admin password and print it in the logs on next startup.
|
In the event that you are locked out of your instance, you can tell Frigate to reset the admin password and print it in the logs on next startup using the `reset_admin_password` setting in your config file.
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Authentication" />.
|
|
||||||
|
|
||||||
- Set **Reset admin password** to on to reset the admin password and print it in the logs on next startup
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
auth:
|
auth:
|
||||||
reset_admin_password: true
|
reset_admin_password: true
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Password guidance
|
|
||||||
|
|
||||||
Constructing secure passwords and managing them properly is important. Frigate requires a minimum length of 12 characters. For guidance on password standards see [NIST SP 800-63B](https://pages.nist.gov/800-63-3/sp800-63b.html). To learn what makes a password truly secure, read this [article](https://medium.com/peerio/how-to-build-a-billion-dollar-password-3d92568d9277).
|
|
||||||
|
|
||||||
## Login failure rate limiting
|
## Login failure rate limiting
|
||||||
|
|
||||||
In order to limit the risk of brute force attacks, rate limiting is available for login failures. This is implemented with SlowApi, and the string notation for valid values is available in [the documentation](https://limits.readthedocs.io/en/stable/quickstart.html#examples).
|
In order to limit the risk of brute force attacks, rate limiting is available for login failures. This is implemented with SlowApi, and the string notation for valid values is available in [the documentation](https://limits.readthedocs.io/en/stable/quickstart.html#examples).
|
||||||
@ -64,20 +43,7 @@ Restarting Frigate will reset the rate limits.
|
|||||||
|
|
||||||
If you are running Frigate behind a proxy, you will want to set `trusted_proxies` or these rate limits will apply to the upstream proxy IP address. This means that a brute force attack will rate limit login attempts from other devices and could temporarily lock you out of your instance. In order to ensure rate limits only apply to the actual IP address where the requests are coming from, you will need to list the upstream networks that you want to trust. These trusted proxies are checked against the `X-Forwarded-For` header when looking for the IP address where the request originated.
|
If you are running Frigate behind a proxy, you will want to set `trusted_proxies` or these rate limits will apply to the upstream proxy IP address. This means that a brute force attack will rate limit login attempts from other devices and could temporarily lock you out of your instance. In order to ensure rate limits only apply to the actual IP address where the requests are coming from, you will need to list the upstream networks that you want to trust. These trusted proxies are checked against the `X-Forwarded-For` header when looking for the IP address where the request originated.
|
||||||
|
|
||||||
If you are running a reverse proxy in the same Docker Compose file as Frigate, configure rate limiting and trusted proxies as follows:
|
If you are running a reverse proxy in the same Docker Compose file as Frigate, here is an example of how your auth config might look:
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Authentication" />.
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| **Failed login limits** | Rate limit string for login failures (e.g., `1/second;5/minute;20/hour`) |
|
|
||||||
| **Trusted proxies** | List of upstream network CIDRs to trust for `X-Forwarded-For` (e.g., `172.18.0.0/16` for internal Docker Compose network) |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
auth:
|
auth:
|
||||||
@ -86,38 +52,6 @@ auth:
|
|||||||
- 172.18.0.0/16 # <---- this is the subnet for the internal Docker Compose network
|
- 172.18.0.0/16 # <---- this is the subnet for the internal Docker Compose network
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Session Length
|
|
||||||
|
|
||||||
The default session length for user authentication in Frigate is 24 hours. This setting determines how long a user's authenticated session remains active before a token refresh is required. Otherwise, the user will need to log in again.
|
|
||||||
|
|
||||||
While the default provides a balance of security and convenience, you can customize this duration to suit your specific security requirements and user experience preferences. The session length is configured in seconds.
|
|
||||||
|
|
||||||
The default value of `86400` will expire the authentication session after 24 hours. Some other examples:
|
|
||||||
|
|
||||||
- `0`: Setting the session length to 0 will require a user to log in every time they access the application or after a very short, immediate timeout.
|
|
||||||
- `604800`: Setting the session length to 604800 will require a user to log in if the token is not refreshed for 7 days.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Authentication" />.
|
|
||||||
|
|
||||||
- Set **Session length** to the duration in seconds before the authentication session expires (default: 86400 / 24 hours)
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
auth:
|
|
||||||
session_length: 86400
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## JWT Token Secret
|
## JWT Token Secret
|
||||||
|
|
||||||
The JWT token secret needs to be kept secure. Anyone with this secret can generate valid JWT tokens to authenticate with Frigate. This should be a cryptographically random string of at least 64 characters.
|
The JWT token secret needs to be kept secure. Anyone with this secret can generate valid JWT tokens to authenticate with Frigate. This should be a cryptographically random string of at least 64 characters.
|
||||||
@ -131,8 +65,8 @@ python3 -c 'import secrets; print(secrets.token_hex(64))'
|
|||||||
Frigate looks for a JWT token secret in the following order:
|
Frigate looks for a JWT token secret in the following order:
|
||||||
|
|
||||||
1. An environment variable named `FRIGATE_JWT_SECRET`
|
1. An environment variable named `FRIGATE_JWT_SECRET`
|
||||||
2. A file named `FRIGATE_JWT_SECRET` in the directory specified by the `CREDENTIALS_DIRECTORY` environment variable (defaults to the Docker Secrets directory: `/run/secrets/`)
|
2. A docker secret named `FRIGATE_JWT_SECRET` in `/run/secrets/`
|
||||||
3. A `jwt_secret` option from the Home Assistant App options
|
3. A `jwt_secret` option from the Home Assistant Add-on options
|
||||||
4. A `.jwt_secret` file in the config directory
|
4. A `.jwt_secret` file in the config directory
|
||||||
|
|
||||||
If no secret is found on startup, Frigate generates one and stores it in a `.jwt_secret` file in the config directory.
|
If no secret is found on startup, Frigate generates one and stores it in a `.jwt_secret` file in the config directory.
|
||||||
@ -141,22 +75,11 @@ Changing the secret will invalidate current tokens.
|
|||||||
|
|
||||||
## Proxy configuration
|
## Proxy configuration
|
||||||
|
|
||||||
Frigate can be configured to leverage features of common upstream authentication proxies such as Authelia, Authentik, oauth2_proxy, or traefik-forward-auth. Frigate does not implement OIDC, SAML, or LDAP natively; as an NVR focused on recording and object detection, it relies on robust, battle-tested proxies to handle those protocols and passes the authenticated user and role through via headers (see below).
|
Frigate can be configured to leverage features of common upstream authentication proxies such as Authelia, Authentik, oauth2_proxy, or traefik-forward-auth.
|
||||||
|
|
||||||
If you are leveraging the authentication of an upstream proxy, you likely want to disable Frigate's authentication as there is no correspondence between users in Frigate's database and users authenticated via the proxy. Optionally, if communication between the reverse proxy and Frigate is over an untrusted network, you should set an `auth_secret` in the `proxy` config and configure the proxy to send the secret value as a header named `X-Proxy-Secret`. Assuming this is an untrusted network, you will also want to [configure a real TLS certificate](tls.md) to ensure the traffic can't simply be sniffed to steal the secret.
|
If you are leveraging the authentication of an upstream proxy, you likely want to disable Frigate's authentication. Optionally, if communication between the reverse proxy and Frigate is over an untrusted network, you should set an `auth_secret` in the `proxy` config and configure the proxy to send the secret value as a header named `X-Proxy-Secret`. Assuming this is an untrusted network, you will also want to [configure a real TLS certificate](tls.md) to ensure the traffic can't simply be sniffed to steal the secret.
|
||||||
|
|
||||||
To disable Frigate's authentication and ensure requests come only from your known proxy:
|
Here is an example of how to disable Frigate's authentication and also ensure the requests come only from your known proxy.
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > System > Authentication" />.
|
|
||||||
- Set **Enable authentication** to off
|
|
||||||
2. Navigate to <NavPath path="Settings > System > Proxy" />.
|
|
||||||
- Set **Proxy secret** to `<some random long string>`
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
auth:
|
auth:
|
||||||
@ -166,9 +89,6 @@ proxy:
|
|||||||
auth_secret: <some random long string>
|
auth_secret: <some random long string>
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
You can use the following code to generate a random secret.
|
You can use the following code to generate a random secret.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
@ -177,113 +97,26 @@ python3 -c 'import secrets; print(secrets.token_hex(64))'
|
|||||||
|
|
||||||
### Header mapping
|
### Header mapping
|
||||||
|
|
||||||
If you have disabled Frigate's authentication and your proxy supports passing a header with authenticated usernames and/or roles, you can use the `header_map` config to specify the header name so it is passed to Frigate. For example, the following will map the `X-Forwarded-User` and `X-Forwarded-Groups` values. Header names are not case sensitive. Multiple values can be included in the role header. Frigate expects that the character separating the roles is a comma, but this can be specified using the `separator` config entry.
|
If you have disabled Frigate's authentication and your proxy supports passing a header with authenticated usernames and/or roles, you can use the `header_map` config to specify the header name so it is passed to Frigate. For example, the following will map the `X-Forwarded-User` and `X-Forwarded-Role` values. Header names are not case sensitive.
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Proxy" /> and configure the header mapping and separator settings.
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| -------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
||||||
| **Separator character** | Character separating multiple roles in the role header (default: comma). Authentik uses a pipe `\|`. |
|
|
||||||
| **Header mapping > User header** | Header name for the authenticated username (e.g., `x-forwarded-user`) |
|
|
||||||
| **Header mapping > Role header** | Header name for the authenticated role/groups (e.g., `x-forwarded-groups`) |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
proxy:
|
|
||||||
...
|
|
||||||
separator: "|" # This value defaults to a comma, but Authentik uses a pipe, for example.
|
|
||||||
header_map:
|
|
||||||
user: x-forwarded-user
|
|
||||||
role: x-forwarded-groups
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
Frigate supports `admin`, `viewer`, and custom roles (see below). When using port `8971`, Frigate validates these headers and subsequent requests use the headers `remote-user` and `remote-role` for authorization.
|
|
||||||
|
|
||||||
A default role can be provided. Any value in the mapped `role` header will override the default.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Proxy" /> and set the default role.
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ---------------- | ------------------------------------------------------------- |
|
|
||||||
| **Default role** | Fallback role when no role header is present (e.g., `viewer`) |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
proxy:
|
|
||||||
...
|
|
||||||
default_role: viewer
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Role mapping
|
|
||||||
|
|
||||||
In some environments, upstream identity providers (OIDC, SAML, LDAP, etc.) do not pass a Frigate-compatible role directly, but instead pass one or more group claims. To handle this, Frigate supports a `role_map` that translates upstream group names into Frigate's internal roles (`admin`, `viewer`, or custom). This is configurable via YAML in the configuration file:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
proxy:
|
proxy:
|
||||||
...
|
...
|
||||||
header_map:
|
header_map:
|
||||||
user: x-forwarded-user
|
user: x-forwarded-user
|
||||||
role: x-forwarded-groups
|
role: x-forwarded-role
|
||||||
role_map:
|
|
||||||
admin:
|
|
||||||
- sysadmins
|
|
||||||
- access-level-security
|
|
||||||
viewer:
|
|
||||||
- camera-viewer
|
|
||||||
operator: # Custom role mapping
|
|
||||||
- operators
|
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example:
|
Frigate supports both `admin` and `viewer` roles (see below). When using port `8971`, Frigate validates these headers and subsequent requests use the headers `remote-user` and `remote-role` for authorization.
|
||||||
|
|
||||||
- If the proxy passes a role header containing `sysadmins` or `access-level-security`, the user is assigned the `admin` role.
|
|
||||||
- If the proxy passes a role header containing `camera-viewer`, the user is assigned the `viewer` role.
|
|
||||||
- If the proxy passes a role header containing `operators`, the user is assigned the `operator` custom role.
|
|
||||||
- If no mapping matches, Frigate falls back to `default_role` if configured.
|
|
||||||
- If `role_map` is not defined, Frigate assumes the role header directly contains `admin`, `viewer`, or a custom role name.
|
|
||||||
|
|
||||||
**Note on matching semantics:**
|
|
||||||
|
|
||||||
- Admin precedence: if the `admin` mapping matches, Frigate resolves the session to `admin` to avoid accidental downgrade when a user belongs to multiple groups (for example both `admin` and `viewer` groups).
|
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
If a user isn't getting the role you expect, enable debug logging to see exactly what headers Frigate is receiving from your proxy:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
logger:
|
|
||||||
default: info
|
|
||||||
logs:
|
|
||||||
frigate.api.auth: debug
|
|
||||||
```
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
#### Port Considerations
|
#### Port Considerations
|
||||||
|
|
||||||
**Authenticated Port (8971)**
|
**Authenticated Port (8971)**
|
||||||
|
|
||||||
- Header mapping is **fully supported**.
|
- Header mapping is **fully supported**.
|
||||||
- The `remote-role` header determines the user's privileges:
|
- The `remote-role` header determines the user’s privileges:
|
||||||
- **admin** → Full access (user management, configuration changes).
|
- **admin** → Full access (user management, configuration changes).
|
||||||
- **viewer** → Read-only access.
|
- **viewer** → Read-only access.
|
||||||
- **Custom roles** → Read-only access limited to the cameras defined in `auth.roles[role]`.
|
|
||||||
- Ensure your **proxy sends both user and role headers** for proper role enforcement.
|
- Ensure your **proxy sends both user and role headers** for proper role enforcement.
|
||||||
|
|
||||||
**Unauthenticated Port (5000)**
|
**Unauthenticated Port (5000)**
|
||||||
@ -329,52 +162,6 @@ Frigate supports user roles to control access to certain features in the UI and
|
|||||||
|
|
||||||
- **admin**: Full access to all features, including user management and configuration.
|
- **admin**: Full access to all features, including user management and configuration.
|
||||||
- **viewer**: Read-only access to the UI and API, including viewing cameras, review items, and historical footage. Configuration editor and settings in the UI are inaccessible.
|
- **viewer**: Read-only access to the UI and API, including viewing cameras, review items, and historical footage. Configuration editor and settings in the UI are inaccessible.
|
||||||
- **Custom Roles**: Arbitrary role names (alphanumeric, dots/underscores) with specific camera permissions. These extend the system for granular access (e.g., "operator" for select cameras).
|
|
||||||
|
|
||||||
### Custom Roles and Camera Access
|
|
||||||
|
|
||||||
The viewer role provides read-only access to all cameras in the UI and API. Custom roles allow admins to limit read-only access to specific cameras. Each role specifies an array of allowed camera names. If a user is assigned a custom role, their account is like the **viewer** role - they can only view Live, Review/History, Explore, and Export for the designated cameras. Backend API endpoints enforce this server-side (e.g., returning 403 for unauthorized cameras), and the frontend UI filters content accordingly (e.g., camera dropdowns show only permitted options).
|
|
||||||
|
|
||||||
### Role Configuration Example
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > Users > Roles" /> to define custom roles and assign which cameras each role can access.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml {11-16}
|
|
||||||
cameras:
|
|
||||||
front_door:
|
|
||||||
# ... camera config
|
|
||||||
side_yard:
|
|
||||||
# ... camera config
|
|
||||||
garage:
|
|
||||||
# ... camera config
|
|
||||||
|
|
||||||
auth:
|
|
||||||
enabled: true
|
|
||||||
roles:
|
|
||||||
operator: # Custom role
|
|
||||||
- front_door
|
|
||||||
- garage # Operator can access front and garage
|
|
||||||
neighbor:
|
|
||||||
- side_yard
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
If you want to provide access to all cameras to a specific user, just use the **viewer** role.
|
|
||||||
|
|
||||||
### Managing User Roles
|
|
||||||
|
|
||||||
1. Log in as an **admin** user via port `8971` (preferred), or unauthenticated via port `5000`.
|
|
||||||
2. Navigate to **Settings**.
|
|
||||||
3. In the **Users** section, edit a user's role by selecting from available roles (admin, viewer, or custom).
|
|
||||||
4. In the **Roles** section, add/edit/delete custom roles (select cameras via switches). Deleting a role auto-reassigns users to "viewer".
|
|
||||||
|
|
||||||
### Role Enforcement
|
### Role Enforcement
|
||||||
|
|
||||||
@ -393,43 +180,4 @@ To use role-based access control, you must connect to Frigate via the **authenti
|
|||||||
|
|
||||||
1. Log in as an **admin** user via port `8971`.
|
1. Log in as an **admin** user via port `8971`.
|
||||||
2. Navigate to **Settings > Users**.
|
2. Navigate to **Settings > Users**.
|
||||||
3. Edit a user's role by selecting **admin** or **viewer**.
|
3. Edit a user’s role by selecting **admin** or **viewer**.
|
||||||
|
|
||||||
## API Authentication Guide
|
|
||||||
|
|
||||||
### Getting a Bearer Token
|
|
||||||
|
|
||||||
To use the Frigate API, you need to authenticate first. Follow these steps to obtain a Bearer token:
|
|
||||||
|
|
||||||
#### 1. Login
|
|
||||||
|
|
||||||
Make a POST request to `/login` with your credentials:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -i -X POST https://frigate_ip:8971/api/login \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"user": "admin", "password": "your_password"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
You may need to include `-k` in the argument list in these steps (eg: `curl -k -i -X POST ...`) if your Frigate instance is using a self-signed certificate.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
The response will contain a cookie with the JWT token.
|
|
||||||
|
|
||||||
#### 2. Using the Bearer Token
|
|
||||||
|
|
||||||
Once you have the token, include it in the Authorization header for subsequent requests:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -H "Authorization: Bearer <your_token>" https://frigate_ip:8971/api/profile
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. Token Lifecycle
|
|
||||||
|
|
||||||
- Tokens are valid for the configured session length
|
|
||||||
- Tokens are automatically refreshed when you visit the `/auth` endpoint
|
|
||||||
- Tokens are invalidated when the user's password is changed
|
|
||||||
- Use `/logout` to clear your session cookie
|
|
||||||
|
|||||||
@ -3,11 +3,6 @@ id: autotracking
|
|||||||
title: Camera Autotracking
|
title: Camera Autotracking
|
||||||
---
|
---
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
import FaqItem from "@site/src/components/FaqItem";
|
|
||||||
|
|
||||||
An ONVIF-capable, PTZ (pan-tilt-zoom) camera that supports relative movement within the field of view (FOV) can be configured to automatically track moving objects and keep them in the center of the frame.
|
An ONVIF-capable, PTZ (pan-tilt-zoom) camera that supports relative movement within the field of view (FOV) can be configured to automatically track moving objects and keep them in the center of the frame.
|
||||||
|
|
||||||

|

|
||||||
@ -26,7 +21,7 @@ Frigate autotracking functions with PTZ cameras capable of relative movement wit
|
|||||||
|
|
||||||
Many cheaper or older PTZs may not support this standard. Frigate will report an error message in the log and disable autotracking if your PTZ is unsupported.
|
Many cheaper or older PTZs may not support this standard. Frigate will report an error message in the log and disable autotracking if your PTZ is unsupported.
|
||||||
|
|
||||||
The FeatureList on the [ONVIF Conformant Products Database](https://www.onvif.org/conformant-products/) can provide a starting point to determine a camera's compatibility with Frigate's autotracking. Look to see if a camera lists `PTZRelative`, `PTZRelativePanTilt` and/or `PTZRelativeZoom`. These features are required for autotracking, but some cameras still fail to respond even if they claim support.
|
Alternatively, you can download and run [this simple Python script](https://gist.github.com/hawkeye217/152a1d4ba80760dac95d46e143d37112), replacing the details on line 4 with your camera's IP address, ONVIF port, username, and password to check your camera.
|
||||||
|
|
||||||
A growing list of cameras and brands that have been reported by users to work with Frigate's autotracking can be found [here](cameras.md).
|
A growing list of cameras and brands that have been reported by users to work with Frigate's autotracking can be found [here](cameras.md).
|
||||||
|
|
||||||
@ -34,44 +29,12 @@ A growing list of cameras and brands that have been reported by users to work wi
|
|||||||
|
|
||||||
First, set up a PTZ preset in your camera's firmware and give it a name. If you're unsure how to do this, consult the documentation for your camera manufacturer's firmware. Some tutorials for common brands: [Amcrest](https://www.youtube.com/watch?v=lJlE9-krmrM), [Reolink](https://www.youtube.com/watch?v=VAnxHUY5i5w), [Dahua](https://www.youtube.com/watch?v=7sNbc5U-k54).
|
First, set up a PTZ preset in your camera's firmware and give it a name. If you're unsure how to do this, consult the documentation for your camera manufacturer's firmware. Some tutorials for common brands: [Amcrest](https://www.youtube.com/watch?v=lJlE9-krmrM), [Reolink](https://www.youtube.com/watch?v=VAnxHUY5i5w), [Dahua](https://www.youtube.com/watch?v=7sNbc5U-k54).
|
||||||
|
|
||||||
Configure the ONVIF connection and autotracking parameters for your camera. Specify the object types to track, a required zone the object must enter to begin autotracking, and the camera preset name you configured in your camera's firmware to return to when tracking has ended. Optionally, specify a delay in seconds before Frigate returns the camera to the preset.
|
Edit your Frigate configuration file and enter the ONVIF parameters for your camera. Specify the object types to track, a required zone the object must enter to begin autotracking, and the camera preset name you configured in your camera's firmware to return to when tracking has ended. Optionally, specify a delay in seconds before Frigate returns the camera to the preset.
|
||||||
|
|
||||||
An [ONVIF connection](cameras.md) is required for autotracking to function. Also, a [motion mask](masks.md) over your camera's timestamp and any overlay text is recommended to ensure they are completely excluded from scene change calculations when the camera is moving.
|
An [ONVIF connection](cameras.md) is required for autotracking to function. Also, a [motion mask](masks.md) over your camera's timestamp and any overlay text is recommended to ensure they are completely excluded from scene change calculations when the camera is moving.
|
||||||
|
|
||||||
Note that `autotracking` is disabled by default but can be enabled in the configuration or by MQTT.
|
Note that `autotracking` is disabled by default but can be enabled in the configuration or by MQTT.
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > Camera configuration > ONVIF" /> for the desired camera.
|
|
||||||
|
|
||||||
**ONVIF Connection**
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| **ONVIF host** | Host of the camera being connected to. HTTP is assumed by default; prefix with `https://` for HTTPS. |
|
|
||||||
| **ONVIF port** | ONVIF port for device (default: 8000) |
|
|
||||||
| **ONVIF username** | Username for login. Some devices require admin to access ONVIF. |
|
|
||||||
| **ONVIF password** | Password for login |
|
|
||||||
| **Disable TLS verify** | Skip TLS verification and disable digest auth for ONVIF (default: false) |
|
|
||||||
| **ONVIF profile** | ONVIF media profile to use for PTZ control, matched by token or name. If not set, the first profile with valid PTZ configuration is selected automatically. |
|
|
||||||
|
|
||||||
**Autotracking**
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
||||||
| **Enable Autotracking** | Enable or disable object autotracking (default: false) |
|
|
||||||
| **Calibrate on start** | Calibrate the camera on startup by measuring PTZ motor speed (default: false) |
|
|
||||||
| **Zoom mode** | Zoom mode during autotracking: `disabled`, `absolute`, or `relative` (default: disabled) |
|
|
||||||
| **Zoom Factor** | Controls zoom behavior on tracked objects, between 0.1 and 0.75. Lower keeps more scene visible; higher zooms in more (default: 0.3) |
|
|
||||||
| **Tracked objects** | List of object types to track (default: person) |
|
|
||||||
| **Required Zones** | Zones an object must enter to begin autotracking |
|
|
||||||
| **Return Preset** | Name of ONVIF preset in camera firmware to return to when tracking ends (default: home) |
|
|
||||||
| **Return timeout** | Seconds to delay before returning to preset (default: 10) |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
cameras:
|
cameras:
|
||||||
ptzcamera:
|
ptzcamera:
|
||||||
@ -89,10 +52,6 @@ cameras:
|
|||||||
password: admin
|
password: admin
|
||||||
# Optional: Skip TLS verification from the ONVIF server (default: shown below)
|
# Optional: Skip TLS verification from the ONVIF server (default: shown below)
|
||||||
tls_insecure: False
|
tls_insecure: False
|
||||||
# Optional: ONVIF media profile to use for PTZ control, matched by token or name. (default: shown below)
|
|
||||||
# If not set, the first profile with valid PTZ configuration is selected automatically.
|
|
||||||
# Use this when your camera has multiple ONVIF profiles and you need to select a specific one.
|
|
||||||
profile: None
|
|
||||||
# Optional: PTZ camera object autotracking. Keeps a moving object in
|
# Optional: PTZ camera object autotracking. Keeps a moving object in
|
||||||
# the center of the frame by automatically moving the PTZ camera.
|
# the center of the frame by automatically moving the PTZ camera.
|
||||||
autotracking:
|
autotracking:
|
||||||
@ -129,16 +88,13 @@ cameras:
|
|||||||
movement_weights: []
|
movement_weights: []
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Calibration
|
## Calibration
|
||||||
|
|
||||||
PTZ motors operate at different speeds. Performing a calibration will direct Frigate to measure this speed over a variety of movements and use those measurements to better predict the amount of movement necessary to keep autotracked objects in the center of the frame.
|
PTZ motors operate at different speeds. Performing a calibration will direct Frigate to measure this speed over a variety of movements and use those measurements to better predict the amount of movement necessary to keep autotracked objects in the center of the frame.
|
||||||
|
|
||||||
Calibration is optional, but will greatly assist Frigate in autotracking objects that move across the camera's field of view more quickly.
|
Calibration is optional, but will greatly assist Frigate in autotracking objects that move across the camera's field of view more quickly.
|
||||||
|
|
||||||
To begin calibration, set `calibrate_on_startup` for your camera to `True` and restart Frigate. Frigate will then make a series of small and large movements with your camera. Don't move the PTZ manually while calibration is in progress. Once complete, camera motion will stop and your config file will be automatically updated with a `movement_weights` parameter to be used in movement calculations. You should not modify this parameter manually.
|
To begin calibration, set the `calibrate_on_startup` for your camera to `True` and restart Frigate. Frigate will then make a series of small and large movements with your camera. Don't move the PTZ manually while calibration is in progress. Once complete, camera motion will stop and your config file will be automatically updated with a `movement_weights` parameter to be used in movement calculations. You should not modify this parameter manually.
|
||||||
|
|
||||||
After calibration has ended, your PTZ will be moved to the preset specified by `return_preset`.
|
After calibration has ended, your PTZ will be moved to the preset specified by `return_preset`.
|
||||||
|
|
||||||
@ -162,13 +118,13 @@ Every PTZ camera is different, so autotracking may not perform ideally in every
|
|||||||
|
|
||||||
The object tracker in Frigate estimates the motion of the PTZ so that tracked objects are preserved when the camera moves. In most cases 5 fps is sufficient, but if you plan to track faster moving objects, you may want to increase this slightly. Higher frame rates (> 10fps) will only slow down Frigate and the motion estimator and may lead to dropped frames, especially if you are using experimental zooming.
|
The object tracker in Frigate estimates the motion of the PTZ so that tracked objects are preserved when the camera moves. In most cases 5 fps is sufficient, but if you plan to track faster moving objects, you may want to increase this slightly. Higher frame rates (> 10fps) will only slow down Frigate and the motion estimator and may lead to dropped frames, especially if you are using experimental zooming.
|
||||||
|
|
||||||
A fast [detector](object_detectors.md) is recommended. CPU detectors will not perform well or won't work at all. You can watch Frigate's [debug viewer](/usage/live#the-single-camera-view) for your camera to see a thicker colored box around the object currently being autotracked.
|
A fast [detector](object_detectors.md) is recommended. CPU detectors will not perform well or won't work at all. You can watch Frigate's debug viewer for your camera to see a thicker colored box around the object currently being autotracked.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
A full-frame zone in `required_zones` is not recommended, especially if you've calibrated your camera and there are `movement_weights` defined in the configuration file. Frigate will continue to autotrack an object that has entered one of the `required_zones`, even if it moves outside of that zone.
|
A full-frame zone in `required_zones` is not recommended, especially if you've calibrated your camera and there are `movement_weights` defined in the configuration file. Frigate will continue to autotrack an object that has entered one of the `required_zones`, even if it moves outside of that zone.
|
||||||
|
|
||||||
Some users have found it helpful to adjust the zone `inertia` value. See the [configuration reference](advanced/reference.md).
|
Some users have found it helpful to adjust the zone `inertia` value. See the [configuration reference](index.md).
|
||||||
|
|
||||||
## Zooming
|
## Zooming
|
||||||
|
|
||||||
@ -188,96 +144,30 @@ In security and surveillance, it's common to use "spotter" cameras in combinatio
|
|||||||
|
|
||||||
## Troubleshooting and FAQ
|
## Troubleshooting and FAQ
|
||||||
|
|
||||||
### Camera Compatibility
|
### The autotracker loses track of my object. Why?
|
||||||
|
|
||||||
<FaqItem id="which-ptz-camera-should-i-use-for-autotracking" question="Which PTZ camera should I use for autotracking?">
|
|
||||||
|
|
||||||
See the community-maintained list of [ONVIF PTZ camera recommendations](cameras.md#onvif-ptz-camera-recommendations) for cameras and brands reported to work (and not work) with autotracking. This is not an exhaustive list that is frequently updated, so other cameras not listed may also work well. Frigate's autotracking was developed with a Dahua SD1A404XB-GNR (now sold as the EmpireTech PTZ1A4M-4X-S2), and Dahua / EmpireTech PTZs are the most consistently reported as working well.
|
|
||||||
|
|
||||||
When comparing models:
|
|
||||||
|
|
||||||
- Verify ONVIF support first. See [Checking ONVIF camera support](#checking-onvif-camera-support) above.
|
|
||||||
- Favor a camera with a fast PTZ motor. Cameras with slow motors may fail [calibration](#calibration) and will struggle to keep up with objects that move across the field of view quickly.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
<FaqItem id="does-autotracking-work-with-reolink-ptz-cameras" question="Does autotracking work with Reolink PTZ cameras?">
|
|
||||||
|
|
||||||
No. Reolink cameras (including the TrackMix series) lack the ONVIF FOV RelativeMove firmware support that Frigate's autotracker requires, so autotracking will not work with any current Reolink PTZ. Their video streams and basic PTZ controls still work in Frigate. If you want object tracking on a Reolink PTZ, you will need to use the tracking feature built into the camera's firmware, which is proprietary and operates independently of Frigate.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
<FaqItem id="im-seeing-an-error-in-the-logs-that-my-camera-is-still-in-onvif-moving-status-what-does-this-mean" question={"I'm seeing an error in the logs that my camera \"is still in ONVIF 'MOVING' status.\" What does this mean?"}>
|
|
||||||
|
|
||||||
There are two possible known reasons for this (and perhaps others yet unknown): a slow PTZ motor or buggy camera firmware. Frigate uses an ONVIF parameter provided by the camera, `MoveStatus`, to determine when the PTZ's motor is moving or idle. According to some users, Hikvision PTZs (even with the latest firmware), are not updating this value after PTZ movement. Unfortunately there is no workaround to this bug in Hikvision firmware, so autotracking will not function correctly and should be disabled in your config. This may also be the case with other non-Hikvision cameras utilizing Hikvision firmware, such as some Annke models. In rare cases the vendor may provide fixed firmware on request; for example, Annke has supplied firmware that resolves this for the CZ504 (see the [camera recommendations list](cameras.md#onvif-ptz-camera-recommendations)).
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
<FaqItem id="calibration-seems-to-have-completed-but-the-camera-is-not-actually-moving-to-track-my-object-why" question="Calibration seems to have completed, but the camera is not actually moving to track my object. Why?">
|
|
||||||
|
|
||||||
Some cameras have firmware that reports that FOV RelativeMove, the ONVIF command that Frigate uses for autotracking, is supported. However, if the camera does not pan or tilt when an object comes into the required zone, your camera's firmware does not actually support FOV RelativeMove. One such camera is the Uniview IPC672LR-AX4DUPK. It actually moves its zoom motor instead of panning and tilting and does not follow the ONVIF standard whatsoever.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
### Calibration Issues
|
|
||||||
|
|
||||||
<FaqItem id="i-tried-calibrating-my-camera-but-the-logs-show-that-it-is-stuck-at-0-and-frigate-is-not-starting-up" question="I tried calibrating my camera, but the logs show that it is stuck at 0% and Frigate is not starting up.">
|
|
||||||
|
|
||||||
This is often caused by the same reason as the "MOVING" status error above - the `MoveStatus` ONVIF parameter is not changing due to a bug in your camera's firmware. Also, see the note above: Frigate's web UI and all other cameras will be unresponsive while calibration is in progress. This is expected and normal. But if you don't see log entries every few seconds for calibration progress, your camera is not compatible with autotracking.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
<FaqItem id="frigate-reports-an-error-saying-that-calibration-has-failed-why" question="Frigate reports an error saying that calibration has failed. Why?">
|
|
||||||
|
|
||||||
Calibration measures the amount of time it takes for Frigate to make a series of movements with your PTZ. This error message is recorded in the log if these values are too high for Frigate to support calibrated autotracking. This is often the case when your camera's motor or network connection is too slow or your camera's firmware doesn't report the motor status in a timely manner.
|
|
||||||
|
|
||||||
Some things to try:
|
|
||||||
|
|
||||||
- If your camera's firmware has a PTZ or motor speed setting, set it to the fastest available speed and calibrate again.
|
|
||||||
- Run without calibration: remove the `movement_weights` line from your config, set `calibrate_on_startup` to `False`, and restart.
|
|
||||||
|
|
||||||
If calibration consistently fails, this often means your camera's motor is too slow and autotracking will behave unpredictably or won't be able to keep up with moving objects.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
<FaqItem id="autotracking-is-erratic-or-moves-the-camera-in-the-wrong-direction" question="Autotracking is erratic, moves the camera in the wrong direction, or zooms past my object. Why?">
|
|
||||||
|
|
||||||
Frigate uses the `movement_weights` measured during calibration to predict how far the camera needs to move to keep an object centered, so inaccurate values produce movements that don't seem to make sense: overshooting, moving the opposite direction, or zooming in on an object's last known position and losing it entirely. This is almost always a calibration issue.
|
|
||||||
|
|
||||||
- Remove the `movement_weights` entry from your config and restart Frigate to run without calibration. If tracking improves, try recalibrating.
|
|
||||||
- Recalibrate several times. The `movement_weights` values should be close to each other after each run. If they vary significantly between runs, your camera may not be reporting its motor status reliably, and you may get better results without calibration.
|
|
||||||
- If you are using zooming, a high `zoom_factor` can cause the camera to zoom in too far and lose the object. Try a lower value.
|
|
||||||
|
|
||||||
Remember to recalibrate whenever you change your `return_preset`, change your camera's detect `fps`, or enable zooming after calibrating with it disabled.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
### Tracking Behavior
|
|
||||||
|
|
||||||
<FaqItem id="the-autotracker-loses-track-of-my-object-why" question="The autotracker loses track of my object. Why?">
|
|
||||||
|
|
||||||
There are many reasons this could be the case. If you are using experimental zooming, your `zoom_factor` value might be too high, the object might be traveling too quickly, the scene might be too dark, there are not enough details in the scene (for example, a PTZ looking down on a driveway or other monotone background without a sufficient number of hard edges or corners), or the scene is otherwise less than optimal for Frigate to maintain tracking.
|
There are many reasons this could be the case. If you are using experimental zooming, your `zoom_factor` value might be too high, the object might be traveling too quickly, the scene might be too dark, there are not enough details in the scene (for example, a PTZ looking down on a driveway or other monotone background without a sufficient number of hard edges or corners), or the scene is otherwise less than optimal for Frigate to maintain tracking.
|
||||||
|
|
||||||
Your camera's shutter speed may also be set too low so that blurring occurs with motion. Check your camera's firmware to see if you can increase the shutter speed.
|
Your camera's shutter speed may also be set too low so that blurring occurs with motion. Check your camera's firmware to see if you can increase the shutter speed.
|
||||||
|
|
||||||
Watching Frigate's debug view can help to determine a possible cause. The autotracked object will have a thicker colored box around it. If the camera consistently zooms in on the object and then loses it, see [Autotracking is erratic, moves the camera in the wrong direction, or zooms past my object. Why?](#autotracking-is-erratic-or-moves-the-camera-in-the-wrong-direction) above.
|
Watching Frigate's debug view can help to determine a possible cause. The autotracked object will have a thicker colored box around it.
|
||||||
|
|
||||||
</FaqItem>
|
### I'm seeing an error in the logs that my camera "is still in ONVIF 'MOVING' status." What does this mean?
|
||||||
|
|
||||||
<FaqItem id="im-seeing-this-error-in-the-logs-autotracker-motion-estimator-couldnt-get-transformations-what-does-this-mean" question={"I'm seeing this error in the logs: \"Autotracker: motion estimator couldn't get transformations\". What does this mean?"}>
|
There are two possible known reasons for this (and perhaps others yet unknown): a slow PTZ motor or buggy camera firmware. Frigate uses an ONVIF parameter provided by the camera, `MoveStatus`, to determine when the PTZ's motor is moving or idle. According to some users, Hikvision PTZs (even with the latest firmware), are not updating this value after PTZ movement. Unfortunately there is no workaround to this bug in Hikvision firmware, so autotracking will not function correctly and should be disabled in your config. This may also be the case with other non-Hikvision cameras utilizing Hikvision firmware.
|
||||||
|
|
||||||
|
### I tried calibrating my camera, but the logs show that it is stuck at 0% and Frigate is not starting up.
|
||||||
|
|
||||||
|
This is often caused by the same reason as above - the `MoveStatus` ONVIF parameter is not changing due to a bug in your camera's firmware. Also, see the note above: Frigate's web UI and all other cameras will be unresponsive while calibration is in progress. This is expected and normal. But if you don't see log entries every few seconds for calibration progress, your camera is not compatible with autotracking.
|
||||||
|
|
||||||
|
### I'm seeing this error in the logs: "Autotracker: motion estimator couldn't get transformations". What does this mean?
|
||||||
|
|
||||||
To maintain object tracking during PTZ moves, Frigate tracks the motion of your camera based on the details of the frame. If you are seeing this message, it could mean that your `zoom_factor` may be set too high, the scene around your detected object does not have enough details (like hard edges or color variations), or your camera's shutter speed is too slow and motion blur is occurring. Try reducing `zoom_factor`, finding a way to alter the scene around your object, or changing your camera's shutter speed.
|
To maintain object tracking during PTZ moves, Frigate tracks the motion of your camera based on the details of the frame. If you are seeing this message, it could mean that your `zoom_factor` may be set too high, the scene around your detected object does not have enough details (like hard edges or color variations), or your camera's shutter speed is too slow and motion blur is occurring. Try reducing `zoom_factor`, finding a way to alter the scene around your object, or changing your camera's shutter speed.
|
||||||
|
|
||||||
</FaqItem>
|
### Calibration seems to have completed, but the camera is not actually moving to track my object. Why?
|
||||||
|
|
||||||
<FaqItem id="why-does-object-detection-pause-briefly-when-the-camera-moves" question="Why does object detection pause briefly when the camera moves?">
|
Some cameras have firmware that reports that FOV RelativeMove, the ONVIF command that Frigate uses for autotracking, is supported. However, if the camera does not pan or tilt when an object comes into the required zone, your camera's firmware does not actually support FOV RelativeMove. One such camera is the Uniview IPC672LR-AX4DUPK. It actually moves its zoom motor instead of panning and tilting and does not follow the ONVIF standard whatsoever.
|
||||||
|
|
||||||
When the PTZ moves, the entire frame changes at once. Frigate's motion detection treats sudden scene-wide changes (like a lightning flash, an infrared mode switch, or a camera move) specially and pauses detection momentarily until the scene stabilizes. This is expected and normal, and detection resumes shortly after the camera stops moving. If detection does not resume once the camera is stationary, use the [debug view](/usage/live#the-single-camera-view) to see what is happening.
|
### Frigate reports an error saying that calibration has failed. Why?
|
||||||
|
|
||||||
</FaqItem>
|
Calibration measures the amount of time it takes for Frigate to make a series of movements with your PTZ. This error message is recorded in the log if these values are too high for Frigate to support calibrated autotracking. This is often the case when your camera's motor or network connection is too slow or your camera's firmware doesn't report the motor status in a timely manner. You can try running without calibration (just remove the `movement_weights` line from your config and restart), but if calibration fails, this often means that autotracking will behave unpredictably.
|
||||||
|
|
||||||
<FaqItem id="can-i-turn-autotracking-on-and-off-automatically" question="Can I turn autotracking on and off automatically?">
|
|
||||||
|
|
||||||
Yes. Autotracking can be toggled per camera at runtime over MQTT with the [`frigate/<camera_name>/ptz_autotracker/set`](../integrations/mqtt.md#frigatecamera_nameptz_autotrackerset) topic, and the [Home Assistant integration](../integrations/home-assistant.md) exposes a switch for it. This pairs well with the "spotter" camera automations described in [Usage applications](#usage-applications) above, for example only enabling autotracking at night or when nobody is home.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|||||||
@ -3,18 +3,8 @@ id: bird_classification
|
|||||||
title: Bird Classification
|
title: Bird Classification
|
||||||
---
|
---
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
|
|
||||||
Bird classification identifies known birds using a quantized Tensorflow model. When a known bird is recognized, its common name will be added as a `sub_label`. This information is included in the UI, filters, as well as in notifications.
|
Bird classification identifies known birds using a quantized Tensorflow model. When a known bird is recognized, its common name will be added as a `sub_label`. This information is included in the UI, filters, as well as in notifications.
|
||||||
|
|
||||||
:::info
|
|
||||||
|
|
||||||
Bird classification requires a one-time internet connection to download the classification model and label map from GitHub. Once cached, models work fully offline. See [Network Requirements](/frigate/network_requirements#one-time-model-downloads) for details.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Minimum System Requirements
|
## Minimum System Requirements
|
||||||
|
|
||||||
Bird classification runs a lightweight tflite model on the CPU, there are no significantly different system requirements than running Frigate itself.
|
Bird classification runs a lightweight tflite model on the CPU, there are no significantly different system requirements than running Frigate itself.
|
||||||
@ -25,18 +15,7 @@ The classification model used is the MobileNet INat Bird Classification, [availa
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Bird classification is disabled by default and must be enabled before it can be used. Bird classification is a global configuration setting.
|
Bird classification is disabled by default, it must be enabled in your config file before it can be used. Bird classification is a global configuration setting.
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > Enrichments > Object classification" />.
|
|
||||||
|
|
||||||
- Set **Bird classification config > Bird classification** to on
|
|
||||||
- Set **Bird classification config > Minimum score** to the desired confidence score (default: 0.9)
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
classification:
|
classification:
|
||||||
@ -44,9 +23,6 @@ classification:
|
|||||||
enabled: true
|
enabled: true
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Advanced Configuration
|
## Advanced Configuration
|
||||||
|
|
||||||
Fine-tune bird classification with these optional parameters:
|
Fine-tune bird classification with these optional parameters:
|
||||||
|
|||||||
@ -1,21 +1,11 @@
|
|||||||
# Birdseye
|
# Birdseye
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
|
|
||||||
In addition to Frigate's Live camera dashboard, Birdseye allows a portable heads-up view of your cameras to see what is going on around your property / space without having to watch all cameras that may have nothing happening. Birdseye allows specific modes that intelligently show and disappear based on what you care about.
|
In addition to Frigate's Live camera dashboard, Birdseye allows a portable heads-up view of your cameras to see what is going on around your property / space without having to watch all cameras that may have nothing happening. Birdseye allows specific modes that intelligently show and disappear based on what you care about.
|
||||||
|
|
||||||
Birdseye can be viewed by adding the "Birdseye" camera to a Camera Group in the Web UI. Add a Camera Group by pressing the pencil icon in the sidebar on the Live page, and choose "Birdseye" as one of the cameras.
|
Birdseye can be viewed by adding the "Birdseye" camera to a Camera Group in the Web UI. Add a Camera Group by pressing the "+" icon on the Live page, and choose "Birdseye" as one of the cameras.
|
||||||
|
|
||||||
Birdseye can also be used in Home Assistant dashboards, cast to media devices, etc.
|
Birdseye can also be used in Home Assistant dashboards, cast to media devices, etc.
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
Each camera tile in Birdseye is composed from the frames of the stream assigned the `detect` role, so a camera's image quality in Birdseye matches its detect stream resolution rather than a higher-resolution recording stream. If a camera looks low quality in Birdseye, increasing the detect width and height (or assigning the `detect` role to a higher-resolution stream) is what affects it. See [setting up camera inputs](./cameras.md#setting-up-camera-inputs) for how roles are assigned.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Birdseye Behavior
|
## Birdseye Behavior
|
||||||
|
|
||||||
### Birdseye Modes
|
### Birdseye Modes
|
||||||
@ -32,24 +22,9 @@ A custom icon can be added to the birdseye background by providing a 180x180 ima
|
|||||||
|
|
||||||
### Birdseye view override at camera level
|
### Birdseye view override at camera level
|
||||||
|
|
||||||
To include a camera in Birdseye view only for specific circumstances, or exclude it entirely, configure Birdseye at the camera level.
|
If you want to include a camera in Birdseye view only for specific circumstances, or just don't include it at all, the Birdseye setting can be set at the camera level.
|
||||||
|
|
||||||
<ConfigTabs>
|
```yaml
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
**Global settings:** Navigate to <NavPath path="Settings > System > Birdseye" /> to configure the default Birdseye behavior for all cameras.
|
|
||||||
|
|
||||||
**Per-camera overrides:** Navigate to <NavPath path="Settings > Camera configuration > Birdseye" /> to override the mode or disable Birdseye for a specific camera.
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ------------------- | ------------------------------------------------------------- |
|
|
||||||
| **Enable Birdseye** | Whether this camera appears in Birdseye view |
|
|
||||||
| **Tracking mode** | When to show the camera: `continuous`, `motion`, or `objects` |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml {8-10,12-14}
|
|
||||||
# Include all cameras by default in Birdseye view
|
# Include all cameras by default in Birdseye view
|
||||||
birdseye:
|
birdseye:
|
||||||
enabled: True
|
enabled: True
|
||||||
@ -66,54 +41,22 @@ cameras:
|
|||||||
enabled: False
|
enabled: False
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### Birdseye Inactivity
|
### Birdseye Inactivity
|
||||||
|
|
||||||
By default birdseye shows all cameras that have had the configured activity in the last 30 seconds. This threshold can be configured.
|
By default birdseye shows all cameras that have had the configured activity in the last 30 seconds, this can be configured:
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Birdseye" />.
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ------------------------ | --------------------------------------------------------------------------- |
|
|
||||||
| **Inactivity threshold** | Seconds of inactivity before a camera is hidden from Birdseye (default: 30) |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
birdseye:
|
birdseye:
|
||||||
enabled: True
|
enabled: True
|
||||||
# highlight-next-line
|
|
||||||
inactivity_threshold: 15
|
inactivity_threshold: 15
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Birdseye Layout
|
## Birdseye Layout
|
||||||
|
|
||||||
### Birdseye Dimensions
|
### Birdseye Dimensions
|
||||||
|
|
||||||
The resolution and aspect ratio of birdseye can be configured. Resolution will increase the quality but does not affect the layout. Changing the aspect ratio of birdseye does affect how cameras are laid out.
|
The resolution and aspect ratio of birdseye can be configured. Resolution will increase the quality but does not affect the layout. Changing the aspect ratio of birdseye does affect how cameras are laid out.
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Birdseye" />.
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ---------- | ----------------------------------------------- |
|
|
||||||
| **Width** | Birdseye output width in pixels (default: 1280) |
|
|
||||||
| **Height** | Birdseye output height in pixels (default: 720) |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
birdseye:
|
birdseye:
|
||||||
enabled: True
|
enabled: True
|
||||||
@ -121,20 +64,10 @@ birdseye:
|
|||||||
height: 720
|
height: 720
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### Sorting cameras in the Birdseye view
|
### Sorting cameras in the Birdseye view
|
||||||
|
|
||||||
It is possible to override the order of cameras that are being shown in the Birdseye view. The order is set at the camera level (when using YAML).
|
It is possible to override the order of cameras that are being shown in the Birdseye view.
|
||||||
|
The order needs to be set at the camera level.
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Birdseye" /> and in the **Camera order** field, use the drag handle next to each camera name to control the display order.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# Include all cameras by default in Birdseye view
|
# Include all cameras by default in Birdseye view
|
||||||
@ -145,67 +78,34 @@ birdseye:
|
|||||||
cameras:
|
cameras:
|
||||||
front:
|
front:
|
||||||
birdseye:
|
birdseye:
|
||||||
# highlight-next-line
|
|
||||||
order: 1
|
order: 1
|
||||||
back:
|
back:
|
||||||
birdseye:
|
birdseye:
|
||||||
# highlight-next-line
|
|
||||||
order: 2
|
order: 2
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
_Note_: Cameras are sorted by default using their name to ensure a constant view inside Birdseye.
|
_Note_: Cameras are sorted by default using their name to ensure a constant view inside Birdseye.
|
||||||
|
|
||||||
### Birdseye Cameras
|
### Birdseye Cameras
|
||||||
|
|
||||||
It is possible to limit the number of cameras shown on birdseye at one time. When this is enabled, birdseye will show the cameras with most recent activity. There is a cooldown to ensure that cameras do not switch too frequently.
|
It is possible to limit the number of cameras shown on birdseye at one time. When this is enabled, birdseye will show the cameras with most recent activity. There is a cooldown to ensure that cameras do not switch too frequently.
|
||||||
|
|
||||||
<ConfigTabs>
|
For example, this can be configured to only show the most recently active camera.
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Birdseye" />.
|
```yaml
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ------------------------ | ----------------------------------------------------------------------------------- |
|
|
||||||
| **Layout > Max cameras** | Maximum number of cameras shown at once (e.g., `1` for only the most active camera) |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml {3-4}
|
|
||||||
birdseye:
|
birdseye:
|
||||||
enabled: True
|
enabled: True
|
||||||
layout:
|
layout:
|
||||||
max_cameras: 1
|
max_cameras: 1
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### Birdseye Scaling
|
### Birdseye Scaling
|
||||||
|
|
||||||
By default birdseye tries to fit 2 cameras in each row and then double in size until a suitable layout is found. The scaling can be configured with a value between 1.0 and 5.0 depending on use case.
|
By default birdseye tries to fit 2 cameras in each row and then double in size until a suitable layout is found. The scaling can be configured with a value between 1.0 and 5.0 depending on use case.
|
||||||
|
|
||||||
<ConfigTabs>
|
```yaml
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Birdseye" />.
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| --------------------------- | -------------------------------------------------------- |
|
|
||||||
| **Layout > Scaling factor** | Camera scaling factor between 1.0 and 5.0 (default: 2.0) |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml {3-4}
|
|
||||||
birdseye:
|
birdseye:
|
||||||
enabled: True
|
enabled: True
|
||||||
layout:
|
layout:
|
||||||
scaling_factor: 3.0
|
scaling_factor: 3.0
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|||||||
@ -3,8 +3,6 @@ id: camera_specific
|
|||||||
title: Camera Specific Configurations
|
title: Camera Specific Configurations
|
||||||
---
|
---
|
||||||
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
|
|
||||||
This page makes use of presets of FFmpeg args. For more information on presets, see the [FFmpeg Presets](/configuration/ffmpeg_presets) page.
|
This page makes use of presets of FFmpeg args. For more information on presets, see the [FFmpeg Presets](/configuration/ffmpeg_presets) page.
|
||||||
@ -25,7 +23,6 @@ Some cameras support h265 with different formats, but Safari only supports the a
|
|||||||
cameras:
|
cameras:
|
||||||
h265_cam: # <------ Doesn't matter what the camera is called
|
h265_cam: # <------ Doesn't matter what the camera is called
|
||||||
ffmpeg:
|
ffmpeg:
|
||||||
# highlight-next-line
|
|
||||||
apple_compatibility: true # <- Adds compatibility with MacOS and iPhone
|
apple_compatibility: true # <- Adds compatibility with MacOS and iPhone
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -33,7 +30,7 @@ cameras:
|
|||||||
|
|
||||||
Note that mjpeg cameras require encoding the video into h264 for recording, and restream roles. This will use significantly more CPU than if the cameras supported h264 feeds directly. It is recommended to use the restream role to create an h264 restream and then use that as the source for ffmpeg.
|
Note that mjpeg cameras require encoding the video into h264 for recording, and restream roles. This will use significantly more CPU than if the cameras supported h264 feeds directly. It is recommended to use the restream role to create an h264 restream and then use that as the source for ffmpeg.
|
||||||
|
|
||||||
```yaml {3,10}
|
```yaml
|
||||||
go2rtc:
|
go2rtc:
|
||||||
streams:
|
streams:
|
||||||
mjpeg_cam: "ffmpeg:http://your_mjpeg_stream_url#video=h264#hardware" # <- use hardware acceleration to create an h264 stream usable for other components.
|
mjpeg_cam: "ffmpeg:http://your_mjpeg_stream_url#video=h264#hardware" # <- use hardware acceleration to create an h264 stream usable for other components.
|
||||||
@ -99,7 +96,6 @@ This camera is H.265 only. To be able to play clips on some devices (like MacOs
|
|||||||
cameras:
|
cameras:
|
||||||
annkec800: # <------ Name the camera
|
annkec800: # <------ Name the camera
|
||||||
ffmpeg:
|
ffmpeg:
|
||||||
# highlight-next-line
|
|
||||||
apple_compatibility: true # <- Adds compatibility with MacOS and iPhone
|
apple_compatibility: true # <- Adds compatibility with MacOS and iPhone
|
||||||
output_args:
|
output_args:
|
||||||
record: preset-record-generic-audio-aac
|
record: preset-record-generic-audio-aac
|
||||||
@ -148,70 +144,32 @@ WEB Digest Algorithm - MD5
|
|||||||
|
|
||||||
### Reolink Cameras
|
### Reolink Cameras
|
||||||
|
|
||||||
Reolink has many different camera models with inconsistently supported features and behavior. The below table shows a summary of various features and recommendations.
|
Reolink has older cameras (ex: 410 & 520) as well as newer camera (ex: 520a & 511wa) which support different subsets of options. In both cases using the http stream is recommended.
|
||||||
|
Frigate works much better with newer reolink cameras that are setup with the below options:
|
||||||
| Camera Resolution | Camera Generation | Recommended Stream Type | Additional Notes |
|
|
||||||
| ----------------- | ------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------- |
|
|
||||||
| 5MP or lower | All | http-flv | Stream is h264 |
|
|
||||||
| 6MP or higher | Latest (ex: Duo3, CX-8##) | http-flv with ffmpeg 8.0, or rtsp | This uses the new http-flv-enhanced over H265 which requires ffmpeg 8.0 (Frigate's default) |
|
|
||||||
| 6MP or higher | Older (ex: RLC-8##) | rtsp | |
|
|
||||||
|
|
||||||
Frigate works much better with newer Reolink cameras that are setup with the below options:
|
|
||||||
|
|
||||||
If available, recommended settings are:
|
If available, recommended settings are:
|
||||||
|
|
||||||
- `On, fluency first` this sets the camera to CBR (constant bit rate)
|
- `On, fluency first` this sets the camera to CBR (constant bit rate)
|
||||||
- `Interframe Space 1x` this sets the iframe interval to the same as the frame rate
|
- `Interframe Space 1x` this sets the iframe interval to the same as the frame rate
|
||||||
|
|
||||||
#### Setup via the Add Camera Wizard
|
|
||||||
|
|
||||||
The [Add Camera Wizard](cameras.md#adding-a-camera-with-the-add-camera-wizard) is the recommended way to add a standard Reolink camera. Before starting, make sure [HTTP is enabled](https://support.reolink.com/articles/360003452893-How-to-Access-Reolink-Cameras-NVRs-Home-Hub-Locally-via-Web-Browsers/) in the camera's advanced network settings. The wizard uses the camera's HTTP API to determine its resolution and choose the recommended stream type from the table above.
|
|
||||||
|
|
||||||
1. Click **Add Camera** in <NavPath path="Settings > Global configuration > Camera management" />.
|
|
||||||
2. Choose **Manual selection** as the stream detection method and select **Reolink** as the camera brand.
|
|
||||||
3. The wizard queries the camera and automatically uses an http-flv stream for cameras 5MP and lower, or an RTSP stream for higher resolution cameras.
|
|
||||||
4. In the validation step, enable **Use stream compatibility mode** for http-flv streams when the wizard recommends it.
|
|
||||||
|
|
||||||
If you use the **Probe camera** method instead, the discovered stream URLs will be RTSP. For Reolink cameras where http-flv is recommended, the wizard will show a warning in the validation step.
|
|
||||||
|
|
||||||
The wizard covers standard single-camera setups. For two way talk, cameras connected through a Reolink NVR, or audio transcoding for WebRTC live view, configure the camera manually as shown below.
|
|
||||||
|
|
||||||
#### Manual configuration
|
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
Cameras connected via a Reolink NVR can be connected with the http stream, use `channel[0..15]` in the stream url for the additional channels.
|
Cameras connected via a Reolink NVR can be connected with the http stream, use `channel[0..15]` in the stream url for the additional channels.
|
||||||
The setup of main stream can be also done via RTSP, but isn't always reliable on all hardware versions. The example configuration is working with the oldest HW version RLN16-410 device with multiple types of cameras.
|
The setup of main stream can be also done via RTSP, but isn't always reliable on all hardware versions. The example configuration is working with the oldest HW version RLN16-410 device with multiple types of cameras.
|
||||||
|
|
||||||
<details>
|
:::warning
|
||||||
<summary>Example Config</summary>
|
|
||||||
|
|
||||||
:::tip
|
The below configuration only works for reolink cameras with stream resolution of 5MP or lower, 8MP+ cameras need to use RTSP as http-flv is not supported in this case.
|
||||||
|
|
||||||
Reolink's latest cameras support two way audio via go2rtc and other applications. It is important that the http-flv stream is still used for stability, a secondary rtsp stream can be added that will be using for the two way audio only.
|
|
||||||
|
|
||||||
NOTE: The RTSP stream can not be prefixed with `ffmpeg:`, as go2rtc needs to handle the stream to support two way audio.
|
|
||||||
|
|
||||||
Ensure [HTTP is enabled](https://support.reolink.com/articles/360003452893-How-to-Access-Reolink-Cameras-NVRs-Home-Hub-Locally-via-Web-Browsers/) in the camera's advanced network settings. To use two way talk with Frigate, see the [Live view documentation](/configuration/live#two-way-talk).
|
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
go2rtc:
|
go2rtc:
|
||||||
streams:
|
streams:
|
||||||
# example for connecting to a standard Reolink camera
|
|
||||||
your_reolink_camera:
|
your_reolink_camera:
|
||||||
- "ffmpeg:http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=username&password=password#video=copy#audio=copy#audio=opus"
|
- "ffmpeg:http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=username&password=password#video=copy#audio=copy#audio=opus"
|
||||||
your_reolink_camera_sub:
|
your_reolink_camera_sub:
|
||||||
- "ffmpeg:http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_ext.bcs&user=username&password=password"
|
- "ffmpeg:http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_ext.bcs&user=username&password=password"
|
||||||
# example for connecting to a Reolink camera that supports two way talk
|
|
||||||
your_reolink_camera_twt:
|
|
||||||
- "ffmpeg:http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=username&password=password#video=copy#audio=copy#audio=opus"
|
|
||||||
- "rtsp://username:password@reolink_ip/Preview_01_sub"
|
|
||||||
your_reolink_camera_twt_sub:
|
|
||||||
- "ffmpeg:http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_ext.bcs&user=username&password=password"
|
|
||||||
- "rtsp://username:password@reolink_ip/Preview_01_sub"
|
|
||||||
# example for connecting to a Reolink NVR
|
|
||||||
your_reolink_camera_via_nvr:
|
your_reolink_camera_via_nvr:
|
||||||
- "ffmpeg:http://reolink_nvr_ip/flv?port=1935&app=bcs&stream=channel3_main.bcs&user=username&password=password" # channel numbers are 0-15
|
- "ffmpeg:http://reolink_nvr_ip/flv?port=1935&app=bcs&stream=channel3_main.bcs&user=username&password=password" # channel numbers are 0-15
|
||||||
- "ffmpeg:your_reolink_camera_via_nvr#audio=aac"
|
- "ffmpeg:your_reolink_camera_via_nvr#audio=aac"
|
||||||
@ -243,16 +201,24 @@ cameras:
|
|||||||
- detect
|
- detect
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
#### Reolink Doorbell
|
||||||
|
|
||||||
|
The reolink doorbell supports two way audio via go2rtc and other applications. It is important that the http-flv stream is still used for stability, a secondary rtsp stream can be added that will be using for the two way audio only.
|
||||||
|
|
||||||
|
Ensure HTTP is enabled in the camera's advanced network settings. To use two way talk with Frigate, see the [Live view documentation](/configuration/live#two-way-talk).
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
go2rtc:
|
||||||
|
streams:
|
||||||
|
your_reolink_doorbell:
|
||||||
|
- "ffmpeg:http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=username&password=password#video=copy#audio=copy#audio=opus"
|
||||||
|
- rtsp://reolink_ip/Preview_01_sub
|
||||||
|
your_reolink_doorbell_sub:
|
||||||
|
- "ffmpeg:http://reolink_ip/flv?port=1935&app=bcs&stream=channel0_ext.bcs&user=username&password=password"
|
||||||
|
```
|
||||||
|
|
||||||
### Unifi Protect Cameras
|
### Unifi Protect Cameras
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
Unifi G5s cameras and newer need a Unifi Protect server to enable rtsps stream, it's not possible to enable it in standalone mode.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
Unifi protect cameras require the rtspx stream to be used with go2rtc.
|
Unifi protect cameras require the rtspx stream to be used with go2rtc.
|
||||||
To utilize a Unifi protect camera, modify the rtsps link to begin with rtspx.
|
To utilize a Unifi protect camera, modify the rtsps link to begin with rtspx.
|
||||||
Additionally, remove the "?enableSrtp" from the end of the Unifi link.
|
Additionally, remove the "?enableSrtp" from the end of the Unifi link.
|
||||||
@ -264,7 +230,7 @@ go2rtc:
|
|||||||
- rtspx://192.168.1.1:7441/abcdefghijk
|
- rtspx://192.168.1.1:7441/abcdefghijk
|
||||||
```
|
```
|
||||||
|
|
||||||
[See the go2rtc docs for more information](https://github.com/AlexxIT/go2rtc/tree/v1.9.14#source-rtsp)
|
[See the go2rtc docs for more information](https://github.com/AlexxIT/go2rtc/tree/v1.9.9#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 if used directly with unifi protect.
|
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 if used directly with unifi protect.
|
||||||
|
|
||||||
@ -277,40 +243,3 @@ ffmpeg:
|
|||||||
### TP-Link VIGI Cameras
|
### TP-Link VIGI Cameras
|
||||||
|
|
||||||
TP-Link VIGI cameras need some adjustments to the main stream settings on the camera itself to avoid issues. The stream needs to be configured as `H264` with `Smart Coding` set to `off`. Without these settings you may have problems when trying to watch recorded footage. For example Firefox will stop playback after a few seconds and show the following error message: `The media playback was aborted due to a corruption problem or because the media used features your browser did not support.`.
|
TP-Link VIGI cameras need some adjustments to the main stream settings on the camera itself to avoid issues. The stream needs to be configured as `H264` with `Smart Coding` set to `off`. Without these settings you may have problems when trying to watch recorded footage. For example Firefox will stop playback after a few seconds and show the following error message: `The media playback was aborted due to a corruption problem or because the media used features your browser did not support.`.
|
||||||
|
|
||||||
### Wyze Wireless Cameras
|
|
||||||
|
|
||||||
Some community members have found better performance on Wyze cameras by using an alternative firmware known as [Thingino](https://thingino.com/).
|
|
||||||
|
|
||||||
## USB Cameras (aka Webcams)
|
|
||||||
|
|
||||||
To use a USB camera (webcam) with Frigate, the recommendation is to use go2rtc's [FFmpeg Device](https://github.com/AlexxIT/go2rtc?tab=readme-ov-file#source-ffmpeg-device) support:
|
|
||||||
|
|
||||||
- Preparation outside of Frigate:
|
|
||||||
- Get USB camera path. Run `v4l2-ctl --list-devices` to get a listing of locally-connected cameras available. (You may need to install `v4l-utils` in a way appropriate for your Linux distribution). In the sample configuration below, we use `video=0` to correlate with a detected device path of `/dev/video0`
|
|
||||||
- Get USB camera formats & resolutions. Run `ffmpeg -f v4l2 -list_formats all -i /dev/video0` to get an idea of what formats and resolutions the USB Camera supports. In the sample configuration below, we use a width of 1024 and height of 576 in the stream and detection settings based on what was reported back.
|
|
||||||
- If using Frigate in a container (e.g. Docker on TrueNAS), ensure you have USB Passthrough support enabled, along with a specific Host Device (`/dev/video0`) + Container Device (`/dev/video0`) listed.
|
|
||||||
|
|
||||||
- In your Frigate Configuration File, add the go2rtc stream and roles as appropriate:
|
|
||||||
|
|
||||||
```yaml {4,11-12}
|
|
||||||
go2rtc:
|
|
||||||
streams:
|
|
||||||
usb_camera:
|
|
||||||
- "ffmpeg:device?video=0&video_size=1024x576#video=h264"
|
|
||||||
|
|
||||||
cameras:
|
|
||||||
usb_camera:
|
|
||||||
enabled: true
|
|
||||||
ffmpeg:
|
|
||||||
inputs:
|
|
||||||
- path: rtsp://127.0.0.1:8554/usb_camera
|
|
||||||
input_args: preset-rtsp-restream
|
|
||||||
roles:
|
|
||||||
- detect
|
|
||||||
- record
|
|
||||||
detect:
|
|
||||||
enabled: false # <---- disable detection until you have a working camera feed
|
|
||||||
width: 1024
|
|
||||||
height: 576
|
|
||||||
```
|
|
||||||
|
|||||||
@ -3,78 +3,6 @@ id: cameras
|
|||||||
title: Camera Configuration
|
title: Camera Configuration
|
||||||
---
|
---
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
|
|
||||||
## Adding a camera with the Add Camera Wizard
|
|
||||||
|
|
||||||
The Add Camera Wizard is the recommended way to add a camera. Click **Add Camera** in <NavPath path="Settings > Global configuration > Camera management" />. The wizard connects to your camera, tests each stream, and writes the camera's configuration for you, including the [go2rtc](go2rtc.md) restream and the live view stream mapping, so a standard setup needs no hand-written YAML.
|
|
||||||
|
|
||||||
### Step 1: Name and connection
|
|
||||||
|
|
||||||
Enter a name for the camera along with its host or IP address and credentials, then choose how the wizard should find the camera's streams:
|
|
||||||
|
|
||||||
- **Probe camera** queries the camera over ONVIF (the ONVIF port is usually 80 or 8080) and asks it for its stream URLs. Some cameras use a separate ONVIF/service account rather than the device admin user, and some require **Use digest authentication** to be enabled.
|
|
||||||
- **Manual selection** builds a stream URL from a template for the camera brand you pick (Dahua/Amcrest/EmpireTech, Hikvision/Uniview/Annke, Ubiquiti, Reolink, Axis, TP-Link, or Foscam). Choose **Other** to enter a custom RTSP URL directly. Non-RTSP stream types must be [configured manually](#setting-up-camera-inputs).
|
|
||||||
|
|
||||||
The name you enter is lowercased and spaces become underscores. If the result still isn't a valid config key, the wizard generates a safe name and stores what you typed as `friendly_name`.
|
|
||||||
|
|
||||||
### Step 2: Probe or snapshot
|
|
||||||
|
|
||||||
In probe mode, the wizard reports what the camera returned (manufacturer, model, firmware, profile count, and whether PTZ, presets, and [autotracking](autotracking.md) are supported) along with the RTSP URLs it discovered. Test each candidate to see its resolution, frame rate, and codecs together with a snapshot, then select the one you want to use.
|
|
||||||
|
|
||||||
In manual mode, the wizard tests the templated URL and shows the same metadata and snapshot.
|
|
||||||
|
|
||||||
If no RTSP URLs are found, the credentials may be wrong or the camera may not support ONVIF. Go back and use manual selection instead.
|
|
||||||
|
|
||||||
### Step 3: Stream configuration
|
|
||||||
|
|
||||||
Assign [roles](#setting-up-camera-inputs) to the stream, and use **Add Another Stream** to add the camera's other streams, for example a substream for `detect` alongside the main stream for `record`. At least one stream must have the `detect` role before you can continue.
|
|
||||||
|
|
||||||
**Reduce connections to camera** routes that input through the go2rtc restream so Frigate and the live view share a single connection to the camera instead of each opening their own. See [restream](restream.md) for more detail.
|
|
||||||
|
|
||||||
### Step 4: Validation and testing
|
|
||||||
|
|
||||||
Connect each stream to get a live preview, an estimated bandwidth figure, and a list of validation results. The wizard checks for the most common misconfigurations, including:
|
|
||||||
|
|
||||||
- A detect resolution that is too high (increased resource usage) or too low for reliable detection, or one it could not probe at all
|
|
||||||
- A stream marked `record` whose audio codec is not AAC, or that has no audio at all
|
|
||||||
- A stream marked `audio` that carries no audio stream
|
|
||||||
- Using a restreamed input for the `record` role
|
|
||||||
- Brand-specific issues, such as an RTSP stream on a Reolink camera that should use http-flv, or a Dahua/Hikvision substream selected for `detect`
|
|
||||||
|
|
||||||
**Use stream compatibility mode** passes the stream through go2rtc's ffmpeg module. Enable it if a stream fails to load after several attempts. Note that this also prevents [two way talk](/configuration/live#two-way-talk) from being detected for that stream.
|
|
||||||
|
|
||||||
**Save New Camera** writes the configuration and starts the camera right away. No restart is required.
|
|
||||||
|
|
||||||
Other features, including [hardware acceleration](hardware_acceleration_video.md), [two way talk](/configuration/live#two-way-talk), and audio transcoding, is configured after the camera has been added. For camera model specific quirks, see the [camera specific](camera_specific.md) docs.
|
|
||||||
|
|
||||||
## Deleting a camera
|
|
||||||
|
|
||||||
Click **Delete Camera** in <NavPath path="Settings > Global configuration > Camera management" />, choose the camera, and confirm. Deleting a camera requires the `admin` role and cannot be undone.
|
|
||||||
|
|
||||||
:::warning
|
|
||||||
|
|
||||||
Deleting a camera permanently removes its recordings, tracked objects, and configuration. If you only want to stop processing a camera, set its state to **Off** or **Disabled** in <NavPath path="Settings > Global configuration > Camera management" /> instead. See [camera state](/configuration/live#camera-state).
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
Deleting a camera removes:
|
|
||||||
|
|
||||||
- The camera's section of your config file, along with its entries in any [role](authentication.md#user-roles) camera list. A custom role left with no cameras is removed as well.
|
|
||||||
- Every database record for the camera: tracked objects, review items, recordings, previews, timeline entries, the saved region grid, and [triggers](semantic_search.md#triggers).
|
|
||||||
- Every media file for the camera: recordings, snapshots, thumbnails, and preview clips.
|
|
||||||
|
|
||||||
[Exports](/usage/exports) are kept by default, so saved footage survives the deletion of the camera it came from. Turn on **Also delete exports for this camera** in the confirmation step to remove those too.
|
|
||||||
|
|
||||||
The camera's processes are stopped and the change takes effect immediately, so no restart is required. If the resulting config cannot be parsed, Frigate restores the previous config and reports an error instead of leaving Frigate in a broken state.
|
|
||||||
|
|
||||||
Two things are not cleaned up for you:
|
|
||||||
|
|
||||||
- **go2rtc streams.** Frigate makes a best effort to stop a running [go2rtc](go2rtc.md) stream named after the camera, but stream entries in your config file remain and are recreated on the next restart. Remove them in <NavPath path="Settings > System > go2rtc streams" /> or in your config file.
|
|
||||||
- **Camera groups.** A deleted camera stays listed in any [camera group](#setting-up-camera-groups) that referenced it. The group skips the missing camera, so this is harmless, but you can edit the group to drop the stale entry.
|
|
||||||
|
|
||||||
## Setting Up Camera Inputs
|
## Setting Up Camera Inputs
|
||||||
|
|
||||||
Several inputs can be configured for each camera and the role of each input can be mixed and matched based on your needs. This allows you to use a lower resolution stream for object detection, but create recordings from a higher resolution stream, or vice versa.
|
Several inputs can be configured for each camera and the role of each input can be mixed and matched based on your needs. This allows you to use a lower resolution stream for object detection, but create recordings from a higher resolution stream, or vice versa.
|
||||||
@ -89,27 +17,6 @@ Each role can only be assigned to one input per camera. The options for roles ar
|
|||||||
| `record` | Saves segments of the video feed based on configuration settings. [docs](record.md) |
|
| `record` | Saves segments of the video feed based on configuration settings. [docs](record.md) |
|
||||||
| `audio` | Feed for audio based detection. [docs](audio_detectors.md) |
|
| `audio` | Feed for audio based detection. [docs](audio_detectors.md) |
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > Camera configuration > Streams (FFmpeg)" />.
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ----------------- | ------------------------------------------------------------------- |
|
|
||||||
| **Camera inputs** | List of input stream definitions (paths and roles) for this camera. |
|
|
||||||
|
|
||||||
For each input you can choose its source: select **Restream (go2rtc)** to pick an existing [go2rtc stream](restream.md) from a dropdown (Frigate uses the `rtsp://127.0.0.1:8554/<stream>` path and `preset-rtsp-restream` input args for that input automatically), or **Manual input path** to type the stream URL directly.
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > Camera configuration > Object detection" />.
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ----------------- | ------------------------------------------------------------------------------------------------------ |
|
|
||||||
| **Detect width** | Width (pixels) of frames used for the detect stream; leave empty to use the native stream resolution. |
|
|
||||||
| **Detect height** | Height (pixels) of frames used for the detect stream; leave empty to use the native stream resolution. |
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
mqtt:
|
mqtt:
|
||||||
host: mqtt.server.com
|
host: mqtt.server.com
|
||||||
@ -129,18 +36,7 @@ cameras:
|
|||||||
height: 720 # <- optional, by default Frigate tries to automatically detect resolution
|
height: 720 # <- optional, by default Frigate tries to automatically detect resolution
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
Additional cameras are simply added to the config under the `cameras` entry.
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
Additional cameras are simply added under the camera configuration section.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > Global configuration > Camera management" /> and use the [Add Camera Wizard](#adding-a-camera-with-the-add-camera-wizard) to configure each additional camera.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
mqtt: ...
|
mqtt: ...
|
||||||
@ -150,9 +46,6 @@ cameras:
|
|||||||
side: ...
|
side: ...
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
|
|
||||||
If you only define one stream in your `inputs` and do not assign a `detect` role to it, Frigate will automatically assign it the `detect` role. Frigate will always decode a stream to support motion detection, Birdseye, the API image endpoints, and other features, even if you have disabled object detection with `enabled: False` in your config's `detect` section.
|
If you only define one stream in your `inputs` and do not assign a `detect` role to it, Frigate will automatically assign it the `detect` role. Frigate will always decode a stream to support motion detection, Birdseye, the API image endpoints, and other features, even if you have disabled object detection with `enabled: False` in your config's `detect` section.
|
||||||
@ -171,21 +64,9 @@ Not every PTZ supports ONVIF, which is the standard protocol Frigate uses to com
|
|||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Configure the ONVIF connection for your camera to enable PTZ controls.
|
Add the onvif section to your camera in your configuration file:
|
||||||
|
|
||||||
<ConfigTabs>
|
```yaml
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > Camera configuration > ONVIF" /> and select your camera.
|
|
||||||
- Set **ONVIF host** to your camera's IP address, e.g.: `10.0.10.10`
|
|
||||||
- Set **ONVIF port** to your camera's ONVIF port, e.g.: `8000`
|
|
||||||
- Set **ONVIF username** to your camera's ONVIF username, e.g.: `admin`
|
|
||||||
- Set **ONVIF password** to your camera's ONVIF password, e.g.: `password`
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml {4-8}
|
|
||||||
cameras:
|
cameras:
|
||||||
back:
|
back:
|
||||||
ffmpeg: ...
|
ffmpeg: ...
|
||||||
@ -196,76 +77,53 @@ cameras:
|
|||||||
password: password
|
password: password
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
If the ONVIF connection is successful, PTZ controls will be available in the camera's WebUI.
|
If the ONVIF connection is successful, PTZ controls will be available in the camera's WebUI.
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
Some cameras use a separate ONVIF/service account that is distinct from the device administrator credentials. If ONVIF authentication fails with the admin account, try creating or using an ONVIF/service user in the camera's firmware. Refer to your camera manufacturer's documentation for more.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
:::tip
|
:::tip
|
||||||
|
|
||||||
If your ONVIF camera does not require authentication credentials, you may still need to specify an empty string for `user` and `password`, eg: `user: ""` and `password: ""`.
|
If your ONVIF camera does not require authentication credentials, you may still need to specify an empty string for `user` and `password`, eg: `user: ""` and `password: ""`.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
If a camera connects but fails to authenticate, two optional fields can help:
|
|
||||||
|
|
||||||
- `tls_insecure`: Skips TLS certificate verification and sends the ONVIF password as plaintext (`PasswordText`) instead of a hashed digest (`PasswordDigest`). Some cameras reject the digest token and only accept plaintext. This weakens connection security, so only enable it on a trusted local network.
|
|
||||||
- `ignore_time_mismatch`: ONVIF authentication tokens include a timestamp, and a camera will reject the token if its clock differs too much from Frigate's. Enabling this makes Frigate compensate for the time offset so authentication can still succeed. Running NTP on both the camera and the Frigate host is the recommended fix; only use this in a "safe" environment, as it slightly weakens token validation.
|
|
||||||
|
|
||||||
If your camera has multiple ONVIF profiles, you can specify which one to use for PTZ control with the `profile` option, matched by token or name. When not set, Frigate selects the first profile with a valid PTZ configuration. Check the Frigate debug logs (`frigate.ptz.onvif: debug`) to see available profile names and tokens for your camera.
|
|
||||||
|
|
||||||
An ONVIF-capable camera that supports relative movement within the field of view (FOV) can also be configured to automatically track moving objects and keep them in the center of the frame. For autotracking setup, see the [autotracking](autotracking.md) docs.
|
An ONVIF-capable camera that supports relative movement within the field of view (FOV) can also be configured to automatically track moving objects and keep them in the center of the frame. For autotracking setup, see the [autotracking](autotracking.md) docs.
|
||||||
|
|
||||||
## ONVIF PTZ camera recommendations
|
## ONVIF PTZ camera recommendations
|
||||||
|
|
||||||
This list of working and non-working PTZ cameras is based on user feedback. If you'd like to report specific quirks or issues with a manufacturer or camera that would be helpful for other users, open a pull request to add to this list.
|
This list of working and non-working PTZ cameras is based on user feedback.
|
||||||
|
|
||||||
The FeatureList on the [ONVIF Conformant Products Database](https://www.onvif.org/conformant-products/) can provide a starting point to determine a camera's compatibility with Frigate's autotracking. Look to see if a camera lists `PTZRelative`, `PTZRelativePanTilt` and/or `PTZRelativeZoom`. These features are required for autotracking, but some cameras still fail to respond even if they claim support. If they are missing, autotracking will not work (though basic PTZ in the WebUI might). Avoid cameras with no database entry unless they are confirmed as working below.
|
| Brand or specific camera | PTZ Controls | Autotracking | Notes |
|
||||||
|
| ---------------------------- | :----------: | :----------: | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| Brand or specific camera | PTZ Controls | Autotracking | Notes |
|
| Amcrest | ✅ | ✅ | ⛔️ Generally, Amcrest should work, but some older models (like the common IP2M-841) don't support autotracking |
|
||||||
| ---------------------------- | :----------: | :----------: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| Amcrest ASH21 | ✅ | ❌ | ONVIF service port: 80 |
|
||||||
| Amcrest | ✅ | ✅ | ⛔️ Generally, Amcrest should work, but some older models (like the common IP2M-841) don't support autotracking |
|
| Amcrest IP4M-S2112EW-AI | ✅ | ❌ | FOV relative movement not supported. |
|
||||||
| Amcrest ASH21 | ✅ | ❌ | ONVIF service port: 80 |
|
| Amcrest IP5M-1190EW | ✅ | ❌ | ONVIF Port: 80. FOV relative movement not supported. |
|
||||||
| Amcrest IP4M-S2112EW-AI | ✅ | ❌ | FOV relative movement not supported. |
|
| Ctronics PTZ | ✅ | ❌ | |
|
||||||
| Amcrest IP5M-1190EW | ✅ | ❌ | ONVIF Port: 80. FOV relative movement not supported. |
|
| Dahua | ✅ | ✅ | |
|
||||||
| Annke CZ504 | ✅ | ✅ | Annke support provide specific firmware ([V5.7.1 build 250227](https://github.com/pierrepinon/annke_cz504/raw/refs/heads/main/digicap_V5-7-1_build_250227.dav)) to fix issue with ONVIF "TranslationSpaceFov" |
|
| Dahua DH-SD2A500HB | ✅ | ❌ | |
|
||||||
| Axis Q-6155E | ✅ | ❌ | ONVIF service port: 80; Camera does not support MoveStatus. |
|
| Foscam R5 | ✅ | ❌ | |
|
||||||
| Ctronics PTZ | ✅ | ❌ | |
|
| Hanwha XNP-6550RH | ✅ | ❌ | |
|
||||||
| Dahua | ✅ | ✅ | Some low-end Dahuas (lite series, picoo series (commonly), among others) have been reported to not support autotracking. These models usually don't have a four digit model number with chassis prefix and options postfix (e.g. DH-P5AE-PV vs DH-SD49825GB-HNR). |
|
| Hikvision | ✅ | ❌ | Incomplete ONVIF support (MoveStatus won't update even on latest firmware) - reported with HWP-N4215IH-DE and DS-2DE3304W-DE, but likely others |
|
||||||
| Dahua DH-SD2A500HB | ✅ | ❌ | |
|
| Hikvision DS-2DE3A404IWG-E/W | ✅ | ✅ | |
|
||||||
| Dahua DH-SD49825GB-HNR | ✅ | ✅ | |
|
| Reolink 511WA | ✅ | ❌ | Zoom only |
|
||||||
| Dahua DH-P5AE-PV | ❌ | ❌ | |
|
| Reolink E1 Pro | ✅ | ❌ | |
|
||||||
| Foscam | ✅ | ❌ | In general support PTZ, but not relative move. There are no official ONVIF certifications and tests available on the ONVIF Conformant Products Database |
|
| Reolink E1 Zoom | ✅ | ❌ | |
|
||||||
| Foscam R5 | ✅ | ❌ | |
|
| Reolink RLC-823A 16x | ✅ | ❌ | |
|
||||||
| Foscam SD4 | ✅ | ❌ | |
|
| Speco O8P32X | ✅ | ❌ | |
|
||||||
| Hanwha XNP-6550RH | ✅ | ❌ | |
|
| Sunba 405-D20X | ✅ | ❌ | Incomplete ONVIF support reported on original, and 4k models. All models are suspected incompatable. |
|
||||||
| Hikvision | ✅ | ❌ | Incomplete ONVIF support (MoveStatus won't update even on latest firmware) - reported with HWP-N4215IH-DE and DS-2DE3304W-DE, but likely others |
|
| Tapo | ✅ | ❌ | Many models supported, ONVIF Service Port: 2020 |
|
||||||
| Hikvision DS-2DE3A404IWG-E/W | ✅ | ✅ | |
|
| Uniview IPC672LR-AX4DUPK | ✅ | ❌ | Firmware says FOV relative movement is supported, but camera doesn't actually move when sending ONVIF commands |
|
||||||
| Reolink | ✅ | ❌ | |
|
| Uniview IPC6612SR-X33-VG | ✅ | ✅ | Leave `calibrate_on_startup` as `False`. A user has reported that zooming with `absolute` is working. |
|
||||||
| Speco O8P32X | ✅ | ❌ | |
|
| Vikylin PTZ-2804X-I2 | ❌ | ❌ | Incomplete ONVIF support |
|
||||||
| Sunba 405-D20X | ✅ | ❌ | Incomplete ONVIF support reported on original, and 4k models. All models are suspected incompatible. |
|
|
||||||
| Tapo | ✅ | ❌ | Many models supported, ONVIF Service Port: 2020 |
|
|
||||||
| Uniview IPC672LR-AX4DUPK | ✅ | ❌ | Firmware says FOV relative movement is supported, but camera doesn't actually move when sending ONVIF commands |
|
|
||||||
| Uniview IPC6612SR-X33-VG | ✅ | ✅ | Leave `calibrate_on_startup` as `False`. A user has reported that zooming with `absolute` is working. |
|
|
||||||
| Vikylin PTZ-2804X-I2 | ❌ | ❌ | Incomplete ONVIF support |
|
|
||||||
|
|
||||||
## Setting up camera groups
|
## Setting up camera groups
|
||||||
|
|
||||||
Camera groups let you organize cameras together with a shared name and icon, making it easier to review and filter them. A default group for all cameras is always available.
|
:::tip
|
||||||
|
|
||||||
<ConfigTabs>
|
It is recommended to set up camera groups using the UI.
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
On the Live dashboard, press the **pencil icon** in the main navigation to add a new camera group. Configure the group name, select which cameras to include, choose an icon, and set the display order.
|
:::
|
||||||
|
|
||||||
</TabItem>
|
Cameras can be grouped together and assigned a name and icon, this allows them to be reviewed and filtered together. There will always be the default group for all cameras.
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
camera_groups:
|
camera_groups:
|
||||||
@ -276,10 +134,3 @@ camera_groups:
|
|||||||
icon: LuCar
|
icon: LuCar
|
||||||
order: 0
|
order: 0
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Two-Way Audio
|
|
||||||
|
|
||||||
See the guide [here](/configuration/live/#two-way-talk)
|
|
||||||
|
|||||||
@ -1,383 +0,0 @@
|
|||||||
---
|
|
||||||
id: config
|
|
||||||
title: Frigate Configuration
|
|
||||||
---
|
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
|
|
||||||
Frigate can be configured through the **Settings UI** or by editing the YAML configuration file directly. The Settings UI is the recommended approach. It provides validation and a guided experience for all configuration options.
|
|
||||||
|
|
||||||
## Using the Settings UI
|
|
||||||
|
|
||||||
The Settings UI groups every configuration option into sections that are listed in the left-hand menu. Each section presents a guided form with validation, so you don't need to remember the structure of the YAML or look up option names by hand.
|
|
||||||
|
|
||||||
### Global vs. camera-level configuration
|
|
||||||
|
|
||||||
Settings are organized into two scopes:
|
|
||||||
|
|
||||||
- **Global configuration**: values under <NavPath path="Settings > Global configuration" /> apply to every camera by default. This is where you set the baseline behavior for object detection, recording, snapshots, motion, and so on.
|
|
||||||
- **Camera configuration**: values under <NavPath path="Settings > Camera configuration" /> apply to a single camera. Use the camera selector button at the top of these pages to choose which camera you are editing.
|
|
||||||
|
|
||||||
When a camera-level section is left untouched, the camera simply inherits the global values. Changing a value on a camera page **overrides** the global value for that camera only: the global setting and every other camera are unaffected. This mirrors how the YAML works, where a value set under `cameras.<name>` takes precedence over the same value set at the top level. See [Global and Camera-Level Configuration](./config_overrides.md) for the full details, including how lists and maps are handled and which settings must be enabled globally first.
|
|
||||||
|
|
||||||
To undo an override and go back to inheriting from the parent scope, use the reset button at the bottom of the section:
|
|
||||||
|
|
||||||
- On a camera section, the button is labeled **Reset to Global** and restores the camera to the global value.
|
|
||||||
- On a global section, the button is labeled **Reset to Default** and restores Frigate's built-in default.
|
|
||||||
|
|
||||||
Resetting asks for confirmation and cannot be undone once applied.
|
|
||||||
|
|
||||||
### Saving changes and the Save All button
|
|
||||||
|
|
||||||
Edits are not applied until you save them. As soon as you change a value, the UI tracks it as a pending change:
|
|
||||||
|
|
||||||
- The edited section shows a **Modified** badge, and the changed fields are highlighted.
|
|
||||||
- A **You have unsaved changes** notice appears above the section's **Save** and **Undo** buttons. **Save** commits just that section; **Undo** discards its pending edits.
|
|
||||||
|
|
||||||
Because pending changes can span multiple sections (and multiple cameras), the header provides a **Save All** button that writes every pending change at once. Next to it, **Review pending changes** opens a summary that lists each pending edit with its scope (Global or a specific camera), the affected field, and the new value, so you can confirm exactly what will be written before committing. **Undo All** discards every pending change across all sections.
|
|
||||||
|
|
||||||
### Restart-required indicators
|
|
||||||
|
|
||||||
Most settings take effect immediately, but some require Frigate to restart before they apply. Fields that require a restart are marked with a small restart icon and a **Restart required** tooltip next to the field label.
|
|
||||||
|
|
||||||
When you save a change that touches one of these fields, Frigate confirms the save and reminds you that a restart is needed (for example, _"Settings saved successfully. Restart Frigate to apply your changes."_). The notification includes a one-click **Restart Frigate** action so you can apply the change right away, or you can continue editing and restart later.
|
|
||||||
|
|
||||||
### The colored dots in the camera configuration menu
|
|
||||||
|
|
||||||
When you are working under <NavPath path="Settings > Camera configuration" />, small colored dots can appear next to a section's name in the menu. They give you an at-a-glance summary of that section's state for the selected camera:
|
|
||||||
|
|
||||||
- **Blue dot**: this section **overrides the global configuration**. One or more values in the section have been set specifically for this camera and differ from the global defaults.
|
|
||||||
- **Profile-colored dot**: when you are viewing a [camera profile](./profiles.md), a dot in that profile's assigned color indicates the section is **overridden by that profile**. Each profile is given its own distinct color so you can tell at a glance which sections it changes.
|
|
||||||
- **Amber dot**: this section has **unsaved changes**. It appears alongside the **Modified** badge whenever you have pending edits in the section that haven't been saved yet.
|
|
||||||
|
|
||||||
Hover over any dot to see a tooltip describing what it means. Open a section to see exactly which fields are overridden: the section header indicates how many fields differ from the global (or base) configuration.
|
|
||||||
|
|
||||||
## Configuration File Location
|
|
||||||
|
|
||||||
For users who prefer to edit the YAML configuration file directly, it is recommended to start with a minimal configuration and add to it as described in [the getting started guide](../guides/getting_started.md).
|
|
||||||
|
|
||||||
- **Home Assistant App:** `/addon_configs/<addon_directory>/config.yml` (see [directory list](#accessing-app-config-dir))
|
|
||||||
- **All other installations:** Map to `/config/config.yml` inside the container
|
|
||||||
|
|
||||||
It can be named `config.yml` or `config.yaml`, but if both files exist `config.yml` will be preferred and `config.yaml` will be ignored.
|
|
||||||
|
|
||||||
A minimal starting configuration:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
mqtt:
|
|
||||||
enabled: False
|
|
||||||
|
|
||||||
cameras:
|
|
||||||
dummy_camera: # <--- this will be changed to your actual camera later
|
|
||||||
enabled: False
|
|
||||||
ffmpeg:
|
|
||||||
inputs:
|
|
||||||
- path: rtsp://127.0.0.1:554/rtsp
|
|
||||||
roles:
|
|
||||||
- detect
|
|
||||||
```
|
|
||||||
|
|
||||||
## Accessing the Home Assistant App configuration directory {#accessing-app-config-dir}
|
|
||||||
|
|
||||||
When running Frigate through the HA App, the Frigate `/config` directory is mapped to `/addon_configs/<addon_directory>` in the host, where `<addon_directory>` is specific to the variant of the Frigate App you are running.
|
|
||||||
|
|
||||||
| App Variant | Configuration directory |
|
|
||||||
| -------------------------- | ----------------------------------------- |
|
|
||||||
| Frigate | `/addon_configs/ccab4aaf_frigate` |
|
|
||||||
| Frigate (Full Access) | `/addon_configs/ccab4aaf_frigate-fa` |
|
|
||||||
| Frigate Beta | `/addon_configs/ccab4aaf_frigate-beta` |
|
|
||||||
| Frigate Beta (Full Access) | `/addon_configs/ccab4aaf_frigate-fa-beta` |
|
|
||||||
|
|
||||||
**Whenever you see `/config` in the documentation, it refers to this directory.**
|
|
||||||
|
|
||||||
If for example you are running the standard App variant and use the [VS Code App](https://github.com/hassio-addons/addon-vscode) to browse your files, you can click _File_ > _Open folder..._ and navigate to `/addon_configs/ccab4aaf_frigate` to access the Frigate `/config` directory and edit the `config.yaml` file. You can also use the built-in config editor in the Frigate UI.
|
|
||||||
|
|
||||||
## VS Code Configuration Schema
|
|
||||||
|
|
||||||
VS Code supports JSON schemas for automatically validating configuration files. You can enable this feature by adding `# yaml-language-server: $schema=http://frigate_host:5000/api/config/schema.json` to the beginning of the configuration file. Replace `frigate_host` with the IP address or hostname of your Frigate server. If you're using both VS Code and Frigate as an App, you should use `ccab4aaf-frigate` instead. Make sure to expose the internal unauthenticated port `5000` when accessing the config from VS Code on another machine.
|
|
||||||
|
|
||||||
## Environment Variable Substitution
|
|
||||||
|
|
||||||
Frigate supports the use of environment variables starting with `FRIGATE_` **only** where specifically indicated in the [reference config](./advanced/reference.md). For example, the following values can be replaced at runtime by using environment variables:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
mqtt:
|
|
||||||
host: "{FRIGATE_MQTT_HOST}"
|
|
||||||
user: "{FRIGATE_MQTT_USER}"
|
|
||||||
password: "{FRIGATE_MQTT_PASSWORD}"
|
|
||||||
```
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- path: rtsp://{FRIGATE_RTSP_USER}:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:8554/unicast
|
|
||||||
```
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
onvif:
|
|
||||||
host: "192.168.1.12"
|
|
||||||
port: 8000
|
|
||||||
user: "{FRIGATE_RTSP_USER}"
|
|
||||||
password: "{FRIGATE_RTSP_PASSWORD}"
|
|
||||||
```
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
go2rtc:
|
|
||||||
rtsp:
|
|
||||||
username: "{FRIGATE_GO2RTC_RTSP_USERNAME}"
|
|
||||||
password: "{FRIGATE_GO2RTC_RTSP_PASSWORD}"
|
|
||||||
```
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
genai:
|
|
||||||
my_provider:
|
|
||||||
api_key: "{FRIGATE_GENAI_API_KEY}"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Common configuration examples
|
|
||||||
|
|
||||||
Here are some common starter configuration examples. These can be configured through the Settings UI or via YAML. Refer to the [reference config](./advanced/reference.md) for detailed information about all config values.
|
|
||||||
|
|
||||||
### Raspberry Pi Home Assistant App with USB Coral
|
|
||||||
|
|
||||||
- Single camera with 720p, 5fps stream for detect
|
|
||||||
- MQTT connected to the Home Assistant Mosquitto App
|
|
||||||
- Hardware acceleration for decoding video
|
|
||||||
- USB Coral detector
|
|
||||||
- Save all video with any detectable motion for 7 days regardless of whether any objects were detected or not
|
|
||||||
- Continue to keep all video if it qualified as an alert or detection for 30 days
|
|
||||||
- Save snapshots for 30 days
|
|
||||||
- Motion mask for the camera timestamp
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > System > MQTT" /> and configure the MQTT connection to your Home Assistant Mosquitto broker
|
|
||||||
2. Navigate to <NavPath path="Settings > Global configuration > FFmpeg" /> and set **Hardware acceleration arguments** to `Raspberry Pi (H.264)`
|
|
||||||
3. Navigate to <NavPath path="Settings > System > Detectors and model" /> and add a detector with **Type** `EdgeTPU` and **Device** `usb`
|
|
||||||
4. Navigate to <NavPath path="Settings > Global configuration > Recording" /> and set **Enable recording** to on, **Motion retention > Retention days** to `7`, **Alert retention > Event retention > Retention days** to `30`, **Alert retention > Event retention > Retention mode** to `motion`, **Detection retention > Event retention > Retention days** to `30`, **Detection retention > Event retention > Retention mode** to `motion`
|
|
||||||
5. Navigate to <NavPath path="Settings > Global configuration > Snapshots" /> and set **Enable snapshots** to on, **Snapshot retention > Default retention** to `30`
|
|
||||||
6. Navigate to <NavPath path="Settings > Global configuration > Camera management" /> and add your camera with the appropriate RTSP stream URL
|
|
||||||
7. Navigate to <NavPath path="Settings > Camera configuration > Masks / Zones" /> to add a motion mask for the camera timestamp
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
mqtt:
|
|
||||||
host: core-mosquitto
|
|
||||||
user: mqtt-user
|
|
||||||
password: xxxxxxxxxx
|
|
||||||
|
|
||||||
ffmpeg:
|
|
||||||
hwaccel_args: preset-rpi-64-h264
|
|
||||||
|
|
||||||
detectors:
|
|
||||||
coral:
|
|
||||||
type: edgetpu
|
|
||||||
device: usb
|
|
||||||
|
|
||||||
record:
|
|
||||||
enabled: True
|
|
||||||
motion:
|
|
||||||
days: 7
|
|
||||||
alerts:
|
|
||||||
retain:
|
|
||||||
days: 30
|
|
||||||
mode: motion
|
|
||||||
detections:
|
|
||||||
retain:
|
|
||||||
days: 30
|
|
||||||
mode: motion
|
|
||||||
|
|
||||||
snapshots:
|
|
||||||
enabled: True
|
|
||||||
retain:
|
|
||||||
default: 30
|
|
||||||
|
|
||||||
cameras:
|
|
||||||
name_of_your_camera:
|
|
||||||
detect:
|
|
||||||
width: 1280
|
|
||||||
height: 720
|
|
||||||
fps: 5
|
|
||||||
ffmpeg:
|
|
||||||
inputs:
|
|
||||||
- path: rtsp://10.0.10.10:554/rtsp
|
|
||||||
roles:
|
|
||||||
- detect
|
|
||||||
motion:
|
|
||||||
mask:
|
|
||||||
timestamp:
|
|
||||||
friendly_name: "Camera timestamp"
|
|
||||||
enabled: true
|
|
||||||
coordinates: "0.000,0.427,0.002,0.000,0.999,0.000,0.999,0.781,0.885,0.456,0.700,0.424,0.701,0.311,0.507,0.294,0.453,0.347,0.451,0.400"
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### Standalone Intel Mini PC with USB Coral
|
|
||||||
|
|
||||||
- Single camera with 720p, 5fps stream for detect
|
|
||||||
- MQTT disabled (not integrated with Home Assistant)
|
|
||||||
- VAAPI hardware acceleration for decoding video
|
|
||||||
- USB Coral detector
|
|
||||||
- Save all video with any detectable motion for 7 days regardless of whether any objects were detected or not
|
|
||||||
- Continue to keep all video if it qualified as an alert or detection for 30 days
|
|
||||||
- Save snapshots for 30 days
|
|
||||||
- Motion mask for the camera timestamp
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > System > MQTT" /> and set **Enable MQTT** to off
|
|
||||||
2. Navigate to <NavPath path="Settings > Global configuration > FFmpeg" /> and set **Hardware acceleration arguments** to `VAAPI (Intel/AMD GPU)`
|
|
||||||
3. Navigate to <NavPath path="Settings > System > Detectors and model" /> and add a detector with **Type** `EdgeTPU` and **Device** `usb`
|
|
||||||
4. Navigate to <NavPath path="Settings > Global configuration > Recording" /> and set **Enable recording** to on, **Motion retention > Retention days** to `7`, **Alert retention > Event retention > Retention days** to `30`, **Alert retention > Event retention > Retention mode** to `motion`, **Detection retention > Event retention > Retention days** to `30`, **Detection retention > Event retention > Retention mode** to `motion`
|
|
||||||
5. Navigate to <NavPath path="Settings > Global configuration > Snapshots" /> and set **Enable snapshots** to on, **Snapshot retention > Default retention** to `30`
|
|
||||||
6. Navigate to <NavPath path="Settings > Global configuration > Camera management" /> and add your camera with the appropriate RTSP stream URL
|
|
||||||
7. Navigate to <NavPath path="Settings > Camera configuration > Masks / Zones" /> to add a motion mask for the camera timestamp
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
mqtt:
|
|
||||||
enabled: False
|
|
||||||
|
|
||||||
ffmpeg:
|
|
||||||
hwaccel_args: preset-vaapi
|
|
||||||
|
|
||||||
detectors:
|
|
||||||
coral:
|
|
||||||
type: edgetpu
|
|
||||||
device: usb
|
|
||||||
|
|
||||||
record:
|
|
||||||
enabled: True
|
|
||||||
motion:
|
|
||||||
days: 7
|
|
||||||
alerts:
|
|
||||||
retain:
|
|
||||||
days: 30
|
|
||||||
mode: motion
|
|
||||||
detections:
|
|
||||||
retain:
|
|
||||||
days: 30
|
|
||||||
mode: motion
|
|
||||||
|
|
||||||
snapshots:
|
|
||||||
enabled: True
|
|
||||||
retain:
|
|
||||||
default: 30
|
|
||||||
|
|
||||||
cameras:
|
|
||||||
name_of_your_camera:
|
|
||||||
detect:
|
|
||||||
width: 1280
|
|
||||||
height: 720
|
|
||||||
fps: 5
|
|
||||||
ffmpeg:
|
|
||||||
inputs:
|
|
||||||
- path: rtsp://10.0.10.10:554/rtsp
|
|
||||||
roles:
|
|
||||||
- detect
|
|
||||||
motion:
|
|
||||||
mask:
|
|
||||||
timestamp:
|
|
||||||
friendly_name: "Camera timestamp"
|
|
||||||
enabled: true
|
|
||||||
coordinates: "0.000,0.427,0.002,0.000,0.999,0.000,0.999,0.781,0.885,0.456,0.700,0.424,0.701,0.311,0.507,0.294,0.453,0.347,0.451,0.400"
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### Home Assistant integrated Intel Mini PC with OpenVINO
|
|
||||||
|
|
||||||
- Single camera with 720p, 5fps stream for detect
|
|
||||||
- MQTT connected to same MQTT server as Home Assistant
|
|
||||||
- VAAPI hardware acceleration for decoding video
|
|
||||||
- OpenVINO detector
|
|
||||||
- Save all video with any detectable motion for 7 days regardless of whether any objects were detected or not
|
|
||||||
- Continue to keep all video if it qualified as an alert or detection for 30 days
|
|
||||||
- Save snapshots for 30 days
|
|
||||||
- Motion mask for the camera timestamp
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > System > MQTT" /> and configure the connection to your MQTT broker
|
|
||||||
2. Navigate to <NavPath path="Settings > Global configuration > FFmpeg" /> and set **Hardware acceleration arguments** to `VAAPI (Intel/AMD GPU)`
|
|
||||||
3. Navigate to <NavPath path="Settings > System > Detectors and model" /> and add a detector with **Type** `openvino` and **Device** `AUTO`
|
|
||||||
4. On the same page, in the **Custom Model** tab, configure the OpenVINO model path and settings
|
|
||||||
5. Navigate to <NavPath path="Settings > Global configuration > Recording" /> and set **Enable recording** to on, **Motion retention > Retention days** to `7`, **Alert retention > Event retention > Retention days** to `30`, **Alert retention > Event retention > Retention mode** to `motion`, **Detection retention > Event retention > Retention days** to `30`, **Detection retention > Event retention > Retention mode** to `motion`
|
|
||||||
6. Navigate to <NavPath path="Settings > Global configuration > Snapshots" /> and set **Enable snapshots** to on, **Snapshot retention > Default retention** to `30`
|
|
||||||
7. Navigate to <NavPath path="Settings > Global configuration > Camera management" /> and add your camera with the appropriate RTSP stream URL
|
|
||||||
8. Navigate to <NavPath path="Settings > Camera configuration > Masks / Zones" /> to add a motion mask for the camera timestamp
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
mqtt:
|
|
||||||
host: 192.168.X.X # <---- same mqtt broker that home assistant uses
|
|
||||||
user: mqtt-user
|
|
||||||
password: xxxxxxxxxx
|
|
||||||
|
|
||||||
ffmpeg:
|
|
||||||
hwaccel_args: preset-vaapi
|
|
||||||
|
|
||||||
detectors:
|
|
||||||
ov:
|
|
||||||
type: openvino
|
|
||||||
device: AUTO
|
|
||||||
|
|
||||||
model:
|
|
||||||
width: 300
|
|
||||||
height: 300
|
|
||||||
input_tensor: nhwc
|
|
||||||
input_pixel_format: bgr
|
|
||||||
path: /openvino-model/ssdlite_mobilenet_v2.xml
|
|
||||||
labelmap_path: /openvino-model/coco_91cl_bkgr.txt
|
|
||||||
|
|
||||||
record:
|
|
||||||
enabled: True
|
|
||||||
motion:
|
|
||||||
days: 7
|
|
||||||
alerts:
|
|
||||||
retain:
|
|
||||||
days: 30
|
|
||||||
mode: motion
|
|
||||||
detections:
|
|
||||||
retain:
|
|
||||||
days: 30
|
|
||||||
mode: motion
|
|
||||||
|
|
||||||
snapshots:
|
|
||||||
enabled: True
|
|
||||||
retain:
|
|
||||||
default: 30
|
|
||||||
|
|
||||||
cameras:
|
|
||||||
name_of_your_camera:
|
|
||||||
detect:
|
|
||||||
width: 1280
|
|
||||||
height: 720
|
|
||||||
fps: 5
|
|
||||||
ffmpeg:
|
|
||||||
inputs:
|
|
||||||
- path: rtsp://10.0.10.10:554/rtsp
|
|
||||||
roles:
|
|
||||||
- detect
|
|
||||||
motion:
|
|
||||||
mask:
|
|
||||||
timestamp:
|
|
||||||
friendly_name: "Camera timestamp"
|
|
||||||
enabled: true
|
|
||||||
coordinates: "0.000,0.427,0.002,0.000,0.999,0.000,0.999,0.781,0.885,0.456,0.700,0.424,0.701,0.311,0.507,0.294,0.453,0.347,0.451,0.400"
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
@ -1,244 +0,0 @@
|
|||||||
---
|
|
||||||
id: config_overrides
|
|
||||||
title: Global and Camera-Level Configuration
|
|
||||||
---
|
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
|
|
||||||
Most of Frigate's configuration can be set once for all cameras and then adjusted for individual cameras. The global value acts as the default for every camera, and any camera can override it.
|
|
||||||
|
|
||||||
This page explains how that inheritance works. For a tour of the Settings UI itself, see [Frigate Configuration](./config.md).
|
|
||||||
|
|
||||||
## The basics
|
|
||||||
|
|
||||||
Set a value globally and every camera uses it. Set the same value on a camera and that camera uses its own value instead.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > Global configuration > Object detection" /> and set **Detect FPS** to `5`. Every camera now detects at 5 fps.
|
|
||||||
2. Navigate to <NavPath path="Settings > Camera configuration > Object detection" />, select the `driveway` camera, and set **Detect FPS** to `10`.
|
|
||||||
|
|
||||||
The `driveway` camera now detects at 10 fps. Every other camera still uses the global value of 5.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
detect:
|
|
||||||
fps: 5 # every camera detects at 5 fps
|
|
||||||
|
|
||||||
cameras:
|
|
||||||
front_door:
|
|
||||||
ffmpeg: ...
|
|
||||||
driveway:
|
|
||||||
ffmpeg: ...
|
|
||||||
detect:
|
|
||||||
fps: 10 # except this one
|
|
||||||
```
|
|
||||||
|
|
||||||
`front_door` inherits `fps: 5`, and `driveway` uses `10`.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Overrides apply per value, not per section
|
|
||||||
|
|
||||||
Overriding one value in a section does not detach the rest of that section. Everything you don't set on the camera still comes from the global configuration.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
If you set a camera's **Motion threshold** but leave **Contour area** alone, only the threshold is overridden. The contour area continues to follow <NavPath path="Settings > Global configuration > Motion detection" />, and changing it there still affects that camera.
|
|
||||||
|
|
||||||
Open a section to see which values are overridden: the section header indicates how many fields differ from the global configuration.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
motion:
|
|
||||||
threshold: 30
|
|
||||||
contour_area: 10
|
|
||||||
|
|
||||||
cameras:
|
|
||||||
driveway:
|
|
||||||
motion:
|
|
||||||
threshold: 40
|
|
||||||
```
|
|
||||||
|
|
||||||
The `driveway` camera ends up with `threshold: 40` and `contour_area: 10`. Only the value you wrote was overridden.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Returning a camera to the global value
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
A camera section that has its own values shows an **Overridden** badge. To remove the override and go back to inheriting, use the **Reset to Global** button at the bottom of the section.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
Frigate treats a camera value as an override because it is written in the config file, not because it differs from the global value. Repeating the global value under a camera still creates an override:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
snapshots:
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
cameras:
|
|
||||||
driveway:
|
|
||||||
snapshots:
|
|
||||||
enabled: true # this is an override, even though it matches
|
|
||||||
```
|
|
||||||
|
|
||||||
If you later change the global `snapshots.enabled` to `false`, `driveway` keeps saving snapshots, because it has its own value. To make a camera follow the global value again, delete the key from the camera rather than setting it to match.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Lists replace, maps merge
|
|
||||||
|
|
||||||
This is the distinction that surprises people most.
|
|
||||||
|
|
||||||
**Lists are replaced entirely.** A camera's list does not add to the global list, it takes its place.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
The camera page shows the objects the camera is currently tracking, starting from the global list. Changing that selection under <NavPath path="Settings > Camera configuration > Objects" /> replaces the list for that camera, so make sure every object you want tracked is selected, not just the ones you are adding.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
objects:
|
|
||||||
track:
|
|
||||||
- person
|
|
||||||
- car
|
|
||||||
|
|
||||||
cameras:
|
|
||||||
backyard:
|
|
||||||
objects:
|
|
||||||
track:
|
|
||||||
- dog # backyard tracks ONLY dog, not person or car
|
|
||||||
```
|
|
||||||
|
|
||||||
To track `dog` in addition to the global objects, list all of them on the camera.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
An empty list is a valid override, and is the normal way to opt a camera out of something:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
review:
|
|
||||||
alerts:
|
|
||||||
labels:
|
|
||||||
- person
|
|
||||||
|
|
||||||
cameras:
|
|
||||||
street:
|
|
||||||
review:
|
|
||||||
alerts:
|
|
||||||
labels: [] # this camera never creates alerts
|
|
||||||
```
|
|
||||||
|
|
||||||
**Maps are merged key by key.** A camera can add an entry without redeclaring the others.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Adding a filter for one object under <NavPath path="Settings > Camera configuration > Objects" /> does not remove the filters inherited from <NavPath path="Settings > Global configuration > Objects" />. The camera keeps both.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
objects:
|
|
||||||
filters:
|
|
||||||
person:
|
|
||||||
min_area: 5000
|
|
||||||
|
|
||||||
cameras:
|
|
||||||
driveway:
|
|
||||||
objects:
|
|
||||||
filters:
|
|
||||||
car:
|
|
||||||
min_area: 10000
|
|
||||||
```
|
|
||||||
|
|
||||||
The `driveway` camera ends up with both the `car` filter it defined and the `person` filter from the global configuration.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Which settings can be overridden
|
|
||||||
|
|
||||||
Most, but not all. The [full reference config](./advanced/reference.md) is the authoritative source: sections that support camera-level overrides are marked with the comment `# NOTE: Can be overridden at the camera level`. In the UI, a setting can be overridden if it appears under both <NavPath path="Settings > Global configuration" /> and <NavPath path="Settings > Camera configuration" />.
|
|
||||||
|
|
||||||
A few things worth knowing beyond that:
|
|
||||||
|
|
||||||
- Some sections are **global only** and have no camera-level equivalent, including `go2rtc`, `genai` providers, `classification`, `telemetry`, `camera_groups`, and `ui`.
|
|
||||||
- Some sections exist **only at the camera level**, such as `zones` and `onvif`.
|
|
||||||
- Some sections are **partially overridable**, meaning a camera accepts only a few of the keys available globally. `face_recognition`, `lpr`, and `audio_transcription` work this way, and the reference config notes which keys apply.
|
|
||||||
|
|
||||||
## Enrichments that must be enabled globally first
|
|
||||||
|
|
||||||
License plate recognition and face recognition are special: the global setting is not just a default, it is a switch that must be on before any camera can use the feature. Enabling one on a camera while it is disabled globally is a configuration error, and Frigate will refuse to start:
|
|
||||||
|
|
||||||
```
|
|
||||||
Camera driveway has lpr enabled but lpr is disabled at the global level of the config. You must enable lpr at the global level.
|
|
||||||
```
|
|
||||||
|
|
||||||
Enable the feature globally, then turn it off on the cameras that don't need it.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > Global configuration > License plate recognition" /> and enable **LPR**.
|
|
||||||
2. Navigate to <NavPath path="Settings > Camera configuration > License plate recognition" />, select each camera that should not run LPR, and disable the **Enable LPR** toggle.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
lpr:
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
cameras:
|
|
||||||
driveway:
|
|
||||||
ffmpeg: ... # inherits lpr, enabled
|
|
||||||
backyard:
|
|
||||||
ffmpeg: ...
|
|
||||||
lpr:
|
|
||||||
enabled: false # opted out
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
This applies only to `lpr` and `face_recognition`, because the global setting controls whether the supporting background process starts at all. Other features do not work this way. Audio transcription, for example, can be enabled on a single camera without being enabled globally.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Profiles
|
|
||||||
|
|
||||||
[Profiles](./profiles.md) add a further layer on top of everything described above. A profile is a named set of camera overrides that you can switch on and off while Frigate is running, for example to change detection and recording behavior when you leave the house.
|
|
||||||
|
|
||||||
Profiles are applied on top of a camera's already-resolved configuration, so a profile value wins over both the camera and the global value while that profile is active. Profiles cover a subset of the camera sections and do not modify your config file.
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
- A camera inherits every value you don't set on it.
|
|
||||||
- Overriding one value does not detach the rest of the section.
|
|
||||||
- Writing a value on a camera overrides it, even if it matches the global value. Remove it to inherit again.
|
|
||||||
- Lists replace the global list. Maps merge into it.
|
|
||||||
- An empty list is an override, not an omission.
|
|
||||||
- `lpr` and `face_recognition` must be enabled globally before a camera can use them.
|
|
||||||
@ -1,195 +0,0 @@
|
|||||||
---
|
|
||||||
id: object_classification
|
|
||||||
title: Object Classification
|
|
||||||
---
|
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
|
|
||||||
Object classification allows you to train a custom MobileNetV2 classification model to run on tracked objects (persons, cars, animals, etc.) to identify a finer category or attribute for that object. Classification results are visible in the Tracked Object Details pane in Explore, through the `frigate/tracked_object_details` MQTT topic, in Home Assistant sensors via the official Frigate integration, or through the event endpoints in the HTTP API.
|
|
||||||
|
|
||||||
:::info
|
|
||||||
|
|
||||||
Training a custom object classification model requires an internet connection to download MobileNetV2 base weights. By default these weights are not cached in `/config/`, so they are downloaded again after the container is recreated. Once trained, the model runs fully offline. See [Network Requirements](/frigate/network_requirements#one-time-model-downloads) for details.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Minimum System Requirements
|
|
||||||
|
|
||||||
Object classification models are lightweight and run very fast on CPU.
|
|
||||||
|
|
||||||
Training the model does briefly use a high amount of system resources for about 1-3 minutes per training run. On lower-power devices, training may take longer.
|
|
||||||
|
|
||||||
A CPU with AVX + AVX2 instructions is required for training and inference.
|
|
||||||
|
|
||||||
## Classes
|
|
||||||
|
|
||||||
Classes are the categories your model will learn to distinguish between. Each class represents a distinct visual category that the model will predict.
|
|
||||||
|
|
||||||
For object classification:
|
|
||||||
|
|
||||||
- Define classes that represent different types or attributes of the detected object
|
|
||||||
- Examples: For `person` objects, classes might be `delivery_person`, `resident`, `stranger`
|
|
||||||
- Include a `none` class for objects that don't fit any specific category
|
|
||||||
- Keep classes visually distinct to improve accuracy
|
|
||||||
|
|
||||||
### Classification Type
|
|
||||||
|
|
||||||
- **Sub label**:
|
|
||||||
- Applied to the object's `sub_label` field.
|
|
||||||
- Ideal for a single, more specific identity or type.
|
|
||||||
- Example: `cat` → `Leo`, `Charlie`, `None`.
|
|
||||||
|
|
||||||
- **Attribute**:
|
|
||||||
- Added as metadata to the object, visible in the Tracked Object Details pane in Explore, `frigate/events` MQTT messages, and the HTTP API response as `<model_name>: <predicted_value>`.
|
|
||||||
- Ideal when multiple attributes can coexist independently.
|
|
||||||
- Example: Detecting if a `person` in a construction yard is wearing a helmet or not, and if they are wearing a yellow vest or not.
|
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
A tracked object can only have a single sub label. If you are using Triggers or Face Recognition and you configure an object classification model for `person` using the sub label type, your sub label may not be assigned correctly as it depends on which enrichment completes its analysis first. This could also occur with `car` objects that are assigned a sub label for a delivery carrier. Consider using the `attribute` type instead.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Assignment Requirements
|
|
||||||
|
|
||||||
Sub labels and attributes are only assigned when both conditions are met:
|
|
||||||
|
|
||||||
1. **Threshold**: Each classification attempt must have a confidence score that meets or exceeds the configured `threshold` (default: `0.8`).
|
|
||||||
2. **Class Consensus**: After at least 3 classification attempts, 60% of attempts must agree on the same class label. If the consensus class is `none`, no assignment is made.
|
|
||||||
|
|
||||||
This two-step verification prevents false positives by requiring consistent predictions across multiple frames before assigning a sub label or attribute.
|
|
||||||
|
|
||||||
## Example use cases
|
|
||||||
|
|
||||||
### Sub label
|
|
||||||
|
|
||||||
- **Known pet vs unknown**: For `dog` objects, set sub label to your pet's name (e.g., `buddy`) or `none` for others.
|
|
||||||
- **Mail truck vs normal car**: For `car`, classify as `mail_truck` vs `car` to filter important arrivals.
|
|
||||||
- **Delivery vs non-delivery person**: For `person`, classify `delivery` vs `visitor` based on uniform/props.
|
|
||||||
|
|
||||||
### Attributes
|
|
||||||
|
|
||||||
- **Backpack**: For `person`, add attribute `backpack: yes/no`.
|
|
||||||
- **Helmet**: For `person` (worksite), add `helmet: yes/no`.
|
|
||||||
- **Leash**: For `dog`, add `leash: yes/no` (useful for park or yard rules).
|
|
||||||
- **Ladder rack**: For `truck`, add `ladder_rack: yes/no` to flag service vehicles.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
Object classification is configured as a custom classification model. Each model has its own name and settings. Specify which object labels should be classified.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to the **Classification** page from the main navigation sidebar, then click **Add Classification**.
|
|
||||||
|
|
||||||
In the **Create New Classification** dialog:
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ----------------------- | ------------------------------------------------------------- |
|
|
||||||
| **Name** | A name for your classification model (e.g., `dog`) |
|
|
||||||
| **Type** | Select **Object** for object classification |
|
|
||||||
| **Object Label** | The object label to classify (e.g., `dog`, `person`, `car`) |
|
|
||||||
| **Classification Type** | Whether to assign results as a **Sub Label** or **Attribute** |
|
|
||||||
| **Classes** | The class names the model will learn to distinguish between |
|
|
||||||
|
|
||||||
The `threshold` (default: `0.8`) can be adjusted in the YAML configuration.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
classification:
|
|
||||||
custom:
|
|
||||||
dog:
|
|
||||||
threshold: 0.8
|
|
||||||
object_config:
|
|
||||||
objects: [dog] # object labels to classify
|
|
||||||
classification_type: sub_label # or: attribute
|
|
||||||
```
|
|
||||||
|
|
||||||
An optional config, `save_attempts`, can be set as a key under the model name. This defines the number of classification attempts to save in the Recent Classifications tab. For object classification models, the default is 200.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Training the model
|
|
||||||
|
|
||||||
Creating and training the model is done within the Frigate UI using the `Classification` page. The process consists of two steps:
|
|
||||||
|
|
||||||
### Step 1: Name and Define
|
|
||||||
|
|
||||||
Enter a name for your model, select the object label to classify (e.g., `person`, `dog`, `car`), choose the classification type (sub label or attribute), and define your classes. Frigate will automatically include a `none` class for objects that don't fit any specific category.
|
|
||||||
|
|
||||||
For example: To classify your two cats, create a model named "Our Cats" and create two classes, "Charlie" and "Leo". A third class, "none", will be created automatically for other neighborhood cats that are not your own.
|
|
||||||
|
|
||||||
### Step 2: Assign Training Examples
|
|
||||||
|
|
||||||
The system will automatically generate example images from detected objects matching your selected label. You'll be guided through each class one at a time to select which images represent that class. Any images not assigned to a specific class will automatically be assigned to `none` when you complete the last class. Once all images are processed, training will begin automatically.
|
|
||||||
|
|
||||||
When choosing which objects to classify, start with a small number of visually distinct classes and ensure your training samples match camera viewpoints and distances typical for those objects.
|
|
||||||
|
|
||||||
If examples for some of your classes do not appear in the grid, you can continue configuring the model without them. New images will begin to appear in the Recent Classifications view. When your missing classes are seen, classify them from this view and retrain your model.
|
|
||||||
|
|
||||||
### Improving the Model
|
|
||||||
|
|
||||||
:::tip Diversity matters far more than volume
|
|
||||||
|
|
||||||
Selecting dozens of nearly identical images is one of the fastest ways to degrade model performance. MobileNetV2 can overfit quickly when trained on homogeneous data. The model learns what _that exact moment_ looked like rather than what actually defines the class. **This is why Frigate does not implement bulk training in the UI.**
|
|
||||||
|
|
||||||
For more detail, see [Frigate Tip: Best Practices for Training Face and Custom Classification Models](https://github.com/blakeblackshear/frigate/discussions/21374).
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
- **Start small and iterate**: Begin with a small, representative set of images per class. Models often begin working well with surprisingly few examples and improve naturally over time.
|
|
||||||
- **Favor hard examples**: When images appear in the Recent Classifications tab, prioritize images scoring below 90-100% or those captured under new lighting, weather, or distance conditions.
|
|
||||||
- **Avoid bulk training similar images**: Training large batches of images that already score 100% (or close) adds little new information and increases the risk of overfitting.
|
|
||||||
- **The wizard is just the starting point**: You don't need to find and label every class upfront. Missing classes will naturally appear in Recent Classifications, and those images tend to be more valuable because they represent new conditions and edge cases.
|
|
||||||
- **Problem framing**: Keep classes visually distinct and relevant to the chosen object types.
|
|
||||||
- **Preprocessing**: Ensure examples reflect object crops similar to Frigate's boxes; keep the subject centered.
|
|
||||||
- **Crop size**: Aim for crops of at least 100×100 pixels (a 10,000 pixel area). Crops smaller than ~80×80 get stretched 3-7× by the model's 224×224 input resize and tend to collapse into a generic "blob" region of feature space where identity becomes unreliable. If most of your detections are small because the camera is far from the subject, consider repositioning the camera for closer crops.
|
|
||||||
- **Class balance**: Aim to keep your largest class within ~3× the count of your smallest. Beyond that, the model becomes biased toward the dominant class and tends to default borderline predictions to it (the "everything looks like Buddy" failure mode).
|
|
||||||
- **Threshold**: Tune `threshold` per model to reduce false assignments. Start at `0.8` and adjust based on validation.
|
|
||||||
|
|
||||||
:::tip `none` works differently from named classes
|
|
||||||
|
|
||||||
Named classes work best with visually uniform examples. Every Buddy photo should look like Buddy. The `none` class needs the opposite: visual diversity across sizes, framings, and qualities, because at inference it has to absorb everything that isn't one of your named classes. Don't apply the same "only keep large, well-framed images" rule to `none` that you would to a named class. Mix in small crops, partial views, and false positives deliberately - otherwise the model has no signal for "small/ambiguous thing = not one of my known classes" and will force those crops into a named class by default.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Debugging Classification Models
|
|
||||||
|
|
||||||
To troubleshoot issues with object classification models, enable debug logging to see detailed information about classification attempts, scores, and consensus calculations.
|
|
||||||
|
|
||||||
Enable debug logs for classification models by adding `frigate.data_processing.real_time.custom_classification: debug` to your `logger` configuration. These logs are verbose, so only keep this enabled when necessary. Restart Frigate after this change.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Logging" />.
|
|
||||||
|
|
||||||
- Set **Logging level** to `debug`
|
|
||||||
- Set **Per-process log level > `frigate.data_processing.real_time.custom_classification`** to `debug` for verbose classification logging
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
logger:
|
|
||||||
default: info
|
|
||||||
logs:
|
|
||||||
# highlight-next-line
|
|
||||||
frigate.data_processing.real_time.custom_classification: debug
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
The debug logs will show:
|
|
||||||
|
|
||||||
- Classification probabilities for each attempt
|
|
||||||
- Whether scores meet the threshold requirement
|
|
||||||
- Consensus calculations and when assignments are made
|
|
||||||
- Object classification history and weighted scores
|
|
||||||
@ -1,168 +0,0 @@
|
|||||||
---
|
|
||||||
id: state_classification
|
|
||||||
title: State Classification
|
|
||||||
---
|
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
|
|
||||||
State classification allows you to train a custom MobileNetV2 classification model on a fixed region of your camera frame(s) to determine a current state. The model can be configured to run on a schedule and/or when motion is detected in that region. Classification results are available through the `frigate/<camera_name>/classification/<model_name>` MQTT topic and in Home Assistant sensors via the official Frigate integration.
|
|
||||||
|
|
||||||
:::info
|
|
||||||
|
|
||||||
Training a custom state classification model requires an internet connection to download MobileNetV2 base weights. By default these weights are not cached in `/config/`, so they are downloaded again after the container is recreated. Once trained, the model runs fully offline. See [Network Requirements](/frigate/network_requirements#one-time-model-downloads) for details.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Minimum System Requirements
|
|
||||||
|
|
||||||
State classification models are lightweight and run very fast on CPU.
|
|
||||||
|
|
||||||
Training the model does briefly use a high amount of system resources for about 1-3 minutes per training run. On lower-power devices, training may take longer.
|
|
||||||
|
|
||||||
A CPU with AVX + AVX2 instructions is required for training and inference.
|
|
||||||
|
|
||||||
## Classes
|
|
||||||
|
|
||||||
Classes are the different states an area on your camera can be in. Each class represents a distinct visual state that the model will learn to recognize.
|
|
||||||
|
|
||||||
For state classification:
|
|
||||||
|
|
||||||
- Define classes that represent mutually exclusive states
|
|
||||||
- Examples: `open` and `closed` for a garage door, `on` and `off` for lights
|
|
||||||
- Use at least 2 classes (typically binary states work best)
|
|
||||||
- Keep class names clear and descriptive
|
|
||||||
|
|
||||||
## Example use cases
|
|
||||||
|
|
||||||
- **Door state**: Detect if a garage or front door is open vs closed.
|
|
||||||
- **Gate state**: Track if a driveway gate is open or closed.
|
|
||||||
- **Trash day**: Bins at curb vs no bins present.
|
|
||||||
- **Pool cover**: Cover on vs off.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
State classification is configured as a custom classification model. Each model has its own name and settings. Provide at least one camera crop under `state_config.cameras`.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to the **Classification** page from the main navigation sidebar, select the **States** tab, then click **Add Classification**.
|
|
||||||
|
|
||||||
In the **Create New Classification** dialog:
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
| ----------- | ------------------------------------------------------------------------------------ |
|
|
||||||
| **Name** | A name for your state classification model (e.g., `front_door`) |
|
|
||||||
| **Type** | Select **State** for state classification |
|
|
||||||
| **Classes** | The state names the model will learn to distinguish between (e.g., `open`, `closed`) |
|
|
||||||
|
|
||||||
After creating the model, the wizard will guide you through selecting the camera crop area and assigning training examples. The `threshold` (default: `0.8`), `motion`, and `interval` settings can be adjusted in the YAML configuration.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
classification:
|
|
||||||
custom:
|
|
||||||
front_door:
|
|
||||||
threshold: 0.8
|
|
||||||
state_config:
|
|
||||||
motion: true # run when motion overlaps the crop
|
|
||||||
interval: 10 # also run every N seconds (optional)
|
|
||||||
cameras:
|
|
||||||
front:
|
|
||||||
# [x1, y1, x2, y2] as decimals between 0 and 1, relative to the
|
|
||||||
# camera's detect resolution
|
|
||||||
crop: [0.0, 0.25, 0.3, 0.85]
|
|
||||||
```
|
|
||||||
|
|
||||||
Crop coordinates are normalized: each value is a fraction of the camera's `detect` width or height, not a pixel value. Drawing the crop in the UI wizard writes these values for you.
|
|
||||||
|
|
||||||
An optional config, `save_attempts`, can be set as a key under the model name. This defines the number of classification attempts to save in the Recent Classifications tab. For state classification models, the default is 100.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Training the model
|
|
||||||
|
|
||||||
Creating and training the model is done within the Frigate UI using the `Classification` page. The process consists of three steps:
|
|
||||||
|
|
||||||
### Step 1: Name and Define
|
|
||||||
|
|
||||||
Enter a name for your model and define at least 2 classes (states) that represent mutually exclusive states. For example, `open` and `closed` for a door, or `on` and `off` for lights.
|
|
||||||
|
|
||||||
### Step 2: Select the Crop Area
|
|
||||||
|
|
||||||
Choose one or more cameras and draw a rectangle over the area of interest for each camera. The crop should be tight around the region you want to classify to avoid extra signals unrelated to what is being classified. You can drag and resize the rectangle to adjust the crop area.
|
|
||||||
|
|
||||||
### Step 3: Assign Training Examples
|
|
||||||
|
|
||||||
The system will automatically generate example images from your camera feeds. You'll be guided through each class one at a time to select which images represent that state. It's not strictly required to select all images you see. If a state is missing from the samples, you can train it from the Recent tab later.
|
|
||||||
|
|
||||||
Once some images are assigned, training will begin automatically.
|
|
||||||
|
|
||||||
### Improving the Model
|
|
||||||
|
|
||||||
:::tip Diversity matters far more than volume
|
|
||||||
|
|
||||||
Selecting dozens of nearly identical images is one of the fastest ways to degrade model performance. MobileNetV2 can overfit quickly when trained on homogeneous data. The model learns what _that exact moment_ looked like rather than what actually defines the state. This often leads to models that work perfectly under the original conditions but become unstable when day turns to night, weather changes, or seasonal lighting shifts. **This is why Frigate does not implement bulk training in the UI.**
|
|
||||||
|
|
||||||
For more detail, see [Frigate Tip: Best Practices for Training Face and Custom Classification Models](https://github.com/blakeblackshear/frigate/discussions/21374).
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
- **Start small and iterate**: Begin with a small, representative set of images per class. Models often begin working well with surprisingly few examples and improve naturally over time.
|
|
||||||
- **Problem framing**: Keep classes visually distinct and state-focused (e.g., `open`, `closed`, `unknown`). Avoid combining object identity with state in a single model unless necessary.
|
|
||||||
- **Data collection**: Use the model's Recent Classifications tab to gather balanced examples across times of day and weather.
|
|
||||||
- **When to train**: Focus on cases where the model is entirely incorrect or flips between states when it should not. There's no need to train additional images when the model is already working consistently.
|
|
||||||
- **Favor hard examples**: When images appear in the Recent Classifications tab, prioritize images scoring below 90-100% or those captured under new conditions (e.g., first snow of the year, seasonal changes, objects temporarily in view, insects at night). These represent scenarios different from the default state and help prevent overfitting.
|
|
||||||
- **Avoid bulk training similar images**: Training large batches of images that already score 100% (or close) adds little new information and increases the risk of overfitting.
|
|
||||||
- **The wizard is just the starting point**: You don't need to find and label every state upfront. Missing states will naturally appear in Recent Classifications, and those images tend to be more valuable because they represent new conditions and edge cases.
|
|
||||||
|
|
||||||
## Debugging Classification Models
|
|
||||||
|
|
||||||
To troubleshoot issues with state classification models, enable debug logging to see detailed information about classification attempts, scores, and state verification.
|
|
||||||
|
|
||||||
Enable debug logs for classification models by adding `frigate.data_processing.real_time.custom_classification: debug` to your `logger` configuration. These logs are verbose, so only keep this enabled when necessary. Restart Frigate after this change.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > System > Logging" />.
|
|
||||||
|
|
||||||
- Set **Logging level** to `debug`
|
|
||||||
- Set **Per-process log level > `frigate.data_processing.real_time.custom_classification`** to `debug` for verbose classification logging
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
logger:
|
|
||||||
default: info
|
|
||||||
logs:
|
|
||||||
# highlight-next-line
|
|
||||||
frigate.data_processing.real_time.custom_classification: debug
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
The debug logs will show:
|
|
||||||
|
|
||||||
- Classification probabilities for each attempt
|
|
||||||
- Whether scores meet the threshold requirement
|
|
||||||
- State verification progress (consecutive detections needed)
|
|
||||||
- When state changes are published
|
|
||||||
|
|
||||||
### Recent Classifications
|
|
||||||
|
|
||||||
For state classification, images are only added to recent classifications under specific circumstances:
|
|
||||||
|
|
||||||
- **First detection**: The first classification attempt for a camera is always saved
|
|
||||||
- **State changes**: Images are saved when the detected state differs from the current verified state
|
|
||||||
- **Pending verification**: Images are saved when there's a pending state change being verified (requires 3 consecutive identical states)
|
|
||||||
- **Low confidence**: Images with scores below 100% are saved even if the state matches the current state (useful for training)
|
|
||||||
|
|
||||||
Images are **not** saved when the state is stable (detected state matches current state) **and** the score is 100%. This prevents unnecessary storage of redundant high-confidence classifications.
|
|
||||||
@ -3,163 +3,67 @@ id: face_recognition
|
|||||||
title: Face Recognition
|
title: Face Recognition
|
||||||
---
|
---
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
Face recognition identifies known individuals by matching detected faces with previously learned facial data. When a known person is recognized, their name will be added as a `sub_label`. This information is included in the UI, filters, as well as in notifications.
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
import FaqItem from "@site/src/components/FaqItem";
|
|
||||||
|
|
||||||
Face recognition identifies known individuals by matching detected faces with previously learned facial data. When a known `person` is recognized, their name will be added as a `sub_label`. This information is included in the UI, filters, as well as in notifications.
|
|
||||||
|
|
||||||
:::info
|
|
||||||
|
|
||||||
Face recognition requires a one-time internet connection to download detection and embedding models from GitHub. Once cached, models work fully offline. See [Network Requirements](/frigate/network_requirements#one-time-model-downloads) for details.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Model Requirements
|
## Model Requirements
|
||||||
|
|
||||||
### Face Detection
|
### Face Detection
|
||||||
|
|
||||||
When running a Frigate+ model (or any custom model that natively detects faces) should ensure that `face` is added to the [list of objects to track](../plus/index.md#available-label-types) either globally or for a specific camera. This will allow face detection to run at the same time as object detection and be more efficient.
|
When running a Frigate+ model (or any custom model that natively detects faces) should ensure that `face` is added to the [list of objects to track](../plus/#available-label-types) either globally or for a specific camera. This will allow face detection to run at the same time as object detection and be more efficient.
|
||||||
|
|
||||||
When running a default COCO model or another model that does not include `face` as a detectable label, face detection will run via CV2 using a lightweight DNN model that runs on the CPU. In this case, you should _not_ define `face` in your list of objects to track.
|
When running a default COCO model or another model that does not include `face` as a detectable label, face detection will run via CV2 using a lightweight DNN model that runs on the CPU. In this case, you should _not_ define `face` in your list of objects to track.
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
Frigate needs to first detect a `person` before it can detect and recognize a face.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Face Recognition
|
### Face Recognition
|
||||||
|
|
||||||
Frigate has support for two face recognition model types:
|
Frigate has support for two face recognition model types:
|
||||||
|
|
||||||
- **small**: Frigate will run a FaceNet embedding model to recognize faces, which runs locally on the CPU. This model is optimized for efficiency and is not as accurate.
|
- **small**: Frigate will run a FaceNet embedding model to recognize faces, which runs locally on the CPU. This model is optimized for efficiency and is not as accurate.
|
||||||
- **large**: Frigate will run a large ArcFace embedding model that is optimized for accuracy. It is only recommended to be run when an integrated or dedicated GPU / NPU is available.
|
- **large**: Frigate will run a large ArcFace embedding model that is optimized for accuracy. It is only recommended to be run when an integrated or dedicated GPU is available.
|
||||||
|
|
||||||
In both cases, a lightweight face landmark detection model is also used to align faces before running recognition.
|
In both cases, a lightweight face landmark detection model is also used to align faces before running recognition.
|
||||||
|
|
||||||
All of these features run locally on your system.
|
|
||||||
|
|
||||||
## Minimum System Requirements
|
## Minimum System Requirements
|
||||||
|
|
||||||
A CPU with AVX + AVX2 instructions is required to run Face Recognition.
|
|
||||||
|
|
||||||
The `small` model is optimized for efficiency and runs on the CPU, most CPUs should run the model efficiently.
|
The `small` model is optimized for efficiency and runs on the CPU, most CPUs should run the model efficiently.
|
||||||
|
|
||||||
The `large` model is optimized for accuracy, an integrated or discrete GPU / NPU is required. See the [Hardware Accelerated Enrichments](/configuration/hardware_acceleration_enrichments.md) documentation.
|
The `large` model is optimized for accuracy, an integrated or discrete GPU is highly recommended. See the [Hardware Accelerated Enrichments](/configuration/hardware_acceleration_enrichments.md) documentation.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Face recognition is disabled by default and must be enabled before it can be used. Face recognition is a global configuration setting.
|
Face recognition is disabled by default, face recognition must be enabled in the UI or in your config file before it can be used. Face recognition is a global configuration setting.
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > Enrichments > Face recognition" />.
|
|
||||||
|
|
||||||
- Set **Enable face recognition** to on
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
face_recognition:
|
face_recognition:
|
||||||
enabled: true
|
enabled: true
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
Like the other real-time processors in Frigate, face recognition runs on the camera stream defined by the `detect` role in your config. To ensure optimal performance, select a suitable resolution for this stream in your camera's firmware that fits your specific scene and requirements.
|
|
||||||
|
|
||||||
## Advanced Configuration
|
## Advanced Configuration
|
||||||
|
|
||||||
Fine-tune face recognition with these optional parameters. The only optional parameters that can be set at the camera level are `enabled` and `min_area`.
|
Fine-tune face recognition with these optional parameters:
|
||||||
|
|
||||||
### Detection
|
### Detection
|
||||||
|
|
||||||
<ConfigTabs>
|
- `detection_threshold`: Face detection confidence score required before recognition runs:
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
Navigate to <NavPath path="Settings > Enrichments > Face recognition" />.
|
|
||||||
|
|
||||||
- **Detection threshold**: Face detection confidence score required before recognition runs. This field only applies to the standalone face detection model; `min_score` should be used to filter for models that have face detection built in.
|
|
||||||
- Default: `0.7`
|
- Default: `0.7`
|
||||||
- **Minimum face area**: Minimum size (in pixels) a face must be before recognition runs. Depending on the resolution of your camera's `detect` stream, you can increase this value to ignore small or distant faces.
|
- Note: This is field only applies to the standalone face detection model, `min_score` should be used to filter for models that have face detection built in.
|
||||||
- Default: `750` pixels
|
- `min_area`: Defines the minimum size (in pixels) a face must be before recognition runs.
|
||||||
|
- Default: `500` pixels.
|
||||||
</TabItem>
|
- Depending on the resolution of your camera's `detect` stream, you can increase this value to ignore small or distant faces.
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
face_recognition:
|
|
||||||
enabled: true
|
|
||||||
detection_threshold: 0.7
|
|
||||||
min_area: 750
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### Recognition
|
### Recognition
|
||||||
|
|
||||||
<ConfigTabs>
|
- `model_size`: Which model size to use, options are `small` or `large`
|
||||||
<TabItem value="ui">
|
- `unknown_score`: Min score to mark a person as a potential match, matches at or below this will be marked as unknown.
|
||||||
|
- Default: `0.8`.
|
||||||
Navigate to <NavPath path="Settings > Enrichments > Face recognition" />.
|
- `recognition_threshold`: Recognition confidence score required to add the face to the object as a sub label.
|
||||||
|
- Default: `0.9`.
|
||||||
- **Model size**: Which model size to use, options are `small` or `large`.
|
- `save_attempts`: Number of images of recognized faces to save for training.
|
||||||
- **Unknown score threshold**: Min score to mark a person as a potential match; matches at or below this will be marked as unknown.
|
- Default: `100`.
|
||||||
- Default: `0.8`
|
- `blur_confidence_filter`: Enables a filter that calculates how blurry the face is and adjusts the confidence based on this.
|
||||||
- **Recognition threshold**: Recognition confidence score required to add the face to the object as a sub label.
|
- Default: `True`.
|
||||||
- Default: `0.9`
|
|
||||||
- **Minimum faces**: Min face recognitions for the sub label to be applied to the person object.
|
|
||||||
- Default: `1`
|
|
||||||
- **Save attempts**: Number of images of recognized faces to save for training.
|
|
||||||
- Default: `200`
|
|
||||||
- **Blur confidence filter**: Enables a filter that calculates how blurry the face is and adjusts the confidence based on this.
|
|
||||||
- Default: `True`
|
|
||||||
- **Device**: Target a specific device to run the face recognition model on (multi-GPU installation). This setting is only applicable when using the `large` model. See [onnxruntime's provider options](https://onnxruntime.ai/docs/execution-providers/).
|
|
||||||
- Default: `None`
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
face_recognition:
|
|
||||||
enabled: true
|
|
||||||
model_size: small
|
|
||||||
unknown_score: 0.8
|
|
||||||
recognition_threshold: 0.9
|
|
||||||
min_faces: 1
|
|
||||||
save_attempts: 200
|
|
||||||
blur_confidence_filter: true
|
|
||||||
device: None
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Follow these steps to begin:
|
|
||||||
|
|
||||||
1. **Enable face recognition** in your configuration and restart Frigate.
|
|
||||||
2. **Upload one face** using the **Add Face** button's wizard in the Face Library section of the Frigate UI. Read below for the best practices on expanding your training set.
|
|
||||||
3. When Frigate detects and attempts to recognize a face, it will appear in the **Train** tab of the Face Library, along with its associated recognition confidence.
|
|
||||||
4. From the **Train** tab, you can **assign the face** to a new or existing person to improve recognition accuracy for the future.
|
|
||||||
|
|
||||||
## Creating a Robust Training Set
|
## Creating a Robust Training Set
|
||||||
|
|
||||||
:::tip
|
|
||||||
|
|
||||||
**The short version:** Start with a few clear, front-facing photos of each person. As faces are detected in the Recent Recognitions tab, train clear images that scored lower, adding variety (different angles, lighting, and expressions) slowly. Diversity matters far more than volume, and low-quality images hurt recognition more than they help.
|
|
||||||
|
|
||||||
For a step-by-step narrative of these best practices (and the same principles applied to state and object classification), see the [Frigate Tips: Best Practices for Training](https://github.com/blakeblackshear/frigate/discussions/21374) discussion.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
The number of images needed for a sufficient training set for face recognition varies depending on several factors:
|
The number of images needed for a sufficient training set for face recognition varies depending on several factors:
|
||||||
|
|
||||||
- Diversity of the dataset: A dataset with diverse images, including variations in lighting, pose, and facial expressions, will require fewer images per person than a less diverse dataset.
|
- Diversity of the dataset: A dataset with diverse images, including variations in lighting, pose, and facial expressions, will require fewer images per person than a less diverse dataset.
|
||||||
@ -180,127 +84,37 @@ When choosing images to include in the face training set it is recommended to al
|
|||||||
- If it is difficult to make out details in a persons face it will not be helpful in training.
|
- If it is difficult to make out details in a persons face it will not be helpful in training.
|
||||||
- Avoid images with extreme under/over-exposure.
|
- Avoid images with extreme under/over-exposure.
|
||||||
- Avoid blurry / pixelated images.
|
- Avoid blurry / pixelated images.
|
||||||
- Avoid training on infrared (gray-scale). The models are trained on color images and will not be able to extract features from gray-scale images.
|
- Avoid training on infrared (gray-scale). The models are trained on color images and will be able to extract features from gray-scale images.
|
||||||
- Using images of people wearing hats / sunglasses may confuse the model.
|
- Using images of people wearing hats / sunglasses may confuse the model.
|
||||||
- Do not upload too many similar images at the same time, it is recommended to train no more than 4-6 similar images for each person to avoid over-fitting.
|
- Do not upload too many similar images at the same time, it is recommended to train no more than 4-6 similar images for each person to avoid over-fitting.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### Understanding the Recent Recognitions Tab
|
|
||||||
|
|
||||||
The Recent Recognitions tab in the face library displays recent face recognition attempts. Detected face images are grouped according to the person they were identified as potentially matching.
|
|
||||||
|
|
||||||
Each face image is labeled with a name (or `Unknown`) along with the confidence score of that recognition attempt. Images are grouped by the person they were matched against, not by who they actually are, so a group labeled with a person's name can contain a crop that is really someone else but happened to score as a partial match. The name and score shown on each individual crop describe that single attempt.
|
|
||||||
|
|
||||||
While each image can be used to train the system for a specific person, not all images are suitable for training. Refer to the guidelines below for best practices on selecting images for training.
|
|
||||||
|
|
||||||
### How Frigate Decides Who a Person Is
|
|
||||||
|
|
||||||
Recognition does not happen one frame at a time. While a `person` is in view, Frigate runs face recognition on many frames, not just a single frame. The final `sub_label` is decided from all of those attempts together, weighted by the area of each face (larger, closer faces count more), not from any single frame.
|
|
||||||
|
|
||||||
This has a few practical consequences:
|
|
||||||
|
|
||||||
- A handful of wrong guesses on blurry or distant frames usually do not change the result. If Frigate sees a person as "Tom, Tom, Sam, Tom, Tom," it will still conclude the person was Tom.
|
|
||||||
- The goal is not for every individual face crop to be correct. The goal is for each person to be recognized correctly overall, across all the faces captured while they were present.
|
|
||||||
- A single very high confidence match will not by itself assign a sub label. Recognition must be consistent. See [I see scores above the threshold in the Recent Recognitions tab, but a sub label wasn't assigned?](#i-see-scores-above-the-threshold-in-the-recent-recognitions-tab-but-a-sub-label-wasnt-assigned) below.
|
|
||||||
|
|
||||||
### Which Faces Are Worth Training?
|
|
||||||
|
|
||||||
Whether a face is worth training has little to do with what it was recognized as. A crop is a good training candidate when all of these are true:
|
|
||||||
|
|
||||||
- It did not already score high and correctly. Faces that are already recognized confidently add little and increase the risk of over-fitting.
|
|
||||||
- It is clear enough to be useful: not blurry, not heavily off-axis, not infrared (gray-scale). If it is hard for you to make out the face, it will not help the model.
|
|
||||||
- It adds something new: a different angle, lighting, expression, or distance than what you already have.
|
|
||||||
|
|
||||||
### Step 1 - Building a Strong Foundation
|
### Step 1 - Building a Strong Foundation
|
||||||
|
|
||||||
When first enabling face recognition it is important to build a foundation of strong images. It is recommended to start by uploading 1-5 photos containing just this person's face. It is important that the person's face in the photo is front-facing and not turned, this will ensure a good starting point.
|
When first enabling face recognition it is important to build a foundation of strong images. It is recommended to start by uploading 1-5 "portrait" photos for each person. It is important that the person's face in the photo is straight-on and not turned which will ensure a good starting point.
|
||||||
|
|
||||||
Then it is recommended to use the `Face Library` tab in Frigate to select and train images for each person as they are detected. When building a strong foundation it is strongly recommended to only train on images that are front-facing. Ignore images from cameras that recognize faces from an angle. Aim to strike a balance between the quality of images while also having a range of conditions (day / night, different weather conditions, different times of day, etc.) in order to have diversity in the images used for each person and not have over-fitting.
|
Then it is recommended to use the `Face Library` tab in Frigate to select and train images for each person as they are detected. When building a strong foundation it is strongly recommended to only train on images that are straight-on. Ignore images from cameras that recognize faces from an angle.
|
||||||
|
|
||||||
You do not want to train images that are 90%+ as these are already being confidently recognized. In this step the goal is to train on clear, lower scoring front-facing images until the majority of front-facing images for a given person are consistently recognized correctly. Then it is time to move on to step 2.
|
Aim to strike a balance between the quality of images while also having a range of conditions (day / night, different weather conditions, different times of day, etc.) in order to have diversity in the images used for each person and not have over-fitting.
|
||||||
|
|
||||||
|
Once a person starts to be consistently recognized correctly on images that are straight-on, it is time to move on to the next step.
|
||||||
|
|
||||||
### Step 2 - Expanding The Dataset
|
### Step 2 - Expanding The Dataset
|
||||||
|
|
||||||
Once front-facing images are performing well, start choosing slightly off-angle images to include for training. It is important to still choose images where enough face detail is visible to recognize someone, and you still only want to train on images that score lower.
|
Once straight-on images are performing well, start choosing slightly off-angle images to include for training. It is important to still choose images where enough face detail is visible to recognize someone.
|
||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
### Getting Recognition Working
|
### Why can't I bulk upload photos?
|
||||||
|
|
||||||
<FaqItem id="how-do-i-debug-face-recognition-issues" question="How do I debug Face Recognition issues?">
|
|
||||||
|
|
||||||
Start with the [Usage](#usage) section and re-read the [Model Requirements](#model-requirements) above.
|
|
||||||
|
|
||||||
1. Enable debug logs to see exactly what Frigate is doing.
|
|
||||||
- Enable debug logs for face recognition by adding `frigate.data_processing.real_time.face: debug` to your `logger` configuration. Restart Frigate after this change.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
logger:
|
|
||||||
default: info
|
|
||||||
logs:
|
|
||||||
# highlight-next-line
|
|
||||||
frigate.data_processing.real_time.face: debug
|
|
||||||
```
|
|
||||||
|
|
||||||
- These logs report where the pipeline stopped for each `person` object, such as no face being found within the person's bounding box, the detected face being smaller than `min_area`, or a face being recognized but scoring too low.
|
|
||||||
- If you see no face-related messages at all, also add `frigate.embeddings.maintainer: debug` to confirm that the face processor was created at startup and that `person` updates are reaching it.
|
|
||||||
|
|
||||||
2. Ensure `person` is being _detected_. A `person` will automatically be scanned by Frigate for a face. Any detected faces will appear in the Recent Recognitions tab in the Frigate UI's Face Library.
|
|
||||||
|
|
||||||
If you are using a Frigate+ or `face` detecting model:
|
|
||||||
- Watch the [debug view](/usage/live#the-single-camera-view) to ensure that `face` is being detected along with `person`.
|
|
||||||
- You may need to adjust the `min_score` for the `face` object if faces are not being detected.
|
|
||||||
|
|
||||||
If you are **not** using a Frigate+ or `face` detecting model:
|
|
||||||
- Check your `detect` stream resolution and ensure it is sufficiently high enough to capture face details on `person` objects.
|
|
||||||
- You may need to lower your `detection_threshold` if faces are not being detected.
|
|
||||||
|
|
||||||
3. Any detected faces will then be _recognized_.
|
|
||||||
- Make sure you have trained at least one face per the recommendations above.
|
|
||||||
- Adjust `recognition_threshold` settings per the suggestions [above](#advanced-configuration).
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
<FaqItem id="does-face-recognition-run-on-the-recording-stream" question="Does face recognition run on the recording stream?">
|
|
||||||
|
|
||||||
Face recognition does not run on the recording stream, this would be suboptimal for many reasons:
|
|
||||||
|
|
||||||
1. The latency of accessing the recordings means the notifications would not include the names of recognized people because recognition would not complete until after.
|
|
||||||
2. The embedding models used run on a set image size, so larger images will be scaled down to match this anyway.
|
|
||||||
3. Motion clarity is much more important than extra pixels, over-compression and motion blur are much more detrimental to results than resolution.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
### Improving Accuracy and Training
|
|
||||||
|
|
||||||
<FaqItem id="detection-does-not-work-well-with-blurry-images" question="Detection does not work well with blurry images?">
|
|
||||||
|
|
||||||
Accuracy is definitely going to be improved with higher quality cameras / streams. It is important to look at the DORI (Detection Observation Recognition Identification) range of your camera, if that specification is posted. This specification explains the distance from the camera that a person can be detected, observed, recognized, and identified. The identification range is the most relevant here, and the distance listed by the camera is the furthest that face recognition will realistically work.
|
|
||||||
|
|
||||||
Some users have also noted that setting the stream in camera firmware to a constant bit rate (CBR) leads to better image clarity than with a variable bit rate (VBR).
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
<FaqItem id="can-i-train-faces-for-people-who-only-appear-at-night" question="Can I train faces for people who only appear at night?">
|
|
||||||
|
|
||||||
The embedding models are trained on color images, so gray-scale and infrared (IR) faces sit in a different feature distribution and are more easily confused with other people. Prefer color images, and avoid mixing gray-scale samples in early while you are building a foundation. If someone only ever appears at night, gray-scale training is acceptable, but keep those samples limited and as clear as possible, and add them only once color recognition is stable for your other people.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
<FaqItem id="why-cant-i-bulk-upload-photos" question="Why can't I bulk upload photos?">
|
|
||||||
|
|
||||||
It is important to methodically add photos to the library, bulk importing photos (especially from a general photo library) will lead to over-fitting in that particular scenario and hurt recognition performance.
|
It is important to methodically add photos to the library, bulk importing photos (especially from a general photo library) will lead to over-fitting in that particular scenario and hurt recognition performance.
|
||||||
|
|
||||||
</FaqItem>
|
### Why can't I bulk reprocess faces?
|
||||||
|
|
||||||
<FaqItem id="why-cant-i-bulk-reprocess-faces" question="Why can't I bulk reprocess faces?">
|
|
||||||
|
|
||||||
Face embedding models work by breaking apart faces into different features. This means that when reprocessing an image, only images from a similar angle will have its score affected.
|
Face embedding models work by breaking apart faces into different features. This means that when reprocessing an image, only images from a similar angle will have its score affected.
|
||||||
|
|
||||||
</FaqItem>
|
### Why do unknown people score similarly to known people?
|
||||||
|
|
||||||
<FaqItem id="why-do-unknown-people-score-similarly-to-known-people" question="Why do unknown people score similarly to known people?">
|
|
||||||
|
|
||||||
This can happen for a few different reasons, but this is usually an indicator that the training set needs to be improved. This is often related to over-fitting:
|
This can happen for a few different reasons, but this is usually an indicator that the training set needs to be improved. This is often related to over-fitting:
|
||||||
|
|
||||||
@ -308,56 +122,22 @@ This can happen for a few different reasons, but this is usually an indicator th
|
|||||||
- When you provide images with different poses, lighting, and expressions, the algorithm extracts features that are consistent across those variations.
|
- When you provide images with different poses, lighting, and expressions, the algorithm extracts features that are consistent across those variations.
|
||||||
- By training on a diverse set of images, the algorithm becomes less sensitive to minor variations and noise in the input image.
|
- By training on a diverse set of images, the algorithm becomes less sensitive to minor variations and noise in the input image.
|
||||||
|
|
||||||
Review your face collections and remove most of the unclear or low-quality images. Then, use the **Reprocess** button on each face in the **Train** tab to evaluate how the changes affect recognition scores.
|
### I see scores above the threshold in the train tab, but a sub label wasn't assigned?
|
||||||
|
|
||||||
Avoid training on images that already score highly, as this can lead to over-fitting. Instead, focus on relatively clear images that score lower (ideally with different lighting, angles, and conditions) to help the model generalize more effectively.
|
The Frigate considers the recognition scores across all recognition attempts for each person object. The scores are continually weighted based on the area of the face, and a sub label will only be assigned to person if a person is confidently recognized consistently. This avoids cases where a single high confidence recognition would throw off the results.
|
||||||
|
|
||||||
</FaqItem>
|
### Can I use other face recognition software like DoubleTake at the same time as the built in face recognition?
|
||||||
|
|
||||||
<FaqItem id="should-i-correct-a-face-that-was-recognized-as-the-wrong-person" question="Should I correct a face that was recognized as the wrong person?">
|
|
||||||
|
|
||||||
Only if it is a good image. Reassigning a face does add it to that person's training set, but two things are true at once:
|
|
||||||
|
|
||||||
- Reassigning a single misclassified frame has a small effect. The image is weighted against every other sample for that person, so correcting 1 frame out of 20 will not move recognition much. Occasional wrong guesses on poor frames are normal and do not need to be fixed.
|
|
||||||
- Reassigning a poor image (blurry, off-angle, low-resolution, gray-scale) can hurt more than the misidentification did, because low-quality samples degrade recognition for that whole person.
|
|
||||||
|
|
||||||
So the decision is about image quality, not about the wrong label. If the crop is clear, well-lit, and reasonably front-facing, and it scored low or was wrong, assigning it to the correct person is useful. If you can barely make out the face yourself, ignore it; do not train it just to correct the label.
|
|
||||||
|
|
||||||
If a person is repeatedly misidentified, do not keep reassigning the same frame. Instead, remove low-quality or misleading images and add a few high-quality samples to the correct person. See [Why do unknown people score similarly to known people?](#why-do-unknown-people-score-similarly-to-known-people) above.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
<FaqItem id="frigate-misidentified-a-face-can-i-tell-it-that-a-face-is-not-a-specific-person" question={'Frigate misidentified a face. Can I tell it that a face is "not" a specific person?'}>
|
|
||||||
|
|
||||||
No, face recognition does not support negative training (i.e., explicitly telling it who someone is _not_). Instead, the best approach is to improve the training data by using a more diverse and representative set of images for each person.
|
|
||||||
For more guidance, refer to the section above on improving recognition accuracy.
|
|
||||||
|
|
||||||
This also applies to a stranger who is repeatedly matched to a known person (for example, a delivery driver recognized as you). Do not create a profile for them and do not reassign their faces to yourself, as this pollutes your training set and makes recognition worse. Leave the detection as unknown and improve the known person's training set instead. Face recognition learns who someone is, not who they are not.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
<FaqItem id="i-see-scores-above-the-threshold-in-the-recent-recognitions-tab-but-a-sub-label-wasnt-assigned" question="I see scores above the threshold in the Recent Recognitions tab, but a sub label wasn't assigned?">
|
|
||||||
|
|
||||||
Frigate considers the recognition scores across all recognition attempts for each person object. The scores are continually weighted based on the area of the face, and a sub label will only be assigned to person if a person is confidently recognized consistently. This avoids cases where a single high confidence recognition would throw off the results.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
### Compatibility and Maintenance
|
|
||||||
|
|
||||||
<FaqItem id="can-i-use-other-face-recognition-software-like-doubletake-at-the-same-time-as-the-built-in-face-recognition" question="Can I use other face recognition software like DoubleTake at the same time as the built in face recognition?">
|
|
||||||
|
|
||||||
No, using another face recognition service will interfere with Frigate's built in face recognition. When using double-take the sub_label feature must be disabled if the built in face recognition is also desired.
|
No, using another face recognition service will interfere with Frigate's built in face recognition. When using double-take the sub_label feature must be disabled if the built in face recognition is also desired.
|
||||||
|
|
||||||
</FaqItem>
|
### Does face recognition run on the recording stream?
|
||||||
|
|
||||||
<FaqItem id="i-get-an-unknown-error-when-taking-a-photo-directly-with-my-iphone" question="I get an unknown error when taking a photo directly with my iPhone">
|
Face recognition does not run on the recording stream, this would be suboptimal for many reasons:
|
||||||
|
|
||||||
|
1. The latency of accessing the recordings means the notifications would not include the names of recognized people because recognition would not complete until after.
|
||||||
|
2. The embedding models used run on a set image size, so larger images will be scaled down to match this anyway.
|
||||||
|
3. Motion clarity is much more important than extra pixels, over-compression and motion blur are much more detrimental to results than resolution.
|
||||||
|
|
||||||
|
### I get an unknown error when taking a photo directly with my iPhone
|
||||||
|
|
||||||
By default iOS devices will use HEIC (High Efficiency Image Container) for images, but this format is not supported for uploads. Choosing `large` as the format instead of `original` will use JPG which will work correctly.
|
By default iOS devices will use HEIC (High Efficiency Image Container) for images, but this format is not supported for uploads. Choosing `large` as the format instead of `original` will use JPG which will work correctly.
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|
||||||
<FaqItem id="how-can-i-delete-the-face-database-and-start-over" question="How can I delete the face database and start over?">
|
|
||||||
|
|
||||||
Frigate does not store anything in its database related to face recognition. You can simply delete all of your faces through the Frigate UI or remove the contents of the `/media/frigate/clips/faces` directory.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
|
|||||||
@ -3,75 +3,48 @@ id: ffmpeg_presets
|
|||||||
title: FFmpeg presets
|
title: FFmpeg presets
|
||||||
---
|
---
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
Some presets of FFmpeg args are provided by default to make the configuration easier. All presets can be seen in [this file](https://github.com/blakeblackshear/frigate/blob/master/frigate/ffmpeg_presets.py).
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
|
|
||||||
Frigate ships with a set of FFmpeg presets to keep your configuration short and readable. Each preset expands to a longer list of FFmpeg arguments at runtime. You can see exactly what every preset expands to in [this file](https://github.com/blakeblackshear/frigate/blob/master/frigate/ffmpeg_presets.py).
|
### Hwaccel Presets
|
||||||
|
|
||||||
In the config file you reference a preset by its name (for example, `preset-vaapi`). In the UI, the same preset is shown with a friendly label (for example, **VAAPI (Intel/AMD GPU)**). Both refer to the same thing: the tables below list the config name alongside the label you'll see in the UI.
|
It is highly recommended to use hwaccel presets in the config. These presets not only replace the longer args, but they also give Frigate hints of what hardware is available and allows Frigate to make other optimizations using the GPU such as when encoding the birdseye restream or when scaling a stream that has a size different than the native stream size.
|
||||||
|
|
||||||
### Hwaccel (Hardware Acceleration) Presets {#hwaccel-presets}
|
See [the hwaccel docs](/configuration/hardware_acceleration_video.md) for more info on how to setup hwaccel for your GPU / iGPU.
|
||||||
|
|
||||||
Hardware acceleration arguments tell FFmpeg to decode your camera's video stream on a GPU or integrated graphics chip instead of the CPU, which dramatically lowers CPU usage. Using a preset is highly recommended. Beyond replacing a long list of arguments, each preset also tells Frigate what hardware is available so it can offload additional work to the GPU, for example, encoding the Birdseye restream or scaling a stream whose resolution differs from the camera's native size.
|
| Preset | Usage | Other Notes |
|
||||||
|
| --------------------- | ------------------------------ | ----------------------------------------------------- |
|
||||||
See [the hardware acceleration docs](/configuration/hardware_acceleration_video.md) for details on setting up hardware acceleration for your GPU / iGPU, then select the preset that matches your hardware.
|
| preset-rpi-64-h264 | 64 bit Rpi with h264 stream | |
|
||||||
|
| preset-rpi-64-h265 | 64 bit Rpi with h265 stream | |
|
||||||
| Preset (YAML config) | UI Label | Usage | Notes |
|
| preset-vaapi | Intel & AMD VAAPI | Check hwaccel docs to ensure correct driver is chosen |
|
||||||
| --------------------- | ----------------------- | --------------------------------- | --------------------------------------------------------------- |
|
| preset-intel-qsv-h264 | Intel QSV with h264 stream | If issues occur recommend using vaapi preset instead |
|
||||||
| preset-rpi-64-h264 | Raspberry Pi (H.264) | 64-bit Raspberry Pi, H.264 stream | |
|
| preset-intel-qsv-h265 | Intel QSV with h265 stream | If issues occur recommend using vaapi preset instead |
|
||||||
| preset-rpi-64-h265 | Raspberry Pi (H.265) | 64-bit Raspberry Pi, H.265 stream | |
|
| preset-nvidia | Nvidia GPU | |
|
||||||
| preset-vaapi | VAAPI (Intel/AMD GPU) | Intel or AMD GPU via VAAPI | Check the hwaccel docs to ensure the correct driver is selected |
|
| preset-jetson-h264 | Nvidia Jetson with h264 stream | |
|
||||||
| preset-intel-qsv-h264 | Intel QuickSync (H.264) | Intel QuickSync, H.264 stream | If you have issues, use the VAAPI preset instead |
|
| preset-jetson-h265 | Nvidia Jetson with h265 stream | |
|
||||||
| preset-intel-qsv-h265 | Intel QuickSync (H.265) | Intel QuickSync, H.265 stream | If you have issues, use the VAAPI preset instead |
|
| preset-rk-h264 | Rockchip MPP with h264 stream | Use image with \*-rk suffix and privileged mode |
|
||||||
| preset-nvidia | NVIDIA GPU | NVIDIA GPU | |
|
| preset-rk-h265 | Rockchip MPP with h265 stream | Use image with \*-rk suffix and privileged mode |
|
||||||
| preset-jetson-h264 | NVIDIA Jetson (H.264) | NVIDIA Jetson, H.264 stream | |
|
|
||||||
| preset-jetson-h265 | NVIDIA Jetson (H.265) | NVIDIA Jetson, H.265 stream | |
|
|
||||||
| preset-rkmpp | Rockchip RKMPP | Rockchip MPP | Use an image with the `-rk` suffix and run in privileged mode |
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > Global configuration > FFmpeg" /> and set **Hardware acceleration arguments** to the appropriate preset for your hardware.
|
|
||||||
2. To override for a specific camera, navigate to <NavPath path="Settings > Camera configuration > Streams (FFmpeg)" /> and set **Hardware acceleration arguments** for that camera.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
ffmpeg:
|
|
||||||
hwaccel_args: preset-vaapi
|
|
||||||
|
|
||||||
cameras:
|
|
||||||
front_door:
|
|
||||||
ffmpeg:
|
|
||||||
hwaccel_args: preset-nvidia
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### Input Args Presets
|
### Input Args Presets
|
||||||
|
|
||||||
Input arguments are passed to FFmpeg before your camera source and control how Frigate connects to and reads the stream: the transport protocol, timeouts, reconnection behavior, and how the stream is probed. The right input args ensure a reliable connection and maximum compatibility for each type of stream.
|
Input args presets help make the config more readable and handle use cases for different types of streams to ensure maximum compatibility.
|
||||||
|
|
||||||
See [the camera-specific docs](/configuration/camera_specific.md) for more 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 (config) | UI Label | Usage | Notes |
|
| Preset | Usage | Other Notes |
|
||||||
| -------------------------------- | ----------------------------------------- | --------------------------- | ------------------------------------------------------------------------------- |
|
| -------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------ |
|
||||||
| preset-http-jpeg-generic | HTTP JPEG (Generic) | HTTP live JPEG | Restreaming the live JPEG is recommended instead |
|
| preset-http-jpeg-generic | HTTP Live Jpeg | Recommend restreaming live jpeg instead |
|
||||||
| preset-http-mjpeg-generic | HTTP MJPEG (Generic) | HTTP MJPEG stream | Restreaming the MJPEG stream is recommended instead |
|
| preset-http-mjpeg-generic | HTTP Mjpeg Stream | Recommend restreaming mjpeg stream instead |
|
||||||
| preset-http-reolink | HTTP - Reolink Cameras | 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 (Generic) | RTMP stream | |
|
| preset-rtmp-generic | RTMP Stream | |
|
||||||
| preset-rtsp-generic | RTSP (Generic) | RTSP stream | The default when no input args are specified |
|
| preset-rtsp-generic | RTSP Stream | This is the default when nothing is specified |
|
||||||
| preset-rtsp-restream | RTSP - Restream from go2rtc | RTSP stream from a restream | Use when a go2rtc restream is the source for Frigate |
|
| preset-rtsp-restream | RTSP Stream from restream | Use for rtsp restream as source for frigate |
|
||||||
| preset-rtsp-restream-low-latency | RTSP - Restream from go2rtc (Low Latency) | RTSP stream from a restream | Lowers latency for a go2rtc restream source; may cause issues with some cameras |
|
| 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-udp | RTSP - UDP | RTSP stream over UDP | Use when the camera only supports UDP |
|
| preset-rtsp-udp | RTSP Stream via UDP | Use when camera is UDP only |
|
||||||
| preset-rtsp-blue-iris | RTSP - Blue Iris | Blue Iris RTSP stream | Use when consuming a stream from Blue Iris |
|
| preset-rtsp-blue-iris | Blue Iris RTSP Stream | Use when consuming a stream from Blue Iris |
|
||||||
|
|
||||||
:::warning
|
:::warning
|
||||||
|
|
||||||
Be mindful of input arguments when restreaming, because you can end up with a mix of protocols. The `http` and `rtmp` presets cannot be used with `rtsp` streams. For example, using a Reolink camera with an RTSP restream as the recording source while `preset-http-reolink` is applied will cause a crash. In cases like this, set the preset at the stream level instead. See the example below.
|
It is important to be mindful of input args when using restream because you can have a mix of protocols. `http` and `rtmp` presets cannot be used with `rtsp` streams. For example, when using a reolink cam with the rtsp restream as a source for record the preset-http-reolink will cause a crash. In this case presets will need to be set at the stream level. See the example below.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
@ -96,13 +69,13 @@ cameras:
|
|||||||
|
|
||||||
### Output Args Presets
|
### Output Args Presets
|
||||||
|
|
||||||
Output arguments are passed to FFmpeg after your camera source and control how recordings are written: which codecs are used and whether audio and video are copied as-is or re-encoded. The right output args ensure consistent, playable recordings for each type of stream.
|
Output args presets help make the config more readable and handle use cases for different types of streams to ensure consistent recordings.
|
||||||
|
|
||||||
| Preset (config) | UI Label | Usage | Notes |
|
| Preset | Usage | Other Notes |
|
||||||
| -------------------------------- | ------------------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| -------------------------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| preset-record-generic | Record (Generic, no audio) | Record without audio | Use this if your camera has no audio, or if you don't want to record audio |
|
| preset-record-generic | Record WITHOUT audio | This is the default when nothing is specified |
|
||||||
| preset-record-generic-audio-copy | Record (Generic + Copy Audio) | Record with the original audio | Use this to keep the camera's audio in recordings without re-encoding |
|
| preset-record-generic-audio-copy | Record WITH original audio | Use this to enable audio in recordings |
|
||||||
| preset-record-generic-audio-aac | Record (Generic + Audio to AAC) | Record with audio transcoded to AAC | The default when no output args are specified. Transcodes audio to AAC. If the source is already AAC, use `preset-record-generic-audio-copy` to avoid re-encoding |
|
| preset-record-generic-audio-aac | Record WITH transcoded aac audio | Use this to transcode to aac audio. If your source is already aac, use preset-record-generic-audio-copy instead to avoid re-encoding |
|
||||||
| preset-record-mjpeg | Record - MJPEG Cameras | Record an MJPEG stream | Restreaming the MJPEG stream is recommended instead |
|
| preset-record-mjpeg | Record an mjpeg stream | Recommend restreaming mjpeg stream instead |
|
||||||
| preset-record-jpeg | Record - JPEG Cameras | Record a live JPEG | Restreaming the live JPEG is recommended instead |
|
| preset-record-jpeg | Record live jpeg | Recommend restreaming live jpeg instead |
|
||||||
| preset-record-ubiquiti | Record - Ubiquiti Cameras | Record a Ubiquiti stream with audio | Handles Ubiquiti's non-standard audio format |
|
| preset-record-ubiquiti | Record ubiquiti stream with audio | Recordings with ubiquiti non-standard audio |
|
||||||
|
|||||||
214
docs/docs/configuration/genai.md
Normal file
214
docs/docs/configuration/genai.md
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
---
|
||||||
|
id: genai
|
||||||
|
title: Generative AI
|
||||||
|
---
|
||||||
|
|
||||||
|
Generative AI can be used to automatically generate descriptive text based on the thumbnails of your tracked objects. This helps with [Semantic Search](/configuration/semantic_search) in Frigate to provide more context about your tracked objects. Descriptions are accessed via the _Explore_ view in the Frigate UI by clicking on a tracked object's thumbnail.
|
||||||
|
|
||||||
|
Requests for a description are sent off automatically to your AI provider at the end of the tracked object's lifecycle, or can optionally be sent earlier after a number of significantly changed frames, for example in use in more real-time notifications. Descriptions can also be regenerated manually via the Frigate UI. Note that if you are manually entering a description for tracked objects prior to its end, this will be overwritten by the generated response.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Generative AI can be enabled for all cameras or only for specific cameras. There are currently 3 native providers available to integrate with Frigate. Other providers that support the OpenAI standard API can also be used. See the OpenAI section below.
|
||||||
|
|
||||||
|
To use Generative AI, you must define a single provider at the global level of your Frigate configuration. If the provider you choose requires an API key, you may either directly paste it in your configuration, or store it in an environment variable prefixed with `FRIGATE_`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
genai:
|
||||||
|
enabled: True
|
||||||
|
provider: gemini
|
||||||
|
api_key: "{FRIGATE_GEMINI_API_KEY}"
|
||||||
|
model: gemini-1.5-flash
|
||||||
|
|
||||||
|
cameras:
|
||||||
|
front_camera: ...
|
||||||
|
indoor_camera:
|
||||||
|
genai: # <- disable GenAI for your indoor camera
|
||||||
|
enabled: False
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ollama
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
|
||||||
|
Using Ollama on CPU is not recommended, high inference times make using Generative AI impractical.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
[Ollama](https://ollama.com/) allows you to self-host large language models and keep everything running locally. It provides a nice API over [llama.cpp](https://github.com/ggerganov/llama.cpp). It is highly recommended to host this server on a machine with an Nvidia graphics card, or on a Apple silicon Mac for best performance.
|
||||||
|
|
||||||
|
Most of the 7b parameter 4-bit vision models will fit inside 8GB of VRAM. There is also a [Docker container](https://hub.docker.com/r/ollama/ollama) available.
|
||||||
|
|
||||||
|
Parallel requests also come with some caveats. You will need to set `OLLAMA_NUM_PARALLEL=1` and choose a `OLLAMA_MAX_QUEUE` and `OLLAMA_MAX_LOADED_MODELS` values that are appropriate for your hardware and preferences. See the [Ollama documentation](https://github.com/ollama/ollama/blob/main/docs/faq.md#how-does-ollama-handle-concurrent-requests).
|
||||||
|
|
||||||
|
### Supported Models
|
||||||
|
|
||||||
|
You must use a vision capable model with Frigate. Current model variants can be found [in their model library](https://ollama.com/library). At the time of writing, this includes `llava`, `llava-llama3`, `llava-phi3`, and `moondream`. Note that Frigate will not automatically download the model you specify in your config, you must download the model to your local instance of Ollama first i.e. by running `ollama pull llava:7b` on your Ollama server/Docker container. Note that the model specified in Frigate's config must match the downloaded model tag.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
|
||||||
|
You should have at least 8 GB of RAM available (or VRAM if running on GPU) to run the 7B models, 16 GB to run the 13B models, and 32 GB to run the 33B models.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
genai:
|
||||||
|
enabled: True
|
||||||
|
provider: ollama
|
||||||
|
base_url: http://localhost:11434
|
||||||
|
model: llava:7b
|
||||||
|
```
|
||||||
|
|
||||||
|
## Google Gemini
|
||||||
|
|
||||||
|
Google Gemini has a free tier allowing [15 queries per minute](https://ai.google.dev/pricing) to the API, which is more than sufficient for standard Frigate usage.
|
||||||
|
|
||||||
|
### Supported Models
|
||||||
|
|
||||||
|
You must use a vision capable model with Frigate. Current model variants can be found [in their documentation](https://ai.google.dev/gemini-api/docs/models/gemini). At the time of writing, this includes `gemini-1.5-pro` and `gemini-1.5-flash`.
|
||||||
|
|
||||||
|
### Get API Key
|
||||||
|
|
||||||
|
To start using Gemini, you must first get an API key from [Google AI Studio](https://aistudio.google.com).
|
||||||
|
|
||||||
|
1. Accept the Terms of Service
|
||||||
|
2. Click "Get API Key" from the right hand navigation
|
||||||
|
3. Click "Create API key in new project"
|
||||||
|
4. Copy the API key for use in your config
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
genai:
|
||||||
|
enabled: True
|
||||||
|
provider: gemini
|
||||||
|
api_key: "{FRIGATE_GEMINI_API_KEY}"
|
||||||
|
model: gemini-1.5-flash
|
||||||
|
```
|
||||||
|
|
||||||
|
## OpenAI
|
||||||
|
|
||||||
|
OpenAI does not have a free tier for their API. With the release of gpt-4o, pricing has been reduced and each generation should cost fractions of a cent if you choose to go this route.
|
||||||
|
|
||||||
|
### Supported Models
|
||||||
|
|
||||||
|
You must use a vision capable model with Frigate. Current model variants can be found [in their documentation](https://platform.openai.com/docs/models). At the time of writing, this includes `gpt-4o` and `gpt-4-turbo`.
|
||||||
|
|
||||||
|
### Get API Key
|
||||||
|
|
||||||
|
To start using OpenAI, you must first [create an API key](https://platform.openai.com/api-keys) and [configure billing](https://platform.openai.com/settings/organization/billing/overview).
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
genai:
|
||||||
|
enabled: True
|
||||||
|
provider: openai
|
||||||
|
api_key: "{FRIGATE_OPENAI_API_KEY}"
|
||||||
|
model: gpt-4o
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
|
||||||
|
To use a different OpenAI-compatible API endpoint, set the `OPENAI_BASE_URL` environment variable to your provider's API URL.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Azure OpenAI
|
||||||
|
|
||||||
|
Microsoft offers several vision models through Azure OpenAI. A subscription is required.
|
||||||
|
|
||||||
|
### Supported Models
|
||||||
|
|
||||||
|
You must use a vision capable model with Frigate. Current model variants can be found [in their documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models). At the time of writing, this includes `gpt-4o` and `gpt-4-turbo`.
|
||||||
|
|
||||||
|
### Create Resource and Get API Key
|
||||||
|
|
||||||
|
To start using Azure OpenAI, you must first [create a resource](https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource). You'll need your API key and resource URL, which must include the `api-version` parameter (see the example below). The model field is not required in your configuration as the model is part of the deployment name you chose when deploying the resource.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
genai:
|
||||||
|
enabled: True
|
||||||
|
provider: azure_openai
|
||||||
|
base_url: https://example-endpoint.openai.azure.com/openai/deployments/gpt-4o/chat/completions?api-version=2023-03-15-preview
|
||||||
|
api_key: "{FRIGATE_OPENAI_API_KEY}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage and Best Practices
|
||||||
|
|
||||||
|
Frigate's thumbnail search excels at identifying specific details about tracked objects – for example, using an "image caption" approach to find a "person wearing a yellow vest," "a white dog running across the lawn," or "a red car on a residential street." To enhance this further, Frigate’s default prompts are designed to ask your AI provider about the intent behind the object's actions, rather than just describing its appearance.
|
||||||
|
|
||||||
|
While generating simple descriptions of detected objects is useful, understanding intent provides a deeper layer of insight. Instead of just recognizing "what" is in a scene, Frigate’s default prompts aim to infer "why" it might be there or "what" it could do next. Descriptions tell you what’s happening, but intent gives context. For instance, a person walking toward a door might seem like a visitor, but if they’re moving quickly after hours, you can infer a potential break-in attempt. Detecting a person loitering near a door at night can trigger an alert sooner than simply noting "a person standing by the door," helping you respond based on the situation’s context.
|
||||||
|
|
||||||
|
### Using GenAI for notifications
|
||||||
|
|
||||||
|
Frigate provides an [MQTT topic](/integrations/mqtt), `frigate/tracked_object_update`, that is updated with a JSON payload containing `event_id` and `description` when your AI provider returns a description for a tracked object. This description could be used directly in notifications, such as sending alerts to your phone or making audio announcements. If additional details from the tracked object are needed, you can query the [HTTP API](/integrations/api/event-events-event-id-get) using the `event_id`, eg: `http://frigate_ip:5000/api/events/<event_id>`.
|
||||||
|
|
||||||
|
If looking to get notifications earlier than when an object ceases to be tracked, an additional send trigger can be configured of `after_significant_updates`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
genai:
|
||||||
|
send_triggers:
|
||||||
|
tracked_object_end: true # default
|
||||||
|
after_significant_updates: 3 # how many updates to a tracked object before we should send an image
|
||||||
|
```
|
||||||
|
|
||||||
|
## Custom Prompts
|
||||||
|
|
||||||
|
Frigate sends multiple frames from the tracked object along with a prompt to your Generative AI provider asking it to generate a description. The default prompt is as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
Analyze the sequence of images containing the {label}. Focus on the likely intent or behavior of the {label} based on its actions and movement, rather than describing its appearance or the surroundings. Consider what the {label} is doing, why, and what it might do next.
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
|
||||||
|
Prompts can use variable replacements like `{label}`, `{sub_label}`, and `{camera}` to substitute information from the tracked object as part of the prompt.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
You are also able to define custom prompts in your configuration.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
genai:
|
||||||
|
enabled: True
|
||||||
|
provider: ollama
|
||||||
|
base_url: http://localhost:11434
|
||||||
|
model: llava
|
||||||
|
prompt: "Analyze the {label} in these images from the {camera} security camera. Focus on the actions, behavior, and potential intent of the {label}, rather than just describing its appearance."
|
||||||
|
object_prompts:
|
||||||
|
person: "Examine the main person in these images. What are they doing and what might their actions suggest about their intent (e.g., approaching a door, leaving an area, standing still)? Do not describe the surroundings or static details."
|
||||||
|
car: "Observe the primary vehicle in these images. Focus on its movement, direction, or purpose (e.g., parking, approaching, circling). If it's a delivery vehicle, mention the company."
|
||||||
|
```
|
||||||
|
|
||||||
|
Prompts can also be overriden at the camera level to provide a more detailed prompt to the model about your specific camera, if you desire. By default, descriptions will be generated for all tracked objects and all zones. But you can also optionally specify `objects` and `required_zones` to only generate descriptions for certain tracked objects or zones.
|
||||||
|
|
||||||
|
Optionally, you can generate the description using a snapshot (if enabled) by setting `use_snapshot` to `True`. By default, this is set to `False`, which sends the uncompressed images from the `detect` stream collected over the object's lifetime to the model. Once the object lifecycle ends, only a single compressed and cropped thumbnail is saved with the tracked object. Using a snapshot might be useful when you want to _regenerate_ a tracked object's description as it will provide the AI with a higher-quality image (typically downscaled by the AI itself) than the cropped/compressed thumbnail. Using a snapshot otherwise has a trade-off in that only a single image is sent to your provider, which will limit the model's ability to determine object movement or direction.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
cameras:
|
||||||
|
front_door:
|
||||||
|
genai:
|
||||||
|
use_snapshot: True
|
||||||
|
prompt: "Analyze the {label} in these images from the {camera} security camera at the front door. Focus on the actions and potential intent of the {label}."
|
||||||
|
object_prompts:
|
||||||
|
person: "Examine the person in these images. What are they doing, and how might their actions suggest their purpose (e.g., delivering something, approaching, leaving)? If they are carrying or interacting with a package, include details about its source or destination."
|
||||||
|
cat: "Observe the cat in these images. Focus on its movement and intent (e.g., wandering, hunting, interacting with objects). If the cat is near the flower pots or engaging in any specific actions, mention it."
|
||||||
|
objects:
|
||||||
|
- person
|
||||||
|
- cat
|
||||||
|
required_zones:
|
||||||
|
- steps
|
||||||
|
```
|
||||||
|
|
||||||
|
### Experiment with prompts
|
||||||
|
|
||||||
|
Many providers also have a public facing chat interface for their models. Download a couple of different thumbnails or snapshots from Frigate and try new things in the playground to get descriptions to your liking before updating the prompt in Frigate.
|
||||||
|
|
||||||
|
- OpenAI - [ChatGPT](https://chatgpt.com)
|
||||||
|
- Gemini - [Google AI Studio](https://aistudio.google.com)
|
||||||
|
- Ollama - [Open WebUI](https://docs.openwebui.com/)
|
||||||
@ -1,522 +0,0 @@
|
|||||||
---
|
|
||||||
id: genai_config
|
|
||||||
title: Configuring Generative AI
|
|
||||||
---
|
|
||||||
|
|
||||||
import ConfigTabs from "@site/src/components/ConfigTabs";
|
|
||||||
import TabItem from "@theme/TabItem";
|
|
||||||
import NavPath from "@site/src/components/NavPath";
|
|
||||||
import FaqItem from "@site/src/components/FaqItem";
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
A Generative AI provider can be configured in the global config, which will make the Generative AI features available for use. There are currently 5 native providers available to integrate with Frigate. Other providers that support the OpenAI standard API can also be used. See the OpenAI-Compatible section below.
|
|
||||||
|
|
||||||
`genai` is a map of named providers. Each key under `genai` is a name you choose, and its value is that provider's settings:
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > Enrichments > Generative AI" />.
|
|
||||||
- Click **Add** and enter a **Provider name**. Any name of letters, numbers, hyphens, and underscores is accepted, but it cannot be changed from the UI after the provider is created.
|
|
||||||
- Set **Provider** to the service you are using (e.g., `ollama`)
|
|
||||||
- Set **Base URL**, **API key**, and **Model** as required by that provider
|
|
||||||
- Set **Roles** to the roles this provider should handle.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
genai:
|
|
||||||
my_provider: # any name you like
|
|
||||||
provider: ollama
|
|
||||||
base_url: http://localhost:11434
|
|
||||||
model: qwen3-vl:4b
|
|
||||||
roles:
|
|
||||||
- descriptions
|
|
||||||
- embeddings
|
|
||||||
- chat
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
The examples on this page all use `my_provider`, but the name is arbitrary and is only used to reference the provider elsewhere in the config (for example, `semantic_search.model`).
|
|
||||||
|
|
||||||
Each provider handles one or more **roles**: `chat`, `descriptions`, and `embeddings`. A provider handles all three by default, and each role may be assigned to exactly one provider. Define a single provider if you want it to do everything, or split the roles across several providers using the `roles` option.
|
|
||||||
|
|
||||||
If the provider you choose requires an API key, you may either directly paste it in your configuration, or store it in an environment variable prefixed with `FRIGATE_`.
|
|
||||||
|
|
||||||
## Local Providers
|
|
||||||
|
|
||||||
Local providers run on your own hardware and keep all data processing private. These require a GPU or dedicated hardware for best performance.
|
|
||||||
|
|
||||||
:::warning
|
|
||||||
|
|
||||||
Running Generative AI models on CPU is not recommended, as high inference times make using Generative AI impractical.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Recommended Local Models
|
|
||||||
|
|
||||||
#### Vision models
|
|
||||||
|
|
||||||
You must use a vision-capable model with Frigate. The following models are recommended for local deployment of the `descriptions` and `chat` roles:
|
|
||||||
|
|
||||||
| Model | Notes |
|
|
||||||
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| `qwen3-vl` | Strong visual and situational understanding, enhanced ability to identify smaller objects and interactions with object. |
|
|
||||||
| `qwen3.6`/`qwen3.8` | Strong situational understanding, but missing DeepStack from qwen3-vl leading to worse performance for identifying objects in people's hand and other small details. |
|
|
||||||
| `gemma4` | Strong situational understanding, sometimes resorts to more vague terms like 'interacts' instead of assigning a specific action. |
|
|
||||||
|
|
||||||
#### Embedding models
|
|
||||||
|
|
||||||
The `embeddings` role needs a different kind of model. Text queries are matched against the stored image embeddings, so the model must be trained to place images and text into the same vector space. A chat or description model will still return vectors when asked, but those vectors are not trained for retrieval and text searches will return poor matches with no error to indicate why.
|
|
||||||
|
|
||||||
| Model | Notes |
|
|
||||||
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| `qwen3-vl-embedding` | Multimodal embeddings for [Semantic Search](/configuration/semantic_search#genai-provider). Must be served by llama.cpp started with `--embeddings` and `--mmproj`. |
|
|
||||||
|
|
||||||
:::info
|
|
||||||
|
|
||||||
Each model is available in multiple parameter sizes (3b, 4b, 8b, etc.). Larger sizes are more capable of complex tasks and understanding of situations, but requires more memory and computational resources. It is recommended to try multiple models and experiment to see which performs best.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
You should have at least 8 GB of RAM available (or VRAM if running on GPU) to run the 7B models, 16 GB to run the 13B models, and 24 GB to run the 33B models.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Model Types: Instruct vs Thinking
|
|
||||||
|
|
||||||
Vision-language models come in **instruct** variants (fine-tuned to follow instructions and respond concisely), **thinking** variants (fine-tuned for free-form, speculative reasoning), and **hybrid** variants that support both modes per request. Most modern vision-language models are hybrid.
|
|
||||||
|
|
||||||
Frigate manages reasoning per task automatically:
|
|
||||||
|
|
||||||
- **Description tasks** (object descriptions, review descriptions, review summaries) are synthesis-only and benefit from concise, direct output, so Frigate disables thinking for these calls when the model exposes a per-request toggle.
|
|
||||||
- **Chat** lets you toggle thinking on or off from the composer when the configured model supports it.
|
|
||||||
|
|
||||||
You can use a pure instruct, hybrid, or thinking-capable model with Frigate. No extra configuration is required to disable thinking for descriptions.
|
|
||||||
|
|
||||||
### llama.cpp
|
|
||||||
|
|
||||||
[llama.cpp](https://github.com/ggml-org/llama.cpp) is a C++ implementation of LLaMA that provides a high-performance inference server.
|
|
||||||
|
|
||||||
It is highly recommended to host the llama.cpp server on a machine with a discrete graphics card, or on an Apple silicon Mac for best performance.
|
|
||||||
|
|
||||||
#### Supported Models
|
|
||||||
|
|
||||||
You must use a vision capable model with Frigate. The llama.cpp server supports various vision models in GGUF format.
|
|
||||||
|
|
||||||
#### Configuration
|
|
||||||
|
|
||||||
All llama.cpp native options can be passed through `provider_options`, including `temperature`, `top_k`, `top_p`, `min_p`, `repeat_penalty`, `repeat_last_n`, `seed`, `grammar`, and more. See the [llama.cpp server documentation](https://github.com/ggml-org/llama.cpp/blob/master/tools/server/README.md) for a complete list of available parameters.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > Enrichments > Generative AI" />.
|
|
||||||
- Set **Provider** to `llamacpp`
|
|
||||||
- Set **Base URL** to your llama.cpp server address (e.g., `http://localhost:8080`)
|
|
||||||
- Set **Model** to the name of your model
|
|
||||||
- Optionally, under **Provider Options**, set `context_size` to override the context size Frigate detects from the server
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
genai:
|
|
||||||
my_provider:
|
|
||||||
provider: llamacpp
|
|
||||||
base_url: http://localhost:8080
|
|
||||||
model: your-model-name
|
|
||||||
provider_options:
|
|
||||||
context_size: 16000 # Optional, overrides the context size reported by the server.
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
Frigate queries the llama.cpp server for the model's context size at startup and logs it along with the other detected capabilities. If `context_size` is set in `provider_options`, that value is always used instead, even when the server reports its own.
|
|
||||||
|
|
||||||
### Ollama
|
|
||||||
|
|
||||||
[Ollama](https://ollama.com/) allows you to self-host large language models and keep everything running locally. It is highly recommended to host this server on a machine with an Nvidia graphics card, or on a Apple silicon Mac for best performance.
|
|
||||||
|
|
||||||
Most of the 7b parameter 4-bit vision models will fit inside 8GB of VRAM. There is also a [Docker container](https://hub.docker.com/r/ollama/ollama) available.
|
|
||||||
|
|
||||||
Parallel requests also come with some caveats. You will need to set `OLLAMA_NUM_PARALLEL=1` and choose a `OLLAMA_MAX_QUEUE` and `OLLAMA_MAX_LOADED_MODELS` values that are appropriate for your hardware and preferences. See the [Ollama documentation](https://docs.ollama.com/faq#how-does-ollama-handle-concurrent-requests).
|
|
||||||
|
|
||||||
:::tip
|
|
||||||
|
|
||||||
If you are trying to use a single model for Frigate and HomeAssistant, it will need to support vision and tools calling. qwen3-VL supports vision and tools simultaneously in Ollama.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
Note that Frigate will not automatically download the model you specify in your config. Ollama will try to download the model but it may take longer than the timeout, so it is recommended to pull the model beforehand by running `ollama pull your_model` on your Ollama server/Docker container. The model specified in Frigate's config must match the downloaded model tag.
|
|
||||||
|
|
||||||
#### Configuration
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > Enrichments > Generative AI" />.
|
|
||||||
- Set **Provider** to `ollama`
|
|
||||||
- Set **Base URL** to your Ollama server address (e.g., `http://localhost:11434`)
|
|
||||||
- Set **Model** to the model tag (e.g., `qwen3-vl:4b`)
|
|
||||||
- Under **Provider Options**, set `keep_alive` (e.g., `-1`) and `options.num_ctx` to match your desired context size
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
genai:
|
|
||||||
my_provider:
|
|
||||||
provider: ollama
|
|
||||||
base_url: http://localhost:11434
|
|
||||||
model: qwen3-vl:4b
|
|
||||||
provider_options: # other Ollama client options can be defined
|
|
||||||
keep_alive: -1
|
|
||||||
options:
|
|
||||||
num_ctx: 8192 # make sure the context matches other services that are using ollama
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### OpenAI-Compatible
|
|
||||||
|
|
||||||
Frigate supports any provider that implements the OpenAI API standard. This includes self-hosted solutions like [vLLM](https://docs.vllm.ai/), [LocalAI](https://localai.io/), and other OpenAI-compatible servers.
|
|
||||||
|
|
||||||
:::tip
|
|
||||||
|
|
||||||
For OpenAI-compatible servers (such as llama.cpp) that don't expose the configured context size in the API response, you can manually specify the context size in `provider_options`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
genai:
|
|
||||||
my_provider:
|
|
||||||
provider: openai
|
|
||||||
base_url: http://your-llama-server
|
|
||||||
model: your-model-name
|
|
||||||
provider_options:
|
|
||||||
context_size: 8192 # Specify the configured context size
|
|
||||||
```
|
|
||||||
|
|
||||||
This ensures Frigate uses the correct context window size when generating prompts.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
#### Configuration
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > Enrichments > Generative AI" />.
|
|
||||||
- Set **Provider** to `openai`
|
|
||||||
- Set **Base URL** to your server address (e.g., `http://your-server:port`)
|
|
||||||
- Set **API key** if required by your server
|
|
||||||
- Set **Model** to the model name
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
genai:
|
|
||||||
my_provider:
|
|
||||||
provider: openai
|
|
||||||
base_url: http://your-server:port
|
|
||||||
api_key: your-api-key # May not be required for local servers
|
|
||||||
model: your-model-name
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
To use a different OpenAI-compatible API endpoint, set the `OPENAI_BASE_URL` environment variable to your provider's API URL.
|
|
||||||
|
|
||||||
## Cloud Providers
|
|
||||||
|
|
||||||
Cloud providers run on remote infrastructure and require an API key for authentication. These services handle all model inference on their servers.
|
|
||||||
|
|
||||||
:::info
|
|
||||||
|
|
||||||
Cloud Generative AI providers require an active internet connection to send images and prompts for processing. Local providers like llama.cpp and Ollama (with local models) do not require internet. See [Network Requirements](/frigate/network_requirements#generative-ai) for details.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Ollama Cloud
|
|
||||||
|
|
||||||
Ollama also supports [cloud models](https://ollama.com/cloud), where model inference is performed in the cloud. You can connect directly to Ollama Cloud by setting `base_url` to `https://ollama.com` and providing an API key. Alternatively, you can run Ollama locally and use a cloud model name so your local instance forwards requests to the cloud. For more details, see the Ollama cloud model [docs](https://docs.ollama.com/cloud).
|
|
||||||
|
|
||||||
#### Configuration
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > Enrichments > Generative AI" />.
|
|
||||||
- Set **Provider** to `ollama`
|
|
||||||
- Set **Base URL** to your local Ollama address (e.g., `http://localhost:11434`) or `https://ollama.com` for direct cloud inference
|
|
||||||
- Set **API key** if required by your endpoint (e.g., when using `https://ollama.com`)
|
|
||||||
- Set **Model** to the cloud model name
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
genai:
|
|
||||||
my_provider:
|
|
||||||
provider: ollama
|
|
||||||
base_url: http://localhost:11434
|
|
||||||
model: cloud-model-name
|
|
||||||
```
|
|
||||||
|
|
||||||
or when using Ollama Cloud directly
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
genai:
|
|
||||||
my_provider:
|
|
||||||
provider: ollama
|
|
||||||
base_url: https://ollama.com
|
|
||||||
model: cloud-model-name
|
|
||||||
api_key: your-api-key
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
### Google Gemini
|
|
||||||
|
|
||||||
Google Gemini has a [free tier](https://ai.google.dev/pricing) for the API, however the limits may not be sufficient for standard Frigate usage. Choose a plan appropriate for your installation.
|
|
||||||
|
|
||||||
#### Supported Models
|
|
||||||
|
|
||||||
You must use a vision capable model with Frigate. Current model variants can be found [in their documentation](https://ai.google.dev/gemini-api/docs/models/gemini).
|
|
||||||
|
|
||||||
#### Get API Key
|
|
||||||
|
|
||||||
To start using Gemini, you must first get an API key from [Google AI Studio](https://aistudio.google.com).
|
|
||||||
|
|
||||||
1. Accept the Terms of Service
|
|
||||||
2. Click "Get API Key" from the right hand navigation
|
|
||||||
3. Click "Create API key in new project"
|
|
||||||
4. Copy the API key for use in your config
|
|
||||||
|
|
||||||
#### Configuration
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > Enrichments > Generative AI" />.
|
|
||||||
- Set **Provider** to `gemini`
|
|
||||||
- Set **API key** to your Gemini API key (or use an environment variable such as `{FRIGATE_GEMINI_API_KEY}`)
|
|
||||||
- Set **Model** to the desired model (e.g., `gemini-2.5-flash`)
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
genai:
|
|
||||||
my_provider:
|
|
||||||
provider: gemini
|
|
||||||
api_key: "{FRIGATE_GEMINI_API_KEY}"
|
|
||||||
model: gemini-2.5-flash
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
To use a different Gemini-compatible API endpoint, set the `provider_options` with the `base_url` key to your provider's API URL. For example:
|
|
||||||
|
|
||||||
```yaml {5,6}
|
|
||||||
genai:
|
|
||||||
my_provider:
|
|
||||||
provider: gemini
|
|
||||||
...
|
|
||||||
provider_options:
|
|
||||||
base_url: https://...
|
|
||||||
```
|
|
||||||
|
|
||||||
Other HTTP options are available, see the [python-genai documentation](https://github.com/googleapis/python-genai).
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
### OpenAI
|
|
||||||
|
|
||||||
OpenAI does not have a free tier for their API.
|
|
||||||
|
|
||||||
#### Supported Models
|
|
||||||
|
|
||||||
You must use a vision capable model with Frigate. Current model variants can be found [in their documentation](https://platform.openai.com/docs/models).
|
|
||||||
|
|
||||||
#### Get API Key
|
|
||||||
|
|
||||||
To start using OpenAI, you must first [create an API key](https://platform.openai.com/api-keys) and [configure billing](https://platform.openai.com/settings/organization/billing/overview).
|
|
||||||
|
|
||||||
#### Configuration
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > Enrichments > Generative AI" />.
|
|
||||||
- Set **Provider** to `openai`
|
|
||||||
- Set **API key** to your OpenAI API key (or use an environment variable such as `{FRIGATE_OPENAI_API_KEY}`)
|
|
||||||
- Set **Model** to the desired model (e.g., `gpt-4o`)
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
genai:
|
|
||||||
my_provider:
|
|
||||||
provider: openai
|
|
||||||
api_key: "{FRIGATE_OPENAI_API_KEY}"
|
|
||||||
model: gpt-4o
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
To use a different OpenAI-compatible API endpoint, set the `OPENAI_BASE_URL` environment variable to your provider's API URL.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
:::tip
|
|
||||||
|
|
||||||
For OpenAI-compatible servers (such as llama.cpp) that don't expose the configured context size in the API response, you can manually specify the context size in `provider_options`:
|
|
||||||
|
|
||||||
```yaml {6,7}
|
|
||||||
genai:
|
|
||||||
my_provider:
|
|
||||||
provider: openai
|
|
||||||
base_url: http://your-llama-server
|
|
||||||
model: your-model-name
|
|
||||||
provider_options:
|
|
||||||
context_size: 8192 # Specify the configured context size
|
|
||||||
```
|
|
||||||
|
|
||||||
This ensures Frigate uses the correct context window size when generating prompts.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
### Azure OpenAI
|
|
||||||
|
|
||||||
Microsoft offers several vision models through Azure OpenAI. A subscription is required.
|
|
||||||
|
|
||||||
#### Supported Models
|
|
||||||
|
|
||||||
You must use a vision capable model with Frigate. Current model variants can be found [in their documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models).
|
|
||||||
|
|
||||||
#### Create Resource and Get API Key
|
|
||||||
|
|
||||||
To start using Azure OpenAI, you must first [create a resource](https://learn.microsoft.com/azure/cognitive-services/openai/how-to/create-resource?pivots=web-portal#create-a-resource). You'll need your API key, model name, and resource URL, which must include the `api-version` parameter (see the example below).
|
|
||||||
|
|
||||||
#### Configuration
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
1. Navigate to <NavPath path="Settings > Enrichments > Generative AI" />.
|
|
||||||
- Set **Provider** to `azure_openai`
|
|
||||||
- Set **Base URL** to your Azure resource URL including the `api-version` parameter (e.g., `https://instance.cognitiveservices.azure.com/openai/responses?api-version=2025-04-01-preview`)
|
|
||||||
- Set **Model** to your deployed model name (e.g., `gpt-5-mini`)
|
|
||||||
- Set **API key** to your Azure OpenAI API key (or use an environment variable such as `{FRIGATE_OPENAI_API_KEY}`)
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
genai:
|
|
||||||
my_provider:
|
|
||||||
provider: azure_openai
|
|
||||||
base_url: https://instance.cognitiveservices.azure.com/openai/responses?api-version=2025-04-01-preview
|
|
||||||
model: gpt-5-mini
|
|
||||||
api_key: "{FRIGATE_OPENAI_API_KEY}"
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
## FAQ
|
|
||||||
|
|
||||||
<FaqItem id="how-do-i-debug-genai-issues" question="How do I debug GenAI issues?">
|
|
||||||
|
|
||||||
Frigate's Generative AI features are configured and enabled separately. [Review descriptions and summaries](/configuration/genai/genai_review) live under `review.genai`, and [object descriptions](/configuration/genai/genai_objects) live under `objects.genai`. Configuring a provider on this page does not enable either feature, and enabling one does not enable the other. Decide which of the two is not working, then work through the steps below.
|
|
||||||
|
|
||||||
1. Confirm a provider is available and holds the `descriptions` role.
|
|
||||||
- Review descriptions, review summaries, and object descriptions all use the provider that has the `descriptions` role assigned in <NavPath path="Settings > Enrichments > Generative AI > Roles" /> (`genai.<provider>.roles`).
|
|
||||||
- A provider is contacted the first time one of its roles is actually used. A provider holding the `embeddings` role for semantic search is initialized during startup, while a `descriptions` provider is not initialized until the first description is requested, which may be well after boot.
|
|
||||||
- In <NavPath path="Settings > Enrichments > Generative AI" />, use **Refresh models** next to the model field. It queries the provider for its model list and is a quick way to verify that the base URL, API key, and network path between Frigate and your provider are correct.
|
|
||||||
|
|
||||||
2. Confirm the feature you expect is actually enabled.
|
|
||||||
- Object descriptions are disabled by default. Turn on <NavPath path="Settings > Global configuration > Objects > GenAI object config > Enable GenAI" /> (`objects.genai.enabled`), either globally or per camera. This is the most common reason custom prompts appear to be ignored while review summaries are still being generated.
|
|
||||||
- Review descriptions are disabled by default. Turn on <NavPath path="Settings > Global configuration > Review > GenAI config > Enable GenAI descriptions" /> (`review.genai.enabled`). Once enabled, alerts are described by default but detections are not, so a detection-only review item will never get a summary unless **Enable GenAI for detections** (`review.genai.detections`) is also on.
|
|
||||||
|
|
||||||
3. If object descriptions are never requested, check the filters that skip generation.
|
|
||||||
- <NavPath path="Settings > Global configuration > Objects > GenAI object config > GenAI objects" /> (`objects.genai.objects`) limits generation to specific labels, and **Required zones** (`objects.genai.required_zones`) requires the object to have entered one of those zones. If either is set and does not match, Frigate skips the request silently.
|
|
||||||
- Thumbnails are only collected while an object is moving. Objects that go stationary early contribute fewer frames.
|
|
||||||
- **Use snapshots** (`objects.genai.use_snapshot`) requires snapshots to be enabled for the camera. If the snapshot cannot be read, Frigate logs `Cannot load snapshot for <id>, file not found` and no description is generated.
|
|
||||||
- **Send on end** (`objects.genai.send_triggers.tracked_object_end`) is on by default. If you have turned it off in favor of **Early GenAI trigger** (`objects.genai.send_triggers.after_significant_updates`), descriptions are only requested once that number of updates is reached.
|
|
||||||
|
|
||||||
4. Enable debug logs to see exactly what Frigate is doing. Restart Frigate after this change. The next step also requires a restart, so turn both on at the same time to avoid restarting twice.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
logger:
|
|
||||||
default: info
|
|
||||||
logs:
|
|
||||||
# highlight-start
|
|
||||||
frigate.genai: debug
|
|
||||||
frigate.data_processing.post.object_descriptions: debug
|
|
||||||
frigate.data_processing.post.review_descriptions: debug
|
|
||||||
# highlight-end
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Save the exact images and prompts that were sent to your provider.
|
|
||||||
- Turn on **Save thumbnails** for the feature you are debugging (`review.genai.debug_save_thumbnails` or `objects.genai.debug_save_thumbnails`). Both features write to `/media/frigate/clips/genai-requests/`, and these files are admin-only.
|
|
||||||
- Review descriptions write `genai-requests/<review_id>/` containing the numbered frames that were sent, plus `prompt.txt` and `response.txt` with the exact prompt and the raw, unparsed model response.
|
|
||||||
- Review summary reports write `genai-requests/<start_ts>-<end_ts>/prompt.txt` and `response.txt`. No images are involved, since a report summarizes existing review descriptions.
|
|
||||||
- Object descriptions write `genai-requests/<event_id>/` containing the numbered thumbnails. The prompt for object descriptions is not written to a file, it is only visible in the debug logs from step 4.
|
|
||||||
- Look at the saved images before blaming the model. If the object is small, blurry, or out of frame, no prompt will fix the result. For object descriptions, consider turning on **Use snapshots** (`objects.genai.use_snapshot`) to send a higher quality image. For review items, consider setting **Review image source** (`review.genai.image_source`) to `recordings` for 480p frames instead of the lower resolution preview frames.
|
|
||||||
|
|
||||||
<ConfigTabs>
|
|
||||||
<TabItem value="ui">
|
|
||||||
|
|
||||||
For review descriptions, navigate to <NavPath path="Settings > Global configuration > Review" /> and set **GenAI config > Save thumbnails** to on.
|
|
||||||
|
|
||||||
For object descriptions, navigate to <NavPath path="Settings > Global configuration > Objects" />, expand **GenAI object config**, and set **Save thumbnails** to on.
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
<TabItem value="yaml">
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
review:
|
|
||||||
genai:
|
|
||||||
enabled: true
|
|
||||||
# highlight-next-line
|
|
||||||
debug_save_thumbnails: true
|
|
||||||
|
|
||||||
objects:
|
|
||||||
genai:
|
|
||||||
enabled: true
|
|
||||||
# highlight-next-line
|
|
||||||
debug_save_thumbnails: true
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</ConfigTabs>
|
|
||||||
|
|
||||||
6. Verify the prompt is what you think it is.
|
|
||||||
- Object description prompts are the ones you control directly. A camera-level <NavPath path="Settings > Camera configuration > Objects > GenAI object config > Caption prompt" /> (`objects.genai.prompt`) overrides the global one, and an entry in **Object prompts** (`objects.genai.object_prompts`) for a label overrides both for that label. Only `{label}`, `{sub_label}`, and `{camera}` are substituted.
|
|
||||||
- Review description prompts are built by Frigate and request a structured JSON response, so they are not fully replaceable. The parts you control are <NavPath path="Settings > Global configuration > Review > GenAI config > Activity context prompt" /> (`review.genai.activity_context_prompt`) and **Additional concerns** (`review.genai.additional_concerns`). Keep the activity context prompt general, since overly specific rules will sway the model's threat level scoring.
|
|
||||||
|
|
||||||
7. If descriptions are generated but the results are poor or inconsistent, look at the model and the context window.
|
|
||||||
- Empty fields, missing `shortSummary` values, or `Failed to parse review description` errors usually mean the model is not following the requested JSON schema. Smaller models struggle with structured output. Try a larger parameter size or one of the [recommended models](#recommended-local-models).
|
|
||||||
- Frigate calculates how many frames to send from the context size the provider reports. If your server reports a different value than it is actually running with, frames will be truncated or the request will fail. Pin the value by adding `context_size` under <NavPath path="Settings > Enrichments > Generative AI > Provider options" /> (`genai.<provider>.provider_options`), and for Ollama also confirm `options.num_ctx` there matches the context you have configured.
|
|
||||||
- Check **Review Description Speed** and **Object Description Speed** in <NavPath path="System metrics > Enrichments" />. If inference takes tens of seconds, requests will queue behind each other and descriptions will appear to stop. For Ollama, review `OLLAMA_NUM_PARALLEL`, `OLLAMA_MAX_QUEUE`, and `OLLAMA_MAX_LOADED_MODELS` so that concurrent requests from Frigate are handled the way you expect.
|
|
||||||
|
|
||||||
</FaqItem>
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user