Compare commits
3 Commits
v0.16.0-rc
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
334b6670e1 | ||
|
b5067c07f8 | ||
|
21e9b2f2ce |
@ -2,7 +2,6 @@ aarch
|
||||
absdiff
|
||||
airockchip
|
||||
Alloc
|
||||
alpr
|
||||
Amcrest
|
||||
amdgpu
|
||||
analyzeduration
|
||||
@ -44,7 +43,6 @@ codeproject
|
||||
colormap
|
||||
colorspace
|
||||
comms
|
||||
cooldown
|
||||
coro
|
||||
ctypeslib
|
||||
CUDA
|
||||
@ -63,7 +61,6 @@ dsize
|
||||
dtype
|
||||
ECONNRESET
|
||||
edgetpu
|
||||
facenet
|
||||
fastapi
|
||||
faststart
|
||||
fflags
|
||||
@ -108,8 +105,8 @@ imagestream
|
||||
imdecode
|
||||
imencode
|
||||
imread
|
||||
imutils
|
||||
imwrite
|
||||
inpoint
|
||||
interp
|
||||
iostat
|
||||
iotop
|
||||
@ -117,8 +114,6 @@ itemsize
|
||||
Jellyfin
|
||||
jetson
|
||||
jetsons
|
||||
jina
|
||||
jinaai
|
||||
joserfc
|
||||
jsmpeg
|
||||
jsonify
|
||||
@ -192,7 +187,6 @@ openai
|
||||
opencv
|
||||
openvino
|
||||
OWASP
|
||||
paddleocr
|
||||
paho
|
||||
passwordless
|
||||
popleft
|
||||
@ -265,7 +259,6 @@ tensorrt
|
||||
tflite
|
||||
thresholded
|
||||
timelapse
|
||||
titlecase
|
||||
tmpfs
|
||||
tobytes
|
||||
toggleable
|
||||
@ -315,4 +308,4 @@ yolo
|
||||
yolonas
|
||||
yolox
|
||||
zeep
|
||||
zerolatency
|
||||
zerolatency
|
||||
|
@ -8,25 +8,9 @@
|
||||
"overrideCommand": false,
|
||||
"remoteUser": "vscode",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/common-utils:2": {}
|
||||
// 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": {}
|
||||
"ghcr.io/devcontainers/features/common-utils:1": {}
|
||||
},
|
||||
"forwardPorts": [
|
||||
8971,
|
||||
5000,
|
||||
5001,
|
||||
5173,
|
||||
8554,
|
||||
8555
|
||||
],
|
||||
"forwardPorts": [8971, 5000, 5001, 5173, 8554, 8555],
|
||||
"portsAttributes": {
|
||||
"8971": {
|
||||
"label": "External NGINX",
|
||||
@ -80,18 +64,10 @@
|
||||
"editor.formatOnType": true,
|
||||
"python.testing.pytestEnabled": false,
|
||||
"python.testing.unittestEnabled": true,
|
||||
"python.testing.unittestArgs": [
|
||||
"-v",
|
||||
"-s",
|
||||
"./frigate/test"
|
||||
],
|
||||
"python.testing.unittestArgs": ["-v", "-s", "./frigate/test"],
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"eslint.workingDirectories": [
|
||||
"./web"
|
||||
],
|
||||
"isort.args": [
|
||||
"--settings-path=./pyproject.toml"
|
||||
],
|
||||
"eslint.workingDirectories": ["./web"],
|
||||
"isort.args": ["--settings-path=./pyproject.toml"],
|
||||
"[python]": {
|
||||
"editor.defaultFormatter": "charliermarsh.ruff",
|
||||
"editor.formatOnSave": true,
|
||||
@ -110,16 +86,9 @@
|
||||
],
|
||||
"editor.tabSize": 2
|
||||
},
|
||||
"cSpell.ignoreWords": [
|
||||
"rtmp"
|
||||
],
|
||||
"cSpell.words": [
|
||||
"preact",
|
||||
"astype",
|
||||
"hwaccel",
|
||||
"mqtt"
|
||||
]
|
||||
"cSpell.ignoreWords": ["rtmp"],
|
||||
"cSpell.words": ["preact", "astype", "hwaccel", "mqtt"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
]
|
||||
}
|
@ -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!"
|
@ -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
|
||||
# s6 service file. For dev, where frigate is started from an interactive
|
||||
# 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
|
||||
|
||||
|
@ -73,7 +73,7 @@ body:
|
||||
attributes:
|
||||
label: Operating system
|
||||
options:
|
||||
- Home Assistant OS
|
||||
- HassOS
|
||||
- Debian
|
||||
- Other Linux
|
||||
- Proxmox
|
||||
@ -87,7 +87,7 @@ body:
|
||||
attributes:
|
||||
label: Install method
|
||||
options:
|
||||
- Home Assistant Add-on
|
||||
- HassOS Addon
|
||||
- Docker Compose
|
||||
- Docker CLI
|
||||
- Proxmox via Docker
|
||||
|
@ -59,7 +59,7 @@ body:
|
||||
attributes:
|
||||
label: Operating system
|
||||
options:
|
||||
- Home Assistant OS
|
||||
- HassOS
|
||||
- Debian
|
||||
- Other Linux
|
||||
- Proxmox
|
||||
@ -73,7 +73,7 @@ body:
|
||||
attributes:
|
||||
label: Install method
|
||||
options:
|
||||
- Home Assistant Add-on
|
||||
- HassOS Addon
|
||||
- Docker Compose
|
||||
- Docker CLI
|
||||
- Proxmox via Docker
|
||||
|
@ -53,7 +53,7 @@ body:
|
||||
attributes:
|
||||
label: Install method
|
||||
options:
|
||||
- Home Assistant Add-on
|
||||
- HassOS Addon
|
||||
- Docker Compose
|
||||
- Docker CLI
|
||||
- Proxmox via Docker
|
||||
|
@ -73,7 +73,7 @@ body:
|
||||
attributes:
|
||||
label: Install method
|
||||
options:
|
||||
- Home Assistant Add-on
|
||||
- HassOS Addon
|
||||
- Docker Compose
|
||||
- Docker CLI
|
||||
- Proxmox via Docker
|
||||
|
@ -69,7 +69,7 @@ body:
|
||||
attributes:
|
||||
label: Install method
|
||||
options:
|
||||
- Home Assistant Add-on
|
||||
- HassOS Addon
|
||||
- Docker Compose
|
||||
- Docker CLI
|
||||
- Proxmox via Docker
|
||||
|
4
.github/DISCUSSION_TEMPLATE/report-a-bug.yml
vendored
@ -97,7 +97,7 @@ body:
|
||||
attributes:
|
||||
label: Operating system
|
||||
options:
|
||||
- Home Assistant OS
|
||||
- HassOS
|
||||
- Debian
|
||||
- Other Linux
|
||||
- Proxmox
|
||||
@ -111,7 +111,7 @@ body:
|
||||
attributes:
|
||||
label: Install method
|
||||
options:
|
||||
- Home Assistant Add-on
|
||||
- HassOS Addon
|
||||
- Docker Compose
|
||||
- Docker CLI
|
||||
validations:
|
||||
|
11
.github/pull_request_template.md
vendored
@ -1,13 +1,7 @@
|
||||
## 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.
|
||||
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.
|
||||
-->
|
||||
|
||||
@ -24,7 +18,7 @@
|
||||
## Additional information
|
||||
|
||||
- This PR fixes or closes issue: fixes #
|
||||
- This PR is related to issue:
|
||||
- This PR is related to issue:
|
||||
|
||||
## Checklist
|
||||
|
||||
@ -35,5 +29,4 @@
|
||||
- [ ] The code change is tested and works locally.
|
||||
- [ ] Local tests pass. **Your PR cannot be merged unless tests pass**
|
||||
- [ ] 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`)
|
||||
|
122
.github/workflows/ci.yml
vendored
@ -41,9 +41,8 @@ jobs:
|
||||
target: frigate
|
||||
tags: ${{ steps.setup.outputs.image-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:
|
||||
runs-on: ubuntu-22.04-arm
|
||||
runs-on: ubuntu-22.04
|
||||
name: ARM Build
|
||||
steps:
|
||||
- name: Check out code
|
||||
@ -77,8 +76,36 @@ jobs:
|
||||
rpi.tags=${{ steps.setup.outputs.image-name }}-rpi
|
||||
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-arm64
|
||||
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-arm64,mode=max
|
||||
jetson_jp4_build:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Jetson Jetpack 4
|
||||
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 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@v6
|
||||
with:
|
||||
source: .
|
||||
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:
|
||||
if: false
|
||||
runs-on: ubuntu-22.04
|
||||
name: Jetson Jetpack 5
|
||||
steps:
|
||||
@ -107,35 +134,6 @@ jobs:
|
||||
tensorrt.tags=${{ steps.setup.outputs.image-name }}-tensorrt-jp5
|
||||
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-jp5
|
||||
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-jp5,mode=max
|
||||
jetson_jp6_build:
|
||||
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:
|
||||
runs-on: ubuntu-22.04
|
||||
name: AMD64 Extra Build
|
||||
@ -162,24 +160,10 @@ jobs:
|
||||
files: docker/tensorrt/trt.hcl
|
||||
set: |
|
||||
tensorrt.tags=${{ steps.setup.outputs.image-name }}-tensorrt
|
||||
*.cache-from=type=registry,ref=${{ steps.setup.outputs.cache-name }}-tensorrt
|
||||
*.cache-to=type=registry,ref=${{ steps.setup.outputs.cache-name }}-tensorrt,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
|
||||
*.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_extra_builds:
|
||||
runs-on: ubuntu-22.04-arm
|
||||
runs-on: ubuntu-22.04
|
||||
name: ARM Extra Build
|
||||
needs:
|
||||
- arm64_build
|
||||
@ -203,6 +187,46 @@ jobs:
|
||||
set: |
|
||||
rk.tags=${{ steps.setup.outputs.image-name }}-rk
|
||||
*.cache-from=type=gha
|
||||
combined_extra_builds:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Combined Extra Builds
|
||||
needs:
|
||||
- amd64_build
|
||||
- arm64_build
|
||||
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 Hailo-8l build
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
source: .
|
||||
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@v6
|
||||
with:
|
||||
source: .
|
||||
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
|
||||
# build should be the primary arm64 image
|
||||
assemble_default_build:
|
||||
|
18
.github/workflows/pull_request.yml
vendored
@ -4,10 +4,9 @@ on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "docs/**"
|
||||
- ".github/**"
|
||||
|
||||
env:
|
||||
DEFAULT_PYTHON: 3.11
|
||||
DEFAULT_PYTHON: 3.9
|
||||
|
||||
jobs:
|
||||
build_devcontainer:
|
||||
@ -24,7 +23,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-node@master
|
||||
with:
|
||||
node-version: 20.x
|
||||
node-version: 16.x
|
||||
- name: Install devcontainer cli
|
||||
run: npm install --global @devcontainers/cli
|
||||
- name: Build devcontainer
|
||||
@ -64,9 +63,6 @@ jobs:
|
||||
node-version: 20.x
|
||||
- run: npm install
|
||||
working-directory: ./web
|
||||
- name: Build web
|
||||
run: npm run build
|
||||
working-directory: ./web
|
||||
# - name: Test
|
||||
# run: npm run test
|
||||
# working-directory: ./web
|
||||
@ -80,7 +76,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v5.4.0
|
||||
uses: actions/setup-python@v5.3.0
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Install requirements
|
||||
@ -102,6 +98,14 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-node@master
|
||||
with:
|
||||
node-version: 16.x
|
||||
- run: npm install
|
||||
working-directory: ./web
|
||||
- name: Build web
|
||||
run: npm run build
|
||||
working-directory: ./web
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
|
4
.github/workflows/release.yml
vendored
@ -39,14 +39,14 @@ jobs:
|
||||
STABLE_TAG=${BASE}:stable
|
||||
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}
|
||||
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}
|
||||
done
|
||||
|
||||
# stable tag
|
||||
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}
|
||||
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}
|
||||
done
|
||||
fi
|
||||
|
2
Makefile
@ -1,7 +1,7 @@
|
||||
default_target: local
|
||||
|
||||
COMMIT_HASH := $(shell git log -1 --pretty=format:"%h"|tail -1)
|
||||
VERSION = 0.16.0
|
||||
VERSION = 0.15.2
|
||||
IMAGE_REPO ?= ghcr.io/blakeblackshear/frigate
|
||||
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
BOARDS= #Initialized empty
|
||||
|
20
README.md
@ -4,15 +4,9 @@
|
||||
|
||||
# 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.
|
||||
|
||||
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)
|
||||
- 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
|
||||
|
||||
### Live dashboard
|
||||
|
||||
<div>
|
||||
<img width="800" alt="Live dashboard" src="https://github.com/blakeblackshear/frigate/assets/569905/5e713cb9-9db5-41dc-947a-6937c3bc376e">
|
||||
</div>
|
||||
|
||||
### Streamlined review workflow
|
||||
|
||||
<div>
|
||||
<img width="800" alt="Streamlined review workflow" src="https://github.com/blakeblackshear/frigate/assets/569905/6fed96e8-3b18-40e5-9ddc-31e6f3c9f2ff">
|
||||
</div>
|
||||
|
||||
### Multi-camera scrubbing
|
||||
|
||||
<div>
|
||||
<img width="800" alt="Multi-camera scrubbing" src="https://github.com/blakeblackshear/frigate/assets/569905/d6788a15-0eeb-4427-a8d4-80b93cae3d74">
|
||||
</div>
|
||||
|
||||
### Built-in mask and zone editor
|
||||
|
||||
<div>
|
||||
<img width="800" alt="Multi-camera scrubbing" src="https://github.com/blakeblackshear/frigate/assets/569905/d7885fc3-bfe6-452f-b7d0-d957cb3e31f5">
|
||||
</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>
|
||||
|
70
README_CN.md
@ -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)
|
||||
|
||||
Bilibili:https://space.bilibili.com/3546894915602564
|
||||
|
||||
|
||||
## 中文社区赞助商
|
||||
[](https://edgeone.ai/zh?from=github)
|
||||
本项目 CDN 加速及安全防护由 Tencent EdgeOne 赞助
|
@ -6,7 +6,7 @@ import numpy as np
|
||||
|
||||
import frigate.util as util
|
||||
from frigate.config import DetectorTypeEnum
|
||||
from frigate.object_detection.base import (
|
||||
from frigate.object_detection import (
|
||||
ObjectDetectProcess,
|
||||
RemoteObjectDetector,
|
||||
load_labels,
|
||||
|
@ -1,8 +1,8 @@
|
||||
version: "3"
|
||||
services:
|
||||
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'
|
||||
# Must add these exact IDs in container's group_add section or OpenVINO GPU acceleration will fail
|
||||
# add groups from host for render, plugdev, video
|
||||
group_add:
|
||||
- "109" # render
|
||||
- "110" # render
|
||||
@ -24,8 +24,8 @@ services:
|
||||
# capabilities: [gpu]
|
||||
environment:
|
||||
YOLO_MODELS: ""
|
||||
# devices:
|
||||
# - /dev/bus/usb:/dev/bus/usb # Uncomment for Google Coral USB
|
||||
devices:
|
||||
- /dev/bus/usb:/dev/bus/usb
|
||||
# - /dev/dri:/dev/dri # for intel hwaccel, needs to be updated for your hardware
|
||||
volumes:
|
||||
- .:/workspace/frigate:cached
|
||||
@ -33,10 +33,9 @@ services:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- ./config:/config
|
||||
- ./debug:/media/frigate
|
||||
# - /dev/bus/usb:/dev/bus/usb # Uncomment for Google Coral USB
|
||||
- /dev/bus/usb:/dev/bus/usb
|
||||
mqtt:
|
||||
container_name: mqtt
|
||||
image: eclipse-mosquitto:2.0
|
||||
command: mosquitto -c /mosquitto-no-auth.conf # enable no-auth mode
|
||||
image: eclipse-mosquitto:1.6
|
||||
ports:
|
||||
- "1883:1883"
|
||||
|
40
docker/hailo8l/Dockerfile
Normal 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
@ -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
@ -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
|
19
docker/hailo8l/install_hailort.sh
Executable 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"
|
||||
|
12
docker/hailo8l/requirements-wheels-h8l.txt
Normal file
@ -0,0 +1,12 @@
|
||||
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.*
|
@ -4,7 +4,6 @@
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential cmake git wget
|
||||
|
||||
hailo_version="4.21.0"
|
||||
arch=$(uname -m)
|
||||
|
||||
if [[ $arch == "x86_64" ]]; then
|
||||
@ -14,7 +13,7 @@ else
|
||||
fi
|
||||
|
||||
# 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
|
||||
cd hailort-drivers/linux/pcie
|
||||
|
@ -3,29 +3,14 @@
|
||||
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Globally set pip break-system-packages option to avoid having to specify it every time
|
||||
ARG PIP_BREAK_SYSTEM_PACKAGES=1
|
||||
|
||||
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=
|
||||
ARG BASE_IMAGE=debian:11
|
||||
ARG SLIM_BASE=debian:11-slim
|
||||
|
||||
FROM ${BASE_IMAGE} AS base
|
||||
ARG PIP_BREAK_SYSTEM_PACKAGES
|
||||
ARG BASE_HOOK
|
||||
|
||||
RUN sh -c "$BASE_HOOK"
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} debian:12 AS base_host
|
||||
ARG PIP_BREAK_SYSTEM_PACKAGES
|
||||
FROM --platform=${BUILDPLATFORM} debian:11 AS base_host
|
||||
|
||||
FROM ${SLIM_BASE} AS slim-base
|
||||
ARG PIP_BREAK_SYSTEM_PACKAGES
|
||||
ARG BASE_HOOK
|
||||
|
||||
RUN sh -c "$BASE_HOOK"
|
||||
|
||||
FROM slim-base AS wget
|
||||
ARG DEBIAN_FRONTEND
|
||||
@ -39,7 +24,10 @@ ARG DEBIAN_FRONTEND
|
||||
ENV CCACHE_DIR /root/.ccache
|
||||
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
|
||||
|
||||
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
|
||||
ARG TARGETARCH
|
||||
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
|
||||
ARG TARGETARCH
|
||||
@ -78,9 +66,8 @@ COPY docker/main/requirements-ov.txt /requirements-ov.txt
|
||||
RUN apt-get -qq update \
|
||||
&& 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 \
|
||||
&& sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' get-pip.py \
|
||||
&& python3 get-pip.py "pip" \
|
||||
&& pip3 install -r /requirements-ov.txt
|
||||
&& pip install -r /requirements-ov.txt
|
||||
|
||||
# Get OpenVino Model
|
||||
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
|
||||
RUN apt-get -qq update \
|
||||
&& apt-get -qq install -y \
|
||||
apt-transport-https wget \
|
||||
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 install -y \
|
||||
python3.11 \
|
||||
python3.11-dev \
|
||||
python3.9 \
|
||||
python3.9-dev \
|
||||
# opencv dependencies
|
||||
build-essential cmake git pkg-config libgtk-3-dev \
|
||||
libavcodec-dev libavformat-dev libswscale-dev libv4l-dev \
|
||||
libxvidcore-dev libx264-dev libjpeg-dev libpng-dev libtiff-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 \
|
||||
# sqlite3 dependencies
|
||||
tclsh \
|
||||
@ -170,10 +164,10 @@ RUN apt-get -qq update \
|
||||
gcc gfortran libopenblas-dev liblapack-dev && \
|
||||
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 \
|
||||
&& sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' get-pip.py \
|
||||
&& python3 get-pip.py "pip"
|
||||
|
||||
COPY docker/main/requirements.txt /requirements.txt
|
||||
@ -186,9 +180,6 @@ RUN /build_pysqlite3.sh
|
||||
COPY docker/main/requirements-wheels.txt /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
|
||||
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=s6-overlay /rootfs/ /
|
||||
COPY --from=models /rootfs/ /
|
||||
COPY --from=wheels /rootfs/ /
|
||||
COPY docker/main/rootfs/ /
|
||||
|
||||
|
||||
@ -224,23 +214,14 @@ ENV TRANSFORMERS_NO_ADVISORY_WARNINGS=1
|
||||
# Set OpenCV ffmpeg loglevel to fatal: https://ffmpeg.org/doxygen/trunk/log_8h.html
|
||||
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}"
|
||||
|
||||
# Install dependencies
|
||||
RUN --mount=type=bind,source=docker/main/install_deps.sh,target=/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 \
|
||||
python3 -m pip install --upgrade pip && \
|
||||
pip3 install -U /deps/wheels/*.whl
|
||||
|
||||
COPY --from=deps-rootfs / /
|
||||
@ -260,12 +241,12 @@ ENTRYPOINT ["/init"]
|
||||
CMD []
|
||||
|
||||
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
|
||||
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
|
||||
COPY docker/main/fake_frigate_run /etc/s6-overlay/s6-rc.d/frigate/run
|
||||
|
||||
|
@ -2,22 +2,16 @@
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
NGINX_VERSION="1.27.4"
|
||||
NGINX_VERSION="1.25.3"
|
||||
VOD_MODULE_VERSION="1.31"
|
||||
SECURE_TOKEN_MODULE_VERSION="1.5"
|
||||
SET_MISC_MODULE_VERSION="v0.33"
|
||||
NGX_DEVEL_KIT_VERSION="v0.3.3"
|
||||
|
||||
source /etc/os-release
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
apt-get update
|
||||
|
||||
apt-get -yqq build-dep nginx
|
||||
|
||||
apt-get -yqq install --no-install-recommends ca-certificates wget
|
||||
|
@ -4,7 +4,7 @@ from openvino.tools import mo
|
||||
ov_model = mo.convert_model(
|
||||
"/models/ssdlite_mobilenet_v2_coco_2018_05_09/frozen_inference_graph.pb",
|
||||
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",
|
||||
reverse_input_channels=True,
|
||||
)
|
||||
|
@ -4,15 +4,8 @@ set -euxo pipefail
|
||||
|
||||
SQLITE_VEC_VERSION="0.1.3"
|
||||
|
||||
source /etc/os-release
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
apt-get update
|
||||
apt-get -yqq build-dep sqlite3 gettext git
|
||||
|
||||
|
@ -6,66 +6,82 @@ apt-get -qq update
|
||||
|
||||
apt-get -qq install --no-install-recommends -y \
|
||||
apt-transport-https \
|
||||
ca-certificates \
|
||||
gnupg \
|
||||
wget \
|
||||
lbzip2 \
|
||||
procps vainfo \
|
||||
unzip locales tzdata libxml2 xz-utils \
|
||||
python3.11 \
|
||||
python3.9 \
|
||||
python3-pip \
|
||||
curl \
|
||||
lsof \
|
||||
jq \
|
||||
nethogs \
|
||||
libgl1 \
|
||||
libglib2.0-0 \
|
||||
libusb-1.0.0
|
||||
nethogs
|
||||
|
||||
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
|
||||
|
||||
# install coral runtime
|
||||
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"
|
||||
unset DEBIAN_FRONTEND
|
||||
yes | dpkg -i /tmp/libedgetpu1-max.deb && export DEBIAN_FRONTEND=noninteractive
|
||||
rm /tmp/libedgetpu1-max.deb
|
||||
# add coral repo
|
||||
curl -fsSLo - https://packages.cloud.google.com/apt/doc/apt-key.gpg | \
|
||||
gpg --dearmor -o /etc/apt/trusted.gpg.d/google-cloud-packages-archive-keyring.gpg
|
||||
echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | tee /etc/apt/sources.list.d/coral-edgetpu.list
|
||||
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
|
||||
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
|
||||
wget -qO ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2024-09-19-12-51/ffmpeg-n7.0.2-18-g3e6cec1286-linux64-gpl-7.0.tar.xz"
|
||||
tar -xf ffmpeg.tar.xz -C /usr/lib/ffmpeg/7.0 --strip-components 1 amd64/bin/ffmpeg amd64/bin/ffprobe
|
||||
rm -rf ffmpeg.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 btbn-ffmpeg.tar.xz -C /usr/lib/ffmpeg/5.0 --strip-components 1
|
||||
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
|
||||
|
||||
# ffmpeg -> arm64
|
||||
if [[ "${TARGETARCH}" == "arm64" ]]; then
|
||||
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
|
||||
wget -qO ffmpeg.tar.xz "https://github.com/NickM-27/FFmpeg-Builds/releases/download/autobuild-2024-09-19-12-51/ffmpeg-n7.0.2-18-g3e6cec1286-linuxarm64-gpl-7.0.tar.xz"
|
||||
tar -xf ffmpeg.tar.xz -C /usr/lib/ffmpeg/7.0 --strip-components 1 arm64/bin/ffmpeg arm64/bin/ffprobe
|
||||
rm -f ffmpeg.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 btbn-ffmpeg.tar.xz -C /usr/lib/ffmpeg/5.0 --strip-components 1
|
||||
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
|
||||
|
||||
# arch specific packages
|
||||
if [[ "${TARGETARCH}" == "amd64" ]]; then
|
||||
# install amd / intel-i965 driver packages
|
||||
# use debian bookworm for amd / intel-i965 driver packages
|
||||
echo 'deb https://deb.debian.org/debian bookworm main contrib non-free' >/etc/apt/sources.list.d/debian-bookworm.list
|
||||
apt-get -qq update
|
||||
apt-get -qq install --no-install-recommends --no-install-suggests -y \
|
||||
i965-va-driver intel-gpu-tools onevpl-tools \
|
||||
libva-drm2 \
|
||||
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
|
||||
apt-get install -y dpkg
|
||||
|
||||
rm -f /etc/apt/sources.list.d/debian-bookworm.list
|
||||
|
||||
# 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
|
||||
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
|
||||
|
@ -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"
|
@ -2,7 +2,7 @@
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
s6_version="3.2.1.0"
|
||||
s6_version="3.1.5.0"
|
||||
|
||||
if [[ "${TARGETARCH}" == "amd64" ]]; then
|
||||
s6_arch="x86_64"
|
||||
|
@ -1,73 +1,47 @@
|
||||
aiofiles == 24.1.*
|
||||
click == 8.1.*
|
||||
# FastAPI
|
||||
aiohttp == 3.11.3
|
||||
aiohttp == 3.11.2
|
||||
starlette == 0.41.2
|
||||
starlette-context == 0.3.6
|
||||
fastapi == 0.115.*
|
||||
uvicorn == 0.30.*
|
||||
slowapi == 0.1.*
|
||||
imutils == 0.5.*
|
||||
joserfc == 1.0.*
|
||||
pathvalidate == 3.2.*
|
||||
markupsafe == 3.0.*
|
||||
python-multipart == 0.0.12
|
||||
# General
|
||||
markupsafe == 2.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.*
|
||||
pandas == 2.2.*
|
||||
peewee == 3.17.*
|
||||
peewee_migrate == 1.13.*
|
||||
psutil == 6.1.*
|
||||
pydantic == 2.10.*
|
||||
pydantic == 2.8.*
|
||||
git+https://github.com/fbcotter/py3nvml#egg=py3nvml
|
||||
pytz == 2025.*
|
||||
pytz == 2024.*
|
||||
pyzmq == 26.2.*
|
||||
ruamel.yaml == 0.18.*
|
||||
tzlocal == 5.2
|
||||
requests == 2.32.*
|
||||
types-requests == 2.32.*
|
||||
scipy == 1.13.*
|
||||
norfair == 2.2.*
|
||||
setproctitle == 1.3.*
|
||||
ws4py == 0.5.*
|
||||
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 == 2024.4.*
|
||||
onnxruntime-openvino == 1.20.* ; platform_machine == 'x86_64'
|
||||
onnxruntime == 1.20.* ; platform_machine == 'aarch64'
|
||||
openvino == 2024.3.*
|
||||
onnxruntime-openvino == 1.19.* ; platform_machine == 'x86_64'
|
||||
onnxruntime == 1.19.* ; platform_machine == 'aarch64'
|
||||
# Embeddings
|
||||
transformers == 4.45.*
|
||||
# Generative AI
|
||||
google-generativeai == 0.8.*
|
||||
ollama == 0.3.*
|
||||
openai == 1.65.*
|
||||
openai == 1.51.*
|
||||
# push notifications
|
||||
py-vapid == 1.9.*
|
||||
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'
|
||||
|
@ -1,2 +1,2 @@
|
||||
scikit-build == 0.18.*
|
||||
scikit-build == 0.17.*
|
||||
nvidia-pyindex
|
||||
|
@ -4,26 +4,52 @@
|
||||
|
||||
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
|
||||
|
||||
# Tell S6-Overlay not to restart this service
|
||||
s6-svc -O .
|
||||
|
||||
function migrate_db_path() {
|
||||
# Find config file in yaml or yml, but prefer yaml
|
||||
local config_file="${CONFIG_FILE:-"/config/config.yml"}"
|
||||
local config_file_yaml="${config_file//.yml/.yaml}"
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
local ffmpeg_path=$(python3 /usr/local/ffmpeg/get_ffmpeg_path.py)
|
||||
export LIBAVFORMAT_VERSION_MAJOR=$($ffmpeg_path -version | grep -Po "libavformat\W+\K\d+")
|
||||
}
|
||||
|
||||
echo "[INFO] Preparing Frigate..."
|
||||
migrate_db_path
|
||||
set_libva_version
|
||||
|
||||
echo "[INFO] Starting Frigate..."
|
||||
|
||||
cd /opt/frigate || echo "[ERROR] Failed to change working directory to /opt/frigate"
|
||||
|
@ -44,14 +44,10 @@ function get_ip_and_port_from_supervisor() {
|
||||
}
|
||||
|
||||
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
|
||||
local ffmpeg_path=$(python3 /usr/local/ffmpeg/get_ffmpeg_path.py)
|
||||
export LIBAVFORMAT_VERSION_MAJOR=$($ffmpeg_path -version | grep -Po "libavformat\W+\K\d+")
|
||||
}
|
||||
|
||||
set_libva_version
|
||||
|
||||
if [[ -f "/dev/shm/go2rtc.yaml" ]]; then
|
||||
echo "[INFO] Removing stale config from last run..."
|
||||
rm /dev/shm/go2rtc.yaml
|
||||
@ -61,7 +57,7 @@ if [[ ! -f "/dev/shm/go2rtc.yaml" ]]; then
|
||||
echo "[INFO] Preparing new go2rtc config..."
|
||||
|
||||
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
|
||||
fi
|
||||
|
||||
@ -70,6 +66,8 @@ else
|
||||
echo "[WARNING] Unable to remove existing go2rtc config. Changes made to your frigate config file may not be recognized. Please remove the /dev/shm/go2rtc.yaml from your docker host manually."
|
||||
fi
|
||||
|
||||
set_libva_version
|
||||
|
||||
readonly config_path="/config"
|
||||
|
||||
if [[ -x "${config_path}/go2rtc" ]]; then
|
||||
|
@ -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
|
||||
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
|
||||
python3 /usr/local/nginx/get_tls_settings.py | \
|
||||
tempio -template /usr/local/nginx/templates/listen.gotmpl \
|
||||
|
@ -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
|
@ -1 +0,0 @@
|
||||
oneshot
|
@ -1 +0,0 @@
|
||||
/etc/s6-overlay/s6-rc.d/prepare/run
|
@ -1,6 +1,7 @@
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from typing import Any
|
||||
|
||||
from ruamel.yaml import YAML
|
||||
|
||||
@ -9,28 +10,35 @@ 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()
|
||||
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:
|
||||
with open(config_file) as f:
|
||||
raw_config = f.read()
|
||||
|
||||
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"):
|
||||
config: dict[str, Any] = json.loads(raw_config)
|
||||
config: dict[str, any] = json.loads(raw_config)
|
||||
except FileNotFoundError:
|
||||
config: dict[str, Any] = {}
|
||||
config: dict[str, any] = {}
|
||||
|
||||
path = config.get("ffmpeg", {}).get("path", "default")
|
||||
if path == "default":
|
||||
print(f"/usr/lib/ffmpeg/{DEFAULT_FFMPEG_VERSION}/bin/ffmpeg")
|
||||
if shutil.which("ffmpeg") is None:
|
||||
print(f"/usr/lib/ffmpeg/{DEFAULT_FFMPEG_VERSION}/bin/ffmpeg")
|
||||
else:
|
||||
print("ffmpeg")
|
||||
elif path in INCLUDED_FFMPEG_VERSIONS:
|
||||
print(f"/usr/lib/ffmpeg/{path}/bin/ffmpeg")
|
||||
else:
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from ruamel.yaml import YAML
|
||||
|
||||
@ -13,10 +13,8 @@ from frigate.const import (
|
||||
BIRDSEYE_PIPE,
|
||||
DEFAULT_FFMPEG_VERSION,
|
||||
INCLUDED_FFMPEG_VERSIONS,
|
||||
LIBAVFORMAT_VERSION_MAJOR,
|
||||
)
|
||||
from frigate.ffmpeg_presets import parse_preset_hardware_acceleration_encode
|
||||
from frigate.util.config import find_config_file
|
||||
|
||||
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()
|
||||
)
|
||||
|
||||
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:
|
||||
with open(config_file) as f:
|
||||
raw_config = f.read()
|
||||
|
||||
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"):
|
||||
config: dict[str, Any] = json.loads(raw_config)
|
||||
config: dict[str, any] = json.loads(raw_config)
|
||||
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
|
||||
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
|
||||
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
|
||||
if go2rtc_config.get("log") is None:
|
||||
@ -63,34 +66,56 @@ elif go2rtc_config["log"].get("format") is None:
|
||||
go2rtc_config["log"]["format"] = "text"
|
||||
|
||||
# ensure there is a default webrtc config
|
||||
if go2rtc_config.get("webrtc") is None:
|
||||
if not go2rtc_config.get("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 = []
|
||||
# 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:
|
||||
default_candidates.append(internal_candidate)
|
||||
# should set default stun server so webrtc can work
|
||||
default_candidates.append("stun:8555")
|
||||
|
||||
go2rtc_config["webrtc"]["candidates"] = default_candidates
|
||||
|
||||
if go2rtc_config.get("rtsp", {}).get("username") is not None:
|
||||
go2rtc_config["rtsp"]["username"] = go2rtc_config["rtsp"]["username"].format(
|
||||
**FRIGATE_ENV_VARS
|
||||
go2rtc_config["webrtc"] = {"candidates": default_candidates}
|
||||
else:
|
||||
print(
|
||||
"[INFO] Not injecting WebRTC candidates into go2rtc config as it has been set manually",
|
||||
)
|
||||
|
||||
if go2rtc_config.get("rtsp", {}).get("password") is not None:
|
||||
go2rtc_config["rtsp"]["password"] = go2rtc_config["rtsp"]["password"].format(
|
||||
**FRIGATE_ENV_VARS
|
||||
)
|
||||
# sets default RTSP response to be equivalent to ?video=h264,h265&audio=aac
|
||||
# this means user does not need to specify audio codec when using restream
|
||||
# as source for frigate and the integration supports HLS playback
|
||||
if go2rtc_config.get("rtsp") is None:
|
||||
go2rtc_config["rtsp"] = {"default_query": "mp4"}
|
||||
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
|
||||
path = config.get("ffmpeg", {}).get("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:
|
||||
ffmpeg_path = f"/usr/lib/ffmpeg/{path}/bin/ffmpeg"
|
||||
else:
|
||||
@ -102,12 +127,14 @@ elif go2rtc_config["ffmpeg"].get("bin") is None:
|
||||
go2rtc_config["ffmpeg"]["bin"] = ffmpeg_path
|
||||
|
||||
# need to replace ffmpeg command when using ffmpeg4
|
||||
if LIBAVFORMAT_VERSION_MAJOR < 59:
|
||||
rtsp_args = "-fflags nobuffer -flags low_delay -stimeout 10000000 -user_agent go2rtc/ffmpeg -rtsp_transport tcp -i {input}"
|
||||
if int(os.environ.get("LIBAVFORMAT_VERSION_MAJOR", "59") or "59") < 59:
|
||||
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:
|
||||
go2rtc_config["ffmpeg"] = {"rtsp": rtsp_args}
|
||||
elif go2rtc_config["ffmpeg"].get("rtsp") is None:
|
||||
go2rtc_config["ffmpeg"]["rtsp"] = rtsp_args
|
||||
go2rtc_config["ffmpeg"] = {"path": ""}
|
||||
|
||||
for name in go2rtc_config.get("streams", {}):
|
||||
stream = go2rtc_config["streams"][name]
|
||||
@ -135,7 +162,7 @@ for name in go2rtc_config.get("streams", {}):
|
||||
|
||||
# add birdseye restream stream if enabled
|
||||
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}"
|
||||
ffmpeg_cmd = f"exec:{parse_preset_hardware_acceleration_encode(ffmpeg_path, config.get('ffmpeg', {}).get('hwaccel_args', ''), input, '-rtsp_transport tcp -f rtsp {output}')}"
|
||||
|
@ -1,16 +1,14 @@
|
||||
## Send a subrequest to verify if the user is authenticated and has permission to access the resource.
|
||||
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 $role $upstream_http_remote_role;
|
||||
auth_request_set $groups $upstream_http_remote_groups;
|
||||
auth_request_set $name $upstream_http_remote_name;
|
||||
auth_request_set $email $upstream_http_remote_email;
|
||||
|
||||
## 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-Role $role;
|
||||
proxy_set_header Remote-Groups $groups;
|
||||
proxy_set_header Remote-Email $email;
|
||||
proxy_set_header Remote-Name $name;
|
||||
|
@ -30,7 +30,7 @@ http {
|
||||
|
||||
gzip on;
|
||||
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_vary on;
|
||||
|
||||
@ -81,9 +81,6 @@ http {
|
||||
open_file_cache_errors on;
|
||||
aio on;
|
||||
|
||||
# file upload size
|
||||
client_max_body_size 20M;
|
||||
|
||||
# https://github.com/kaltura/nginx-vod-module#vod_open_file_thread_pool
|
||||
vod_open_file_thread_pool default;
|
||||
|
||||
@ -96,7 +93,6 @@ http {
|
||||
gzip_types application/vnd.apple.mpegurl;
|
||||
|
||||
include auth_location.conf;
|
||||
include base_path.conf;
|
||||
|
||||
location /vod/ {
|
||||
include auth_request.conf;
|
||||
@ -110,14 +106,6 @@ http {
|
||||
expires off;
|
||||
|
||||
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/ {
|
||||
@ -300,29 +288,11 @@ http {
|
||||
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 'url(/BASE_PATH/' 'url($http_x_ingress_path/';
|
||||
sub_filter '"/BASE_PATH/dist/' '"$http_x_ingress_path/dist/';
|
||||
sub_filter '"/BASE_PATH/js/' '"$http_x_ingress_path/js/';
|
||||
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 'return"/BASE_PATH/"' 'return window.baseUrl';
|
||||
sub_filter '<body>' '<body><script>window.baseUrl="$http_x_ingress_path/";</script>';
|
||||
|
@ -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))
|
@ -1,31 +1,30 @@
|
||||
"""Prints the tls config as json to stdout."""
|
||||
|
||||
import json
|
||||
import sys
|
||||
from typing import Any
|
||||
import os
|
||||
|
||||
from ruamel.yaml import YAML
|
||||
|
||||
sys.path.insert(0, "/opt/frigate")
|
||||
from frigate.util.config import find_config_file
|
||||
|
||||
sys.path.remove("/opt/frigate")
|
||||
|
||||
yaml = YAML()
|
||||
|
||||
config_file = find_config_file()
|
||||
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:
|
||||
with open(config_file) as f:
|
||||
raw_config = f.read()
|
||||
|
||||
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"):
|
||||
config: dict[str, Any] = json.loads(raw_config)
|
||||
config: dict[str, any] = json.loads(raw_config)
|
||||
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))
|
||||
|
@ -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 }}
|
@ -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
|
Before Width: | Height: | Size: 207 KiB |
Before Width: | Height: | Size: 209 KiB |
Before Width: | Height: | Size: 150 KiB |
Before Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 201 KiB |
Before Width: | Height: | Size: 233 KiB |
Before Width: | Height: | Size: 242 KiB |
Before Width: | Height: | Size: 230 KiB |
Before Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 136 KiB |
Before Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 281 KiB |
Before Width: | Height: | Size: 272 KiB |
Before Width: | Height: | Size: 152 KiB |
Before Width: | Height: | Size: 166 KiB |
Before Width: | Height: | Size: 109 KiB |
Before Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 203 KiB |
Before Width: | Height: | Size: 110 KiB |
@ -3,34 +3,25 @@
|
||||
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Globally set pip break-system-packages option to avoid having to specify it every time
|
||||
ARG PIP_BREAK_SYSTEM_PACKAGES=1
|
||||
|
||||
FROM wheels as rk-wheels
|
||||
COPY docker/main/requirements-wheels.txt /requirements-wheels.txt
|
||||
COPY docker/rockchip/requirements-wheels-rk.txt /requirements-wheels-rk.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 rm -rf /rk-wheels/opencv_python-*
|
||||
|
||||
FROM deps AS rk-frigate
|
||||
ARG TARGETARCH
|
||||
ARG PIP_BREAK_SYSTEM_PACKAGES
|
||||
|
||||
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/
|
||||
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/
|
||||
ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/6.1-11/ffprobe /usr/lib/ffmpeg/6.0/bin/
|
||||
ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/7.1-1/ffmpeg /usr/lib/ffmpeg/7.0/bin/
|
||||
ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/7.1-1/ffprobe /usr/lib/ffmpeg/7.0/bin/
|
||||
ENV DEFAULT_FFMPEG_VERSION="6.0"
|
||||
ENV INCLUDED_FFMPEG_VERSIONS="${DEFAULT_FFMPEG_VERSION}:${INCLUDED_FFMPEG_VERSIONS}"
|
||||
RUN rm -rf /usr/lib/btbn-ffmpeg/bin/ffmpeg
|
||||
RUN rm -rf /usr/lib/btbn-ffmpeg/bin/ffprobe
|
||||
ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/6.1-7/ffmpeg /usr/lib/ffmpeg/6.0/bin/
|
||||
ADD --chmod=111 https://github.com/MarcA711/Rockchip-FFmpeg-Builds/releases/download/6.1-7/ffprobe /usr/lib/ffmpeg/6.0/bin/
|
||||
ENV PATH="/usr/lib/ffmpeg/6.0/bin/:${PATH}"
|
||||
|
@ -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.")
|
@ -1,2 +1 @@
|
||||
rknn-toolkit2 == 2.3.2
|
||||
rknn-toolkit-lite2 == 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
|
@ -2,49 +2,77 @@
|
||||
|
||||
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG ROCM=6.3.3
|
||||
ARG ROCM=5.7.3
|
||||
ARG AMDGPU=gfx900
|
||||
ARG HSA_OVERRIDE_GFX_VERSION
|
||||
ARG HSA_OVERRIDE
|
||||
|
||||
#######################################################################
|
||||
FROM wget AS rocm
|
||||
FROM ubuntu:focal as rocm
|
||||
|
||||
ARG ROCM
|
||||
ARG AMDGPU
|
||||
|
||||
RUN apt update && \
|
||||
apt install -y wget gpg && \
|
||||
wget -O rocm.deb https://repo.radeon.com/amdgpu-install/$ROCM/ubuntu/jammy/amdgpu-install_6.3.60303-1_all.deb && \
|
||||
apt install -y ./rocm.deb && \
|
||||
apt update && \
|
||||
apt install -y rocm
|
||||
RUN apt-get update && apt-get -y upgrade
|
||||
RUN apt-get -y install gnupg wget
|
||||
|
||||
RUN mkdir --parents --mode=0755 /etc/apt/keyrings
|
||||
|
||||
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 cd /opt/rocm-$ROCM/lib && \
|
||||
cp -dpr libMIOpen*.so* libamd*.so* libhip*.so* libhsa*.so* libmigraphx*.so* librocm*.so* librocblas*.so* libroctracer*.so* librocsolver*.so* librocfft*.so* librocprofiler*.so* libroctx*.so* /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-$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/
|
||||
RUN cd /opt/rocm-dist/opt/ && ln -s rocm-$ROCM rocm
|
||||
|
||||
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
|
||||
|
||||
#######################################################################
|
||||
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
|
||||
|
||||
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 / /
|
||||
|
||||
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
|
||||
RUN pip3 uninstall -y onnxruntime-openvino \
|
||||
RUN python3 -m pip install --upgrade pip \
|
||||
&& pip3 uninstall -y onnxruntime-openvino \
|
||||
&& 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/lib/rocblas/library/*$AMDGPU* /opt/rocm-$ROCM/lib/rocblas/library/
|
||||
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
|
||||
|
||||
ENV HSA_ENABLE_SDMA=0
|
||||
ENV MIGRAPHX_ENABLE_NHWC=1
|
||||
ENV TF_ROCM_USE_IMMEDIATE_MODE=1
|
||||
|
||||
COPY --from=rocm-dist / /
|
||||
|
||||
|
26
docker/rocm/migraphx/CMakeLists.txt
Normal 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
|
||||
)
|
582
docker/rocm/migraphx/migraphx_py.cpp
Normal 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
|
||||
}
|
@ -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
@ -0,0 +1,3 @@
|
||||
Package: *
|
||||
Pin: release o=repo.radeon.com
|
||||
Pin-Priority: 600
|
@ -2,7 +2,7 @@ variable "AMDGPU" {
|
||||
default = "gfx900"
|
||||
}
|
||||
variable "ROCM" {
|
||||
default = "6.3.3"
|
||||
default = "5.7.3"
|
||||
}
|
||||
variable "HSA_OVERRIDE_GFX_VERSION" {
|
||||
default = ""
|
||||
@ -10,13 +10,6 @@ variable "HSA_OVERRIDE_GFX_VERSION" {
|
||||
variable "HSA_OVERRIDE" {
|
||||
default = "1"
|
||||
}
|
||||
|
||||
target wget {
|
||||
dockerfile = "docker/main/Dockerfile"
|
||||
platforms = ["linux/amd64"]
|
||||
target = "wget"
|
||||
}
|
||||
|
||||
target deps {
|
||||
dockerfile = "docker/main/Dockerfile"
|
||||
platforms = ["linux/amd64"]
|
||||
@ -33,7 +26,6 @@ target rocm {
|
||||
dockerfile = "docker/rocm/Dockerfile"
|
||||
contexts = {
|
||||
deps = "target:deps",
|
||||
wget = "target:wget",
|
||||
rootfs = "target:rootfs"
|
||||
}
|
||||
platforms = ["linux/amd64"]
|
||||
|
1
docker/rocm/rocm.list
Normal 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
|
@ -6,12 +6,11 @@ ARG DEBIAN_FRONTEND=noninteractive
|
||||
FROM deps AS rpi-deps
|
||||
ARG TARGETARCH
|
||||
|
||||
RUN rm -rf /usr/lib/btbn-ffmpeg/
|
||||
|
||||
# Install dependencies
|
||||
RUN --mount=type=bind,source=docker/rpi/install_deps.sh,target=/deps/install_deps.sh \
|
||||
/deps/install_deps.sh
|
||||
|
||||
ENV DEFAULT_FFMPEG_VERSION="rpi"
|
||||
ENV INCLUDED_FFMPEG_VERSIONS="${DEFAULT_FFMPEG_VERSION}:${INCLUDED_FFMPEG_VERSIONS}"
|
||||
|
||||
WORKDIR /opt/frigate/
|
||||
COPY --from=rootfs / /
|
||||
|
@ -18,17 +18,13 @@ apt-get -qq install --no-install-recommends -y \
|
||||
mkdir -p -m 600 /root/.gnupg
|
||||
|
||||
# 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
|
||||
apt update
|
||||
sed -i -e's/ main/ main contrib non-free/g' /etc/apt/sources.list
|
||||
|
||||
# ffmpeg -> arm64
|
||||
if [[ "${TARGETARCH}" == "arm64" ]]; then
|
||||
# add raspberry pi repo
|
||||
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 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
|
||||
|
@ -3,32 +3,32 @@
|
||||
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Globally set pip break-system-packages option to avoid having to specify it every time
|
||||
ARG PIP_BREAK_SYSTEM_PACKAGES=1
|
||||
# Make this a separate target so it can be built/cached optionally
|
||||
FROM wheels as trt-wheels
|
||||
ARG DEBIAN_FRONTEND
|
||||
ARG TARGETARCH
|
||||
|
||||
FROM wheels AS trt-wheels
|
||||
ARG PIP_BREAK_SYSTEM_PACKAGES
|
||||
|
||||
# Install TensorRT wheels
|
||||
# Add TensorRT wheels to another folder
|
||||
COPY docker/tensorrt/requirements-amd64.txt /requirements-tensorrt.txt
|
||||
COPY docker/main/requirements-wheels.txt /requirements-wheels.txt
|
||||
RUN pip3 wheel --wheel-dir=/trt-wheels -c /requirements-wheels.txt -r /requirements-tensorrt.txt
|
||||
|
||||
FROM deps AS frigate-tensorrt
|
||||
ARG PIP_BREAK_SYSTEM_PACKAGES
|
||||
RUN mkdir -p /trt-wheels && pip3 wheel --wheel-dir=/trt-wheels -r /requirements-tensorrt.txt
|
||||
|
||||
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 \
|
||||
pip3 uninstall -y onnxruntime-openvino tensorflow-cpu \
|
||||
&& pip3 install -U /deps/trt-wheels/*.whl
|
||||
|
||||
COPY --from=rootfs / /
|
||||
COPY docker/tensorrt/detector/rootfs/etc/ld.so.conf.d /etc/ld.so.conf.d
|
||||
RUN ldconfig
|
||||
pip3 install -U /deps/trt-wheels/*.whl && \
|
||||
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/
|
||||
COPY --from=rootfs / /
|
||||
|
||||
# Dev Container w/ TRT
|
||||
FROM devcontainer AS devcontainer-trt
|
||||
|
||||
COPY --from=trt-deps /usr/local/lib/libyolo_layer.so /usr/local/lib/libyolo_layer.so
|
||||
COPY --from=trt-deps /usr/local/src/tensorrt_demos /usr/local/src/tensorrt_demos
|
||||
COPY --from=trt-deps /usr/local/cuda-12.1 /usr/local/cuda
|
||||
COPY docker/tensorrt/detector/rootfs/ /
|
||||
COPY --from=trt-deps /usr/local/lib/libyolo_layer.so /usr/local/lib/libyolo_layer.so
|
||||
RUN --mount=type=bind,from=trt-wheels,source=/trt-wheels,target=/deps/trt-wheels \
|
||||
pip3 install -U /deps/trt-wheels/*.whl
|
||||
|
@ -1,84 +1,26 @@
|
||||
# syntax=docker/dockerfile:1.6
|
||||
# syntax=docker/dockerfile:1.4
|
||||
|
||||
# https://askubuntu.com/questions/972516/debian-frontend-environment-variable
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
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
|
||||
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
|
||||
RUN apt-get -qq update \
|
||||
&& apt-get -qq install -y --no-install-recommends \
|
||||
python3.11 python3.11-dev \
|
||||
python3.9 python3.9-dev \
|
||||
wget build-essential cmake git \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Ensure python3 defaults to python3.11
|
||||
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 \
|
||||
&& sed -i 's/args.append("setuptools")/args.append("setuptools==77.0.3")/' get-pip.py \
|
||||
&& python3 get-pip.py "pip"
|
||||
|
||||
|
||||
FROM build-wheels AS trt-wheels
|
||||
ARG DEBIAN_FRONTEND
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
# See https://elinux.org/Jetson_Zoo#ONNX_Runtime
|
||||
ADD https://nvidia.box.com/shared/static/9yvw05k6u343qfnkhdv2x6xhygze0aq1.whl /trt-wheels/onnxruntime_gpu-1.19.0-cp311-cp311-linux_aarch64.whl
|
||||
RUN pip3 uninstall -y onnxruntime-openvino \
|
||||
&& pip3 wheel --wheel-dir=/trt-wheels -r /requirements-tensorrt.txt \
|
||||
&& pip3 install --no-deps /tmp/onnxruntime_gpu-1.15.1-cp39-cp39-linux_aarch64.whl
|
||||
|
||||
FROM build-wheels AS trt-model-wheels
|
||||
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
|
||||
FROM tensorrt-base AS frigate-tensorrt
|
||||
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/*
|
||||
|
||||
RUN rm -rf /usr/lib/btbn-ffmpeg/
|
||||
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
|
||||
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 \
|
||||
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
|
||||
|
||||
WORKDIR /opt/frigate/
|
||||
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
|
32
docker/tensorrt/Dockerfile.base
Normal file
@ -0,0 +1,32 @@
|
||||
# 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 --from=trt-deps /usr/local/cuda-12.* /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
|
@ -5,7 +5,7 @@
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
INSTALL_PREFIX=/rootfs/usr/lib/ffmpeg/jetson
|
||||
INSTALL_PREFIX=/rootfs/usr/local
|
||||
|
||||
apt-get -qq update
|
||||
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
|
||||
|
||||
# Install libnvmpi to enable nvmpi decoders (h264_nvmpi, hevc_nvmpi)
|
||||
if [ -e /usr/local/cuda-12 ]; 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
|
||||
if [ -e /usr/local/cuda-10.2 ]; then
|
||||
# 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
|
||||
tar xaf jetson_multimedia_api.tbz2 -C / && rm jetson_multimedia_api.tbz2
|
||||
else
|
||||
# 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
|
||||
tar xaf jetson_multimedia_api.tbz2 -C / && rm jetson_multimedia_api.tbz2
|
||||
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
|
||||
unzip jetson-ffmpeg.zip && rm jetson-ffmpeg.zip && mv jetson-ffmpeg-* jetson-ffmpeg && cd jetson-ffmpeg
|
||||
|
@ -6,23 +6,23 @@ mkdir -p /trt-wheels
|
||||
|
||||
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.
|
||||
|
||||
# Get python-tensorrt source
|
||||
mkdir -p /workspace
|
||||
mkdir /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
|
||||
EXT_PATH=/workspace/external && mkdir -p $EXT_PATH
|
||||
pip3 install pybind11 && ln -s /usr/local/lib/python3.11/dist-packages/pybind11 $EXT_PATH/pybind11
|
||||
ln -s /usr/include/python3.11 $EXT_PATH/python3.11
|
||||
pip3 install pybind11 && ln -s /usr/local/lib/python3.9/dist-packages/pybind11 $EXT_PATH/pybind11
|
||||
ln -s /usr/include/python3.9 $EXT_PATH/python3.9
|
||||
ln -s /usr/include/aarch64-linux-gnu/NvOnnxParser.h /workspace/TensorRT/parsers/onnx/
|
||||
|
||||
# Build wheel
|
||||
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
|
||||
mv build/bindings_wheel/dist/*.whl /trt-wheels/
|
||||
EXT_PATH=$EXT_PATH PYTHON_MAJOR_VERSION=3 PYTHON_MINOR_VERSION=9 TARGET_ARCHITECTURE=aarch64 /bin/bash ./build.sh
|
||||
mv build/dist/*.whl /trt-wheels/
|
||||
|
||||
fi
|
||||
|
@ -1,6 +1,6 @@
|
||||
/usr/local/lib/python3.11/dist-packages/nvidia/cudnn/lib
|
||||
/usr/local/lib/python3.11/dist-packages/nvidia/cuda_runtime/lib
|
||||
/usr/local/lib/python3.11/dist-packages/nvidia/cublas/lib
|
||||
/usr/local/lib/python3.11/dist-packages/nvidia/cufft/lib
|
||||
/usr/local/lib/python3.11/dist-packages/nvidia/curand/lib/
|
||||
/usr/local/lib/python3.11/dist-packages/nvidia/cuda_nvrtc/lib/
|
||||
/usr/local/lib
|
||||
/usr/local/lib/python3.9/dist-packages/nvidia/cudnn/lib
|
||||
/usr/local/lib/python3.9/dist-packages/nvidia/cuda_runtime/lib
|
||||
/usr/local/lib/python3.9/dist-packages/nvidia/cublas/lib
|
||||
/usr/local/lib/python3.9/dist-packages/nvidia/cuda_nvrtc/lib
|
||||
/usr/local/lib/python3.9/dist-packages/tensorrt
|
@ -64,7 +64,7 @@ fi
|
||||
# order to run libyolo here.
|
||||
# On Jetpack 5.0, these libraries are not mounted by the runtime and are supplied by the image.
|
||||
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"
|
||||
exit 1
|
||||
elif [[ ! -e /usr/lib/aarch64-linux-gnu/libnvinfer.so.8 ||
|
||||
|
@ -1,18 +1,14 @@
|
||||
# NVidia TensorRT Support (amd64 only)
|
||||
--extra-index-url 'https://pypi.nvidia.com'
|
||||
cython==3.0.*; platform_machine == 'x86_64'
|
||||
nvidia_cuda_cupti_cu12==12.5.82; platform_machine == 'x86_64'
|
||||
nvidia-cublas-cu12==12.5.3.*; platform_machine == 'x86_64'
|
||||
nvidia-cudnn-cu12==9.3.0.*; platform_machine == 'x86_64'
|
||||
nvidia-cufft-cu12==11.2.3.*; platform_machine == 'x86_64'
|
||||
nvidia-curand-cu12==10.3.6.*; platform_machine == 'x86_64'
|
||||
nvidia_cuda_nvcc_cu12==12.5.82; platform_machine == 'x86_64'
|
||||
nvidia-cuda-nvrtc-cu12==12.5.82; platform_machine == 'x86_64'
|
||||
nvidia_cuda_runtime_cu12==12.5.82; 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'
|
||||
numpy < 1.24; platform_machine == 'x86_64'
|
||||
tensorrt == 8.5.3.*; platform_machine == 'x86_64'
|
||||
cuda-python == 11.8; platform_machine == 'x86_64'
|
||||
cython == 0.29.*; platform_machine == 'x86_64'
|
||||
nvidia-cuda-runtime-cu12 == 12.1.*; platform_machine == 'x86_64'
|
||||
nvidia-cuda-runtime-cu11 == 11.8.*; platform_machine == 'x86_64'
|
||||
nvidia-cublas-cu11 == 11.11.3.6; platform_machine == 'x86_64'
|
||||
nvidia-cudnn-cu11 == 8.6.0.*; platform_machine == 'x86_64'
|
||||
nvidia-cufft-cu11==10.*; 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'
|
||||
|
@ -1 +1 @@
|
||||
cuda-python == 12.6.*; platform_machine == 'aarch64'
|
||||
cuda-python == 11.7; platform_machine == 'aarch64'
|
@ -13,29 +13,13 @@ variable "TRT_BASE" {
|
||||
variable "COMPUTE_LEVEL" {
|
||||
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" {
|
||||
args = {
|
||||
BASE_IMAGE = BASE_IMAGE,
|
||||
SLIM_BASE = SLIM_BASE,
|
||||
TRT_BASE = TRT_BASE,
|
||||
COMPUTE_LEVEL = COMPUTE_LEVEL,
|
||||
BASE_HOOK = BASE_HOOK
|
||||
COMPUTE_LEVEL = COMPUTE_LEVEL
|
||||
}
|
||||
platforms = ["linux/${ARCH}"]
|
||||
}
|
||||
@ -79,14 +63,23 @@ target "trt-deps" {
|
||||
inherits = ["_build_args"]
|
||||
}
|
||||
|
||||
target "tensorrt-base" {
|
||||
dockerfile = "docker/tensorrt/Dockerfile.base"
|
||||
context = "."
|
||||
contexts = {
|
||||
deps = "target:deps",
|
||||
}
|
||||
inherits = ["_build_args"]
|
||||
}
|
||||
|
||||
target "tensorrt" {
|
||||
dockerfile = "docker/tensorrt/Dockerfile.${ARCH}"
|
||||
context = "."
|
||||
contexts = {
|
||||
wget = "target:wget",
|
||||
wheels = "target:wheels",
|
||||
deps = "target:deps",
|
||||
tensorrt-base = "target:tensorrt-base",
|
||||
rootfs = "target:rootfs"
|
||||
wheels = "target:wheels"
|
||||
}
|
||||
target = "frigate-tensorrt"
|
||||
inherits = ["_build_args"]
|
||||
|
@ -1,41 +1,41 @@
|
||||
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
|
||||
JETPACK6_BASE ?= nvcr.io/nvidia/tensorrt:23.12-py3-igpu
|
||||
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)
|
||||
JETPACK6_ARGS := ARCH=arm64 BASE_IMAGE=$(JETPACK6_BASE) SLIM_BASE=$(JETPACK6_BASE) TRT_BASE=$(JETPACK6_BASE)
|
||||
|
||||
local-trt: version
|
||||
$(X86_DGPU_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
|
||||
--set tensorrt.tags=frigate:latest-tensorrt \
|
||||
--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
|
||||
$(JETPACK5_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
|
||||
--set tensorrt.tags=frigate:latest-tensorrt-jp5 \
|
||||
--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:
|
||||
$(X86_DGPU_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl 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 \
|
||||
--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
|
||||
$(X86_DGPU_ARGS) docker buildx bake --file=docker/tensorrt/trt.hcl tensorrt \
|
||||
--set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt \
|
||||
--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 \
|
||||
--set tensorrt.tags=$(IMAGE_REPO):${GITHUB_REF_NAME}-$(COMMIT_HASH)-tensorrt-jp5 \
|
||||
--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
|
||||
|
@ -32,19 +32,19 @@ Examples of available modules are:
|
||||
|
||||
#### Go2RTC Logging
|
||||
|
||||
See [the go2rtc docs](https://github.com/AlexxIT/go2rtc?tab=readme-ov-file#module-log) for logging configuration
|
||||
See [the go2rtc docs](for logging configuration)
|
||||
|
||||
```yaml
|
||||
go2rtc:
|
||||
streams:
|
||||
# ...
|
||||
...
|
||||
log:
|
||||
exec: trace
|
||||
```
|
||||
|
||||
### `environment_vars`
|
||||
|
||||
This section can be used to set environment variables for those unable to modify the environment of the container, like within Home Assistant OS.
|
||||
This section can be used to set environment variables for those unable to modify the environment of the container (ie. within HassOS)
|
||||
|
||||
Example:
|
||||
|
||||
@ -172,57 +172,27 @@ listen [::]:8971 ipv6only=off ssl;
|
||||
listen [::]:5000 ipv6only=off;
|
||||
```
|
||||
|
||||
## Base path
|
||||
|
||||
By default, Frigate runs at the root path (`/`). However some setups require to run Frigate under a custom path prefix (e.g. `/frigate`), especially when Frigate is located behind a reverse proxy that requires path-based routing.
|
||||
|
||||
### Set Base Path via HTTP Header
|
||||
The preferred way to configure the base path is through the `X-Ingress-Path` HTTP header, which needs to be set to the desired base path in an upstream reverse proxy.
|
||||
|
||||
For example, in Nginx:
|
||||
```
|
||||
location /frigate {
|
||||
proxy_set_header X-Ingress-Path /frigate;
|
||||
proxy_pass http://frigate_backend;
|
||||
}
|
||||
```
|
||||
|
||||
### Set Base Path via Environment Variable
|
||||
When it is not feasible to set the base path via a HTTP header, it can also be set via the `FRIGATE_BASE_PATH` environment variable in the Docker Compose file.
|
||||
|
||||
For example:
|
||||
```
|
||||
services:
|
||||
frigate:
|
||||
image: blakeblackshear/frigate:latest
|
||||
environment:
|
||||
- FRIGATE_BASE_PATH=/frigate
|
||||
```
|
||||
|
||||
This can be used for example to access Frigate via a Tailscale agent (https), by simply forwarding all requests to the base path (http):
|
||||
```
|
||||
tailscale serve --https=443 --bg --set-path /frigate http://localhost:5000/frigate
|
||||
```
|
||||
|
||||
## Custom Dependencies
|
||||
|
||||
### Custom ffmpeg build
|
||||
|
||||
Included with Frigate is a build of ffmpeg that works for the vast majority of users. However, there exists some hardware setups which have incompatibilities with the included build. In this case, statically built `ffmpeg` and `ffprobe` binaries can be placed in `/config/custom-ffmpeg/bin` for Frigate to use.
|
||||
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:
|
||||
|
||||
1. Download your ffmpeg build and uncompress it to the `/config/custom-ffmpeg` folder. Verify that both the `ffmpeg` and `ffprobe` binaries are located in `/config/custom-ffmpeg/bin`.
|
||||
2. Update the `ffmpeg.path` in your Frigate config to `/config/custom-ffmpeg`.
|
||||
3. Restart Frigate and the custom version will be used if the steps above were done correctly.
|
||||
1. Download your ffmpeg build and uncompress to the Frigate config folder.
|
||||
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 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
|
||||
|
||||
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.2, there may be certain cases where you want to run a different version of go2rtc.
|
||||
|
||||
To do this:
|
||||
|
||||
1. Download the go2rtc build to the `/config` folder.
|
||||
1. Download the go2rtc build to the /config folder.
|
||||
2. Rename the build to `go2rtc`.
|
||||
3. Give `go2rtc` execute permission.
|
||||
4. Restart Frigate and the custom version will be used, you can verify by checking go2rtc logs.
|
||||
|
@ -43,28 +43,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 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
|
||||
auth:
|
||||
failed_login_rate_limit: "1/second;5/minute;20/hour"
|
||||
trusted_proxies:
|
||||
- 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
|
||||
- 172.18.0.0/16 # <---- this is the subnet for the internal docker compose network
|
||||
```
|
||||
|
||||
## JWT Token Secret
|
||||
@ -81,7 +66,7 @@ Frigate looks for a JWT token secret in the following order:
|
||||
|
||||
1. An environment variable named `FRIGATE_JWT_SECRET`
|
||||
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
|
||||
|
||||
If no secret is found on startup, Frigate generates one and stores it in a `.jwt_secret` file in the config directory.
|
||||
@ -92,7 +77,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.
|
||||
|
||||
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.
|
||||
|
||||
@ -112,44 +97,15 @@ python3 -c 'import secrets; print(secrets.token_hex(64))'
|
||||
|
||||
### 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
|
||||
proxy:
|
||||
...
|
||||
separator: "|" # This value defaults to a comma, but Authentik uses a pipe, for example.
|
||||
header_map:
|
||||
user: x-forwarded-user
|
||||
role: x-forwarded-groups
|
||||
```
|
||||
|
||||
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 user’s 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:
|
||||
|
||||
```
|
||||
@ -170,6 +126,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.
|
||||
|
||||
Future versions of Frigate may leverage group and role headers for authorization in Frigate as well.
|
||||
|
||||
### 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.
|
||||
@ -177,31 +135,3 @@ Frigate gracefully performs login page redirection that should work with most au
|
||||
### 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.
|
||||
|
||||
## 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 user’s role by selecting **admin** or **viewer**.
|
||||
|
@ -167,7 +167,3 @@ To maintain object tracking during PTZ moves, Frigate tracks the motion of your
|
||||
### Calibration seems to have completed, but the camera is not actually moving to track my object. Why?
|
||||
|
||||
Some cameras have firmware that reports that FOV RelativeMove, the ONVIF command that Frigate uses for autotracking, is supported. However, if the camera does not pan or tilt when an object comes into the required zone, your camera's firmware does not actually support FOV RelativeMove. One such camera is the Uniview IPC672LR-AX4DUPK. It actually moves its zoom motor instead of panning and tilting and does not follow the ONVIF standard whatsoever.
|
||||
|
||||
### Frigate reports an error saying that calibration has failed. Why?
|
||||
|
||||
Calibration measures the amount of time it takes for Frigate to make a series of movements with your PTZ. This error message is recorded in the log if these values are too high for Frigate to support calibrated autotracking. This is often the case when your camera's motor or network connection is too slow or your camera's firmware doesn't report the motor status in a timely manner. You can try running without calibration (just remove the `movement_weights` line from your config and restart), but if calibration fails, this often means that autotracking will behave unpredictably.
|
||||
|
@ -1,31 +0,0 @@
|
||||
---
|
||||
id: bird_classification
|
||||
title: Bird Classification
|
||||
---
|
||||
|
||||
Bird classification identifies known birds using a quantized Tensorflow model. When a known bird is recognized, its common name will be added as a `sub_label`. This information is included in the UI, filters, as well as in notifications.
|
||||
|
||||
## Minimum System Requirements
|
||||
|
||||
Bird classification runs a lightweight tflite model on the CPU, there are no significantly different system requirements than running Frigate itself.
|
||||
|
||||
## Model
|
||||
|
||||
The classification model used is the MobileNet INat Bird Classification, [available identifiers can be found here.](https://raw.githubusercontent.com/google-coral/test_data/master/inat_bird_labels.txt)
|
||||
|
||||
## Configuration
|
||||
|
||||
Bird classification is disabled by default, it must be enabled in your config file before it can be used. Bird classification is a global configuration setting.
|
||||
|
||||
```yaml
|
||||
classification:
|
||||
bird:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
Fine-tune bird classification with these optional parameters:
|
||||
|
||||
- `threshold`: Classification confidence score required to set the sub label on the object.
|
||||
- Default: `0.9`.
|
@ -4,7 +4,7 @@ In addition to Frigate's Live camera dashboard, Birdseye allows a portable heads
|
||||
|
||||
Birdseye can be viewed by adding the "Birdseye" camera to a Camera Group in the Web UI. Add a Camera Group by pressing the "+" icon on the Live page, and choose "Birdseye" as one of the cameras.
|
||||
|
||||
Birdseye can also be used in Home Assistant dashboards, cast to media devices, etc.
|
||||
Birdseye can also be used in HomeAssistant dashboards, cast to media devices, etc.
|
||||
|
||||
## Birdseye Behavior
|
||||
|
||||
|
@ -15,17 +15,6 @@ Many cameras support encoding options which greatly affect the live view experie
|
||||
|
||||
:::
|
||||
|
||||
## H.265 Cameras via Safari
|
||||
|
||||
Some cameras support h265 with different formats, but Safari only supports the annexb format. When using h265 camera streams for recording with devices that use the Safari browser, the `apple_compatibility` option should be used.
|
||||
|
||||
```yaml
|
||||
cameras:
|
||||
h265_cam: # <------ Doesn't matter what the camera is called
|
||||
ffmpeg:
|
||||
apple_compatibility: true # <- Adds compatibility with MacOS and iPhone
|
||||
```
|
||||
|
||||
## MJPEG Cameras
|
||||
|
||||
Note that mjpeg cameras require encoding the video into h264 for recording, and restream roles. This will use significantly more CPU than if the cameras supported h264 feeds directly. It is recommended to use the restream role to create an h264 restream and then use that as the source for ffmpeg.
|
||||
@ -33,7 +22,7 @@ Note that mjpeg cameras require encoding the video into h264 for recording, and
|
||||
```yaml
|
||||
go2rtc:
|
||||
streams:
|
||||
mjpeg_cam: "ffmpeg:http://your_mjpeg_stream_url#video=h264#hardware" # <- use hardware acceleration to create an h264 stream usable for other components.
|
||||
mjpeg_cam: "ffmpeg:{your_mjpeg_stream_url}#video=h264#hardware" # <- use hardware acceleration to create an h264 stream usable for other components.
|
||||
|
||||
cameras:
|
||||
...
|
||||
@ -90,15 +79,14 @@ rtsp://USERNAME:PASSWORD@CAMERA-IP/cam/realmonitor?channel=1&subtype=3 # new hig
|
||||
|
||||
### Annke C800
|
||||
|
||||
This camera is H.265 only. To be able to play clips on some devices (like MacOs or iPhone) the H.265 stream has to be adjusted using the `apple_compatibility` config.
|
||||
This camera is H.265 only. To be able to play clips on some devices (like MacOs or iPhone) the H.265 stream has to be repackaged and the audio stream has to be converted to aac. Unfortunately direct playback of in the browser is not working (yet), but the downloaded clip can be played locally.
|
||||
|
||||
```yaml
|
||||
cameras:
|
||||
annkec800: # <------ Name the camera
|
||||
ffmpeg:
|
||||
apple_compatibility: true # <- Adds compatibility with MacOS and iPhone
|
||||
output_args:
|
||||
record: preset-record-generic-audio-aac
|
||||
record: -f segment -segment_time 10 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c:v copy -tag:v hvc1 -bsf:v hevc_mp4toannexb -c:a aac
|
||||
|
||||
inputs:
|
||||
- path: rtsp://USERNAME:PASSWORD@CAMERA-IP/H264/ch1/main/av_stream # <----- Update for your camera
|
||||
@ -230,7 +218,7 @@ go2rtc:
|
||||
- rtspx://192.168.1.1:7441/abcdefghijk
|
||||
```
|
||||
|
||||
[See the go2rtc docs for more information](https://github.com/AlexxIT/go2rtc/tree/v1.9.9#source-rtsp)
|
||||
[See the go2rtc docs for more information](https://github.com/AlexxIT/go2rtc/tree/v1.9.2#source-rtsp)
|
||||
|
||||
In the Unifi 2.0 update Unifi Protect Cameras had a change in audio sample rate which causes issues for ffmpeg. The input rate needs to be set for record if used directly with unifi protect.
|
||||
|
||||
|