From f536494a380a9c987d974d04260bba3804ec1724 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Sun, 24 Apr 2022 13:52:12 -0500 Subject: [PATCH] Multi arch image with nvidia decode support * build working * update makefile * use jellyfin-ffmpeg for all arch * just build web once for all arch * update actions build * update docs --- .github/workflows/pull_request.yml | 22 ++--- Makefile | 28 +++++- docker/Dockerfile | 53 +++++----- .../configuration/hardware_acceleration.md | 74 +++++++++++++- docs/docs/configuration/nvdec.md | 99 ------------------- docs/docs/contributing.md | 6 ++ docs/sidebars.js | 1 - 7 files changed, 135 insertions(+), 148 deletions(-) delete mode 100644 docs/docs/configuration/nvdec.md diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 08a1ebbe6..f5efcf8d6 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -20,20 +20,6 @@ jobs: run: npm run lint working-directory: ./web - web_build: - name: Web - Build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - - uses: actions/setup-node@master - with: - node-version: 16.x - - run: npm install - working-directory: ./web - - name: Build - run: npm run build - working-directory: ./web - web_test: name: Web - Test runs-on: ubuntu-latest @@ -71,6 +57,14 @@ jobs: steps: - name: Check out code uses: actions/checkout@v2 + - 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@v1 - name: Set up Docker Buildx diff --git a/Makefile b/Makefile index 2f308c845..6702690b9 100644 --- a/Makefile +++ b/Makefile @@ -1,18 +1,36 @@ -default_target: frigate +default_target: local COMMIT_HASH := $(shell git log -1 --pretty=format:"%h"|tail -1) +VERSION = 0.11.0 +CURRENT_UID := $(shell id -u) +CURRENT_GID := $(shell id -g) version: - echo "VERSION='0.11.0-$(COMMIT_HASH)'" > frigate/version.py + echo "VERSION=\"$(VERSION)-$(COMMIT_HASH)\"" > frigate/version.py + +build_web: + docker run --volume ${PWD}/web:/web -w /web --volume /etc/passwd:/etc/passwd:ro --volume /etc/group:/etc/group:ro -u $(CURRENT_UID):$(CURRENT_GID) node:16 /bin/bash -c "npm install && npm run build" nginx_frigate: docker buildx build --push --platform linux/arm/v7,linux/arm64/v8,linux/amd64 --tag blakeblackshear/frigate-nginx:1.0.2 --file docker/Dockerfile.nginx . -frigate: version +local: DOCKER_BUILDKIT=1 docker build -t frigate -f docker/Dockerfile . -frigate_push: version - docker buildx build --push --platform linux/arm64/v8,linux/amd64 --tag blakeblackshear/frigate:0.11.0-$(COMMIT_HASH) --file docker/Dockerfile . +amd64: + docker buildx build --platform linux/amd64 --tag blakeblackshear/frigate:$(VERSION)-$(COMMIT_HASH) --file docker/Dockerfile . + +arm64: + docker buildx build --platform linux/arm64 --tag blakeblackshear/frigate:$(VERSION)-$(COMMIT_HASH) --file docker/Dockerfile . + +armv7: + docker buildx build --platform linux/arm/v7 --tag blakeblackshear/frigate:$(VERSION)-$(COMMIT_HASH) --file docker/Dockerfile . + +build: version amd64 arm64 armv7 + docker buildx build --platform linux/arm/v7,linux/arm64/v8,linux/amd64 --tag blakeblackshear/frigate:$(VERSION)-$(COMMIT_HASH) --file docker/Dockerfile . + +push: build + docker buildx build --push --platform linux/arm/v7,linux/arm64/v8,linux/amd64 --tag blakeblackshear/frigate:$(VERSION)-$(COMMIT_HASH) --file docker/Dockerfile . run_tests: frigate docker run --rm --entrypoint=python3 frigate:latest -u -m unittest diff --git a/docker/Dockerfile b/docker/Dockerfile index a993ce002..67c35dc96 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,13 +1,5 @@ FROM blakeblackshear/frigate-nginx:1.0.2 as nginx -FROM node:16 as web - -WORKDIR /opt/frigate - -COPY web/ . - -RUN npm install && npm run build - FROM debian:11 as wheels ARG TARGETARCH @@ -54,7 +46,13 @@ RUN pip3 wheel --wheel-dir=/wheels -r requirements-wheels.txt FROM debian:11-slim ARG TARGETARCH -ENV DEBIAN_FRONTEND=noninteractive +# https://askubuntu.com/questions/972516/debian-frontend-environment-variable +ARG DEBIAN_FRONTEND="noninteractive" +# http://stackoverflow.com/questions/48162574/ddg#49462622 +ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn +# https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(Native-GPU-Support) +ENV NVIDIA_DRIVER_CAPABILITIES="compute,video,utility" + ENV FLASK_ENV=development COPY --from=wheels /wheels /wheels @@ -71,30 +69,29 @@ RUN apt-get -qq update \ && wget -O - http://archive.raspberrypi.org/debian/raspberrypi.gpg.key | apt-key add - \ && echo "deb http://archive.raspberrypi.org/debian/ bullseye main" | tee /etc/apt/sources.list.d/raspi.list \ # add coral repo - && APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn apt-key adv --fetch-keys https://packages.cloud.google.com/apt/doc/apt-key.gpg \ + && apt-key adv --fetch-keys https://packages.cloud.google.com/apt/doc/apt-key.gpg \ && echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" > /etc/apt/sources.list.d/coral-edgetpu.list \ && echo "libedgetpu1-max libedgetpu/accepted-eula select true" | debconf-set-selections \ + # jellyfin-ffmpeg + && wget -O - https://repo.jellyfin.org/jellyfin_team.gpg.key | apt-key add - \ + && echo "deb [arch=$( dpkg --print-architecture )] https://repo.jellyfin.org/$( awk -F'=' '/^ID=/{ print $NF }' /etc/os-release ) $( awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release ) main" | tee /etc/apt/sources.list.d/jellyfin.list \ && apt-get -qq update \ - && apt-get -qq install --no-install-recommends -y \ - ffmpeg \ + && apt-get -qq install --no-install-recommends --no-install-suggests -y \ # coral drivers libedgetpu1-max python3-tflite-runtime python3-pycoral \ + jellyfin-ffmpeg \ && pip3 install -U /wheels/*.whl \ - && rm -rf /var/lib/apt/lists/* /wheels \ - && (apt-get autoremove -y; apt-get autoclean -y) - -# AMD64 specific packages -RUN if [ "${TARGETARCH}" = "amd64" ]; \ - then \ - wget -qO - https://repositories.intel.com/graphics/intel-graphics.key | apt-key add - \ - && echo 'deb [arch=amd64] https://repositories.intel.com/graphics/ubuntu focal main' > /etc/apt/sources.list.d/intel-graphics.list \ - && apt-get -qq update \ - && apt-get -qq install --no-install-recommends -y \ - # VAAPI drivers for Intel hardware accel - libva-drm2 libva2 libmfx1 i965-va-driver vainfo intel-media-va-driver-non-free mesa-vdpau-drivers mesa-va-drivers mesa-vdpau-drivers libdrm-radeon1 \ - && rm -rf /var/lib/apt/lists/* \ - && (apt-get autoremove -y; apt-get autoclean -y) \ - fi + && ln -s /usr/lib/jellyfin-ffmpeg/ffmpeg /usr/bin/ffmpeg \ + # amd64 specific packages + && if [ "${TARGETARCH}" = "amd64" ]; then \ + apt-get -qq install --no-install-recommends -y \ + mesa-va-drivers; \ + fi \ + && rm -rf /wheels \ + && apt-get remove gnupg apt-transport-https -y \ + && apt-get clean autoclean -y \ + && apt-get autoremove -y \ + && rm -rf /var/lib/apt/lists/* COPY --from=nginx /usr/local/nginx/ /usr/local/nginx/ @@ -107,7 +104,7 @@ WORKDIR /opt/frigate/ ADD frigate frigate/ ADD migrations migrations/ -COPY --from=web /opt/frigate/dist web/ +COPY web/dist web/ COPY docker/rootfs/ / diff --git a/docs/docs/configuration/hardware_acceleration.md b/docs/docs/configuration/hardware_acceleration.md index e2153f4f2..ecdc038b4 100644 --- a/docs/docs/configuration/hardware_acceleration.md +++ b/docs/docs/configuration/hardware_acceleration.md @@ -67,4 +67,76 @@ ffmpeg: ### NVIDIA GPU -NVIDIA GPU based decoding via NVDEC is supported, but requires special configuration. See the [NVIDIA NVDEC documentation](/configuration/nvdec) for more details. +These instructions are based on the [jellyfin documentation](https://jellyfin.org/docs/general/administration/hardware-acceleration.html#nvidia-hardware-acceleration-on-docker-linux) + +Add `--gpus all` to your docker run command or update your compose file. + +```yaml +services: + frigate: + ... + image: blakeblackshear/frigate:stable + deploy: # <------------- Add this section + resources: + reservations: + devices: + - capabilities: [gpu] +``` + +The decoder you need to pass in the `hwaccel_args` will depend on the input video. + +A list of supported codecs (you can use `ffmpeg -decoders | grep cuvid` in the container to get a list) + +```shell + V..... h263_cuvid Nvidia CUVID H263 decoder (codec h263) + V..... h264_cuvid Nvidia CUVID H264 decoder (codec h264) + V..... hevc_cuvid Nvidia CUVID HEVC decoder (codec hevc) + V..... mjpeg_cuvid Nvidia CUVID MJPEG decoder (codec mjpeg) + V..... mpeg1_cuvid Nvidia CUVID MPEG1VIDEO decoder (codec mpeg1video) + V..... mpeg2_cuvid Nvidia CUVID MPEG2VIDEO decoder (codec mpeg2video) + V..... mpeg4_cuvid Nvidia CUVID MPEG4 decoder (codec mpeg4) + V..... vc1_cuvid Nvidia CUVID VC1 decoder (codec vc1) + V..... vp8_cuvid Nvidia CUVID VP8 decoder (codec vp8) + V..... vp9_cuvid Nvidia CUVID VP9 decoder (codec vp9) +``` + +For example, for H265 video (hevc), you'll select `hevc_cuvid`. + +```yaml +ffmpeg: + hwaccel_args: + - -c:v + - hevc_cuvid +``` + +If everything is working correctly, you should see a significant improvement in performance. +Verify that hardware decoding is working by running `nvidia-smi`, which should show the ffmpeg +processes: + +``` ++-----------------------------------------------------------------------------+ +| NVIDIA-SMI 455.38 Driver Version: 455.38 CUDA Version: 11.1 | +|-------------------------------+----------------------+----------------------+ +| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | +| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | +| | | MIG M. | +|===============================+======================+======================| +| 0 GeForce GTX 166... Off | 00000000:03:00.0 Off | N/A | +| 38% 41C P2 36W / 125W | 2082MiB / 5942MiB | 5% Default | +| | | N/A | ++-------------------------------+----------------------+----------------------+ + ++-----------------------------------------------------------------------------+ +| Processes: | +| GPU GI CI PID Type Process name GPU Memory | +| ID ID Usage | +|=============================================================================| +| 0 N/A N/A 12737 C ffmpeg 249MiB | +| 0 N/A N/A 12751 C ffmpeg 249MiB | +| 0 N/A N/A 12772 C ffmpeg 249MiB | +| 0 N/A N/A 12775 C ffmpeg 249MiB | +| 0 N/A N/A 12800 C ffmpeg 249MiB | +| 0 N/A N/A 12811 C ffmpeg 417MiB | +| 0 N/A N/A 12827 C ffmpeg 417MiB | ++-----------------------------------------------------------------------------+ +``` diff --git a/docs/docs/configuration/nvdec.md b/docs/docs/configuration/nvdec.md deleted file mode 100644 index 69889241b..000000000 --- a/docs/docs/configuration/nvdec.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -id: nvdec -title: NVIDIA hardware decoder ---- - -Certain nvidia cards include a hardware decoder, which can greatly improve the -performance of video decoding. In order to use NVDEC, a special build of -ffmpeg with NVDEC support is required. The special docker architecture 'amd64nvidia' -includes this support for amd64 platforms. An aarch64 for the Jetson, which -also includes NVDEC may be added in the future. - -Some more detailed setup instructions are also available in [this issue](https://github.com/blakeblackshear/frigate/issues/1847#issuecomment-932076731). - -## Docker setup - -### Requirements - -[nVidia closed source driver](https://www.nvidia.com/en-us/drivers/unix/) required to access NVDEC. -[nvidia-docker](https://github.com/NVIDIA/nvidia-docker) required to pass NVDEC to docker. - -### Setting up docker-compose - -In order to pass NVDEC, the docker engine must be set to `nvidia` and the environment variables -`NVIDIA_VISIBLE_DEVICES=all` and `NVIDIA_DRIVER_CAPABILITIES=compute,utility,video` must be set. - -In a docker compose file, these lines need to be set: - -```yaml -services: - frigate: - ... - image: blakeblackshear/frigate:stable-amd64nvidia - runtime: nvidia - environment: - - NVIDIA_VISIBLE_DEVICES=all - - NVIDIA_DRIVER_CAPABILITIES=compute,utility,video -``` - -### Setting up the configuration file - -In your frigate config.yml, you'll need to set ffmpeg to use the hardware decoder. -The decoder you choose will depend on the input video. - -A list of supported codecs (you can use `ffmpeg -decoders | grep cuvid` in the container to get a list) - -```shell - V..... h263_cuvid Nvidia CUVID H263 decoder (codec h263) - V..... h264_cuvid Nvidia CUVID H264 decoder (codec h264) - V..... hevc_cuvid Nvidia CUVID HEVC decoder (codec hevc) - V..... mjpeg_cuvid Nvidia CUVID MJPEG decoder (codec mjpeg) - V..... mpeg1_cuvid Nvidia CUVID MPEG1VIDEO decoder (codec mpeg1video) - V..... mpeg2_cuvid Nvidia CUVID MPEG2VIDEO decoder (codec mpeg2video) - V..... mpeg4_cuvid Nvidia CUVID MPEG4 decoder (codec mpeg4) - V..... vc1_cuvid Nvidia CUVID VC1 decoder (codec vc1) - V..... vp8_cuvid Nvidia CUVID VP8 decoder (codec vp8) - V..... vp9_cuvid Nvidia CUVID VP9 decoder (codec vp9) -``` - -For example, for H265 video (hevc), you'll select `hevc_cuvid`. Add -`-c:v hevc_cuvid` to your ffmpeg input arguments: - -```yaml -ffmpeg: - input_args: ... - - -c:v - - hevc_cuvid -``` - -If everything is working correctly, you should see a significant improvement in performance. -Verify that hardware decoding is working by running `nvidia-smi`, which should show the ffmpeg -processes: - -``` -+-----------------------------------------------------------------------------+ -| NVIDIA-SMI 455.38 Driver Version: 455.38 CUDA Version: 11.1 | -|-------------------------------+----------------------+----------------------+ -| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | -| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | -| | | MIG M. | -|===============================+======================+======================| -| 0 GeForce GTX 166... Off | 00000000:03:00.0 Off | N/A | -| 38% 41C P2 36W / 125W | 2082MiB / 5942MiB | 5% Default | -| | | N/A | -+-------------------------------+----------------------+----------------------+ - -+-----------------------------------------------------------------------------+ -| Processes: | -| GPU GI CI PID Type Process name GPU Memory | -| ID ID Usage | -|=============================================================================| -| 0 N/A N/A 12737 C ffmpeg 249MiB | -| 0 N/A N/A 12751 C ffmpeg 249MiB | -| 0 N/A N/A 12772 C ffmpeg 249MiB | -| 0 N/A N/A 12775 C ffmpeg 249MiB | -| 0 N/A N/A 12800 C ffmpeg 249MiB | -| 0 N/A N/A 12811 C ffmpeg 417MiB | -| 0 N/A N/A 12827 C ffmpeg 417MiB | -+-----------------------------------------------------------------------------+ -``` diff --git a/docs/docs/contributing.md b/docs/docs/contributing.md index a5786a3b2..59c1423f2 100644 --- a/docs/docs/contributing.md +++ b/docs/docs/contributing.md @@ -102,6 +102,12 @@ This should show <50% CPU in top, and ~80% CPU without `-c:v h264_v4l2m2m`. ffmpeg -c:v h264_v4l2m2m -re -stream_loop -1 -i https://streams.videolan.org/ffmpeg/incoming/720p60.mp4 -f rawvideo -pix_fmt yuv420p pipe: > /dev/null ``` +**NVIDIA** + +```shell +ffmpeg -c:v h264_cuvid -re -stream_loop -1 -i https://streams.videolan.org/ffmpeg/incoming/720p60.mp4 -f rawvideo -pix_fmt yuv420p pipe: > /dev/null +``` + ## Web Interface ### Prerequisites diff --git a/docs/sidebars.js b/docs/sidebars.js index 39346c107..d8a3f5b98 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -22,7 +22,6 @@ module.exports = { "configuration/stationary_objects", "configuration/advanced", "configuration/hardware_acceleration", - "configuration/nvdec", "configuration/camera_specific", ], Integrations: [