# syntax=docker/dockerfile:1.6 # # OmniVoice (k2-fsa/OmniVoice) — zero-shot, massively-multilingual (600+ # languages) voice-cloning + voice-design TTS, diffusion-LM architecture, # Apache-2.0. Upstream ships a pip package + its own Gradio demo # (`omnivoice-demo`); there's no official image, so we build a thin CUDA # container around the pip package and run our OWN FastAPI wrapper (app.py): # a batch OpenAI-style /v1/audio/speech plus a streaming /tts driven by the # vendored buffer-ratchet scheduler (scheduler.py) for live chat consumers. ARG CUDA_BASE=nvidia/cuda:12.8.0-cudnn-runtime-ubuntu22.04 FROM ${CUDA_BASE} ENV DEBIAN_FRONTEND=noninteractive \ PIP_ROOT_USER_ACTION=ignore \ PYTHONUNBUFFERED=1 \ PATH="/opt/venv/bin:${PATH}" RUN apt-get update \ && apt-get install -y --no-install-recommends \ python3.10 python3.10-venv python3-pip \ git ffmpeg libsndfile1 \ ca-certificates wget \ && rm -rf /var/lib/apt/lists/* \ && python3.10 -m venv /opt/venv # CUDA 12.8 torch wheels (per OmniVoice's documented install line). RUN pip install --no-cache-dir \ torch==2.8.0 torchaudio==2.8.0 \ --index-url https://download.pytorch.org/whl/cu128 # OmniVoice from PyPI (+ huggingface_hub for the entrypoint weight pre-warm). # Optional reproducible pin via the OMNIVOICE_VERSION build arg (empty=latest). ARG OMNIVOICE_VERSION= RUN pip install --no-cache-dir "omnivoice${OMNIVOICE_VERSION:+==${OMNIVOICE_VERSION}}" huggingface_hub # Our asset-engine wrapper deps (FastAPI stack + soundfile for WAV encoding). RUN pip install --no-cache-dir fastapi 'uvicorn[standard]' soundfile python-multipart # Fail the build loudly if the runtime imports aren't satisfiable. RUN python -c "import omnivoice, fastapi, soundfile, uvicorn; print('omnivoice wrapper deps OK')" WORKDIR /app COPY app.py /app/app.py COPY scheduler.py /app/scheduler.py COPY sanitize.py /app/sanitize.py COPY entrypoint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh # Fail the build if the wrapper (incl. the vendored scheduler + sanitizer) won't # import. Model load is lazy (startup event), so this is a cheap CPU-only check. RUN python -c "import app; print('omnivoice app import OK')" EXPOSE 8001 # Our wrapper exposes /healthz (200 once model + >=1 voice are loaded). Generous # start period: first boot pre-warms OmniVoice + Whisper ASR + clones every voice. HEALTHCHECK --interval=30s --timeout=10s --start-period=1200s --retries=3 \ CMD wget -q -O /dev/null http://127.0.0.1:8001/healthz || exit 1 ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8001"]