Files
cuframes/docs/integrations/frigate.md
T
gx 12708618d4 docs: reference integrations + examples
- docs/integrations/frigate.md — полный production-tested guide:
  Dockerfile, docker-compose, config.yml, troubleshooting (s6+pid, scale_cuda,
  hwaccel issues), build steps
- docs/integrations/cctv-cpp.md — C++ pattern: IFrameSource interface +
  CuframesSource skeleton + CMake setup + runtime requirements
- examples/frigate-compose/ — reference compose stack (cuframes-pub + Frigate)
  с config.yml stub, .env.example, README
- examples/python-consumer/ — ctypes-based skeleton для AI/ML pipeline'ов
  (до v0.3 native pybind11 bindings)
- docs/integration.md — превратился в index-страницу, ссылается на specific guides

Reorganization упрощает onboarding: пользователь выбирает guide по типу
integration'а (Frigate/C++/Python/FFmpeg) и сразу видит реальный code.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 21:37:35 +01:00

306 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Frigate integration
Полный production-tested guide для интеграции cuframes с
[Frigate NVR](https://github.com/blakeblackshear/frigate). На основе реального
deployment (Frigate 0.17.1-tensorrt + RTX 5090 + Dahua HEVC камеры).
## Что вы получаете
- **Один NVDEC decode на камеру** вместо одного у Frigate + одного у каждого
другого consumer'а (cctv-processor, AI-скрипт, mosaic-сервер).
- Frigate видит decoded frames через **обычный FFmpeg URL** — никакого fork'а
Frigate-кода. Frigate сам не подозревает что под капотом cuframes.
## Что вы НЕ получаете в v0.1
- **Record path** (`-c:v copy` для архива) — этот path в Frigate всё ещё через
свой отдельный RTSP. v0.2 cuframes решит это через encoded packet sharing
(см. [issue #2](https://git.goldix.org/gx/cuframes/issues/2)).
- Hwaccel CUDA filters для detect resize (`scale_cuda`) — наш minimal FFmpeg
собран без `--enable-cuda-llvm` (не работает на glibc < 2.38 что у Debian 12,
на котором Frigate base). Workaround: `hwaccel_args: []` в config → CPU
scale (cost ~5-10% CPU на FHD25).
## Архитектура
```
Camera RTSP ──► cuframes-rtsp-source ──► [NVDEC ─► NV12 in CUDA IPC]
├──► Frigate (ffmpeg -f cuframes) → detect
├──► cctv-processor (CuframesSource) → motion+mosaic
└──► AI-script (Python ctypes) → inference
```
## Требования
| | Минимум | Note |
|---|---|---|
| NVIDIA driver | 555+ | для CUDA 12 runtime |
| CUDA Toolkit (для build patched FFmpeg) | 12.4+ | host или builder container |
| GPU compute capability | ≥ 7.5 | требование CUDA IPC |
| OS на target (Frigate runtime) | Debian 12 bookworm | glibc 2.36 — это база Frigate `stable-tensorrt` |
| OS на builder | Ubuntu 22.04 (glibc 2.35) | forward-compat с Debian 12 |
| docker buildx | latest | для multi-stage build |
## Шаг 1 — Build patched Frigate image
Cuframes integration требует patched FFmpeg внутри Frigate с `cuframes://`
demuxer. Самый простой путь — собрать overlay image поверх existing Frigate.
### 1.1. Минимальный Dockerfile (Debian 12 builder + custom FFmpeg)
```dockerfile
# Build patched FFmpeg на Debian 12 (glibc-совместимо с Frigate runtime)
FROM debian:bookworm AS builder
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential cmake git nasm pkg-config ca-certificates wget patch ninja-build \
libssl-dev libx264-dev libx265-dev libnuma-dev zlib1g-dev \
libfreetype-dev libfribidi-dev libharfbuzz-dev libfontconfig-dev \
libvpx-dev libopus-dev libmp3lame-dev libvorbis-dev libtheora-dev libwebp-dev \
libaom-dev libdav1d-dev libsvtav1enc-dev \
libssh-dev librist-dev libsrt-openssl-dev \
libdrm-dev libva-dev libxcb1-dev \
&& rm -rf /var/lib/apt/lists/*
# CUDA toolkit 12.x
RUN wget -q https://developer.download.nvidia.com/compute/cuda/repos/debian12/x86_64/cuda-keyring_1.1-1_all.deb \
&& dpkg -i cuda-keyring_1.1-1_all.deb && rm cuda-keyring_1.1-1_all.deb \
&& apt-get update && apt-get install -y --no-install-recommends cuda-toolkit-12-6 \
&& rm -rf /var/lib/apt/lists/*
ENV PATH=/usr/local/cuda/bin:$PATH
# nv-codec-headers (для FFmpeg ffnvcodec/nvenc/nvdec)
RUN git clone --depth 1 --branch n12.2.72.0 https://github.com/FFmpeg/nv-codec-headers.git /tmp/nvc \
&& make -C /tmp/nvc install && rm -rf /tmp/nvc
# Build libcuframes (static install в /opt/cuframes)
RUN git clone --depth 1 https://git.goldix.org/gx/cuframes.git /src/cuframes \
&& cmake -B /src/cuframes/build -S /src/cuframes -G Ninja \
-DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF \
-DBUILD_EXAMPLES=OFF -DBUILD_TOOLS=OFF \
&& cmake --build /src/cuframes/build -j"$(nproc)" \
&& cmake --install /src/cuframes/build --prefix /opt/cuframes
# Clone patched FFmpeg fork (либо upstream + apply patch — см. filter/README.md)
RUN git clone --depth 1 --branch n7.1-cuframes \
https://git.goldix.org/gx/ffmpeg-patched.git /src/ffmpeg
# Configure (minimal-but-functional для Frigate)
RUN cd /src/ffmpeg && ./configure \
--prefix=/opt/ffmpeg \
--enable-gpl --enable-version3 --enable-nonfree \
--enable-libcuframes \
--enable-libx264 --enable-libx265 \
--enable-libvpx --enable-libopus --enable-libmp3lame \
--enable-libvorbis --enable-libtheora --enable-libwebp \
--enable-libaom --enable-libdav1d --enable-libsvtav1 \
--enable-libfreetype --enable-libfribidi --enable-libharfbuzz \
--enable-libssh --enable-librist --enable-libsrt \
--enable-openssl \
--enable-ffnvcodec --enable-cuvid --enable-nvenc --enable-nvdec \
--extra-cflags="-I/opt/cuframes/include -I/usr/local/cuda/include" \
--extra-ldflags="-L/opt/cuframes/lib -L/usr/local/cuda/lib64" \
--extra-libs="-lcudart -lpthread -lrt -lm" \
--disable-doc --disable-htmlpages --disable-manpages
RUN cd /src/ffmpeg && make -j"$(nproc)" && make install
# ─── Runtime: Frigate + наши binaries поверх ──────────────────────────
FROM ghcr.io/blakeblackshear/frigate:stable-tensorrt
# Missing dynamic .so которые требует наш patched ffmpeg (Frigate image их не имеет —
# bundled статически собран без них в DT_NEEDED)
RUN apt-get update && apt-get install -y --no-install-recommends \
libharfbuzz0b libfribidi0 librist4 libsrt1.5-openssl libssh-4 \
libvpx7 libwebpmux3 libwebp7 libdav1d6 libaom3 libmp3lame0 \
libsvtav1enc1 libtheora0 libvorbis0a libvorbisenc2 \
libx264-164 libx265-199 libopus0 \
&& rm -rf /var/lib/apt/lists/*
# Replace bundled ffmpeg (оригинал backup'нем под .orig)
RUN cp /usr/lib/ffmpeg/7.0/bin/ffmpeg /usr/lib/ffmpeg/7.0/bin/ffmpeg.orig \
&& cp /usr/lib/ffmpeg/7.0/bin/ffprobe /usr/lib/ffmpeg/7.0/bin/ffprobe.orig
COPY --from=builder /opt/ffmpeg/bin/ffmpeg /usr/lib/ffmpeg/7.0/bin/ffmpeg
COPY --from=builder /opt/ffmpeg/bin/ffprobe /usr/lib/ffmpeg/7.0/bin/ffprobe
COPY --from=builder /opt/cuframes/lib/libcuframes.so.0.1.0 /usr/local/lib/
RUN cd /usr/local/lib && ln -sf libcuframes.so.0.1.0 libcuframes.so.0 \
&& ln -sf libcuframes.so.0 libcuframes.so && ldconfig
# Build-time smoke: ldd resolved + cuframes demuxer registered
RUN ldd /usr/lib/ffmpeg/7.0/bin/ffmpeg | grep -q "not found" && exit 1 || true
RUN /usr/lib/ffmpeg/7.0/bin/ffmpeg -hide_banner -formats | grep -q cuframes \
&& echo "OK: cuframes demuxer registered in Frigate image"
```
Build:
```bash
docker build -t local/frigate-cuframes:latest -f Dockerfile.frigate .
```
Размер ~10 GB (наследует Frigate `stable-tensorrt` ~9 GB).
## Шаг 2 — docker-compose: publisher + Frigate
```yaml
services:
# Один publisher на камеру — единственный source RTSP, делает 1× NVDEC.
cuframes-pub-parking:
image: git.goldix.org/gx/cuframes:0.1 # либо local build из filter/Dockerfile.runtime
container_name: cuframes-pub-parking
restart: unless-stopped
runtime: nvidia
# CRITICAL: ipc=shareable — Frigate и другие consumers подсоединяются через
# ipc: container:cuframes-pub-parking
ipc: shareable
shm_size: 256m
environment:
NVIDIA_VISIBLE_DEVICES: all
NVIDIA_DRIVER_CAPABILITIES: compute,video,utility
volumes:
- cuframes_sock:/run/cuframes
command:
- /usr/local/bin/cuframes-rtsp-source
- --rtsp
- "rtsp://admin:${CAM_PASS}@cam-parking-ip:554/cam/realmonitor?channel=1&subtype=1"
- --key
- cam-parking
- --ring
- "6"
- --verbose
frigate:
image: local/frigate-cuframes:latest
container_name: frigate
restart: unless-stopped
depends_on:
cuframes-pub-parking:
condition: service_started
runtime: nvidia
privileged: true
shm_size: 512m
# CUDA IPC c publisher'ом: shared /dev/shm
# WARN: pid намерено НЕ share'ится — Frigate использует s6-overlay,
# которое требует PID 1 в своём namespace.
ipc: "container:cuframes-pub-parking"
environment:
FRIGATE_RTSP_PASSWORD: "${FRIGATE_RTSP_PASSWORD}"
NVIDIA_VISIBLE_DEVICES: all
NVIDIA_DRIVER_CAPABILITIES: compute,video,utility
ports:
- "5000:5000"
- "8971:8971"
volumes:
- cuframes_sock:/run/cuframes:ro
- ./config/config.yml:/config/config.yml:ro
- /home/user/frigate-media:/media/frigate
# ... остальные volumes как обычно
volumes:
cuframes_sock:
```
## Шаг 3 — Frigate config.yml
Ключевые отличия от стандартного config:
```yaml
ffmpeg:
# ВАЖНО: hwaccel cuda отключаем (наш ffmpeg без cuda-llvm → нет scale_cuda).
# Detect-path использует CPU scale, но decode уже done у publisher'а.
hwaccel_args: []
output_args:
record: preset-record-generic-audio-aac
cameras:
parking_overview:
enabled: true
ffmpeg:
inputs:
# main (full-res) — только запись в архив через прямой RTSP
# (decode у Frigate НЕ происходит — это `-c:v copy` мux)
- path: rtsp://admin:${FRIGATE_RTSP_PASSWORD}@cam-parking-ip:554/cam/realmonitor?channel=1&subtype=0
roles: [record]
# sub-stream → через cuframes (decoded у publisher'а, без второго NVDEC у Frigate)
- path: cuframes://cam-parking
input_args: -f cuframes
roles: [detect]
detect:
width: 640
height: 480
fps: 5
```
После v0.2 cuframes (encoded packet sharing) record-path тоже мoжет
переключиться на `cuframes_packets://cam-parking` — тогда **никакого RTSP в
Frigate config'е вообще**.
## Шаг 4 — Run + verify
```bash
docker compose up -d
docker logs -f frigate
```
Что искать в logs:
- `[INFO] Camera processor started for parking_overview` — normal startup
- НЕТ `[ERROR] Ffmpeg process crashed` — если есть, посмотри
[Troubleshooting](#troubleshooting)
- В `nvidia-smi dmon -s u` колонка `%dec` должна показывать ~1-2% на одну
камеру (это publisher), Frigate сам не decode'ит cuframes input
```bash
# Проверить что Frigate реально читает cuframes:
docker exec frigate ps -ef | grep ffmpeg | grep cuframes
# Должна быть линия вида:
# ffmpeg ... -f cuframes -i cuframes://cam-parking -r 5 -vf fps=5,scale=640:480 ...
```
## Troubleshooting
### `s6-overlay-suexec: fatal: can only run as pid 1`
Появляется если попытались добавить `pid: container:cuframes-pub-parking` в
Frigate service. Frigate's s6-overlay strict требует PID 1.
**Fix**: убрать `pid:` из compose. Если только `ipc:` shared — большинство
случаев работают (Frigate подсоединяется первым и его CUDA context служит
для последующих).
**Альтернатива**: запустить Frigate с собственным namespace но дублировать
publisher socket через bind-mount. Frigate сам управляется first CUDA context.
### `[AVFilterGraph] No such filter: 'scale_cuda'`
Frigate config имеет `hwaccel_args: preset-nvidia` (default). Наш patched
ffmpeg собран без `--enable-cuda-llvm` (не работает на glibc < 2.38). Эта
опция компилирует CUDA filters, включая `scale_cuda`.
**Fix**: `hwaccel_args: []` в config.yml. CPU scale (5-10% CPU per FHD25 камера).
**Real fix** (planned): cuframes v0.2 — publisher сам делает resize до detect-size
и публикует pre-scaled frames. Тогда Frigate не нуждается в scale_cuda.
### `cudaIpcOpenEventHandle: invalid device context`
Consumer container не имеет shared pid namespace с publisher'ом → CUDA driver
не валидирует IPC peer.
**Fix для cross-container CUDA IPC**: `pid: container:<publisher>` + `ipc:
container:<publisher>`. Для Frigate этот fix недоступен (см. предыдущий пункт).
Workaround — поднять Frigate первым после publisher (race window) или использовать
encoded packet path (v0.2).
### `Nonmatching transport in server reply` от RTSP-output Frigate
Не относится к cuframes — это нормальное поведение Frigate's go2rtc для
TCP transport. TV/VLC обычно использует UDP — оно работает.
## См. также
- [filter/README.md](../../filter/README.md) — детали FFmpeg demuxer + patch
- [docs/integration.md](../integration.md) — общий integration guide
- [BENCHMARKS.md](../../BENCHMARKS.md) — production-measured результаты
- [ROADMAP.md](../../ROADMAP.md) — v0.2 что улучшит для Frigate