Compare commits

..

No commits in common. "master" and "v0.15.0-beta3" have entirely different histories.

1336 changed files with 16744 additions and 116050 deletions

View File

@ -2,7 +2,6 @@ aarch
absdiff absdiff
airockchip airockchip
Alloc Alloc
alpr
Amcrest Amcrest
amdgpu amdgpu
analyzeduration analyzeduration
@ -44,7 +43,6 @@ codeproject
colormap colormap
colorspace colorspace
comms comms
cooldown
coro coro
ctypeslib ctypeslib
CUDA CUDA
@ -63,7 +61,6 @@ dsize
dtype dtype
ECONNRESET ECONNRESET
edgetpu edgetpu
facenet
fastapi fastapi
faststart faststart
fflags fflags
@ -108,8 +105,8 @@ imagestream
imdecode imdecode
imencode imencode
imread imread
imutils
imwrite imwrite
inpoint
interp interp
iostat iostat
iotop iotop
@ -117,8 +114,6 @@ itemsize
Jellyfin Jellyfin
jetson jetson
jetsons jetsons
jina
jinaai
joserfc joserfc
jsmpeg jsmpeg
jsonify jsonify
@ -192,7 +187,6 @@ openai
opencv opencv
openvino openvino
OWASP OWASP
paddleocr
paho paho
passwordless passwordless
popleft popleft
@ -265,7 +259,6 @@ tensorrt
tflite tflite
thresholded thresholded
timelapse timelapse
titlecase
tmpfs tmpfs
tobytes tobytes
toggleable toggleable

View File

@ -8,25 +8,9 @@
"overrideCommand": false, "overrideCommand": false,
"remoteUser": "vscode", "remoteUser": "vscode",
"features": { "features": {
"ghcr.io/devcontainers/features/common-utils:2": {} "ghcr.io/devcontainers/features/common-utils:1": {}
// Uncomment the following lines to use ONNX Runtime with CUDA support
// "ghcr.io/devcontainers/features/nvidia-cuda:1": {
// "installCudnn": true,
// "installNvtx": true,
// "installToolkit": true,
// "cudaVersion": "12.5",
// "cudnnVersion": "9.4.0.58"
// },
// "./features/onnxruntime-gpu": {}
}, },
"forwardPorts": [ "forwardPorts": [8971, 5000, 5001, 5173, 8554, 8555],
8971,
5000,
5001,
5173,
8554,
8555
],
"portsAttributes": { "portsAttributes": {
"8971": { "8971": {
"label": "External NGINX", "label": "External NGINX",
@ -80,18 +64,10 @@
"editor.formatOnType": true, "editor.formatOnType": true,
"python.testing.pytestEnabled": false, "python.testing.pytestEnabled": false,
"python.testing.unittestEnabled": true, "python.testing.unittestEnabled": true,
"python.testing.unittestArgs": [ "python.testing.unittestArgs": ["-v", "-s", "./frigate/test"],
"-v",
"-s",
"./frigate/test"
],
"files.trimTrailingWhitespace": true, "files.trimTrailingWhitespace": true,
"eslint.workingDirectories": [ "eslint.workingDirectories": ["./web"],
"./web" "isort.args": ["--settings-path=./pyproject.toml"],
],
"isort.args": [
"--settings-path=./pyproject.toml"
],
"[python]": { "[python]": {
"editor.defaultFormatter": "charliermarsh.ruff", "editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true, "editor.formatOnSave": true,
@ -110,15 +86,8 @@
], ],
"editor.tabSize": 2 "editor.tabSize": 2
}, },
"cSpell.ignoreWords": [ "cSpell.ignoreWords": ["rtmp"],
"rtmp" "cSpell.words": ["preact", "astype", "hwaccel", "mqtt"]
],
"cSpell.words": [
"preact",
"astype",
"hwaccel",
"mqtt"
]
} }
} }
} }

View File

@ -1,22 +0,0 @@
{
"id": "onnxruntime-gpu",
"version": "0.0.1",
"name": "ONNX Runtime GPU (Nvidia)",
"description": "Installs ONNX Runtime for Nvidia GPUs.",
"documentationURL": "",
"options": {
"version": {
"type": "string",
"proposals": [
"latest",
"1.20.1",
"1.20.0"
],
"default": "latest",
"description": "Version of ONNX Runtime to install"
}
},
"installsAfter": [
"ghcr.io/devcontainers/features/nvidia-cuda"
]
}

View File

@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -e
VERSION=${VERSION}
python3 -m pip config set global.break-system-packages true
# if VERSION == "latest" or VERSION is empty, install the latest version
if [ "$VERSION" == "latest" ] || [ -z "$VERSION" ]; then
python3 -m pip install onnxruntime-gpu
else
python3 -m pip install onnxruntime-gpu==$VERSION
fi
echo "Done!"

View File

@ -19,7 +19,7 @@ sudo chown -R "$(id -u):$(id -g)" /media/frigate
# When started as a service, LIBAVFORMAT_VERSION_MAJOR is defined in the # When started as a service, LIBAVFORMAT_VERSION_MAJOR is defined in the
# s6 service file. For dev, where frigate is started from an interactive # s6 service file. For dev, where frigate is started from an interactive
# shell, we define it in .bashrc instead. # shell, we define it in .bashrc instead.
echo 'export LIBAVFORMAT_VERSION_MAJOR=$("$(python3 /usr/local/ffmpeg/get_ffmpeg_path.py)" -version | grep -Po "libavformat\W+\K\d+")' >> "$HOME/.bashrc" echo 'export LIBAVFORMAT_VERSION_MAJOR=$(/usr/lib/ffmpeg/7.0/bin/ffmpeg -version | grep -Po "libavformat\W+\K\d+")' >> $HOME/.bashrc
make version make version

View File

@ -73,7 +73,7 @@ body:
attributes: attributes:
label: Operating system label: Operating system
options: options:
- Home Assistant OS - HassOS
- Debian - Debian
- Other Linux - Other Linux
- Proxmox - Proxmox
@ -87,7 +87,7 @@ body:
attributes: attributes:
label: Install method label: Install method
options: options:
- Home Assistant Add-on - HassOS Addon
- Docker Compose - Docker Compose
- Docker CLI - Docker CLI
- Proxmox via Docker - Proxmox via Docker

View File

@ -59,7 +59,7 @@ body:
attributes: attributes:
label: Operating system label: Operating system
options: options:
- Home Assistant OS - HassOS
- Debian - Debian
- Other Linux - Other Linux
- Proxmox - Proxmox
@ -73,7 +73,7 @@ body:
attributes: attributes:
label: Install method label: Install method
options: options:
- Home Assistant Add-on - HassOS Addon
- Docker Compose - Docker Compose
- Docker CLI - Docker CLI
- Proxmox via Docker - Proxmox via Docker

View File

@ -53,7 +53,7 @@ body:
attributes: attributes:
label: Install method label: Install method
options: options:
- Home Assistant Add-on - HassOS Addon
- Docker Compose - Docker Compose
- Docker CLI - Docker CLI
- Proxmox via Docker - Proxmox via Docker

View File

@ -73,7 +73,7 @@ body:
attributes: attributes:
label: Install method label: Install method
options: options:
- Home Assistant Add-on - HassOS Addon
- Docker Compose - Docker Compose
- Docker CLI - Docker CLI
- Proxmox via Docker - Proxmox via Docker

View File

@ -69,7 +69,7 @@ body:
attributes: attributes:
label: Install method label: Install method
options: options:
- Home Assistant Add-on - HassOS Addon
- Docker Compose - Docker Compose
- Docker CLI - Docker CLI
- Proxmox via Docker - Proxmox via Docker

View File

@ -97,7 +97,7 @@ body:
attributes: attributes:
label: Operating system label: Operating system
options: options:
- Home Assistant OS - HassOS
- Debian - Debian
- Other Linux - Other Linux
- Proxmox - Proxmox
@ -111,7 +111,7 @@ body:
attributes: attributes:
label: Install method label: Install method
options: options:
- Home Assistant Add-on - HassOS Addon
- Docker Compose - Docker Compose
- Docker CLI - Docker CLI
validations: validations:

View File

@ -33,9 +33,9 @@ runs:
with: with:
string: ${{ github.repository }} string: ${{ github.repository }}
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v3 uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v2
- name: Log in to the Container registry - name: Log in to the Container registry
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc
with: with:

View File

@ -1,11 +1,5 @@
## Proposed change ## Proposed change
<!-- <!--
Thank you!
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
Frigate's development goals.
Describe what this pull request does and how it will benefit users of Frigate. 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 Please describe in detail any considerations, breaking changes, etc. that are
made in this pull request. made in this pull request.
@ -35,5 +29,4 @@
- [ ] 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.
- [ ] 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`)

View File

@ -7,7 +7,7 @@ on:
- dev - dev
- master - master
paths-ignore: paths-ignore:
- "docs/**" - 'docs/**'
# only run the latest commit to avoid cache overwrites # only run the latest commit to avoid cache overwrites
concurrency: concurrency:
@ -19,13 +19,11 @@ env:
jobs: jobs:
amd64_build: amd64_build:
runs-on: ubuntu-22.04 runs-on: ubuntu-latest
name: AMD64 Build name: AMD64 Build
steps: steps:
- name: Check out code - name: Check out code
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up QEMU and Buildx - name: Set up QEMU and Buildx
id: setup id: setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
@ -41,15 +39,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-latest
name: ARM Build name: ARM Build
steps: steps:
- name: Check out code - name: Check out code
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up QEMU and Buildx - name: Set up QEMU and Buildx
id: setup id: setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
@ -67,9 +62,8 @@ 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@v6 uses: docker/bake-action@v4
with: with:
source: .
push: true push: true
targets: rpi targets: rpi
files: docker/rpi/rpi.hcl files: docker/rpi/rpi.hcl
@ -77,15 +71,47 @@ 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
- name: Build and push Rockchip build
uses: docker/bake-action@v3
with:
push: true
targets: rk
files: docker/rockchip/rk.hcl
set: |
rk.tags=${{ steps.setup.outputs.image-name }}-rk
*.cache-from=type=gha
jetson_jp4_build:
runs-on: ubuntu-latest
name: Jetson Jetpack 4
steps:
- name: Check out code
uses: actions/checkout@v4
- 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 4)
env:
ARCH: arm64
BASE_IMAGE: timongentzsch/l4t-ubuntu20-opencv:latest
SLIM_BASE: timongentzsch/l4t-ubuntu20-opencv:latest
TRT_BASE: timongentzsch/l4t-ubuntu20-opencv:latest
uses: docker/bake-action@v4
with:
push: true
targets: tensorrt
files: docker/tensorrt/trt.hcl
set: |
tensorrt.tags=${{ steps.setup.outputs.image-name }}-tensorrt-jp4
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-jp4
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-jp4,mode=max
jetson_jp5_build: jetson_jp5_build:
if: false runs-on: ubuntu-latest
runs-on: ubuntu-22.04
name: Jetson Jetpack 5 name: Jetson Jetpack 5
steps: steps:
- name: Check out code - name: Check out code
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up QEMU and Buildx - name: Set up QEMU and Buildx
id: setup id: setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
@ -97,9 +123,8 @@ jobs:
BASE_IMAGE: nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime BASE_IMAGE: nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime
SLIM_BASE: 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 TRT_BASE: nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime
uses: docker/bake-action@v6 uses: docker/bake-action@v4
with: with:
source: .
push: true push: true
targets: tensorrt targets: tensorrt
files: docker/tensorrt/trt.hcl files: docker/tensorrt/trt.hcl
@ -107,45 +132,14 @@ jobs:
tensorrt.tags=${{ steps.setup.outputs.image-name }}-tensorrt-jp5 tensorrt.tags=${{ steps.setup.outputs.image-name }}-tensorrt-jp5
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-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 *.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-jp5,mode=max
jetson_jp6_build:
runs-on: ubuntu-22.04-arm
name: Jetson Jetpack 6
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 6)
env:
ARCH: arm64
BASE_IMAGE: 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
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-jp6
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-jp6
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-jp6,mode=max
amd64_extra_builds: amd64_extra_builds:
runs-on: ubuntu-22.04 runs-on: ubuntu-latest
name: AMD64 Extra Build name: AMD64 Extra Build
needs: needs:
- amd64_build - amd64_build
steps: steps:
- name: Check out code - name: Check out code
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up QEMU and Buildx - name: Set up QEMU and Buildx
id: setup id: setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
@ -154,59 +148,77 @@ 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@v6 uses: docker/bake-action@v4
with: with:
source: .
push: true push: true
targets: tensorrt targets: tensorrt
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
env:
AMDGPU: gfx
HSA_OVERRIDE: 0
uses: docker/bake-action@v6
with:
source: .
push: true
targets: rocm
files: docker/rocm/rocm.hcl
set: |
rocm.tags=${{ steps.setup.outputs.image-name }}-rocm
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-rocm,mode=max
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-rocm
arm64_extra_builds: arm64_extra_builds:
runs-on: ubuntu-22.04-arm runs-on: ubuntu-latest
name: ARM Extra Build name: ARM Extra Build
needs: needs:
- arm64_build - arm64_build
steps: steps:
- name: Check out code - name: Check out code
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up QEMU and Buildx - name: Set up QEMU and Buildx
id: setup id: setup
uses: ./.github/actions/setup uses: ./.github/actions/setup
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@v6 uses: docker/bake-action@v3
with: with:
source: .
push: true push: true
targets: rk targets: rk
files: docker/rockchip/rk.hcl files: docker/rockchip/rk.hcl
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
combined_extra_builds:
runs-on: ubuntu-latest
name: Combined Extra Builds
needs:
- amd64_build
- arm64_build
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up QEMU and Buildx
id: setup
uses: ./.github/actions/setup
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Hailo-8l build
uses: docker/bake-action@v4
with:
push: true
targets: h8l
files: docker/hailo8l/h8l.hcl
set: |
h8l.tags=${{ steps.setup.outputs.image-name }}-h8l
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-h8l
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-h8l,mode=max
- name: AMD/ROCm general build
env:
AMDGPU: gfx
HSA_OVERRIDE: 0
uses: docker/bake-action@v3
with:
push: true
targets: rocm
files: docker/rocm/rocm.hcl
set: |
rocm.tags=${{ steps.setup.outputs.image-name }}-rocm
*.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:
runs-on: ubuntu-22.04 runs-on: ubuntu-latest
name: Assemble and push default build name: Assemble and push default build
needs: needs:
- amd64_build - amd64_build

View File

@ -0,0 +1,24 @@
name: dependabot-auto-merge
on: pull_request
permissions:
contents: write
jobs:
dependabot-auto-merge:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- name: Get Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable auto-merge for Dependabot PRs
if: steps.metadata.outputs.dependency-type == 'direct:development' && (steps.metadata.outputs.update-type == 'version-update:semver-minor' || steps.metadata.outputs.update-type == 'version-update:semver-patch')
run: |
gh pr review --approve "$PR_URL"
gh pr merge --auto --squash "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -3,11 +3,10 @@ name: On pull request
on: on:
pull_request: pull_request:
paths-ignore: paths-ignore:
- "docs/**" - 'docs/**'
- ".github/**"
env: env:
DEFAULT_PYTHON: 3.11 DEFAULT_PYTHON: 3.9
jobs: jobs:
build_devcontainer: build_devcontainer:
@ -20,11 +19,9 @@ jobs:
DOCKER_BUILDKIT: "1" DOCKER_BUILDKIT: "1"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-node@master - uses: actions/setup-node@master
with: with:
node-version: 20.x node-version: 16.x
- name: Install devcontainer cli - name: Install devcontainer cli
run: npm install --global @devcontainers/cli run: npm install --global @devcontainers/cli
- name: Build devcontainer - name: Build devcontainer
@ -41,8 +38,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-node@master - uses: actions/setup-node@master
with: with:
node-version: 16.x node-version: 16.x
@ -57,16 +52,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-node@master - uses: actions/setup-node@master
with: with:
node-version: 20.x node-version: 20.x
- run: npm install - run: npm install
working-directory: ./web working-directory: ./web
- name: Build web
run: npm run build
working-directory: ./web
# - name: Test # - name: Test
# run: npm run test # run: npm run test
# working-directory: ./web # working-directory: ./web
@ -77,10 +67,8 @@ jobs:
steps: steps:
- name: Check out the repository - name: Check out the repository
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Python ${{ env.DEFAULT_PYTHON }} - name: Set up Python ${{ env.DEFAULT_PYTHON }}
uses: actions/setup-python@v5.4.0 uses: actions/setup-python@v5.1.0
with: with:
python-version: ${{ env.DEFAULT_PYTHON }} python-version: ${{ env.DEFAULT_PYTHON }}
- name: Install requirements - name: Install requirements
@ -100,8 +88,14 @@ jobs:
steps: steps:
- name: Check out code - name: Check out code
uses: actions/checkout@v4 uses: actions/checkout@v4
- uses: actions/setup-node@master
with: with:
persist-credentials: false node-version: 16.x
- run: npm install
working-directory: ./web
- name: Build web
run: npm run build
working-directory: ./web
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v3 uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx - name: Set up Docker Buildx

View File

@ -11,8 +11,6 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
persist-credentials: false
- id: lowercaseRepo - id: lowercaseRepo
uses: ASzc/change-string-case-action@v6 uses: ASzc/change-string-case-action@v6
with: with:
@ -24,13 +22,10 @@ jobs:
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Create tag variables - name: Create tag variables
env:
TAG: ${{ github.ref_name }}
LOWERCASE_REPO: ${{ steps.lowercaseRepo.outputs.lowercase }}
run: | run: |
BUILD_TYPE=$([[ "${TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] && echo "stable" || echo "beta") BUILD_TYPE=$([[ "${{ github.ref_name }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] && echo "stable" || echo "beta")
echo "BUILD_TYPE=${BUILD_TYPE}" >> $GITHUB_ENV echo "BUILD_TYPE=${BUILD_TYPE}" >> $GITHUB_ENV
echo "BASE=ghcr.io/${LOWERCASE_REPO}" >> $GITHUB_ENV echo "BASE=ghcr.io/${{ steps.lowercaseRepo.outputs.lowercase }}" >> $GITHUB_ENV
echo "BUILD_TAG=${GITHUB_SHA::7}" >> $GITHUB_ENV echo "BUILD_TAG=${GITHUB_SHA::7}" >> $GITHUB_ENV
echo "CLEAN_VERSION=$(echo ${GITHUB_REF##*/} | tr '[:upper:]' '[:lower:]' | sed 's/^[v]//')" >> $GITHUB_ENV echo "CLEAN_VERSION=$(echo ${GITHUB_REF##*/} | tr '[:upper:]' '[:lower:]' | sed 's/^[v]//')" >> $GITHUB_ENV
- name: Tag and push the main image - name: Tag and push the main image
@ -39,14 +34,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; do for variant in standard-arm64 tensorrt tensorrt-jp4 tensorrt-jp5 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; do for variant in standard-arm64 tensorrt tensorrt-jp4 tensorrt-jp5 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

View File

@ -23,9 +23,7 @@ jobs:
exempt-pr-labels: "pinned,security,dependencies" exempt-pr-labels: "pinned,security,dependencies"
operations-per-run: 120 operations-per-run: 120
- name: Print outputs - name: Print outputs
env: run: echo ${{ join(steps.stale.outputs.*, ',') }}
STALE_OUTPUT: ${{ join(steps.stale.outputs.*, ',') }}
run: echo "$STALE_OUTPUT"
# clean_ghcr: # clean_ghcr:
# name: Delete outdated dev container images # name: Delete outdated dev container images
@ -40,3 +38,4 @@ jobs:
# account-type: personal # account-type: personal
# token: ${{ secrets.GITHUB_TOKEN }} # token: ${{ secrets.GITHUB_TOKEN }}
# token-type: github-token # token-type: github-token

View File

@ -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.16.1 VERSION = 0.15.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

View File

@ -4,15 +4,9 @@
# Frigate - NVR With Realtime Object Detection for IP Cameras # Frigate - NVR With Realtime Object Detection for IP Cameras
<a href="https://hosted.weblate.org/engage/frigate-nvr/">
<img src="https://hosted.weblate.org/widget/frigate-nvr/language-badge.svg" alt="Translation status" />
</a>
\[English\] | [简体中文](https://github.com/blakeblackshear/frigate/blob/dev/README_CN.md)
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 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. Use of a [Google Coral Accelerator](https://coral.ai/products/) is optional, but highly recommended. The Coral will outperform even the best CPUs and can process 100+ FPS with very little overhead.
- 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
@ -36,33 +30,21 @@ If you would like to make a donation to support development, please use [Github
## Screenshots ## Screenshots
### Live dashboard ### Live dashboard
<div> <div>
<img width="800" alt="Live dashboard" src="https://github.com/blakeblackshear/frigate/assets/569905/5e713cb9-9db5-41dc-947a-6937c3bc376e"> <img width="800" alt="Live dashboard" src="https://github.com/blakeblackshear/frigate/assets/569905/5e713cb9-9db5-41dc-947a-6937c3bc376e">
</div> </div>
### Streamlined review workflow ### Streamlined review workflow
<div> <div>
<img width="800" alt="Streamlined review workflow" src="https://github.com/blakeblackshear/frigate/assets/569905/6fed96e8-3b18-40e5-9ddc-31e6f3c9f2ff"> <img width="800" alt="Streamlined review workflow" src="https://github.com/blakeblackshear/frigate/assets/569905/6fed96e8-3b18-40e5-9ddc-31e6f3c9f2ff">
</div> </div>
### Multi-camera scrubbing ### Multi-camera scrubbing
<div> <div>
<img width="800" alt="Multi-camera scrubbing" src="https://github.com/blakeblackshear/frigate/assets/569905/d6788a15-0eeb-4427-a8d4-80b93cae3d74"> <img width="800" alt="Multi-camera scrubbing" src="https://github.com/blakeblackshear/frigate/assets/569905/d6788a15-0eeb-4427-a8d4-80b93cae3d74">
</div> </div>
### Built-in mask and zone editor ### Built-in mask and zone editor
<div> <div>
<img width="800" alt="Multi-camera scrubbing" 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
We use [Weblate](https://hosted.weblate.org/projects/frigate-nvr/) to support language translations. Contributions are always welcome.
<a href="https://hosted.weblate.org/engage/frigate-nvr/">
<img src="https://hosted.weblate.org/widget/frigate-nvr/multi-auto.svg" alt="Translation status" />
</a>

View File

@ -1,70 +0,0 @@
<p align="center">
<img align="center" alt="logo" src="docs/static/img/frigate.png">
</p>
# Frigate - 一个具有实时目标检测的本地NVR
[English](https://github.com/blakeblackshear/frigate) | \[简体中文\]
<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="翻译状态" />
</a>
一个完整的本地网络视频录像机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
- 通过MQTT进行通信便于集成到其他系统中
- 根据检测到的物体设置保留时间进行视频录制
- 24/7全天候录制
- 通过RTSP重新流传输以减少摄像头的连接数
- 支持WebRTC和MSE实现低延迟的实时观看
## 社区中文翻译文档
你可以在这里查看文档 https://docs.frigate-cn.video
## 赞助
如果您想通过捐赠支持开发,请使用 [Github Sponsors](https://github.com/sponsors/blakeblackshear)。
## 截图
### 实时监控面板
<div>
<img width="800" alt="实时监控面板" src="https://github.com/blakeblackshear/frigate/assets/569905/5e713cb9-9db5-41dc-947a-6937c3bc376e">
</div>
### 简单的核查工作流程
<div>
<img width="800" alt="简单的审查工作流程" src="https://github.com/blakeblackshear/frigate/assets/569905/6fed96e8-3b18-40e5-9ddc-31e6f3c9f2ff">
</div>
### 多摄像头可按时间轴查看
<div>
<img width="800" alt="多摄像头可按时间轴查看" src="https://github.com/blakeblackshear/frigate/assets/569905/d6788a15-0eeb-4427-a8d4-80b93cae3d74">
</div>
### 内置遮罩和区域编辑器
<div>
<img width="800" alt="内置遮罩和区域编辑器" src="https://github.com/blakeblackshear/frigate/assets/569905/d7885fc3-bfe6-452f-b7d0-d957cb3e31f5">
</div>
## 翻译
我们使用 [Weblate](https://hosted.weblate.org/projects/frigate-nvr/) 平台提供翻译支持,欢迎参与进来一起完善。
## 非官方中文讨论社区
欢迎加入中文讨论QQ群[1043861059](https://qm.qq.com/q/7vQKsTmSz)
Bilibilihttps://space.bilibili.com/3546894915602564
## 中文社区赞助商
[![EdgeOne](https://edgeone.ai/media/34fe3a45-492d-4ea4-ae5d-ea1087ca7b4b.png)](https://edgeone.ai/zh?from=github)
本项目 CDN 加速及安全防护由 Tencent EdgeOne 赞助

View File

@ -6,7 +6,7 @@ import numpy as np
import frigate.util as util 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 import (
ObjectDetectProcess, ObjectDetectProcess,
RemoteObjectDetector, RemoteObjectDetector,
load_labels, load_labels,
@ -61,7 +61,7 @@ def start(id, num_detections, detection_queue, event):
object_detector.cleanup() object_detector.cleanup()
print(f"{id} - Processed for {duration:.2f} seconds.") print(f"{id} - Processed for {duration:.2f} seconds.")
print(f"{id} - FPS: {object_detector.fps.eps():.2f}") print(f"{id} - FPS: {object_detector.fps.eps():.2f}")
print(f"{id} - Average frame processing time: {mean(frame_times) * 1000:.2f}ms") print(f"{id} - Average frame processing time: {mean(frame_times)*1000:.2f}ms")
###### ######

View File

@ -1,8 +1,8 @@
version: "3"
services: services:
devcontainer: devcontainer:
container_name: frigate-devcontainer container_name: frigate-devcontainer
# Check host system's actual render/video/plugdev group IDs with 'getent group render', 'getent group video', and 'getent group plugdev' # add groups from host for render, plugdev, video
# Must add these exact IDs in container's group_add section or OpenVINO GPU acceleration will fail
group_add: group_add:
- "109" # render - "109" # render
- "110" # render - "110" # render
@ -24,8 +24,8 @@ services:
# capabilities: [gpu] # capabilities: [gpu]
environment: environment:
YOLO_MODELS: "" YOLO_MODELS: ""
# devices: devices:
# - /dev/bus/usb:/dev/bus/usb # Uncomment for Google Coral USB - /dev/bus/usb:/dev/bus/usb
# - /dev/dri:/dev/dri # for intel hwaccel, needs to be updated for your hardware # - /dev/dri:/dev/dri # for intel hwaccel, needs to be updated for your hardware
volumes: volumes:
- .:/workspace/frigate:cached - .:/workspace/frigate:cached
@ -33,10 +33,9 @@ services:
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
- ./config:/config - ./config:/config
- ./debug:/media/frigate - ./debug:/media/frigate
# - /dev/bus/usb:/dev/bus/usb # Uncomment for Google Coral USB - /dev/bus/usb:/dev/bus/usb
mqtt: mqtt:
container_name: mqtt container_name: mqtt
image: eclipse-mosquitto:2.0 image: eclipse-mosquitto:1.6
command: mosquitto -c /mosquitto-no-auth.conf # enable no-auth mode
ports: ports:
- "1883:1883" - "1883:1883"

40
docker/hailo8l/Dockerfile Normal file
View File

@ -0,0 +1,40 @@
# syntax=docker/dockerfile:1.6
ARG DEBIAN_FRONTEND=noninteractive
# Build Python wheels
FROM wheels AS h8l-wheels
COPY docker/main/requirements-wheels.txt /requirements-wheels.txt
COPY docker/hailo8l/requirements-wheels-h8l.txt /requirements-wheels-h8l.txt
RUN sed -i "/https:\/\//d" /requirements-wheels.txt
# Create a directory to store the built wheels
RUN mkdir /h8l-wheels
# Build the wheels
RUN pip3 wheel --wheel-dir=/h8l-wheels -c /requirements-wheels.txt -r /requirements-wheels-h8l.txt
FROM wget AS hailort
ARG TARGETARCH
RUN --mount=type=bind,source=docker/hailo8l/install_hailort.sh,target=/deps/install_hailort.sh \
/deps/install_hailort.sh
# Use deps as the base image
FROM deps AS h8l-frigate
# Copy the wheels from the wheels stage
COPY --from=h8l-wheels /h8l-wheels /deps/h8l-wheels
COPY --from=hailort /hailo-wheels /deps/hailo-wheels
COPY --from=hailort /rootfs/ /
# Install the wheels
RUN pip3 install -U /deps/h8l-wheels/*.whl
RUN pip3 install -U /deps/hailo-wheels/*.whl
# Copy base files from the rootfs stage
COPY --from=rootfs / /
# Set workdir
WORKDIR /opt/frigate/

34
docker/hailo8l/h8l.hcl Normal file
View File

@ -0,0 +1,34 @@
target wget {
dockerfile = "docker/main/Dockerfile"
platforms = ["linux/arm64","linux/amd64"]
target = "wget"
}
target wheels {
dockerfile = "docker/main/Dockerfile"
platforms = ["linux/arm64","linux/amd64"]
target = "wheels"
}
target deps {
dockerfile = "docker/main/Dockerfile"
platforms = ["linux/arm64","linux/amd64"]
target = "deps"
}
target rootfs {
dockerfile = "docker/main/Dockerfile"
platforms = ["linux/arm64","linux/amd64"]
target = "rootfs"
}
target h8l {
dockerfile = "docker/hailo8l/Dockerfile"
contexts = {
wget = "target:wget"
wheels = "target:wheels"
deps = "target:deps"
rootfs = "target:rootfs"
}
platforms = ["linux/arm64","linux/amd64"]
}

15
docker/hailo8l/h8l.mk Normal file
View File

@ -0,0 +1,15 @@
BOARDS += h8l
local-h8l: version
docker buildx bake --file=docker/hailo8l/h8l.hcl h8l \
--set h8l.tags=frigate:latest-h8l \
--load
build-h8l: version
docker buildx bake --file=docker/hailo8l/h8l.hcl h8l \
--set h8l.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-h8l
push-h8l: build-h8l
docker buildx bake --file=docker/hailo8l/h8l.hcl h8l \
--set h8l.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-h8l \
--push

View File

@ -0,0 +1,19 @@
#!/bin/bash
set -euxo pipefail
hailo_version="4.19.0"
if [[ "${TARGETARCH}" == "amd64" ]]; then
arch="x86_64"
elif [[ "${TARGETARCH}" == "arm64" ]]; then
arch="aarch64"
fi
wget -qO- "https://github.com/frigate-nvr/hailort/releases/download/v${hailo_version}/hailort-${TARGETARCH}.tar.gz" |
tar -C / -xzf -
mkdir -p /hailo-wheels
wget -P /hailo-wheels/ "https://github.com/frigate-nvr/hailort/releases/download/v${hailo_version}/hailort-${hailo_version}-cp39-cp39-linux_${arch}.whl"

View File

@ -0,0 +1,12 @@
appdirs==1.4.4
argcomplete==2.0.0
contextlib2==0.6.0.post1
distlib==0.3.6
filelock==3.8.0
future==0.18.2
importlib-metadata==5.1.0
importlib-resources==5.1.2
netaddr==0.8.0
netifaces==0.10.9
verboselogs==1.7
virtualenv==20.17.0

View File

@ -4,7 +4,6 @@
sudo apt-get update sudo apt-get update
sudo apt-get install -y build-essential cmake git wget sudo apt-get install -y build-essential cmake git wget
hailo_version="4.21.0"
arch=$(uname -m) arch=$(uname -m)
if [[ $arch == "x86_64" ]]; then if [[ $arch == "x86_64" ]]; then
@ -14,7 +13,7 @@ else
fi fi
# Clone the HailoRT driver repository # Clone the HailoRT driver repository
git clone --depth 1 --branch v${hailo_version} https://github.com/hailo-ai/hailort-drivers.git git clone --depth 1 --branch v4.19.0 https://github.com/hailo-ai/hailort-drivers.git
# Build and install the HailoRT driver # Build and install the HailoRT driver
cd hailort-drivers/linux/pcie cd hailort-drivers/linux/pcie

View File

@ -3,29 +3,14 @@
# 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
# Globally set pip break-system-packages option to avoid having to specify it every time ARG BASE_IMAGE=debian:11
ARG PIP_BREAK_SYSTEM_PACKAGES=1 ARG SLIM_BASE=debian:11-slim
ARG BASE_IMAGE=debian:12
ARG SLIM_BASE=debian:12-slim
# A hook that allows us to inject commands right after the base images
ARG BASE_HOOK=
FROM ${BASE_IMAGE} AS base FROM ${BASE_IMAGE} AS base
ARG PIP_BREAK_SYSTEM_PACKAGES
ARG BASE_HOOK
RUN sh -c "$BASE_HOOK" FROM --platform=${BUILDPLATFORM} debian:11 AS base_host
FROM --platform=${BUILDPLATFORM} debian:12 AS base_host
ARG PIP_BREAK_SYSTEM_PACKAGES
FROM ${SLIM_BASE} AS slim-base FROM ${SLIM_BASE} AS slim-base
ARG PIP_BREAK_SYSTEM_PACKAGES
ARG BASE_HOOK
RUN sh -c "$BASE_HOOK"
FROM slim-base AS wget FROM slim-base AS wget
ARG DEBIAN_FRONTEND ARG DEBIAN_FRONTEND
@ -39,7 +24,10 @@ ARG DEBIAN_FRONTEND
ENV CCACHE_DIR /root/.ccache ENV CCACHE_DIR /root/.ccache
ENV CCACHE_MAXSIZE 2G ENV CCACHE_MAXSIZE 2G
RUN --mount=type=bind,source=docker/main/build_nginx.sh,target=/deps/build_nginx.sh \ # bind /var/cache/apt to tmpfs to speed up nginx build
RUN --mount=type=tmpfs,target=/tmp --mount=type=tmpfs,target=/var/cache/apt \
--mount=type=bind,source=docker/main/build_nginx.sh,target=/deps/build_nginx.sh \
--mount=type=cache,target=/root/.ccache \
/deps/build_nginx.sh /deps/build_nginx.sh
FROM wget AS sqlite-vec FROM wget AS sqlite-vec
@ -55,7 +43,7 @@ RUN --mount=type=tmpfs,target=/tmp --mount=type=tmpfs,target=/var/cache/apt \
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.9/go2rtc_linux_${TARGETARCH}" go2rtc ADD --link --chmod=755 "https://github.com/AlexxIT/go2rtc/releases/download/v1.9.2/go2rtc_linux_${TARGETARCH}" go2rtc
FROM wget AS tempio FROM wget AS tempio
ARG TARGETARCH ARG TARGETARCH
@ -78,9 +66,8 @@ 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-dev python3-distutils gcc pkg-config libhdf5-dev \ && 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 \
&& python3 get-pip.py "pip" \ && python3 get-pip.py "pip" \
&& pip3 install -r /requirements-ov.txt && pip install -r /requirements-ov.txt
# Get OpenVino Model # Get OpenVino Model
RUN --mount=type=bind,source=docker/main/build_ov_model.py,target=/build_ov_model.py \ RUN --mount=type=bind,source=docker/main/build_ov_model.py,target=/build_ov_model.py \
@ -152,17 +139,24 @@ ARG TARGETARCH
# 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 \
gnupg \
wget \
# the key fingerprint can be obtained from https://ftp-master.debian.org/keys.html
&& wget -qO- "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xA4285295FC7B1A81600062A9605C66F00D6C9793" | \
gpg --dearmor > /usr/share/keyrings/debian-archive-bullseye-stable.gpg \
&& echo "deb [signed-by=/usr/share/keyrings/debian-archive-bullseye-stable.gpg] http://deb.debian.org/debian bullseye main contrib non-free" | \
tee /etc/apt/sources.list.d/debian-bullseye-nonfree.list \
&& apt-get -qq update \ && apt-get -qq update \
&& apt-get -qq install -y \ && apt-get -qq install -y \
python3.11 \ python3.9 \
python3.11-dev \ python3.9-dev \
# opencv dependencies # opencv dependencies
build-essential cmake git pkg-config libgtk-3-dev \ build-essential cmake git pkg-config libgtk-3-dev \
libavcodec-dev libavformat-dev libswscale-dev libv4l-dev \ libavcodec-dev libavformat-dev libswscale-dev libv4l-dev \
libxvidcore-dev libx264-dev libjpeg-dev libpng-dev libtiff-dev \ libxvidcore-dev libx264-dev libjpeg-dev libpng-dev libtiff-dev \
gfortran openexr libatlas-base-dev libssl-dev\ gfortran openexr libatlas-base-dev libssl-dev\
libtbbmalloc2 libtbb-dev libdc1394-dev libopenexr-dev \ libtbb2 libtbb-dev libdc1394-22-dev libopenexr-dev \
libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev \ libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev \
# sqlite3 dependencies # sqlite3 dependencies
tclsh \ tclsh \
@ -170,10 +164,10 @@ RUN apt-get -qq update \
gcc gfortran libopenblas-dev liblapack-dev && \ gcc gfortran libopenblas-dev liblapack-dev && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1 # Ensure python3 defaults to python3.9
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1
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 \
&& python3 get-pip.py "pip" && python3 get-pip.py "pip"
COPY docker/main/requirements.txt /requirements.txt COPY docker/main/requirements.txt /requirements.txt
@ -186,9 +180,6 @@ 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
# Install HailoRT & Wheels
RUN --mount=type=bind,source=docker/main/install_hailort.sh,target=/deps/install_hailort.sh \
/deps/install_hailort.sh
# Collect deps in a single layer # Collect deps in a single layer
FROM scratch AS deps-rootfs FROM scratch AS deps-rootfs
@ -199,7 +190,6 @@ COPY --from=libusb-build /usr/local/lib /usr/local/lib
COPY --from=tempio /rootfs/ / COPY --from=tempio /rootfs/ /
COPY --from=s6-overlay /rootfs/ / COPY --from=s6-overlay /rootfs/ /
COPY --from=models /rootfs/ / COPY --from=models /rootfs/ /
COPY --from=wheels /rootfs/ /
COPY docker/main/rootfs/ / COPY docker/main/rootfs/ /
@ -224,23 +214,15 @@ 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 HailoRT to disable logging
ENV HAILORT_LOGGER_PATH=NONE
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}"
ENV LIBAVFORMAT_VERSION_MAJOR=60
# 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="7.0"
ENV INCLUDED_FFMPEG_VERSIONS="${DEFAULT_FFMPEG_VERSION}:5.0"
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 \
&& python3 get-pip.py "pip"
RUN --mount=type=bind,from=wheels,source=/wheels,target=/deps/wheels \ RUN --mount=type=bind,from=wheels,source=/wheels,target=/deps/wheels \
python3 -m pip install --upgrade pip && \
pip3 install -U /deps/wheels/*.whl pip3 install -U /deps/wheels/*.whl
COPY --from=deps-rootfs / / COPY --from=deps-rootfs / /
@ -260,12 +242,12 @@ 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
# Do not start the actual Frigate service on devcontainer as it will be started by VS Code # Do not start the actual Frigate service on devcontainer as it will be started by VSCode
# But start a fake service for simulating the logs # But start a fake service for simulating the logs
COPY docker/main/fake_frigate_run /etc/s6-overlay/s6-rc.d/frigate/run COPY docker/main/fake_frigate_run /etc/s6-overlay/s6-rc.d/frigate/run

View File

@ -2,22 +2,16 @@
set -euxo pipefail set -euxo pipefail
NGINX_VERSION="1.27.4" NGINX_VERSION="1.25.3"
VOD_MODULE_VERSION="1.31" VOD_MODULE_VERSION="1.31"
SECURE_TOKEN_MODULE_VERSION="1.5" SECURE_TOKEN_MODULE_VERSION="1.5"
SET_MISC_MODULE_VERSION="v0.33" SET_MISC_MODULE_VERSION="v0.33"
NGX_DEVEL_KIT_VERSION="v0.3.3" NGX_DEVEL_KIT_VERSION="v0.3.3"
source /etc/os-release cp /etc/apt/sources.list /etc/apt/sources.list.d/sources-src.list
sed -i 's|deb http|deb-src http|g' /etc/apt/sources.list.d/sources-src.list
if [[ "$VERSION_ID" == "12" ]]; then
sed -i '/^Types:/s/deb/& deb-src/' /etc/apt/sources.list.d/debian.sources
else
cp /etc/apt/sources.list /etc/apt/sources.list.d/sources-src.list
sed -i 's|deb http|deb-src http|g' /etc/apt/sources.list.d/sources-src.list
fi
apt-get update apt-get update
apt-get -yqq build-dep nginx apt-get -yqq build-dep nginx
apt-get -yqq install --no-install-recommends ca-certificates wget apt-get -yqq install --no-install-recommends ca-certificates wget

View File

@ -4,7 +4,7 @@ from openvino.tools import mo
ov_model = mo.convert_model( ov_model = mo.convert_model(
"/models/ssdlite_mobilenet_v2_coco_2018_05_09/frozen_inference_graph.pb", "/models/ssdlite_mobilenet_v2_coco_2018_05_09/frozen_inference_graph.pb",
compress_to_fp16=True, compress_to_fp16=True,
transformations_config="/usr/local/lib/python3.11/dist-packages/openvino/tools/mo/front/tf/ssd_v2_support.json", transformations_config="/usr/local/lib/python3.9/dist-packages/openvino/tools/mo/front/tf/ssd_v2_support.json",
tensorflow_object_detection_api_pipeline_config="/models/ssdlite_mobilenet_v2_coco_2018_05_09/pipeline.config", tensorflow_object_detection_api_pipeline_config="/models/ssdlite_mobilenet_v2_coco_2018_05_09/pipeline.config",
reverse_input_channels=True, reverse_input_channels=True,
) )

View File

@ -2,25 +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"
# Fetch the pre-built sqlite amalgamation instead of building from source # Fetch the source code for the latest release of Sqlite.
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.

View File

@ -4,15 +4,8 @@ set -euxo pipefail
SQLITE_VEC_VERSION="0.1.3" SQLITE_VEC_VERSION="0.1.3"
source /etc/os-release cp /etc/apt/sources.list /etc/apt/sources.list.d/sources-src.list
sed -i 's|deb http|deb-src http|g' /etc/apt/sources.list.d/sources-src.list
if [[ "$VERSION_ID" == "12" ]]; then
sed -i '/^Types:/s/deb/& deb-src/' /etc/apt/sources.list.d/debian.sources
else
cp /etc/apt/sources.list /etc/apt/sources.list.d/sources-src.list
sed -i 's|deb http|deb-src http|g' /etc/apt/sources.list.d/sources-src.list
fi
apt-get update apt-get update
apt-get -yqq build-dep sqlite3 gettext git apt-get -yqq build-dep sqlite3 gettext git

View File

@ -6,74 +6,82 @@ apt-get -qq update
apt-get -qq install --no-install-recommends -y \ apt-get -qq install --no-install-recommends -y \
apt-transport-https \ apt-transport-https \
ca-certificates \
gnupg \ gnupg \
wget \ wget \
lbzip2 \ lbzip2 \
procps vainfo \ procps vainfo \
unzip locales tzdata libxml2 xz-utils \ unzip locales tzdata libxml2 xz-utils \
python3.11 \ python3.9 \
python3-pip \
curl \ curl \
lsof \ lsof \
jq \ jq \
nethogs \ nethogs
libgl1 \
libglib2.0-0 \
libusb-1.0.0
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1 # ensure python3 defaults to python3.9
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1
mkdir -p -m 600 /root/.gnupg mkdir -p -m 600 /root/.gnupg
# install coral runtime # add coral repo
wget -q -O /tmp/libedgetpu1-max.deb "https://github.com/feranick/libedgetpu/releases/download/16.0TF2.17.1-1/libedgetpu1-max_16.0tf2.17.1-1.bookworm_${TARGETARCH}.deb" curl -fsSLo - https://packages.cloud.google.com/apt/doc/apt-key.gpg | \
unset DEBIAN_FRONTEND gpg --dearmor -o /etc/apt/trusted.gpg.d/google-cloud-packages-archive-keyring.gpg
yes | dpkg -i /tmp/libedgetpu1-max.deb && export DEBIAN_FRONTEND=noninteractive echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | tee /etc/apt/sources.list.d/coral-edgetpu.list
rm /tmp/libedgetpu1-max.deb echo "libedgetpu1-max libedgetpu/accepted-eula select true" | debconf-set-selections
# ffmpeg -> amd64 # enable non-free repo in Debian
if grep -q "Debian" /etc/issue; then
sed -i -e's/ main/ main contrib non-free/g' /etc/apt/sources.list
fi
# coral drivers
apt-get -qq update
apt-get -qq install --no-install-recommends --no-install-suggests -y \
libedgetpu1-max python3-tflite-runtime python3-pycoral
# btbn-ffmpeg -> amd64
if [[ "${TARGETARCH}" == "amd64" ]]; then if [[ "${TARGETARCH}" == "amd64" ]]; then
mkdir -p /usr/lib/ffmpeg/5.0 mkdir -p /usr/lib/ffmpeg/5.0
wget -qO ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2022-07-31-12-37/ffmpeg-n5.1-2-g915ef932a3-linux64-gpl-5.1.tar.xz"
tar -xf ffmpeg.tar.xz -C /usr/lib/ffmpeg/5.0 --strip-components 1 amd64/bin/ffmpeg amd64/bin/ffprobe
rm -rf ffmpeg.tar.xz
mkdir -p /usr/lib/ffmpeg/7.0 mkdir -p /usr/lib/ffmpeg/7.0
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 btbn-ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2022-07-31-12-37/ffmpeg-n5.1-2-g915ef932a3-linux64-gpl-5.1.tar.xz"
tar -xf ffmpeg.tar.xz -C /usr/lib/ffmpeg/7.0 --strip-components 1 amd64/bin/ffmpeg amd64/bin/ffprobe tar -xf btbn-ffmpeg.tar.xz -C /usr/lib/ffmpeg/5.0 --strip-components 1
rm -rf ffmpeg.tar.xz rm -rf btbn-ffmpeg.tar.xz /usr/lib/ffmpeg/5.0/doc /usr/lib/ffmpeg/5.0/bin/ffplay
wget -qO btbn-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 btbn-ffmpeg.tar.xz -C /usr/lib/ffmpeg/7.0 --strip-components 1
rm -rf btbn-ffmpeg.tar.xz /usr/lib/ffmpeg/7.0/doc /usr/lib/ffmpeg/7.0/bin/ffplay
fi fi
# ffmpeg -> arm64 # ffmpeg -> arm64
if [[ "${TARGETARCH}" == "arm64" ]]; then if [[ "${TARGETARCH}" == "arm64" ]]; then
mkdir -p /usr/lib/ffmpeg/5.0 mkdir -p /usr/lib/ffmpeg/5.0
wget -qO ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2022-07-31-12-37/ffmpeg-n5.1-2-g915ef932a3-linuxarm64-gpl-5.1.tar.xz"
tar -xf ffmpeg.tar.xz -C /usr/lib/ffmpeg/5.0 --strip-components 1 arm64/bin/ffmpeg arm64/bin/ffprobe
rm -f ffmpeg.tar.xz
mkdir -p /usr/lib/ffmpeg/7.0 mkdir -p /usr/lib/ffmpeg/7.0
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 btbn-ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2022-07-31-12-37/ffmpeg-n5.1-2-g915ef932a3-linuxarm64-gpl-5.1.tar.xz"
tar -xf ffmpeg.tar.xz -C /usr/lib/ffmpeg/7.0 --strip-components 1 arm64/bin/ffmpeg arm64/bin/ffprobe tar -xf btbn-ffmpeg.tar.xz -C /usr/lib/ffmpeg/5.0 --strip-components 1
rm -f ffmpeg.tar.xz rm -rf btbn-ffmpeg.tar.xz /usr/lib/ffmpeg/5.0/doc /usr/lib/ffmpeg/5.0/bin/ffplay
wget -qO btbn-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 btbn-ffmpeg.tar.xz -C /usr/lib/ffmpeg/7.0 --strip-components 1
rm -rf btbn-ffmpeg.tar.xz /usr/lib/ffmpeg/7.0/doc /usr/lib/ffmpeg/7.0/bin/ffplay
fi fi
# arch specific packages # arch specific packages
if [[ "${TARGETARCH}" == "amd64" ]]; then if [[ "${TARGETARCH}" == "amd64" ]]; then
# Install non-free version of i965 driver # use debian bookworm for amd / intel-i965 driver packages
CODENAME=$(grep VERSION_CODENAME= /etc/os-release | cut -d= -f2) \ echo 'deb https://deb.debian.org/debian bookworm main contrib non-free' >/etc/apt/sources.list.d/debian-bookworm.list
&& sed -i -E "s/^(deb http:\/\/deb\.debian\.org\/debian ${CODENAME} main)(.*)$/\1 contrib non-free non-free-firmware\2/" /etc/apt/sources.list \ apt-get -qq update
&& apt-get -qq update \
&& apt-get install --no-install-recommends --no-install-suggests -y i965-va-driver-shaders \
&& sed -i -E "s/(deb http:\/\/deb\.debian\.org\/debian ${CODENAME} main) contrib non-free non-free-firmware/\1/" /etc/apt/sources.list \
&& apt-get update
# 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
# something about this dependency requires it to be installed in a separate call rather than in the line above
apt-get -qq install --no-install-recommends --no-install-suggests -y \
i965-va-driver-shaders
# 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
rm -f /etc/apt/sources.list.d/debian-bookworm.list
# use intel apt intel packages # 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

View File

@ -1,14 +0,0 @@
#!/bin/bash
set -euxo pipefail
hailo_version="4.21.0"
if [[ "${TARGETARCH}" == "amd64" ]]; then
arch="x86_64"
elif [[ "${TARGETARCH}" == "arm64" ]]; then
arch="aarch64"
fi
wget -qO- "https://github.com/frigate-nvr/hailort/releases/download/v${hailo_version}/hailort-debian12-${TARGETARCH}.tar.gz" | tar -C / -xzf -
wget -P /wheels/ "https://github.com/frigate-nvr/hailort/releases/download/v${hailo_version}/hailort-${hailo_version}-cp311-cp311-linux_${arch}.whl"

View File

@ -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"

View File

@ -1,73 +1,47 @@
aiofiles == 24.1.*
click == 8.1.* click == 8.1.*
# FastAPI # FastAPI
aiohttp == 3.11.3 aiohttp == 3.11.2
starlette == 0.41.2 starlette == 0.41.2
starlette-context == 0.3.6 starlette-context == 0.3.6
fastapi == 0.115.* fastapi == 0.115.*
uvicorn == 0.30.* uvicorn == 0.30.*
slowapi == 0.1.* slowapi == 0.1.*
imutils == 0.5.*
joserfc == 1.0.* joserfc == 1.0.*
pathvalidate == 3.2.* pathvalidate == 3.2.*
markupsafe == 3.0.* markupsafe == 2.1.*
python-multipart == 0.0.12
# General
mypy == 1.6.1 mypy == 1.6.1
onvif-zeep-async == 3.1.* numpy == 1.26.*
onvif_zeep == 0.2.12
opencv-python-headless == 4.9.0.*
paho-mqtt == 2.1.* paho-mqtt == 2.1.*
pandas == 2.2.* pandas == 2.2.*
peewee == 3.17.* peewee == 3.17.*
peewee_migrate == 1.13.* peewee_migrate == 1.13.*
psutil == 6.1.* psutil == 6.1.*
pydantic == 2.10.* pydantic == 2.8.*
git+https://github.com/fbcotter/py3nvml#egg=py3nvml git+https://github.com/fbcotter/py3nvml#egg=py3nvml
pytz == 2025.* pytz == 2024.*
pyzmq == 26.2.* pyzmq == 26.2.*
ruamel.yaml == 0.18.* ruamel.yaml == 0.18.*
tzlocal == 5.2 tzlocal == 5.2
requests == 2.32.* requests == 2.32.*
types-requests == 2.32.* types-requests == 2.32.*
scipy == 1.13.*
norfair == 2.2.* 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
numpy == 1.26.*
opencv-python-headless == 4.11.0.*
opencv-contrib-python == 4.11.0.*
scipy == 1.14.*
# OpenVino & ONNX # OpenVino & ONNX
openvino == 2024.4.* openvino == 2024.3.*
onnxruntime-openvino == 1.20.* ; platform_machine == 'x86_64' onnxruntime-openvino == 1.19.* ; platform_machine == 'x86_64'
onnxruntime == 1.20.* ; platform_machine == 'aarch64' onnxruntime == 1.19.* ; platform_machine == 'aarch64'
# Embeddings # Embeddings
transformers == 4.45.* transformers == 4.45.*
# Generative AI # Generative AI
google-generativeai == 0.8.* google-generativeai == 0.8.*
ollama == 0.3.* ollama == 0.3.*
openai == 1.65.* openai == 1.51.*
# push notifications # push notifications
py-vapid == 1.9.* py-vapid == 1.9.*
pywebpush == 2.0.* pywebpush == 2.0.*
# alpr
pyclipper == 1.3.*
shapely == 2.0.*
Levenshtein==0.26.*
# HailoRT Wheels
appdirs==1.4.*
argcomplete==2.0.*
contextlib2==0.6.*
distlib==0.3.*
filelock==3.8.*
future==0.18.*
importlib-metadata==5.1.*
importlib-resources==5.1.*
netaddr==0.8.*
netifaces==0.10.*
verboselogs==1.7.*
virtualenv==20.17.*
prometheus-client == 0.21.*
# 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/feranick/TFlite-builds/releases/download/v2.17.1/tflite_runtime-2.17.1-cp311-cp311-linux_aarch64.whl; platform_machine == 'aarch64'

View File

@ -1,2 +1,2 @@
scikit-build == 0.18.* scikit-build == 0.17.*
nvidia-pyindex nvidia-pyindex

View File

@ -4,26 +4,46 @@
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
s6-svc -O . s6-svc -O .
function set_libva_version() { function migrate_db_path() {
local ffmpeg_path # Find config file in yaml or yml, but prefer yaml
ffmpeg_path=$(python3 /usr/local/ffmpeg/get_ffmpeg_path.py) local config_file="${CONFIG_FILE:-"/config/config.yml"}"
LIBAVFORMAT_VERSION_MAJOR=$("$ffmpeg_path" -version | grep -Po "libavformat\W+\K\d+") local config_file_yaml="${config_file//.yml/.yaml}"
export LIBAVFORMAT_VERSION_MAJOR if [[ -f "${config_file_yaml}" ]]; then
config_file="${config_file_yaml}"
elif [[ ! -f "${config_file}" ]]; then
# Frigate will create the config file on startup
return 0
fi
unset config_file_yaml
# Use yq to check if database.path is set
local user_db_path
user_db_path=$(yq eval '.database.path' "${config_file}")
if [[ "${user_db_path}" == "null" ]]; then
local previous_db_path="/media/frigate/frigate.db"
local new_db_dir="/config"
if [[ -f "${previous_db_path}" ]]; then
if mountpoint --quiet "${new_db_dir}"; then
# /config is a mount point, move the db
echo "[INFO] Moving db from '${previous_db_path}' to the '${new_db_dir}' dir..."
# Move all files that starts with frigate.db to the new directory
mv -vf "${previous_db_path}"* "${new_db_dir}"
else
echo "[ERROR] Trying to migrate the db path from '${previous_db_path}' to the '${new_db_dir}' dir, but '${new_db_dir}' is not a mountpoint, please mount the '${new_db_dir}' dir"
return 1
fi
fi
fi
} }
echo "[INFO] Preparing Frigate..." echo "[INFO] Preparing Frigate..."
set_libva_version migrate_db_path
echo "[INFO] Starting Frigate..." echo "[INFO] Starting Frigate..."
cd /opt/frigate || echo "[ERROR] Failed to change working directory to /opt/frigate" cd /opt/frigate || echo "[ERROR] Failed to change working directory to /opt/frigate"

View File

@ -43,15 +43,6 @@ function get_ip_and_port_from_supervisor() {
export FRIGATE_GO2RTC_WEBRTC_CANDIDATE_INTERNAL="${ip_address}:${webrtc_port}" export FRIGATE_GO2RTC_WEBRTC_CANDIDATE_INTERNAL="${ip_address}:${webrtc_port}"
} }
function set_libva_version() {
local ffmpeg_path
ffmpeg_path=$(python3 /usr/local/ffmpeg/get_ffmpeg_path.py)
LIBAVFORMAT_VERSION_MAJOR=$("$ffmpeg_path" -version | grep -Po "libavformat\W+\K\d+")
export LIBAVFORMAT_VERSION_MAJOR
}
set_libva_version
if [[ -f "/dev/shm/go2rtc.yaml" ]]; then if [[ -f "/dev/shm/go2rtc.yaml" ]]; then
echo "[INFO] Removing stale config from last run..." echo "[INFO] Removing stale config from last run..."
rm /dev/shm/go2rtc.yaml rm /dev/shm/go2rtc.yaml
@ -61,7 +52,7 @@ if [[ ! -f "/dev/shm/go2rtc.yaml" ]]; then
echo "[INFO] Preparing new go2rtc config..." echo "[INFO] Preparing new go2rtc config..."
if [[ -n "${SUPERVISOR_TOKEN:-}" ]]; then if [[ -n "${SUPERVISOR_TOKEN:-}" ]]; then
# Running as a Home Assistant Add-on, infer the IP address and port # Running as a Home Assistant add-on, infer the IP address and port
get_ip_and_port_from_supervisor get_ip_and_port_from_supervisor
fi fi

View File

@ -79,11 +79,6 @@ if [ ! \( -f "$letsencrypt_path/privkey.pem" -a -f "$letsencrypt_path/fullchain.
-keyout "$letsencrypt_path/privkey.pem" -out "$letsencrypt_path/fullchain.pem" 2>/dev/null -keyout "$letsencrypt_path/privkey.pem" -out "$letsencrypt_path/fullchain.pem" 2>/dev/null
fi fi
# build templates for optional FRIGATE_BASE_PATH environment variable
python3 /usr/local/nginx/get_base_path.py | \
tempio -template /usr/local/nginx/templates/base_path.gotmpl \
-out /usr/local/nginx/conf/base_path.conf
# build templates for optional TLS support # build templates for optional TLS support
python3 /usr/local/nginx/get_tls_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 \

View File

@ -1,146 +0,0 @@
#!/command/with-contenv bash
# shellcheck shell=bash
# Do preparation tasks before starting the main services
set -o errexit -o nounset -o pipefail
function migrate_addon_config_dir() {
local home_assistant_config_dir="/homeassistant"
if ! mountpoint --quiet "${home_assistant_config_dir}"; then
# Not running as a Home Assistant Add-on
return 0
fi
local config_dir="/config"
local new_config_file="${config_dir}/config.yml"
local new_config_file_yaml="${new_config_file//.yml/.yaml}"
if [[ -f "${new_config_file_yaml}" || -f "${new_config_file}" ]]; then
# Already migrated
return 0
fi
local old_config_file="${home_assistant_config_dir}/frigate.yml"
local old_config_file_yaml="${old_config_file//.yml/.yaml}"
if [[ -f "${old_config_file}" ]]; then
:
elif [[ -f "${old_config_file_yaml}" ]]; then
old_config_file="${old_config_file_yaml}"
new_config_file="${new_config_file_yaml}"
else
# Nothing to migrate
return 0
fi
unset old_config_file_yaml new_config_file_yaml
echo "[INFO] Starting migration from Home Assistant config dir to Add-on config dir..." >&2
local db_path
db_path=$(yq -r '.database.path' "${old_config_file}")
if [[ "${db_path}" == "null" ]]; then
db_path="${config_dir}/frigate.db"
fi
if [[ "${db_path}" == "${config_dir}/"* ]]; then
# replace /config/ prefix with /homeassistant/
local old_db_path="${home_assistant_config_dir}/${db_path:8}"
if [[ -f "${old_db_path}" ]]; then
local new_db_dir
new_db_dir="$(dirname "${db_path}")"
echo "[INFO] Migrating database from '${old_db_path}' to '${new_db_dir}' dir..." >&2
mkdir -vp "${new_db_dir}"
mv -vf "${old_db_path}" "${new_db_dir}"
local db_file
for db_file in "${old_db_path}"-shm "${old_db_path}"-wal; do
if [[ -f "${db_file}" ]]; then
mv -vf "${db_file}" "${new_db_dir}"
fi
done
unset db_file
fi
fi
local config_entry
for config_entry in .model.path .model.labelmap_path .ffmpeg.path .mqtt.tls_ca_certs .mqtt.tls_client_cert .mqtt.tls_client_key; do
local config_entry_path
config_entry_path=$(yq -r "${config_entry}" "${old_config_file}")
if [[ "${config_entry_path}" == "${config_dir}/"* ]]; then
# replace /config/ prefix with /homeassistant/
local old_config_entry_path="${home_assistant_config_dir}/${config_entry_path:8}"
if [[ -f "${old_config_entry_path}" ]]; then
local new_config_entry_entry
new_config_entry_entry="$(dirname "${config_entry_path}")"
echo "[INFO] Migrating ${config_entry} from '${old_config_entry_path}' to '${config_entry_path}'..." >&2
mkdir -vp "${new_config_entry_entry}"
mv -vf "${old_config_entry_path}" "${config_entry_path}"
fi
fi
done
local old_model_cache_path="${home_assistant_config_dir}/model_cache"
if [[ -d "${old_model_cache_path}" ]]; then
echo "[INFO] Migrating '${old_model_cache_path}' to '${config_dir}'..." >&2
mv -f "${old_model_cache_path}" "${config_dir}"
fi
echo "[INFO] Migrating other files from '${home_assistant_config_dir}' to '${config_dir}'..." >&2
local file
for file in .exports .jwt_secret .timeline .vacuum go2rtc; do
file="${home_assistant_config_dir}/${file}"
if [[ -f "${file}" ]]; then
mv -vf "${file}" "${config_dir}"
fi
done
echo "[INFO] Migrating config file from '${old_config_file}' to '${new_config_file}'..." >&2
mv -vf "${old_config_file}" "${new_config_file}"
echo "[INFO] Migration from Home Assistant config dir to Add-on config dir completed." >&2
}
function migrate_db_from_media_to_config() {
# Find config file in yml or yaml, but prefer yml
local config_file="${CONFIG_FILE:-"/config/config.yml"}"
local config_file_yaml="${config_file//.yml/.yaml}"
if [[ -f "${config_file}" ]]; then
:
elif [[ -f "${config_file_yaml}" ]]; then
config_file="${config_file_yaml}"
else
# Frigate will create the config file on startup
return 0
fi
unset config_file_yaml
local user_db_path
user_db_path=$(yq -r '.database.path' "${config_file}")
if [[ "${user_db_path}" == "null" ]]; then
local old_db_path="/media/frigate/frigate.db"
local new_db_dir="/config"
if [[ -f "${old_db_path}" ]]; then
echo "[INFO] Migrating database from '${old_db_path}' to '${new_db_dir}' dir..." >&2
if mountpoint --quiet "${new_db_dir}"; then
# /config is a mount point, move the db
mv -vf "${old_db_path}" "${new_db_dir}"
local db_file
for db_file in "${old_db_path}"-shm "${old_db_path}"-wal; do
if [[ -f "${db_file}" ]]; then
mv -vf "${db_file}" "${new_db_dir}"
fi
done
unset db_file
else
echo "[ERROR] Trying to migrate the database path from '${old_db_path}' to '${new_db_dir}' dir, but '${new_db_dir}' is not a mountpoint, please mount the '${new_db_dir}' dir" >&2
return 1
fi
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_db_from_media_to_config

View File

@ -1 +0,0 @@
oneshot

View File

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

View File

@ -1,37 +0,0 @@
import json
import sys
from typing import Any
from ruamel.yaml import YAML
sys.path.insert(0, "/opt/frigate")
from frigate.const import (
DEFAULT_FFMPEG_VERSION,
INCLUDED_FFMPEG_VERSIONS,
)
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] = {}
path = config.get("ffmpeg", {}).get("path", "default")
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")

View File

@ -2,9 +2,9 @@
import json import json
import os import os
import shutil
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
@ -13,10 +13,8 @@ from frigate.const import (
BIRDSEYE_PIPE, BIRDSEYE_PIPE,
DEFAULT_FFMPEG_VERSION, DEFAULT_FFMPEG_VERSION,
INCLUDED_FFMPEG_VERSIONS, INCLUDED_FFMPEG_VERSIONS,
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
sys.path.remove("/opt/frigate") sys.path.remove("/opt/frigate")
@ -31,20 +29,25 @@ if os.path.isdir("/run/secrets"):
Path(os.path.join("/run/secrets", secret_file)).read_text().strip() Path(os.path.join("/run/secrets", secret_file)).read_text().strip()
) )
config_file = find_config_file() config_file = os.environ.get("CONFIG_FILE", "/config/config.yml")
# Check if we can use .yaml instead of .yml
config_file_yaml = config_file.replace(".yml", ".yaml")
if os.path.isfile(config_file_yaml):
config_file = config_file_yaml
try: try:
with open(config_file) as f: with open(config_file) as f:
raw_config = f.read() raw_config = f.read()
if config_file.endswith((".yaml", ".yml")): if config_file.endswith((".yaml", ".yml")):
config: 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:
@ -54,7 +57,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:
@ -63,34 +66,56 @@ elif go2rtc_config["log"].get("format") is None:
go2rtc_config["log"]["format"] = "text" go2rtc_config["log"]["format"] = "text"
# ensure there is a default webrtc config # ensure there is a default webrtc config
if go2rtc_config.get("webrtc") is None: if not go2rtc_config.get("webrtc"):
go2rtc_config["webrtc"] = {} go2rtc_config["webrtc"] = {}
if go2rtc_config["webrtc"].get("candidates") is None: # go2rtc should listen on 8555 tcp & udp by default
if not go2rtc_config["webrtc"].get("listen"):
go2rtc_config["webrtc"]["listen"] = ":8555"
if not go2rtc_config["webrtc"].get("candidates", []):
default_candidates = [] default_candidates = []
# use internal candidate if it was discovered when running through the add-on # use internal candidate if it was discovered when running through the add-on
internal_candidate = os.environ.get("FRIGATE_GO2RTC_WEBRTC_CANDIDATE_INTERNAL") internal_candidate = os.environ.get(
"FRIGATE_GO2RTC_WEBRTC_CANDIDATE_INTERNAL", None
)
if internal_candidate is not None: if internal_candidate is not None:
default_candidates.append(internal_candidate) default_candidates.append(internal_candidate)
# should set default stun server so webrtc can work # should set default stun server so webrtc can work
default_candidates.append("stun:8555") default_candidates.append("stun:8555")
go2rtc_config["webrtc"]["candidates"] = default_candidates go2rtc_config["webrtc"] = {"candidates": default_candidates}
else:
if go2rtc_config.get("rtsp", {}).get("username") is not None: print(
go2rtc_config["rtsp"]["username"] = go2rtc_config["rtsp"]["username"].format( "[INFO] Not injecting WebRTC candidates into go2rtc config as it has been set manually",
**FRIGATE_ENV_VARS
) )
if go2rtc_config.get("rtsp", {}).get("password") is not None: # sets default RTSP response to be equivalent to ?video=h264,h265&audio=aac
go2rtc_config["rtsp"]["password"] = go2rtc_config["rtsp"]["password"].format( # this means user does not need to specify audio codec when using restream
**FRIGATE_ENV_VARS # as source for frigate and the integration supports HLS playback
) if go2rtc_config.get("rtsp") is None:
go2rtc_config["rtsp"] = {"default_query": "mp4"}
else:
if go2rtc_config["rtsp"].get("default_query") is None:
go2rtc_config["rtsp"]["default_query"] = "mp4"
if go2rtc_config["rtsp"].get("username") is not None:
go2rtc_config["rtsp"]["username"] = go2rtc_config["rtsp"]["username"].format(
**FRIGATE_ENV_VARS
)
if go2rtc_config["rtsp"].get("password") is not None:
go2rtc_config["rtsp"]["password"] = go2rtc_config["rtsp"]["password"].format(
**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")
if path == "default": if path == "default":
ffmpeg_path = f"/usr/lib/ffmpeg/{DEFAULT_FFMPEG_VERSION}/bin/ffmpeg" if shutil.which("ffmpeg") is None:
ffmpeg_path = f"/usr/lib/ffmpeg/{DEFAULT_FFMPEG_VERSION}/bin/ffmpeg"
else:
ffmpeg_path = "ffmpeg"
elif path in INCLUDED_FFMPEG_VERSIONS: elif path in INCLUDED_FFMPEG_VERSIONS:
ffmpeg_path = f"/usr/lib/ffmpeg/{path}/bin/ffmpeg" ffmpeg_path = f"/usr/lib/ffmpeg/{path}/bin/ffmpeg"
else: else:
@ -102,12 +127,14 @@ elif go2rtc_config["ffmpeg"].get("bin") is None:
go2rtc_config["ffmpeg"]["bin"] = ffmpeg_path go2rtc_config["ffmpeg"]["bin"] = ffmpeg_path
# need to replace ffmpeg command when using ffmpeg4 # need to replace ffmpeg command when using ffmpeg4
if LIBAVFORMAT_VERSION_MAJOR < 59: if int(os.environ.get("LIBAVFORMAT_VERSION_MAJOR", "59") or "59") < 59:
rtsp_args = "-fflags nobuffer -flags low_delay -stimeout 10000000 -user_agent go2rtc/ffmpeg -rtsp_transport tcp -i {input}" if go2rtc_config["ffmpeg"].get("rtsp") is None:
go2rtc_config["ffmpeg"]["rtsp"] = (
"-fflags nobuffer -flags low_delay -stimeout 5000000 -user_agent go2rtc/ffmpeg -rtsp_transport tcp -i {input}"
)
else:
if go2rtc_config.get("ffmpeg") is None: if go2rtc_config.get("ffmpeg") is None:
go2rtc_config["ffmpeg"] = {"rtsp": rtsp_args} go2rtc_config["ffmpeg"] = {"path": ""}
elif go2rtc_config["ffmpeg"].get("rtsp") is None:
go2rtc_config["ffmpeg"]["rtsp"] = rtsp_args
for name in go2rtc_config.get("streams", {}): for name in go2rtc_config.get("streams", {}):
stream = go2rtc_config["streams"][name] stream = go2rtc_config["streams"][name]
@ -135,7 +162,7 @@ for name in go2rtc_config.get("streams", {}):
# 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}')}"

View File

@ -1,16 +1,14 @@
## Send a subrequest to verify if the user is authenticated and has permission to access the resource. ## Send a subrequest to verify if the user is authenticated and has permission to access the resource.
auth_request /auth; auth_request /auth;
## Save the upstream metadata response headers from the auth request to variables ## Save the upstream metadata response headers from Authelia to variables.
auth_request_set $user $upstream_http_remote_user; auth_request_set $user $upstream_http_remote_user;
auth_request_set $role $upstream_http_remote_role;
auth_request_set $groups $upstream_http_remote_groups; auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name; auth_request_set $name $upstream_http_remote_name;
auth_request_set $email $upstream_http_remote_email; auth_request_set $email $upstream_http_remote_email;
## Inject the metadata response headers from the variables into the request made to the backend. ## Inject the metadata response headers from the variables into the request made to the backend.
proxy_set_header Remote-User $user; proxy_set_header Remote-User $user;
proxy_set_header Remote-Role $role;
proxy_set_header Remote-Groups $groups; proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Email $email; proxy_set_header Remote-Email $email;
proxy_set_header Remote-Name $name; proxy_set_header Remote-Name $name;

View File

@ -30,7 +30,7 @@ http {
gzip on; gzip on;
gzip_comp_level 6; gzip_comp_level 6;
gzip_types text/plain text/css application/json application/x-javascript application/javascript text/javascript image/svg+xml image/x-icon image/bmp; gzip_types text/plain text/css application/json application/x-javascript application/javascript text/javascript image/svg+xml image/x-icon image/bmp image/png image/gif image/jpeg image/jpg;
gzip_proxied no-cache no-store private expired auth; gzip_proxied no-cache no-store private expired auth;
gzip_vary on; gzip_vary on;
@ -81,9 +81,6 @@ http {
open_file_cache_errors on; open_file_cache_errors on;
aio on; aio on;
# file upload size
client_max_body_size 20M;
# https://github.com/kaltura/nginx-vod-module#vod_open_file_thread_pool # https://github.com/kaltura/nginx-vod-module#vod_open_file_thread_pool
vod_open_file_thread_pool default; vod_open_file_thread_pool default;
@ -96,7 +93,6 @@ http {
gzip_types application/vnd.apple.mpegurl; gzip_types application/vnd.apple.mpegurl;
include auth_location.conf; include auth_location.conf;
include base_path.conf;
location /vod/ { location /vod/ {
include auth_request.conf; include auth_request.conf;
@ -110,14 +106,6 @@ http {
expires off; expires off;
keepalive_disable safari; keepalive_disable safari;
# vod module returns 502 for non-existent media
# https://github.com/kaltura/nginx-vod-module/issues/468
error_page 502 =404 /vod-not-found;
}
location = /vod-not-found {
return 404;
} }
location /stream/ { location /stream/ {
@ -300,29 +288,11 @@ http {
add_header Cache-Control "public"; add_header Cache-Control "public";
} }
location /locales/ {
access_log off;
add_header Cache-Control "public";
}
location ~ ^/.*-([A-Za-z0-9]+)\.webmanifest$ {
access_log off;
expires 1y;
add_header Cache-Control "public";
default_type application/json;
proxy_set_header Accept-Encoding "";
sub_filter_once off;
sub_filter_types application/json;
sub_filter '"start_url": "/BASE_PATH/"' '"start_url" : "$http_x_ingress_path/"';
sub_filter '"src": "/BASE_PATH/' '"src": "$http_x_ingress_path/';
}
sub_filter 'href="/BASE_PATH/' 'href="$http_x_ingress_path/'; sub_filter 'href="/BASE_PATH/' 'href="$http_x_ingress_path/';
sub_filter 'url(/BASE_PATH/' 'url($http_x_ingress_path/'; sub_filter 'url(/BASE_PATH/' 'url($http_x_ingress_path/';
sub_filter '"/BASE_PATH/dist/' '"$http_x_ingress_path/dist/'; sub_filter '"/BASE_PATH/dist/' '"$http_x_ingress_path/dist/';
sub_filter '"/BASE_PATH/js/' '"$http_x_ingress_path/js/'; sub_filter '"/BASE_PATH/js/' '"$http_x_ingress_path/js/';
sub_filter '"/BASE_PATH/assets/' '"$http_x_ingress_path/assets/'; sub_filter '"/BASE_PATH/assets/' '"$http_x_ingress_path/assets/';
sub_filter '"/BASE_PATH/locales/' '"$http_x_ingress_path/locales/';
sub_filter '"/BASE_PATH/monacoeditorwork/' '"$http_x_ingress_path/assets/'; sub_filter '"/BASE_PATH/monacoeditorwork/' '"$http_x_ingress_path/assets/';
sub_filter 'return"/BASE_PATH/"' 'return window.baseUrl'; sub_filter 'return"/BASE_PATH/"' 'return window.baseUrl';
sub_filter '<body>' '<body><script>window.baseUrl="$http_x_ingress_path/";</script>'; sub_filter '<body>' '<body><script>window.baseUrl="$http_x_ingress_path/";</script>';

View File

@ -1,11 +0,0 @@
"""Prints the base path as json to stdout."""
import json
import os
from typing import Any
base_path = os.environ.get("FRIGATE_BASE_PATH", "")
result: dict[str, Any] = {"base_path": base_path}
print(json.dumps(result))

View File

@ -1,31 +1,30 @@
"""Prints the tls config as json to stdout.""" """Prints the tls config as json to stdout."""
import json import json
import sys import os
from typing import Any
from ruamel.yaml import YAML 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() yaml = YAML()
config_file = find_config_file() config_file = os.environ.get("CONFIG_FILE", "/config/config.yml")
# Check if we can use .yaml instead of .yml
config_file_yaml = config_file.replace(".yml", ".yaml")
if os.path.isfile(config_file_yaml):
config_file = config_file_yaml
try: try:
with open(config_file) as f: with open(config_file) as f:
raw_config = f.read() raw_config = f.read()
if config_file.endswith((".yaml", ".yml")): if config_file.endswith((".yaml", ".yml")):
config: 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] = {}
tls_config: dict[str, Any] = config.get("tls", {"enabled": True}) tls_config: dict[str, any] = config.get("tls", {"enabled": True})
print(json.dumps(tls_config)) print(json.dumps(tls_config))

View File

@ -1,19 +0,0 @@
{{ if .base_path }}
location = {{ .base_path }} {
return 302 {{ .base_path }}/;
}
location ^~ {{ .base_path }}/ {
# remove base_url from the path before passing upstream
rewrite ^{{ .base_path }}/(.*) /$1 break;
proxy_pass $scheme://127.0.0.1:8971;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Ingress-Path {{ .base_path }};
access_log off;
}
{{ end }}

View File

@ -1,20 +0,0 @@
./subset/000000005001.jpg
./subset/000000038829.jpg
./subset/000000052891.jpg
./subset/000000075612.jpg
./subset/000000098261.jpg
./subset/000000181542.jpg
./subset/000000215245.jpg
./subset/000000277005.jpg
./subset/000000288685.jpg
./subset/000000301421.jpg
./subset/000000334371.jpg
./subset/000000348481.jpg
./subset/000000373353.jpg
./subset/000000397681.jpg
./subset/000000414673.jpg
./subset/000000419312.jpg
./subset/000000465822.jpg
./subset/000000475732.jpg
./subset/000000559707.jpg
./subset/000000574315.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

View File

@ -3,35 +3,25 @@
# 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
# Globally set pip break-system-packages option to avoid having to specify it every time
ARG PIP_BREAK_SYSTEM_PACKAGES=1
FROM wheels as rk-wheels FROM wheels as rk-wheels
COPY docker/main/requirements-wheels.txt /requirements-wheels.txt 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 pip3 wheel --wheel-dir=/rk-wheels -c /requirements-wheels.txt -r /requirements-wheels-rk.txt RUN 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/torch-*
FROM deps AS rk-frigate FROM deps AS rk-frigate
ARG TARGETARCH ARG TARGETARCH
ARG PIP_BREAK_SYSTEM_PACKAGES
RUN --mount=type=bind,from=rk-wheels,source=/rk-wheels,target=/deps/rk-wheels \ RUN --mount=type=bind,from=rk-wheels,source=/rk-wheels,target=/deps/rk-wheels \
pip3 install --no-deps -U /deps/rk-wheels/*.whl pip3 install -U /deps/rk-wheels/*.whl
WORKDIR /opt/frigate/ WORKDIR /opt/frigate/
COPY --from=rootfs / / COPY --from=rootfs / /
COPY docker/rockchip/COCO /COCO
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.0.0/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/ RUN rm -rf /usr/lib/btbn-ffmpeg/bin/ffmpeg
ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/6.1-11/ffprobe /usr/lib/ffmpeg/6.0/bin/ RUN rm -rf /usr/lib/btbn-ffmpeg/bin/ffprobe
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/6.1-5/ffmpeg /usr/lib/ffmpeg/6.0/bin/
ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/7.1-1/ffprobe /usr/lib/ffmpeg/7.0/bin/ ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/6.1-5/ffprobe /usr/lib/ffmpeg/6.0/bin/
ENV DEFAULT_FFMPEG_VERSION="6.0" ENV PATH="/usr/lib/ffmpeg/6.0/bin/:${PATH}"
ENV INCLUDED_FFMPEG_VERSIONS="${DEFAULT_FFMPEG_VERSION}:${INCLUDED_FFMPEG_VERSIONS}"

View File

@ -1,82 +0,0 @@
import os
import rknn
import yaml
from rknn.api import RKNN
try:
with open(rknn.__path__[0] + "/VERSION") as file:
tk_version = file.read().strip()
except FileNotFoundError:
pass
try:
with open("/config/conv2rknn.yaml", "r") as config_file:
configuration = yaml.safe_load(config_file)
except FileNotFoundError:
raise Exception("Please place a config file at /config/conv2rknn.yaml")
if configuration["config"] != None:
rknn_config = configuration["config"]
else:
rknn_config = {}
if not os.path.isdir("/config/model_cache/rknn_cache/onnx"):
raise Exception(
"Place the onnx models you want to convert to rknn format in /config/model_cache/rknn_cache/onnx"
)
if "soc" not in configuration:
try:
with open("/proc/device-tree/compatible") as file:
soc = file.read().split(",")[-1].strip("\x00")
except FileNotFoundError:
raise Exception("Make sure to run docker in privileged mode.")
configuration["soc"] = [
soc,
]
if "quantization" not in configuration:
configuration["quantization"] = False
if "output_name" not in configuration:
configuration["output_name"] = "{{input_basename}}"
for input_filename in os.listdir("/config/model_cache/rknn_cache/onnx"):
for soc in configuration["soc"]:
quant = "i8" if configuration["quantization"] else "fp16"
input_path = "/config/model_cache/rknn_cache/onnx/" + input_filename
input_basename = input_filename[: input_filename.rfind(".")]
output_filename = (
configuration["output_name"].format(
quant=quant,
input_basename=input_basename,
soc=soc,
tk_version=tk_version,
)
+ ".rknn"
)
output_path = "/config/model_cache/rknn_cache/" + output_filename
rknn_config["target_platform"] = soc
rknn = RKNN(verbose=True)
rknn.config(**rknn_config)
if rknn.load_onnx(model=input_path) != 0:
raise Exception("Error loading model.")
if (
rknn.build(
do_quantization=configuration["quantization"],
dataset="/COCO/coco_subset_20.txt",
)
!= 0
):
raise Exception("Error building model.")
if rknn.export_rknn(output_path) != 0:
raise Exception("Error exporting rknn model.")

View File

@ -1,2 +1 @@
rknn-toolkit2 == 2.3.2 rknn-toolkit-lite2 @ https://github.com/MarcA711/rknn-toolkit2/releases/download/v2.0.0/rknn_toolkit_lite2-2.0.0b0-cp39-cp39-linux_aarch64.whl
rknn-toolkit-lite2 == 2.3.2

View File

@ -2,49 +2,77 @@
# 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=6.3.3 ARG ROCM=5.7.3
ARG AMDGPU=gfx900 ARG AMDGPU=gfx900
ARG HSA_OVERRIDE_GFX_VERSION ARG HSA_OVERRIDE_GFX_VERSION
ARG HSA_OVERRIDE ARG HSA_OVERRIDE
####################################################################### #######################################################################
FROM wget AS rocm FROM ubuntu:focal as rocm
ARG ROCM ARG ROCM
ARG AMDGPU
RUN apt update && \ RUN apt-get update && apt-get -y upgrade
apt install -y wget gpg && \ RUN apt-get -y install gnupg wget
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 && \ RUN mkdir --parents --mode=0755 /etc/apt/keyrings
apt update && \
apt install -y rocm RUN wget https://repo.radeon.com/rocm/rocm.gpg.key -O - | gpg --dearmor | tee /etc/apt/keyrings/rocm.gpg > /dev/null
COPY docker/rocm/rocm.list /etc/apt/sources.list.d/
COPY docker/rocm/rocm-pin-600 /etc/apt/preferences.d/
RUN apt-get update
RUN apt-get -y install --no-install-recommends migraphx hipfft roctracer
RUN apt-get -y install --no-install-recommends migraphx-dev
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* librocfft*.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* librocsolver*.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 && \
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
RUN mkdir -p /opt/rocm-dist/etc/ld.so.conf.d/ RUN mkdir -p /opt/rocm-dist/etc/ld.so.conf.d/
RUN echo /opt/rocm/lib|tee /opt/rocm-dist/etc/ld.so.conf.d/rocm.conf RUN echo /opt/rocm/lib|tee /opt/rocm-dist/etc/ld.so.conf.d/rocm.conf
#######################################################################
FROM --platform=linux/amd64 debian:11 as debian-base
RUN apt-get update && apt-get -y upgrade
RUN apt-get -y install --no-install-recommends libelf1 libdrm2 libdrm-amdgpu1 libnuma1 kmod
RUN apt-get -y install python3
#######################################################################
# ROCm does not come with migraphx wrappers for python 3.9, so we build it here
FROM debian-base as debian-build
ARG ROCM
COPY --from=rocm /opt/rocm-$ROCM /opt/rocm-$ROCM
RUN ln -s /opt/rocm-$ROCM /opt/rocm
RUN apt-get -y install g++ cmake
RUN apt-get -y install python3-pybind11 python3.9-distutils python3-dev
WORKDIR /opt/build
COPY docker/rocm/migraphx .
RUN mkdir build && cd build && cmake .. && make install
####################################################################### #######################################################################
FROM deps AS deps-prelim FROM deps AS deps-prelim
RUN apt-get update && apt-get install -y libnuma1 # need this to install libnuma1
RUN apt-get update
# no ugprade?!?!
RUN apt-get -y install libnuma1
WORKDIR /opt/frigate WORKDIR /opt/frigate/
COPY --from=rootfs / / COPY --from=rootfs / /
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 \
&& python3 get-pip.py "pip" --break-system-packages
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-openvino \ RUN python3 -m pip install --upgrade pip \
&& pip3 uninstall -y onnxruntime-openvino \
&& pip3 install -r /requirements.txt && pip3 install -r /requirements.txt
####################################################################### #######################################################################
@ -58,12 +86,12 @@ COPY --from=rocm /opt/rocm-$ROCM/share/miopen/db/*$AMDGPU* /opt/rocm-$ROCM/share
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/*gfx908* /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/lib/rocblas/library/*$AMDGPU* /opt/rocm-$ROCM/lib/rocblas/library/
COPY --from=rocm /opt/rocm-dist/ / COPY --from=rocm /opt/rocm-dist/ /
COPY --from=debian-build /opt/rocm/lib/migraphx.cpython-39-x86_64-linux-gnu.so /opt/rocm-$ROCM/lib/
####################################################################### #######################################################################
FROM deps-prelim AS rocm-prelim-hsa-override0 FROM deps-prelim AS rocm-prelim-hsa-override0
ENV HSA_ENABLE_SDMA=0 ENV HSA_ENABLE_SDMA=0
ENV MIGRAPHX_ENABLE_NHWC=1
ENV TF_ROCM_USE_IMMEDIATE_MODE=1
COPY --from=rocm-dist / / COPY --from=rocm-dist / /

View File

@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.1)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
project(migraphx_py)
include_directories(/opt/rocm/include)
find_package(pybind11 REQUIRED)
pybind11_add_module(migraphx migraphx_py.cpp)
target_link_libraries(migraphx PRIVATE /opt/rocm/lib/libmigraphx.so /opt/rocm/lib/libmigraphx_tf.so /opt/rocm/lib/libmigraphx_onnx.so)
install(TARGETS migraphx
COMPONENT python
LIBRARY DESTINATION /opt/rocm/lib
)

View File

@ -0,0 +1,582 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 Advanced Micro Devices, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
#include <migraphx/program.hpp>
#include <migraphx/instruction_ref.hpp>
#include <migraphx/operation.hpp>
#include <migraphx/quantization.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/instruction.hpp>
#include <migraphx/ref/target.hpp>
#include <migraphx/stringutils.hpp>
#include <migraphx/tf.hpp>
#include <migraphx/onnx.hpp>
#include <migraphx/load_save.hpp>
#include <migraphx/register_target.hpp>
#include <migraphx/json.hpp>
#include <migraphx/make_op.hpp>
#include <migraphx/op/common.hpp>
#ifdef HAVE_GPU
#include <migraphx/gpu/hip.hpp>
#endif
using half = half_float::half;
namespace py = pybind11;
#ifdef __clang__
#define MIGRAPHX_PUSH_UNUSED_WARNING \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wused-but-marked-unused\"")
#define MIGRAPHX_POP_WARNING _Pragma("clang diagnostic pop")
#else
#define MIGRAPHX_PUSH_UNUSED_WARNING
#define MIGRAPHX_POP_WARNING
#endif
#define MIGRAPHX_PYBIND11_MODULE(...) \
MIGRAPHX_PUSH_UNUSED_WARNING \
PYBIND11_MODULE(__VA_ARGS__) \
MIGRAPHX_POP_WARNING
#define MIGRAPHX_PYTHON_GENERATE_SHAPE_ENUM(x, t) .value(#x, migraphx::shape::type_t::x)
namespace migraphx {
migraphx::value to_value(py::kwargs kwargs);
migraphx::value to_value(py::list lst);
template <class T, class F>
void visit_py(T x, F f)
{
if(py::isinstance<py::kwargs>(x))
{
f(to_value(x.template cast<py::kwargs>()));
}
else if(py::isinstance<py::list>(x))
{
f(to_value(x.template cast<py::list>()));
}
else if(py::isinstance<py::bool_>(x))
{
f(x.template cast<bool>());
}
else if(py::isinstance<py::int_>(x) or py::hasattr(x, "__index__"))
{
f(x.template cast<int>());
}
else if(py::isinstance<py::float_>(x))
{
f(x.template cast<float>());
}
else if(py::isinstance<py::str>(x))
{
f(x.template cast<std::string>());
}
else if(py::isinstance<migraphx::shape::dynamic_dimension>(x))
{
f(migraphx::to_value(x.template cast<migraphx::shape::dynamic_dimension>()));
}
else
{
MIGRAPHX_THROW("VISIT_PY: Unsupported data type!");
}
}
migraphx::value to_value(py::list lst)
{
migraphx::value v = migraphx::value::array{};
for(auto val : lst)
{
visit_py(val, [&](auto py_val) { v.push_back(py_val); });
}
return v;
}
migraphx::value to_value(py::kwargs kwargs)
{
migraphx::value v = migraphx::value::object{};
for(auto arg : kwargs)
{
auto&& key = py::str(arg.first);
auto&& val = arg.second;
visit_py(val, [&](auto py_val) { v[key] = py_val; });
}
return v;
}
} // namespace migraphx
namespace pybind11 {
namespace detail {
template <>
struct npy_format_descriptor<half>
{
static std::string format()
{
// following: https://docs.python.org/3/library/struct.html#format-characters
return "e";
}
static constexpr auto name() { return _("half"); }
};
} // namespace detail
} // namespace pybind11
template <class F>
void visit_type(const migraphx::shape& s, F f)
{
s.visit_type(f);
}
template <class T, class F>
void visit(const migraphx::raw_data<T>& x, F f)
{
x.visit(f);
}
template <class F>
void visit_types(F f)
{
migraphx::shape::visit_types(f);
}
template <class T>
py::buffer_info to_buffer_info(T& x)
{
migraphx::shape s = x.get_shape();
assert(s.type() != migraphx::shape::tuple_type);
if(s.dynamic())
MIGRAPHX_THROW("MIGRAPHX PYTHON: dynamic shape argument passed to to_buffer_info");
auto strides = s.strides();
std::transform(
strides.begin(), strides.end(), strides.begin(), [&](auto i) { return i * s.type_size(); });
py::buffer_info b;
visit_type(s, [&](auto as) {
// migraphx use int8_t data to store bool type, we need to
// explicitly specify the data type as bool for python
if(s.type() == migraphx::shape::bool_type)
{
b = py::buffer_info(x.data(),
as.size(),
py::format_descriptor<bool>::format(),
s.ndim(),
s.lens(),
strides);
}
else
{
b = py::buffer_info(x.data(),
as.size(),
py::format_descriptor<decltype(as())>::format(),
s.ndim(),
s.lens(),
strides);
}
});
return b;
}
migraphx::shape to_shape(const py::buffer_info& info)
{
migraphx::shape::type_t t;
std::size_t n = 0;
visit_types([&](auto as) {
if(info.format == py::format_descriptor<decltype(as())>::format() or
(info.format == "l" and py::format_descriptor<decltype(as())>::format() == "q") or
(info.format == "L" and py::format_descriptor<decltype(as())>::format() == "Q"))
{
t = as.type_enum();
n = sizeof(as());
}
else if(info.format == "?" and py::format_descriptor<decltype(as())>::format() == "b")
{
t = migraphx::shape::bool_type;
n = sizeof(bool);
}
});
if(n == 0)
{
MIGRAPHX_THROW("MIGRAPHX PYTHON: Unsupported data type " + info.format);
}
auto strides = info.strides;
std::transform(strides.begin(), strides.end(), strides.begin(), [&](auto i) -> std::size_t {
return n > 0 ? i / n : 0;
});
// scalar support
if(info.shape.empty())
{
return migraphx::shape{t};
}
else
{
return migraphx::shape{t, info.shape, strides};
}
}
MIGRAPHX_PYBIND11_MODULE(migraphx, m)
{
py::class_<migraphx::shape> shape_cls(m, "shape");
shape_cls
.def(py::init([](py::kwargs kwargs) {
auto v = migraphx::to_value(kwargs);
auto t = migraphx::shape::parse_type(v.get("type", "float"));
if(v.contains("dyn_dims"))
{
auto dyn_dims =
migraphx::from_value<std::vector<migraphx::shape::dynamic_dimension>>(
v.at("dyn_dims"));
return migraphx::shape(t, dyn_dims);
}
auto lens = v.get<std::size_t>("lens", {1});
if(v.contains("strides"))
return migraphx::shape(t, lens, v.at("strides").to_vector<std::size_t>());
else
return migraphx::shape(t, lens);
}))
.def("type", &migraphx::shape::type)
.def("lens", &migraphx::shape::lens)
.def("strides", &migraphx::shape::strides)
.def("ndim", &migraphx::shape::ndim)
.def("elements", &migraphx::shape::elements)
.def("bytes", &migraphx::shape::bytes)
.def("type_string", &migraphx::shape::type_string)
.def("type_size", &migraphx::shape::type_size)
.def("dyn_dims", &migraphx::shape::dyn_dims)
.def("packed", &migraphx::shape::packed)
.def("transposed", &migraphx::shape::transposed)
.def("broadcasted", &migraphx::shape::broadcasted)
.def("standard", &migraphx::shape::standard)
.def("scalar", &migraphx::shape::scalar)
.def("dynamic", &migraphx::shape::dynamic)
.def("__eq__", std::equal_to<migraphx::shape>{})
.def("__ne__", std::not_equal_to<migraphx::shape>{})
.def("__repr__", [](const migraphx::shape& s) { return migraphx::to_string(s); });
py::enum_<migraphx::shape::type_t>(shape_cls, "type_t")
MIGRAPHX_SHAPE_VISIT_TYPES(MIGRAPHX_PYTHON_GENERATE_SHAPE_ENUM);
py::class_<migraphx::shape::dynamic_dimension>(shape_cls, "dynamic_dimension")
.def(py::init<>())
.def(py::init<std::size_t, std::size_t>())
.def(py::init<std::size_t, std::size_t, std::set<std::size_t>>())
.def_readwrite("min", &migraphx::shape::dynamic_dimension::min)
.def_readwrite("max", &migraphx::shape::dynamic_dimension::max)
.def_readwrite("optimals", &migraphx::shape::dynamic_dimension::optimals)
.def("is_fixed", &migraphx::shape::dynamic_dimension::is_fixed);
py::class_<migraphx::argument>(m, "argument", py::buffer_protocol())
.def_buffer([](migraphx::argument& x) -> py::buffer_info { return to_buffer_info(x); })
.def(py::init([](py::buffer b) {
py::buffer_info info = b.request();
return migraphx::argument(to_shape(info), info.ptr);
}))
.def("get_shape", &migraphx::argument::get_shape)
.def("data_ptr",
[](migraphx::argument& x) { return reinterpret_cast<std::uintptr_t>(x.data()); })
.def("tolist",
[](migraphx::argument& x) {
py::list l{x.get_shape().elements()};
visit(x, [&](auto data) { l = py::cast(data.to_vector()); });
return l;
})
.def("__eq__", std::equal_to<migraphx::argument>{})
.def("__ne__", std::not_equal_to<migraphx::argument>{})
.def("__repr__", [](const migraphx::argument& x) { return migraphx::to_string(x); });
py::class_<migraphx::target>(m, "target");
py::class_<migraphx::instruction_ref>(m, "instruction_ref")
.def("shape", [](migraphx::instruction_ref i) { return i->get_shape(); })
.def("op", [](migraphx::instruction_ref i) { return i->get_operator(); });
py::class_<migraphx::module, std::unique_ptr<migraphx::module, py::nodelete>>(m, "module")
.def("print", [](const migraphx::module& mm) { std::cout << mm << std::endl; })
.def(
"add_instruction",
[](migraphx::module& mm,
const migraphx::operation& op,
std::vector<migraphx::instruction_ref>& args,
std::vector<migraphx::module*>& mod_args) {
return mm.add_instruction(op, args, mod_args);
},
py::arg("op"),
py::arg("args"),
py::arg("mod_args") = std::vector<migraphx::module*>{})
.def(
"add_literal",
[](migraphx::module& mm, py::buffer data) {
py::buffer_info info = data.request();
auto literal_shape = to_shape(info);
return mm.add_literal(literal_shape, reinterpret_cast<char*>(info.ptr));
},
py::arg("data"))
.def(
"add_parameter",
[](migraphx::module& mm, const std::string& name, const migraphx::shape shape) {
return mm.add_parameter(name, shape);
},
py::arg("name"),
py::arg("shape"))
.def(
"add_return",
[](migraphx::module& mm, std::vector<migraphx::instruction_ref>& args) {
return mm.add_return(args);
},
py::arg("args"))
.def("__repr__", [](const migraphx::module& mm) { return migraphx::to_string(mm); });
py::class_<migraphx::program>(m, "program")
.def(py::init([]() { return migraphx::program(); }))
.def("get_parameter_names", &migraphx::program::get_parameter_names)
.def("get_parameter_shapes", &migraphx::program::get_parameter_shapes)
.def("get_output_shapes", &migraphx::program::get_output_shapes)
.def("is_compiled", &migraphx::program::is_compiled)
.def(
"compile",
[](migraphx::program& p,
const migraphx::target& t,
bool offload_copy,
bool fast_math,
bool exhaustive_tune) {
migraphx::compile_options options;
options.offload_copy = offload_copy;
options.fast_math = fast_math;
options.exhaustive_tune = exhaustive_tune;
p.compile(t, options);
},
py::arg("t"),
py::arg("offload_copy") = true,
py::arg("fast_math") = true,
py::arg("exhaustive_tune") = false)
.def("get_main_module", [](const migraphx::program& p) { return p.get_main_module(); })
.def(
"create_module",
[](migraphx::program& p, const std::string& name) { return p.create_module(name); },
py::arg("name"))
.def("run",
[](migraphx::program& p, py::dict params) {
migraphx::parameter_map pm;
for(auto x : params)
{
std::string key = x.first.cast<std::string>();
py::buffer b = x.second.cast<py::buffer>();
py::buffer_info info = b.request();
pm[key] = migraphx::argument(to_shape(info), info.ptr);
}
return p.eval(pm);
})
.def("run_async",
[](migraphx::program& p,
py::dict params,
std::uintptr_t stream,
std::string stream_name) {
migraphx::parameter_map pm;
for(auto x : params)
{
std::string key = x.first.cast<std::string>();
py::buffer b = x.second.cast<py::buffer>();
py::buffer_info info = b.request();
pm[key] = migraphx::argument(to_shape(info), info.ptr);
}
migraphx::execution_environment exec_env{
migraphx::any_ptr(reinterpret_cast<void*>(stream), stream_name), true};
return p.eval(pm, exec_env);
})
.def("sort", &migraphx::program::sort)
.def("print", [](const migraphx::program& p) { std::cout << p << std::endl; })
.def("__eq__", std::equal_to<migraphx::program>{})
.def("__ne__", std::not_equal_to<migraphx::program>{})
.def("__repr__", [](const migraphx::program& p) { return migraphx::to_string(p); });
py::class_<migraphx::operation> op(m, "op");
op.def(py::init([](const std::string& name, py::kwargs kwargs) {
migraphx::value v = migraphx::value::object{};
if(kwargs)
{
v = migraphx::to_value(kwargs);
}
return migraphx::make_op(name, v);
}))
.def("name", &migraphx::operation::name);
py::enum_<migraphx::op::pooling_mode>(op, "pooling_mode")
.value("average", migraphx::op::pooling_mode::average)
.value("max", migraphx::op::pooling_mode::max)
.value("lpnorm", migraphx::op::pooling_mode::lpnorm);
py::enum_<migraphx::op::rnn_direction>(op, "rnn_direction")
.value("forward", migraphx::op::rnn_direction::forward)
.value("reverse", migraphx::op::rnn_direction::reverse)
.value("bidirectional", migraphx::op::rnn_direction::bidirectional);
m.def(
"argument_from_pointer",
[](const migraphx::shape shape, const int64_t address) {
return migraphx::argument(shape, reinterpret_cast<void*>(address));
},
py::arg("shape"),
py::arg("address"));
m.def(
"parse_tf",
[](const std::string& filename,
bool is_nhwc,
unsigned int batch_size,
std::unordered_map<std::string, std::vector<std::size_t>> map_input_dims,
std::vector<std::string> output_names) {
return migraphx::parse_tf(
filename, migraphx::tf_options{is_nhwc, batch_size, map_input_dims, output_names});
},
"Parse tf protobuf (default format is nhwc)",
py::arg("filename"),
py::arg("is_nhwc") = true,
py::arg("batch_size") = 1,
py::arg("map_input_dims") = std::unordered_map<std::string, std::vector<std::size_t>>(),
py::arg("output_names") = std::vector<std::string>());
m.def(
"parse_onnx",
[](const std::string& filename,
unsigned int default_dim_value,
migraphx::shape::dynamic_dimension default_dyn_dim_value,
std::unordered_map<std::string, std::vector<std::size_t>> map_input_dims,
std::unordered_map<std::string, std::vector<migraphx::shape::dynamic_dimension>>
map_dyn_input_dims,
bool skip_unknown_operators,
bool print_program_on_error,
int64_t max_loop_iterations) {
migraphx::onnx_options options;
options.default_dim_value = default_dim_value;
options.default_dyn_dim_value = default_dyn_dim_value;
options.map_input_dims = map_input_dims;
options.map_dyn_input_dims = map_dyn_input_dims;
options.skip_unknown_operators = skip_unknown_operators;
options.print_program_on_error = print_program_on_error;
options.max_loop_iterations = max_loop_iterations;
return migraphx::parse_onnx(filename, options);
},
"Parse onnx file",
py::arg("filename"),
py::arg("default_dim_value") = 0,
py::arg("default_dyn_dim_value") = migraphx::shape::dynamic_dimension{1, 1},
py::arg("map_input_dims") = std::unordered_map<std::string, std::vector<std::size_t>>(),
py::arg("map_dyn_input_dims") =
std::unordered_map<std::string, std::vector<migraphx::shape::dynamic_dimension>>(),
py::arg("skip_unknown_operators") = false,
py::arg("print_program_on_error") = false,
py::arg("max_loop_iterations") = 10);
m.def(
"parse_onnx_buffer",
[](const std::string& onnx_buffer,
unsigned int default_dim_value,
migraphx::shape::dynamic_dimension default_dyn_dim_value,
std::unordered_map<std::string, std::vector<std::size_t>> map_input_dims,
std::unordered_map<std::string, std::vector<migraphx::shape::dynamic_dimension>>
map_dyn_input_dims,
bool skip_unknown_operators,
bool print_program_on_error) {
migraphx::onnx_options options;
options.default_dim_value = default_dim_value;
options.default_dyn_dim_value = default_dyn_dim_value;
options.map_input_dims = map_input_dims;
options.map_dyn_input_dims = map_dyn_input_dims;
options.skip_unknown_operators = skip_unknown_operators;
options.print_program_on_error = print_program_on_error;
return migraphx::parse_onnx_buffer(onnx_buffer, options);
},
"Parse onnx file",
py::arg("filename"),
py::arg("default_dim_value") = 0,
py::arg("default_dyn_dim_value") = migraphx::shape::dynamic_dimension{1, 1},
py::arg("map_input_dims") = std::unordered_map<std::string, std::vector<std::size_t>>(),
py::arg("map_dyn_input_dims") =
std::unordered_map<std::string, std::vector<migraphx::shape::dynamic_dimension>>(),
py::arg("skip_unknown_operators") = false,
py::arg("print_program_on_error") = false);
m.def(
"load",
[](const std::string& name, const std::string& format) {
migraphx::file_options options;
options.format = format;
return migraphx::load(name, options);
},
"Load MIGraphX program",
py::arg("filename"),
py::arg("format") = "msgpack");
m.def(
"save",
[](const migraphx::program& p, const std::string& name, const std::string& format) {
migraphx::file_options options;
options.format = format;
return migraphx::save(p, name, options);
},
"Save MIGraphX program",
py::arg("p"),
py::arg("filename"),
py::arg("format") = "msgpack");
m.def("get_target", &migraphx::make_target);
m.def("create_argument", [](const migraphx::shape& s, const std::vector<double>& values) {
if(values.size() != s.elements())
MIGRAPHX_THROW("Values and shape elements do not match");
migraphx::argument a{s};
a.fill(values.begin(), values.end());
return a;
});
m.def("generate_argument", &migraphx::generate_argument, py::arg("s"), py::arg("seed") = 0);
m.def("fill_argument", &migraphx::fill_argument, py::arg("s"), py::arg("value"));
m.def("quantize_fp16",
&migraphx::quantize_fp16,
py::arg("prog"),
py::arg("ins_names") = std::vector<std::string>{"all"});
m.def("quantize_int8",
&migraphx::quantize_int8,
py::arg("prog"),
py::arg("t"),
py::arg("calibration") = std::vector<migraphx::parameter_map>{},
py::arg("ins_names") = std::vector<std::string>{"dot", "convolution"});
#ifdef HAVE_GPU
m.def("allocate_gpu", &migraphx::gpu::allocate_gpu, py::arg("s"), py::arg("host") = false);
m.def("to_gpu", &migraphx::gpu::to_gpu, py::arg("arg"), py::arg("host") = false);
m.def("from_gpu", &migraphx::gpu::from_gpu);
m.def("gpu_sync", [] { migraphx::gpu::gpu_sync(); });
#endif
#ifdef VERSION_INFO
m.attr("__version__") = VERSION_INFO;
#else
m.attr("__version__") = "dev";
#endif
}

View File

@ -1 +1 @@
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 onnxruntime-rocm @ https://github.com/NickM-27/frigate-onnxruntime-rocm/releases/download/v1.0.0/onnxruntime_rocm-1.17.3-cp39-cp39-linux_x86_64.whl

3
docker/rocm/rocm-pin-600 Normal file
View File

@ -0,0 +1,3 @@
Package: *
Pin: release o=repo.radeon.com
Pin-Priority: 600

View File

@ -2,7 +2,7 @@ variable "AMDGPU" {
default = "gfx900" default = "gfx900"
} }
variable "ROCM" { variable "ROCM" {
default = "6.3.3" default = "5.7.3"
} }
variable "HSA_OVERRIDE_GFX_VERSION" { variable "HSA_OVERRIDE_GFX_VERSION" {
default = "" default = ""
@ -10,13 +10,6 @@ variable "HSA_OVERRIDE_GFX_VERSION" {
variable "HSA_OVERRIDE" { variable "HSA_OVERRIDE" {
default = "1" default = "1"
} }
target wget {
dockerfile = "docker/main/Dockerfile"
platforms = ["linux/amd64"]
target = "wget"
}
target deps { target deps {
dockerfile = "docker/main/Dockerfile" dockerfile = "docker/main/Dockerfile"
platforms = ["linux/amd64"] platforms = ["linux/amd64"]
@ -33,7 +26,6 @@ target rocm {
dockerfile = "docker/rocm/Dockerfile" dockerfile = "docker/rocm/Dockerfile"
contexts = { contexts = {
deps = "target:deps", deps = "target:deps",
wget = "target:wget",
rootfs = "target:rootfs" rootfs = "target:rootfs"
} }
platforms = ["linux/amd64"] platforms = ["linux/amd64"]

1
docker/rocm/rocm.list Normal file
View File

@ -0,0 +1 @@
deb [arch=amd64 signed-by=/etc/apt/keyrings/rocm.gpg] https://repo.radeon.com/rocm/apt/5.7.3 focal main

View File

@ -6,12 +6,13 @@ ARG DEBIAN_FRONTEND=noninteractive
FROM deps AS rpi-deps FROM deps AS rpi-deps
ARG TARGETARCH ARG TARGETARCH
RUN rm -rf /usr/lib/btbn-ffmpeg/
# Install dependencies # Install dependencies
RUN --mount=type=bind,source=docker/rpi/install_deps.sh,target=/deps/install_deps.sh \ RUN --mount=type=bind,source=docker/rpi/install_deps.sh,target=/deps/install_deps.sh \
/deps/install_deps.sh /deps/install_deps.sh
ENV DEFAULT_FFMPEG_VERSION="rpi" ENV LIBAVFORMAT_VERSION_MAJOR=58
ENV INCLUDED_FFMPEG_VERSIONS="${DEFAULT_FFMPEG_VERSION}:${INCLUDED_FFMPEG_VERSIONS}"
WORKDIR /opt/frigate/ WORKDIR /opt/frigate/
COPY --from=rootfs / / COPY --from=rootfs / /

View File

@ -18,17 +18,13 @@ apt-get -qq install --no-install-recommends -y \
mkdir -p -m 600 /root/.gnupg mkdir -p -m 600 /root/.gnupg
# enable non-free repo # enable non-free repo
echo "deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware" | tee -a /etc/apt/sources.list sed -i -e's/ main/ main contrib non-free/g' /etc/apt/sources.list
apt update
# ffmpeg -> arm64 # ffmpeg -> arm64
if [[ "${TARGETARCH}" == "arm64" ]]; then if [[ "${TARGETARCH}" == "arm64" ]]; then
# add raspberry pi repo # add raspberry pi repo
gpg --no-default-keyring --keyring /usr/share/keyrings/raspbian.gpg --keyserver keyserver.ubuntu.com --recv-keys 82B129927FA3303E gpg --no-default-keyring --keyring /usr/share/keyrings/raspbian.gpg --keyserver keyserver.ubuntu.com --recv-keys 82B129927FA3303E
echo "deb [signed-by=/usr/share/keyrings/raspbian.gpg] https://archive.raspberrypi.org/debian/ bookworm main" | tee /etc/apt/sources.list.d/raspi.list echo "deb [signed-by=/usr/share/keyrings/raspbian.gpg] https://archive.raspberrypi.org/debian/ bullseye main" | tee /etc/apt/sources.list.d/raspi.list
apt-get -qq update apt-get -qq update
apt-get -qq install --no-install-recommends --no-install-suggests -y ffmpeg apt-get -qq install --no-install-recommends --no-install-suggests -y ffmpeg
mkdir -p /usr/lib/ffmpeg/rpi/bin
ln -svf /usr/bin/ffmpeg /usr/lib/ffmpeg/rpi/bin/ffmpeg
ln -svf /usr/bin/ffprobe /usr/lib/ffmpeg/rpi/bin/ffprobe
fi fi

View File

@ -3,32 +3,47 @@
# 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
# Globally set pip break-system-packages option to avoid having to specify it every time # Make this a separate target so it can be built/cached optionally
ARG PIP_BREAK_SYSTEM_PACKAGES=1 FROM wheels as trt-wheels
ARG DEBIAN_FRONTEND
ARG TARGETARCH
FROM wheels AS trt-wheels # Add TensorRT wheels to another folder
ARG PIP_BREAK_SYSTEM_PACKAGES
# 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 mkdir -p /trt-wheels && pip3 wheel --wheel-dir=/trt-wheels -r /requirements-tensorrt.txt
RUN pip3 wheel --wheel-dir=/trt-wheels -c /requirements-wheels.txt -r /requirements-tensorrt.txt
FROM deps AS frigate-tensorrt # Build CuDNN
ARG PIP_BREAK_SYSTEM_PACKAGES FROM wget AS cudnn-deps
ARG COMPUTE_LEVEL
RUN apt-get update \
&& apt-get install -y git build-essential
RUN wget https://developer.download.nvidia.com/compute/cuda/repos/debian11/x86_64/cuda-keyring_1.1-1_all.deb \
&& dpkg -i cuda-keyring_1.1-1_all.deb \
&& apt-get update \
&& apt-get -y install cuda-toolkit \
&& rm -rf /var/lib/apt/lists/*
FROM tensorrt-base AS frigate-tensorrt
ENV TRT_VER=8.5.3
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 uninstall -y onnxruntime-openvino tensorflow-cpu \ pip3 install -U /deps/trt-wheels/*.whl && \
&& pip3 install -U /deps/trt-wheels/*.whl ldconfig
COPY --from=cudnn-deps /usr/local/cuda-12.6 /usr/local/cuda
COPY --from=rootfs / /
COPY docker/tensorrt/detector/rootfs/etc/ld.so.conf.d /etc/ld.so.conf.d
RUN ldconfig
ENV LD_LIBRARY_PATH=/usr/local/lib/python3.9/dist-packages/tensorrt:/usr/local/cuda/lib64:/usr/local/lib/python3.9/dist-packages/nvidia/cufft/lib
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=cudnn-deps /usr/local/cuda-12.6 /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

View File

@ -1,84 +1,26 @@
# 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
# Add deadsnakes PPA for python3.11
RUN apt-get -qq update && \
apt-get -qq install -y --no-install-recommends \
software-properties-common \
&& add-apt-repository ppa:deadsnakes/ppa
# 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 --no-install-recommends \ && apt-get -qq install -y --no-install-recommends \
python3.11 python3.11-dev \ python3.9 python3.9-dev \
wget build-essential cmake git \ wget build-essential cmake git \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Ensure python3 defaults to python3.11 # Ensure python3 defaults to python3.9
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1 RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1
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 \
&& python3 get-pip.py "pip" && python3 get-pip.py "pip"
FROM build-wheels AS trt-wheels FROM build-wheels AS trt-wheels
ARG DEBIAN_FRONTEND ARG DEBIAN_FRONTEND
ARG TARGETARCH ARG TARGETARCH
@ -99,11 +41,11 @@ 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
ADD https://nvidia.box.com/shared/static/9aemm4grzbbkfaesg5l7fplgjtmswhj8.whl /tmp/onnxruntime_gpu-1.15.1-cp39-cp39-linux_aarch64.whl
RUN pip3 wheel --wheel-dir=/trt-wheels -r /requirements-tensorrt.txt RUN pip3 uninstall -y onnxruntime-openvino \
&& pip3 wheel --wheel-dir=/trt-wheels -r /requirements-tensorrt.txt \
# See https://elinux.org/Jetson_Zoo#ONNX_Runtime && pip3 install --no-deps /tmp/onnxruntime_gpu-1.15.1-cp39-cp39-linux_aarch64.whl
ADD https://nvidia.box.com/shared/static/9yvw05k6u343qfnkhdv2x6xhygze0aq1.whl /trt-wheels/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
@ -125,31 +67,17 @@ RUN --mount=type=bind,source=docker/tensorrt/build_jetson_ffmpeg.sh,target=/deps
# Frigate w/ TensorRT for NVIDIA Jetson platforms # Frigate w/ TensorRT for NVIDIA Jetson platforms
FROM tensorrt-base AS frigate-tensorrt FROM tensorrt-base AS frigate-tensorrt
RUN apt-get update \ RUN apt-get update \
&& apt-get install -y python-is-python3 libprotobuf23 \ && apt-get install -y python-is-python3 libprotobuf17 \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
RUN rm -rf /usr/lib/btbn-ffmpeg/
COPY --from=jetson-ffmpeg /rootfs / COPY --from=jetson-ffmpeg /rootfs /
ENV DEFAULT_FFMPEG_VERSION="jetson"
ENV INCLUDED_FFMPEG_VERSIONS="${DEFAULT_FFMPEG_VERSION}:${INCLUDED_FFMPEG_VERSIONS}"
# ffmpeg runtime dependencies
RUN apt-get -qq update \
&& apt-get -qq install -y --no-install-recommends \
libx264-163 libx265-199 libegl1 \
&& rm -rf /var/lib/apt/lists/*
# Fixes "Error loading shared libs"
RUN mkdir -p /etc/ld.so.conf.d && echo /usr/lib/ffmpeg/jetson/lib/ > /etc/ld.so.conf.d/ffmpeg.conf
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 /deps/trt-model-wheels/*.whl \
&& ldconfig && ldconfig
WORKDIR /opt/frigate/ WORKDIR /opt/frigate/
COPY --from=rootfs / / COPY --from=rootfs / /
# Fixes "Error importing detector runtime: /usr/lib/aarch64-linux-gnu/libstdc++.so.6: cannot allocate memory in static TLS block"
ENV LD_PRELOAD /usr/lib/aarch64-linux-gnu/libstdc++.so.6

View File

@ -0,0 +1,31 @@
# 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.03-py3
# Build TensorRT-specific library
FROM ${TRT_BASE} AS trt-deps
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
# 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 --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 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

View File

@ -5,7 +5,7 @@
set -euxo pipefail set -euxo pipefail
INSTALL_PREFIX=/rootfs/usr/lib/ffmpeg/jetson INSTALL_PREFIX=/rootfs/usr/local
apt-get -qq update apt-get -qq update
apt-get -qq install -y --no-install-recommends build-essential ccache clang cmake pkg-config apt-get -qq install -y --no-install-recommends build-essential ccache clang cmake pkg-config
@ -14,27 +14,14 @@ apt-get -qq install -y --no-install-recommends libx264-dev libx265-dev
pushd /tmp pushd /tmp
# Install libnvmpi to enable nvmpi decoders (h264_nvmpi, hevc_nvmpi) # Install libnvmpi to enable nvmpi decoders (h264_nvmpi, hevc_nvmpi)
if [ -e /usr/local/cuda-12 ]; then if [ -e /usr/local/cuda-10.2 ]; then
# assume Jetpack 6.2
apt-key adv --fetch-key https://repo.download.nvidia.com/jetson/jetson-ota-public.asc
echo "deb https://repo.download.nvidia.com/jetson/common r36.4 main" >> /etc/apt/sources.list.d/nvidia-l4t-apt-source.list
echo "deb https://repo.download.nvidia.com/jetson/t234 r36.4 main" >> /etc/apt/sources.list.d/nvidia-l4t-apt-source.list
echo "deb https://repo.download.nvidia.com/jetson/ffmpeg r36.4 main" >> /etc/apt/sources.list.d/nvidia-l4t-apt-source.list
mkdir -p /opt/nvidia/l4t-packages/
touch /opt/nvidia/l4t-packages/.nv-l4t-disable-boot-fw-update-in-preinstall
apt-get update
apt-get -qq install -y --no-install-recommends -o Dpkg::Options::="--force-confold" nvidia-l4t-jetson-multimedia-api
elif [ -e /usr/local/cuda-10.2 ]; then
# assume Jetpack 4.X # assume Jetpack 4.X
wget -q https://developer.nvidia.com/embedded/L4T/r32_Release_v5.0/T186/Jetson_Multimedia_API_R32.5.0_aarch64.tbz2 -O jetson_multimedia_api.tbz2 wget -q https://developer.nvidia.com/embedded/L4T/r32_Release_v5.0/T186/Jetson_Multimedia_API_R32.5.0_aarch64.tbz2 -O jetson_multimedia_api.tbz2
tar xaf jetson_multimedia_api.tbz2 -C / && rm jetson_multimedia_api.tbz2
else else
# assume Jetpack 5.X # assume Jetpack 5.X
wget -q https://developer.nvidia.com/downloads/embedded/l4t/r35_release_v3.1/release/jetson_multimedia_api_r35.3.1_aarch64.tbz2 -O jetson_multimedia_api.tbz2 wget -q https://developer.nvidia.com/downloads/embedded/l4t/r35_release_v3.1/release/jetson_multimedia_api_r35.3.1_aarch64.tbz2 -O jetson_multimedia_api.tbz2
tar xaf jetson_multimedia_api.tbz2 -C / && rm jetson_multimedia_api.tbz2
fi fi
tar xaf jetson_multimedia_api.tbz2 -C / && rm jetson_multimedia_api.tbz2
wget -q https://github.com/AndBobsYourUncle/jetson-ffmpeg/archive/9c17b09.zip -O jetson-ffmpeg.zip wget -q https://github.com/AndBobsYourUncle/jetson-ffmpeg/archive/9c17b09.zip -O jetson-ffmpeg.zip
unzip jetson-ffmpeg.zip && rm jetson-ffmpeg.zip && mv jetson-ffmpeg-* jetson-ffmpeg && cd jetson-ffmpeg unzip jetson-ffmpeg.zip && rm jetson-ffmpeg.zip && mv jetson-ffmpeg-* jetson-ffmpeg && cd jetson-ffmpeg

View File

@ -6,23 +6,23 @@ mkdir -p /trt-wheels
if [[ "${TARGETARCH}" == "arm64" ]]; then if [[ "${TARGETARCH}" == "arm64" ]]; then
# NVIDIA supplies python-tensorrt for python3.10, but frigate uses python3.11, # NVIDIA supplies python-tensorrt for python3.8, but frigate uses python3.9,
# so we must build python-tensorrt ourselves. # so we must build python-tensorrt ourselves.
# Get python-tensorrt source # Get python-tensorrt source
mkdir -p /workspace mkdir /workspace
cd /workspace cd /workspace
git clone -b release/8.6 https://github.com/NVIDIA/TensorRT.git --depth=1 git clone -b ${TENSORRT_VER} https://github.com/NVIDIA/TensorRT.git --depth=1
# Collect dependencies # Collect dependencies
EXT_PATH=/workspace/external && mkdir -p $EXT_PATH EXT_PATH=/workspace/external && mkdir -p $EXT_PATH
pip3 install pybind11 && ln -s /usr/local/lib/python3.11/dist-packages/pybind11 $EXT_PATH/pybind11 pip3 install pybind11 && ln -s /usr/local/lib/python3.9/dist-packages/pybind11 $EXT_PATH/pybind11
ln -s /usr/include/python3.11 $EXT_PATH/python3.11 ln -s /usr/include/python3.9 $EXT_PATH/python3.9
ln -s /usr/include/aarch64-linux-gnu/NvOnnxParser.h /workspace/TensorRT/parsers/onnx/ ln -s /usr/include/aarch64-linux-gnu/NvOnnxParser.h /workspace/TensorRT/parsers/onnx/
# Build wheel # Build wheel
cd /workspace/TensorRT/python cd /workspace/TensorRT/python
EXT_PATH=$EXT_PATH PYTHON_MAJOR_VERSION=3 PYTHON_MINOR_VERSION=11 TARGET_ARCHITECTURE=aarch64 TENSORRT_MODULE=tensorrt /bin/bash ./build.sh EXT_PATH=$EXT_PATH PYTHON_MAJOR_VERSION=3 PYTHON_MINOR_VERSION=9 TARGET_ARCHITECTURE=aarch64 /bin/bash ./build.sh
mv build/bindings_wheel/dist/*.whl /trt-wheels/ mv build/dist/*.whl /trt-wheels/
fi fi

View File

@ -1,6 +1,6 @@
/usr/local/lib/python3.11/dist-packages/nvidia/cudnn/lib /usr/local/lib
/usr/local/lib/python3.11/dist-packages/nvidia/cuda_runtime/lib /usr/local/lib/python3.9/dist-packages/nvidia/cudnn/lib
/usr/local/lib/python3.11/dist-packages/nvidia/cublas/lib /usr/local/lib/python3.9/dist-packages/nvidia/cuda_runtime/lib
/usr/local/lib/python3.11/dist-packages/nvidia/cufft/lib /usr/local/lib/python3.9/dist-packages/nvidia/cublas/lib
/usr/local/lib/python3.11/dist-packages/nvidia/curand/lib/ /usr/local/lib/python3.9/dist-packages/nvidia/cuda_nvrtc/lib
/usr/local/lib/python3.11/dist-packages/nvidia/cuda_nvrtc/lib/ /usr/local/lib/python3.9/dist-packages/tensorrt

View File

@ -20,7 +20,7 @@ FIRST_MODEL=true
MODEL_DOWNLOAD="" MODEL_DOWNLOAD=""
MODEL_CONVERT="" MODEL_CONVERT=""
if [ -z "$YOLO_MODELS" ]; then if [ -z "$YOLO_MODELS"]; then
echo "tensorrt model preparation disabled" echo "tensorrt model preparation disabled"
exit 0 exit 0
fi fi
@ -64,7 +64,7 @@ fi
# order to run libyolo here. # order to run libyolo here.
# On Jetpack 5.0, these libraries are not mounted by the runtime and are supplied by the image. # On Jetpack 5.0, these libraries are not mounted by the runtime and are supplied by the image.
if [[ "$(arch)" == "aarch64" ]]; then if [[ "$(arch)" == "aarch64" ]]; then
if [[ ! -e /usr/lib/aarch64-linux-gnu/tegra && ! -e /usr/lib/aarch64-linux-gnu/tegra-egl ]]; then if [[ ! -e /usr/lib/aarch64-linux-gnu/tegra ]]; then
echo "ERROR: Container must be launched with nvidia runtime" echo "ERROR: Container must be launched with nvidia runtime"
exit 1 exit 1
elif [[ ! -e /usr/lib/aarch64-linux-gnu/libnvinfer.so.8 || elif [[ ! -e /usr/lib/aarch64-linux-gnu/libnvinfer.so.8 ||

View File

@ -1,18 +1,14 @@
# NVidia TensorRT Support (amd64 only) # 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.5.82; platform_machine == 'x86_64' tensorrt == 8.5.3.*; platform_machine == 'x86_64'
nvidia-cublas-cu12==12.5.3.*; platform_machine == 'x86_64' cuda-python == 11.8; platform_machine == 'x86_64'
nvidia-cudnn-cu12==9.3.0.*; platform_machine == 'x86_64' cython == 0.29.*; platform_machine == 'x86_64'
nvidia-cufft-cu12==11.2.3.*; platform_machine == 'x86_64' nvidia-cuda-runtime-cu12 == 12.1.*; platform_machine == 'x86_64'
nvidia-curand-cu12==10.3.6.*; platform_machine == 'x86_64' nvidia-cuda-runtime-cu11 == 11.8.*; platform_machine == 'x86_64'
nvidia_cuda_nvcc_cu12==12.5.82; platform_machine == 'x86_64' nvidia-cublas-cu11 == 11.11.3.6; platform_machine == 'x86_64'
nvidia-cuda-nvrtc-cu12==12.5.82; platform_machine == 'x86_64' nvidia-cudnn-cu11 == 8.6.0.*; platform_machine == 'x86_64'
nvidia_cuda_runtime_cu12==12.5.82; platform_machine == 'x86_64' nvidia-cufft-cu11==10.*; platform_machine == 'x86_64'
nvidia_cusolver_cu12==11.6.3.*; platform_machine == 'x86_64'
nvidia_cusparse_cu12==12.5.1.*; platform_machine == 'x86_64'
nvidia_nccl_cu12==2.23.4; platform_machine == 'x86_64'
nvidia_nvjitlink_cu12==12.5.82; platform_machine == 'x86_64'
onnx==1.16.*; platform_machine == 'x86_64' onnx==1.16.*; platform_machine == 'x86_64'
onnxruntime-gpu==1.20.*; platform_machine == 'x86_64' onnxruntime-gpu==1.18.*; platform_machine == 'x86_64'
protobuf==3.20.3; platform_machine == 'x86_64' protobuf==3.20.3; platform_machine == 'x86_64'

View File

@ -1 +1 @@
cuda-python == 12.6.*; platform_machine == 'aarch64' cuda-python == 11.7; platform_machine == 'aarch64'

View File

@ -13,29 +13,13 @@ variable "TRT_BASE" {
variable "COMPUTE_LEVEL" { variable "COMPUTE_LEVEL" {
default = "" default = ""
} }
variable "BASE_HOOK" {
# Ensure an up-to-date python 3.11 is available in jetson images
default = <<EOT
if grep -iq \"ubuntu\" /etc/os-release; then
. /etc/os-release
# Add the deadsnakes PPA repository
echo "deb https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu $VERSION_CODENAME main" >> /etc/apt/sources.list.d/deadsnakes.list
echo "deb-src https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu $VERSION_CODENAME main" >> /etc/apt/sources.list.d/deadsnakes.list
# Add deadsnakes signing key
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F23C5A6CF475977595C89F51BA6932366A755776
fi
EOT
}
target "_build_args" { target "_build_args" {
args = { args = {
BASE_IMAGE = BASE_IMAGE, BASE_IMAGE = BASE_IMAGE,
SLIM_BASE = SLIM_BASE, SLIM_BASE = SLIM_BASE,
TRT_BASE = TRT_BASE, TRT_BASE = TRT_BASE,
COMPUTE_LEVEL = COMPUTE_LEVEL, COMPUTE_LEVEL = COMPUTE_LEVEL
BASE_HOOK = BASE_HOOK
} }
platforms = ["linux/${ARCH}"] platforms = ["linux/${ARCH}"]
} }
@ -79,14 +63,23 @@ 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"
wheels = "target:wheels"
} }
target = "frigate-tensorrt" target = "frigate-tensorrt"
inherits = ["_build_args"] inherits = ["_build_args"]

View File

@ -1,41 +1,41 @@
BOARDS += trt BOARDS += trt
JETPACK4_BASE ?= timongentzsch/l4t-ubuntu20-opencv:latest # L4T 32.7.1 JetPack 4.6.1
JETPACK5_BASE ?= nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime # L4T 35.3.1 JetPack 5.1.1 JETPACK5_BASE ?= nvcr.io/nvidia/l4t-tensorrt:r8.5.2-runtime # L4T 35.3.1 JetPack 5.1.1
JETPACK6_BASE ?= nvcr.io/nvidia/tensorrt:23.12-py3-igpu
X86_DGPU_ARGS := ARCH=amd64 COMPUTE_LEVEL="50 60 70 80 90" X86_DGPU_ARGS := ARCH=amd64 COMPUTE_LEVEL="50 60 70 80 90"
JETPACK4_ARGS := ARCH=arm64 BASE_IMAGE=$(JETPACK4_BASE) SLIM_BASE=$(JETPACK4_BASE) TRT_BASE=$(JETPACK4_BASE)
JETPACK5_ARGS := ARCH=arm64 BASE_IMAGE=$(JETPACK5_BASE) SLIM_BASE=$(JETPACK5_BASE) TRT_BASE=$(JETPACK5_BASE) JETPACK5_ARGS := ARCH=arm64 BASE_IMAGE=$(JETPACK5_BASE) SLIM_BASE=$(JETPACK5_BASE) TRT_BASE=$(JETPACK5_BASE)
JETPACK6_ARGS := ARCH=arm64 BASE_IMAGE=$(JETPACK6_BASE) SLIM_BASE=$(JETPACK6_BASE) TRT_BASE=$(JETPACK6_BASE)
local-trt: version local-trt: version
$(X86_DGPU_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \ $(X86_DGPU_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
--set tensorrt.tags=frigate:latest-tensorrt \ --set tensorrt.tags=frigate:latest-tensorrt \
--load --load
local-trt-jp4: version
$(JETPACK4_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
--set tensorrt.tags=frigate:latest-tensorrt-jp4 \
--load
local-trt-jp5: version local-trt-jp5: version
$(JETPACK5_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \ $(JETPACK5_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
--set tensorrt.tags=frigate:latest-tensorrt-jp5 \ --set tensorrt.tags=frigate:latest-tensorrt-jp5 \
--load --load
local-trt-jp6: version
$(JETPACK6_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
--set tensorrt.tags=frigate:latest-tensorrt-jp6 \
--load
build-trt: build-trt:
$(X86_DGPU_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \ $(X86_DGPU_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
--set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt --set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt
$(JETPACK4_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
--set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt-jp4
$(JETPACK5_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \ $(JETPACK5_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
--set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt-jp5 --set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt-jp5
$(JETPACK6_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
--set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt-jp6
push-trt: build-trt push-trt: build-trt
$(X86_DGPU_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \ $(X86_DGPU_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
--set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt \ --set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt \
--push --push
$(JETPACK4_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
--set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt-jp4 \
--push
$(JETPACK5_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \ $(JETPACK5_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
--set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt-jp5 \ --set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt-jp5 \
--push --push
$(JETPACK6_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
--set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt-jp6 \
--push

View File

@ -4,9 +4,7 @@ title: Advanced Options
sidebar_label: Advanced Options sidebar_label: Advanced Options
--- ---
### Logging ### `logger`
#### Frigate `logger`
Change the default log level for troubleshooting purposes. Change the default log level for troubleshooting purposes.
@ -30,21 +28,9 @@ Examples of available modules are:
- `watchdog.<camera_name>` - `watchdog.<camera_name>`
- `ffmpeg.<camera_name>.<sorted_roles>` NOTE: All FFmpeg logs are sent as `error` level. - `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` ### `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. This section can be used to set environment variables for those unable to modify the environment of the container (ie. within HassOS)
Example: Example:
@ -172,57 +158,27 @@ listen [::]:8971 ipv6only=off ssl;
listen [::]:5000 ipv6only=off; 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 Dependencies
### Custom ffmpeg build ### 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. 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 binary can be downloaded to /config and used.
To do this: 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`. 1. Download your ffmpeg build and uncompress to the Frigate config folder.
2. Update the `ffmpeg.path` in your Frigate config to `/config/custom-ffmpeg`. 2. Update your docker-compose or docker CLI to include `'/home/appdata/frigate/custom-ffmpeg':'/usr/lib/btbn-ffmpeg':'ro'` in the volume mappings.
3. Restart Frigate and the custom version will be used if the steps above were done correctly. 3. Restart Frigate and the custom version will be used if the mapping was done correctly.
NOTE: The folder that is set for the config needs to be the folder that contains `/bin`. So if the full structure is `/home/appdata/frigate/custom-ffmpeg/bin/ffmpeg` then the `ffmpeg -> path` field should be `/config/custom-ffmpeg/bin`.
### Custom go2rtc version ### 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. Frigate currently includes go2rtc v1.9.4, there may be certain cases where you want to run a different version of go2rtc.
To do this: To do this:
1. Download the go2rtc build to the `/config` folder. 1. Download the go2rtc build to the /config folder.
2. Rename the build to `go2rtc`. 2. Rename the build to `go2rtc`.
3. Give `go2rtc` execute permission. 3. Give `go2rtc` execute permission.
4. Restart Frigate and the custom version will be used, you can verify by checking go2rtc logs. 4. Restart Frigate and the custom version will be used, you can verify by checking go2rtc logs.
@ -233,16 +189,16 @@ When frigate starts up, it checks whether your config file is valid, and if it i
### Via API ### 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. Frigate can accept a new configuration file as JSON at the `/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 ```bash
curl -X POST http://frigate_host:5000/api/config/save -d @config.json curl -X POST http://frigate_host:5000/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: 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 ```bash
yq r -j config.yml | curl -X POST http://frigate_host:5000/api/config/save -d @- yq r -j config.yml | curl -X POST http://frigate_host:5000/config/save -d @-
``` ```
### Via Command Line ### Via Command Line

View File

@ -24,11 +24,6 @@ On startup, an admin user and password are generated and printed in the logs. It
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. 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.
```yaml
auth:
reset_admin_password: true
```
## 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).
@ -43,28 +38,13 @@ 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, here is an example of how your auth config might look: 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:
```yaml ```yaml
auth: auth:
failed_login_rate_limit: "1/second;5/minute;20/hour" failed_login_rate_limit: "1/second;5/minute;20/hour"
trusted_proxies: trusted_proxies:
- 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
```
## 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.
```yaml
auth:
session_length: 86400
``` ```
## JWT Token Secret ## JWT Token Secret
@ -81,7 +61,7 @@ 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 docker secret named `FRIGATE_JWT_SECRET` in `/run/secrets/` 2. A docker secret named `FRIGATE_JWT_SECRET` in `/run/secrets/`
3. A `jwt_secret` option from the Home Assistant Add-on options 3. A `jwt_secret` option from the Home Assistant Addon 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.
@ -92,7 +72,7 @@ Changing the secret will invalidate current tokens.
Frigate can be configured to leverage features of common upstream authentication proxies such as Authelia, Authentik, oauth2_proxy, or traefik-forward-auth. 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.
Here is an example of how to disable Frigate's authentication and also ensure the 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.
@ -112,44 +92,15 @@ 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 the authenticated username, 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` value. Header names are not case sensitive.
```yaml ```yaml
proxy: proxy:
... ...
separator: "|" # This value defaults to a comma, but Authentik uses a pipe, for example.
header_map: header_map:
user: x-forwarded-user user: x-forwarded-user
role: x-forwarded-groups
``` ```
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.
A default role can be provided. Any value in the mapped `role` header will override the default.
```yaml
proxy:
...
default_role: viewer
```
#### Port Considerations
**Authenticated Port (8971)**
- Header mapping is **fully supported**.
- The `remote-role` header determines the users privileges:
- **admin** → Full access (user management, configuration changes).
- **viewer** → Read-only access.
- Ensure your **proxy sends both user and role headers** for proper role enforcement.
**Unauthenticated Port (5000)**
- Headers are **ignored** for role enforcement.
- All requests are treated as **anonymous**.
- The `remote-role` value is **overridden** to **admin-level access**.
- This design ensures **unauthenticated internal use** within a trusted network.
Note that only the following list of headers are permitted by default: Note that only the following list of headers are permitted by default:
``` ```
@ -170,6 +121,8 @@ X-authentik-uid
If you would like to add more options, you can overwrite the default file with a docker bind mount at `/usr/local/nginx/conf/proxy_trusted_headers.conf`. Reference the source code for the default file formatting. If you would like to add more options, you can overwrite the default file with a docker bind mount at `/usr/local/nginx/conf/proxy_trusted_headers.conf`. Reference the source code for the default file formatting.
Future versions of Frigate may leverage group and role headers for authorization in Frigate as well.
### Login page redirection ### Login page redirection
Frigate gracefully performs login page redirection that should work with most authentication proxies. If your reverse proxy returns a `Location` header on `401`, `302`, or `307` unauthorized responses, Frigate's frontend will automatically detect it and redirect to that URL. Frigate gracefully performs login page redirection that should work with most authentication proxies. If your reverse proxy returns a `Location` header on `401`, `302`, or `307` unauthorized responses, Frigate's frontend will automatically detect it and redirect to that URL.
@ -177,31 +130,3 @@ Frigate gracefully performs login page redirection that should work with most au
### Custom logout url ### Custom logout url
If your reverse proxy has a dedicated logout url, you can specify using the `logout_url` config option. This will update the link for the `Logout` link in the UI. If your reverse proxy has a dedicated logout url, you can specify using the `logout_url` config option. This will update the link for the `Logout` link in the UI.
## User Roles
Frigate supports user roles to control access to certain features in the UI and API, such as managing users or modifying configuration settings. Roles are assigned to users in the database or through proxy headers and are enforced when accessing the UI or API through the authenticated port (`8971`).
### Supported Roles
- **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.
### Role Enforcement
When using the authenticated port (`8971`), roles are validated via the JWT token or proxy headers (e.g., `remote-role`).
On the internal **unauthenticated** port (`5000`), roles are **not enforced**. All requests are treated as **anonymous**, granting access equivalent to the **admin** role without restrictions.
To use role-based access control, you must connect to Frigate via the **authenticated port (`8971`)** directly or through a reverse proxy.
### Role Visibility in the UI
- When logged in via port `8971`, your **username and role** are displayed in the **account menu** (bottom corner).
- When using port `5000`, the UI will always display "anonymous" for the username and "admin" for the role.
### Managing User Roles
1. Log in as an **admin** user via port `8971`.
2. Navigate to **Settings > Users**.
3. Edit a users role by selecting **admin** or **viewer**.

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