# cuDNN 9 in the base image. faster-whisper (CTranslate2) and onnxruntime-gpu both need it, and the # plain runtime image has none: Whisper on the GPU then fails to load, or everything quietly runs on # the CPU while the GPU is billed. FROM nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04 # compute,utility is the default; video adds the GPU's H.264 encoder (NVENC) for the proxy and the # re-encode of masters OpenCV cannot read (app.py nvenc_available, which falls back to libx264). ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility,video # Model caches inside the image, written at build time by prefetch_models.py and read at run time. # HOME too, because HSEmotion, EasyOCR, DeepFace and funasr cache under ~ whatever they are told. ENV HOME=/opt/home \ HF_HOME=/opt/home/.cache/huggingface \ DEEPFACE_HOME=/opt/home \ EASYOCR_MODULE_PATH=/opt/home/.EasyOCR # Install Python and system dependencies RUN apt-get update && apt-get install -y \ python3.10 \ python3-pip \ python3.10-venv \ ffmpeg \ curl \ libsndfile1 \ libgl1 \ libglib2.0-0 \ libegl1 \ libgles2 \ && rm -rf /var/lib/apt/lists/* \ && ln -s /usr/bin/python3.10 /usr/bin/python # Set working directory WORKDIR /app # Copy requirements first for caching COPY requirements.txt . COPY requirements-stage-read.txt . # Install Python dependencies RUN pip install --no-cache-dir --upgrade pip && \ pip install --no-cache-dir -r requirements.txt # Stage Read extras (docs/stage-read-spec.md). Non-fatal: if a package fails to install the # service still starts and only the /stage-read routes are unavailable. RUN pip install --no-cache-dir -r requirements-stage-read.txt || echo "stage-read extras failed to install" # HSEmotion and the packages above pull the CPU build of onnxruntime. Swap it for the GPU build, after them all (same module, adds the # CUDA provider; the same version the CPU build resolves to, built for CUDA 12 and cuDNN 9). RUN pip uninstall -y onnxruntime && pip install --no-cache-dir onnxruntime-gpu==1.23.2 # Copy application code. cei_measures.py is the Creative Effectiveness Index pass; leaving it out # of the image is silent, because app.py imports it inside a try and the report then says # "no measurements" rather than failing. COPY app.py cei_measures.py ffmpeg_util.py memorability.py memorability-model.json service_auth.py prefetch_models.py . COPY stage_read ./stage_read # Every model's weights, into the image (prefetch_models.py). Never fails the build: a model that # does not download here downloads on first use instead. Readable and writable by the user the Space # runs as, which is not the user that built it. RUN mkdir -p $HOME && python prefetch_models.py && chmod -R a+rwX $HOME # Stage Read model files (Apache-2.0), fetched at build time rather than committed (the Space rejects binaries outside LFS) RUN mkdir -p stage_read/models && \ curl -fsSL -o stage_read/models/face_landmarker.task \ https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task && \ curl -fsSL -o stage_read/models/face_detection_yunet_2023mar.onnx \ https://github.com/opencv/opencv_zoo/raw/main/models/face_detection_yunet/face_detection_yunet_2023mar.onnx || \ echo "stage-read model download failed" # Expose port EXPOSE 7860 # Run the FastAPI app CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]