Dockerfile.nvenc
Rama main · réplica de lectura del repositorio original.
# ============================================================================
# Shrinkerr — GPU / NVENC variant.
#
# Runs on:
# - linux/amd64 ONLY (nvidia/cuda:* base image has no arm64 variant)
#
# Encoding: NVENC (hardware) via ffmpeg's hevc_nvenc, with libx265 CPU fallback.
# Requires: an NVIDIA GPU + the NVIDIA Container Toolkit on the host.
#
# If you don't have an NVIDIA GPU (or you're on Mac, Pi, etc.), use the
# portable multi-arch image built from the default `Dockerfile` instead:
# ghcr.io/<owner>/shrinkerr:latest
# ============================================================================
# Stage 1: Build frontend
FROM mirror.gcr.io/library/node:20-slim AS frontend-build
WORKDIR /app/frontend
COPY frontend/package.json frontend/package-lock.json* ./
RUN npm ci
COPY frontend/ ./
RUN npm run build
# Stage 2: Runtime — CUDA base image, x86_64 only.
# v0.5.13: bumped from cuda:12.3.1-runtime-ubuntu22.04 to
# cuda:12.6.3-runtime-ubuntu24.04 for the lower CVE count Ubuntu 24.04
# carries vs 22.04. CUDA 12.6's driver floor is the same 525.60.13+ as
# 12.3, so existing users don't need to upgrade their NVIDIA driver.
# Ubuntu 24.04 ships Python 3.12 by default (3.11 was 22.04's default),
# so the apt-get install list below moves to python3.12 too.
# v0.7.4: pulled from NVIDIA's own registry (nvcr.io) instead of docker.io
# to keep the NVENC build off the Docker Hub rate-limit path. Same image,
# different host. See the CPU Dockerfile for the matching mirror.gcr.io
# swap on the python/node base images.
# v0.9.81: switched runtime -> cudnn-runtime so CTranslate2 (faster-whisper's
# engine) can run audio language detection on the GPU. CTranslate2 4.5+ (we
# ship 4.8.1) needs cuDNN 9, which this image carries; the plain -runtime
# image has none, so whisper silently fell back to CPU. device="auto" still
# falls back to CPU when no GPU/cuDNN is present, so nothing else changes.
FROM nvcr.io/nvidia/cuda:12.6.3-cudnn-runtime-ubuntu24.04
# Install Python, curl, and GPG for repo signing.
#
# VA-API runtime is also baked in here so users with a mixed Intel iGPU
# + NVIDIA dGPU host (e.g. NUC9 + Quadro) can pick `qsv` / `vaapi` /
# `nvenc` as needed in Settings → Encoding. Harmless on hosts without
# Intel/AMD graphics — ffmpeg simply doesn't surface those encoders.
# v0.3.67+. See the base Dockerfile for the rationale.
RUN set -eux; \
apt-get update; \
# v0.5.13: pull latest security patches at build time. Same
# rationale as the CPU Dockerfile — cheap, knocks down the bulk
# of Scout-reported CVEs without changing the base image.
apt-get upgrade -y --no-install-recommends; \
apt-get install -y --no-install-recommends \
python3.12 python3.12-venv python3-pip \
curl xz-utils \
libarchive-tools \
libbluray-bin \
mkvtoolnix \
tesseract-ocr \
tesseract-ocr-eng tesseract-ocr-chi-sim tesseract-ocr-chi-tra \
tesseract-ocr-jpn tesseract-ocr-kor tesseract-ocr-rus tesseract-ocr-ara \
libgl1 libglib2.0-0 \
libva-drm2 \
intel-media-va-driver-non-free \
i965-va-driver \
mesa-va-drivers \
vainfo \
libvpl2 libmfx1 \
build-essential cmake meson ninja-build pkg-config \
libdrm-dev libigdgmm-dev libpciaccess-dev bzip2; \
# libvpl2 + libmfx1: oneVPL dispatcher + legacy MediaSDK fallback.
# Build deps (build-essential, cmake, meson, ninja, dev headers)
# are temporary — purged after the libva and vpl-gpu-rt builds.
#
# === libva 2.22 from source (v0.3.88+) ===
# BtbN n7.x ffmpeg expects libva ≥ 2.20 (vaMapBuffer2). Ubuntu 22.04
# stock libva is 2.14, too old. libva 2.x is ABI-stable so iHD and
# mesa drivers (compiled against 2.14) keep working against 2.22.
LIBVA_VER=2.22.0; \
curl -fsSL "https://github.com/intel/libva/releases/download/${LIBVA_VER}/libva-${LIBVA_VER}.tar.bz2" -o /tmp/libva.tar.bz2; \
mkdir -p /tmp/libva-src; \
tar xjf /tmp/libva.tar.bz2 -C /tmp/libva-src --strip-components=1; \
cd /tmp/libva-src; \
meson setup build --prefix=/usr -Dlibdir=lib/x86_64-linux-gnu --buildtype=release; \
ninja -C build install; \
cd /; rm -rf /tmp/libva-src /tmp/libva.tar.bz2; \
ldconfig; \
# === vpl-gpu-rt (libmfx-gen) from source (v0.3.89+) ===
# Intel's modern oneVPL GPU runtime; not packaged for Ubuntu 22.04.
# Without it, libvpl2 dispatcher falls back to legacy libmfx1 which
# rejects libva-2.22 displays with MFX_ERR_INCOMPATIBLE_VIDEO_PARAM.
# ~3 min build on x86_64.
VPL_VER=24.4.4; \
curl -fsSL "https://github.com/intel/vpl-gpu-rt/archive/refs/tags/intel-onevpl-${VPL_VER}.tar.gz" -o /tmp/vpl.tar.gz; \
mkdir -p /tmp/vpl-src; \
tar xzf /tmp/vpl.tar.gz -C /tmp/vpl-src --strip-components=1; \
cd /tmp/vpl-src; \
# Memory-conservative configure (v0.3.92+) — see Dockerfile for the
# full rationale. Short version: default `--parallel` OOM-kills
# the GHA free runner during mfx_common_hw linking. Build serially
# and skip optional optimisation passes that need extra RAM.
cmake -B build \
-DCMAKE_BUILD_TYPE=MinSizeRel \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_INSTALL_LIBDIR=lib/x86_64-linux-gnu \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=OFF \
-DBUILD_TESTS=OFF; \
cmake --build build --parallel 1; \
cmake --install build; \
cd /; rm -rf /tmp/vpl-src /tmp/vpl.tar.gz; \
ldconfig; \
apt-get purge -y build-essential cmake meson ninja-build pkg-config libdrm-dev libigdgmm-dev libpciaccess-dev bzip2; \
apt-get autoremove -y; \
# === Intel media driver 25.2.4 (v0.9.160) ===
# Ubuntu 24.04's iHD driver (24.1) is too old for Arc / Flex cards (DG2,
# ATS-M): vaInitialize fails with "iHD_drv_video.so init failed" (GitHub
# issue, Flex 170). Intel's own build (its Ubuntu 22.04 repo, same files
# as the standard image) is built for libva 2.22 (the one above) and
# supports Broadwell through Battlemage. Pinned by version and hash.
INTEL_POOL=https://repositories.intel.com/gpu/ubuntu/pool/unified/i; \
curl -fsSL --retry 5 --retry-delay 3 -o /tmp/libigdgmm12.deb "${INTEL_POOL}/intel-gmmlib/libigdgmm12_22.7.2-1135~22.04_amd64.deb"; \
curl -fsSL --retry 5 --retry-delay 3 -o /tmp/intel-media.deb "${INTEL_POOL}/intel-media-driver-non-free/intel-media-va-driver-non-free_25.2.4-1146~22.04_amd64.deb"; \
printf '%s %s\n' \
c8b3dfbc044735e9502fd4b8e9560f9118afd49755f8caa4d173b0a84044638d /tmp/libigdgmm12.deb \
fa22334f9431985f2b09748c365e61f54ff7b9b2a01a9c6d1cf24c1075a315fc /tmp/intel-media.deb \
| sha256sum -c -; \
apt-get install -y --no-install-recommends /tmp/libigdgmm12.deb /tmp/intel-media.deb; \
rm -f /tmp/libigdgmm12.deb /tmp/intel-media.deb; \
rm -rf /var/lib/apt/lists/*
# Install ffmpeg with NVENC + libvmaf.
# BtbN GPL static builds include: NVENC, libvmaf, x265, and all common codecs.
#
# FFMPEG_BUILD picks which BtbN release asset to install. The NVENC SDK baked
# in determines the minimum NVIDIA driver required on the host:
# n7.1 = NVENC SDK 12.2 → driver 525.60.13+ (DEFAULT — widest compat)
# n8.1 = NVENC SDK 13.0 → driver 570.00+
# master = NVENC SDK 13.0 → driver 570.00+ (bleeding edge)
#
# All are assets of the same rolling `latest` BtbN release, but the filename
# pattern differs: `master` builds have no version suffix, while tagged
# releases (nX.Y) append "-X.Y" to the filename.
# Override at build time:
# docker build --build-arg FFMPEG_BUILD=master -t shrinkerr:edge .
ARG FFMPEG_BUILD=n8.1
RUN set -e; \
case "${FFMPEG_BUILD}" in \
master) FF_URL="https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz" ;; \
n*) FF_VER="${FFMPEG_BUILD#n}"; \
FF_URL="https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-${FFMPEG_BUILD}-latest-linux64-gpl-${FF_VER}.tar.xz" ;; \
*) echo "Unknown FFMPEG_BUILD: ${FFMPEG_BUILD} (expected 'master' or 'nX.Y')" >&2; exit 2 ;; \
esac; \
echo "Installing ffmpeg build: ${FFMPEG_BUILD} from ${FF_URL}"; \
# v0.9.105: download to a file with retries, THEN extract (piping curl into
# tar can't retry a mid-stream cut). See Dockerfile for the full rationale.
curl -fsSL --retry 5 --retry-delay 3 --retry-all-errors "${FF_URL}" -o /tmp/ffmpeg.tar.xz; \
tar -xJf /tmp/ffmpeg.tar.xz --strip-components=2 -C /usr/local/bin/ --wildcards '*/bin/ffmpeg' '*/bin/ffprobe'; \
rm -f /tmp/ffmpeg.tar.xz; \
chmod +x /usr/local/bin/ffmpeg /usr/local/bin/ffprobe; \
echo "ffmpeg installed:"; ffmpeg -version 2>&1 | head -1; \
echo "VMAF filter:"; (ffmpeg -filters 2>&1 | grep libvmaf || echo "NOT FOUND")
# v0.9.8: subtile-ocr for VobSub (DVD, dvd_subtitle) subtitle OCR. pgsrip
# (already installed via pip) handles PGS/Blu-ray only and can't read VobSub,
# so DVD image subs get their own tool. Built from crates.io — but via a
# rustup stable toolchain, NOT Ubuntu 24.04's apt cargo (1.75): subtile-ocr's
# deps use Rust edition 2024, which needs Cargo ≥ 1.85 (v0.9.9). The whole
# toolchain (rustup + build headers) is installed and purged in this ONE layer,
# so it doesn't bloat the image — only /usr/local/bin/subtile-ocr and the
# tesseract/leptonica RUNTIME libs (kept by tesseract-ocr) remain. GUARDED
# with `|| echo` so a build failure NEVER breaks the image — the runtime code
# is fail-open and leaves VobSub tracks `und` when the binary is absent.
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates curl gcc libc6-dev \
clang libclang-dev libtesseract-dev libleptonica-dev pkg-config; \
( export RUSTUP_HOME=/opt/rustup CARGO_HOME=/opt/cargo \
&& curl -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable \
&& /opt/cargo/bin/cargo install subtile-ocr --root /usr/local \
&& /usr/local/bin/subtile-ocr --version ) \
|| echo "[BUILD] subtile-ocr install failed — VobSub OCR will be unavailable"; \
apt-get purge -y clang libclang-dev libtesseract-dev libleptonica-dev pkg-config gcc libc6-dev; \
apt-get autoremove -y; \
rm -rf /var/lib/apt/lists/* /opt/rustup /opt/cargo
# Record the ffmpeg lineage + its NVENC-SDK driver floor so the backend can
# produce an actionable error message if the runtime NVENC test fails. Read
# by backend/nodes.py during startup-time capability detection.
ENV SHRINKERR_FFMPEG_BUILD=${FFMPEG_BUILD}
ARG NVENC_MIN_DRIVER=525.60.13
ENV SHRINKERR_NVENC_MIN_DRIVER=${NVENC_MIN_DRIVER}
# Use python3.12 as default (Ubuntu 24.04's stock Python, v0.5.13+)
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 1
WORKDIR /app
# Install Python dependencies.
# Ubuntu 24.04's system Python carries the PEP 668 "externally-managed"
# marker that blocks pip on the system interpreter unless --break-system-
# packages is passed. This is a single-app container so installing into
# the system Python is the right call; the flag is the standard escape
# hatch for the Docker use case. v0.5.13+.
COPY requirements.txt .
RUN pip3 install --no-cache-dir --break-system-packages -r requirements.txt
# Copy backend and version file
COPY backend/ backend/
COPY VERSION .
# CHANGELOG is read at runtime by /api/stats/changelog so the Updates
# section in Settings can show release notes without a network call.
COPY CHANGELOG.md .
# Copy built frontend
COPY --from=frontend-build /app/frontend/dist frontend/dist
# Create data directory
RUN mkdir -p /app/data
EXPOSE 6680
# Bundled TMDB non-commercial API key — see Dockerfile for notes.
ARG TMDB_API_KEY=""
ENV SHRINKERR_TMDB_API_KEY=${TMDB_API_KEY}
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
CMD python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:6680/api/health')" || exit 1
# SHRINKERR_MODE=worker → run as a remote worker node (no server, no UI)
# Default (server) → run the FastAPI server with UI
CMD ["python3", "-m", "backend.main"]