# ============================================================================ # 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//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"]