Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Dockerfile.fish
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,14 @@
FROM nvidia/cuda:12.8.0-runtime-ubuntu24.04

ENV DEBIAN_FRONTEND=noninteractive
# build-essential + python3-dev are REQUIRED on Blackwell: torch.compile
# (Inductor) shells out to gcc at runtime to build CUDA kernels as Python
# extension modules, which needs both the C toolchain AND Python.h. Without
# either, the first synth call crashes the worker with either "Failed to find
# C compiler" or "CalledProcessError ... cuda_utils.c".
RUN apt-get update && apt-get install -y --no-install-recommends \
python3 python3-pip ffmpeg libsndfile1 curl ca-certificates \
python3 python3-pip python3-dev ffmpeg libsndfile1 curl ca-certificates \
build-essential \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /app
Expand Down
8 changes: 6 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ services:
- "${FISH_PORT:-8092}:8092"
volumes:
- ${FISH_REFERENCES_DIR:-/mnt/data/fish-references}:/app/references
# .dockerignore excludes .venv/, so bind-mount from the host checkout.
# Dockerfile comment claims COPY . includes them, but it doesn't.
- /home/ava/dev/fish-speech/.venv:/app/.venv:ro
- /home/ava/dev/fish-speech/checkpoints:/app/checkpoints:ro
Comment on lines +24 to +27

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Hardcoded host bind-mount paths will break startup outside one developer machine.

Line 26 and Line 27 hardcode /home/ava/.... On other hosts this typically mounts the wrong/nonexistent source and the container fails again with missing /app/.venv/bin/python or checkpoints. Please parameterize the checkout root.

🔧 Suggested fix
     volumes:
       - ${FISH_REFERENCES_DIR:-/mnt/data/fish-references}:/app/references
-      - /home/ava/dev/fish-speech/.venv:/app/.venv:ro
-      - /home/ava/dev/fish-speech/checkpoints:/app/checkpoints:ro
+      - ${FISH_SPEECH_DIR:-../fish-speech}/.venv:/app/.venv:ro
+      - ${FISH_SPEECH_DIR:-../fish-speech}/checkpoints:/app/checkpoints:ro
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# .dockerignore excludes .venv/, so bind-mount from the host checkout.
# Dockerfile comment claims COPY . includes them, but it doesn't.
- /home/ava/dev/fish-speech/.venv:/app/.venv:ro
- /home/ava/dev/fish-speech/checkpoints:/app/checkpoints:ro
# .dockerignore excludes .venv/, so bind-mount from the host checkout.
# Dockerfile comment claims COPY . includes them, but it doesn't.
- ${FISH_SPEECH_DIR:-../fish-speech}/.venv:/app/.venv:ro
- ${FISH_SPEECH_DIR:-../fish-speech}/checkpoints:/app/checkpoints:ro
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docker-compose.yml` around lines 24 - 27, The docker-compose binds are
hardcoded to /home/ava/... which breaks on other machines; update the two
bind-mount entries that match "/home/ava/dev/fish-speech/.venv:/app/.venv:ro"
and "/home/ava/dev/fish-speech/checkpoints:/app/checkpoints:ro" to use a
parameterized variable (e.g., ${PROJECT_ROOT} or ${PWD}) sourced from an .env or
environment so the host checkout root is configurable; ensure the .env key is
documented or defaulted and that docker-compose references that variable for
both the .venv and checkpoints mounts.

environment:
- NVIDIA_VISIBLE_DEVICES=${FISH_GPU:-1}
deploy:
Expand All @@ -34,8 +38,8 @@ services:
test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8092/v1/health')"]
interval: 30s
timeout: 10s
start_period: 180s
retries: 3
start_period: 600s # torch.compile warmup can take ~3-5 min from cold
retries: 5

protovoice:
build: .
Expand Down
4 changes: 4 additions & 0 deletions docs/reference/tts-backends.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ Runs as the `fish-speech` sidecar container. Build context is `../fish-speech` (

See [Clone a Voice](/guides/clone-a-voice).

### Exposing Fish as an OpenAI-compatible endpoint

Fish's native `POST /v1/tts` uses its own `ServeTTSRequest` shape, not OpenAI's `/v1/audio/speech`. To put Fish behind a LiteLLM gateway (or any OpenAI SDK client), run the external shim at [`protoLabsAI/lab` → `experiments/fish-openai-shim/`](https://github.com/protoLabsAI/lab). It wraps `POST /v1/audio/speech` and forwards to this sidecar, supporting `wav` (one-shot), `pcm` (streaming), and `mp3` (streaming via ffmpeg). The shim is separate from protoVoice itself because it's deployment-infra, not part of the voice pipeline.

### Env

| Variable | Default | Purpose |
Expand Down
8 changes: 8 additions & 0 deletions docs/tutorials/docker-compose.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ START_VLLM=0 LLM_URL=http://10.0.0.10:8000/v1 docker compose up -d

- `HF_HOME` → `/models` — HuggingFace cache. Default: `/mnt/models/huggingface`.
- `FISH_REFERENCES_DIR` → `/app/references` — persists saved voice references across restarts.
- **`../fish-speech/.venv` → `/app/.venv`** (read-only) — bind-mounted because Fish's `.dockerignore` excludes `.venv/`, so the image ships without it. Without this mount the container crashes at startup with `/app/.venv/bin/python: No such file or directory`.
- **`../fish-speech/checkpoints` → `/app/checkpoints`** (read-only) — same rationale; S2-Pro weights are too large to bake into the image. Keep them in the host checkout and mount.

## GPU allocation

Expand All @@ -49,6 +51,12 @@ On a single-GPU host, set `TTS_BACKEND=kokoro` to skip Fish entirely and keep ev

Fish Audio's first call triggers a ~2-minute `torch.compile` codegen. protoVoice's `prewarm()` on startup sends a single silent utterance to absorb this — you should never see that hit in a real turn.

The sidecar's healthcheck uses `start_period: 600s` so Docker doesn't mark the container unhealthy and restart-loop while `torch.compile` is still running. If you observe the container repeatedly bouncing on first boot, confirm that value hasn't been lowered.

### Fish image needs a C toolchain + Python headers

`Dockerfile.fish` installs `build-essential` and `python3-dev` on top of `nvidia/cuda:runtime`. Both are **required** — torch.compile's Inductor backend shells out to `gcc` at synth time to build CUDA kernels as Python extension modules. Missing either produces `Failed to find C compiler` or `CalledProcessError ... cuda_utils.c` on first synth, followed by an infinite restart loop. If you ever strip these from the Dockerfile for image size, Fish will stop working on any `torch.compile`-gated build.

Whisper takes ~2 s to load + warm.

vLLM takes 30-60 s to load + warm depending on model size.
Expand Down
Loading