Skip to main content
The All-in-One image packages the whole speech stack — edge API, model API layer, inference router and worker, vocoder, text normalizer, and Redis — into one container, with every model weight baked in. Once the image is on the host it runs with no Kubernetes and no internet access, which makes it the turnkey option for single-node appliances and strict air gaps.
The All-in-One image runs a single inference worker across two GPUs. It does not autoscale or shard across more GPUs or nodes, and it does not ship the forced aligner, so it serves no word or segment timings. For elastic, multi-tenant, or higher aggregate throughput deployments, use the Kubernetes chart, which scales replicas across all GPUs and nodes. This image is also offline only; there is no hosted-billing variant of it.

Prerequisites

Load the image

On a host with registry access:
On a disconnected host, transfer the image instead — see Air-gapped deployments.

Run

Generate a JWT secret once, store it, and reuse the same value on every run. A new value invalidates tokens and sessions issued under the old one.
Everything in the container runs as a non-root user (UID 1000). A fresh named volume inherits the right ownership; a reused volume or a host bind mount must be writable by UID 1000.

First start and readiness

On the first cold start the worker compiles its inference graphs and the vocoder builds its engine. Expect roughly ten minutes once the image is on the host, and considerably longer on a fully cold host that also has to transfer the image. Subsequent starts on the same volume take minutes, because both artifacts are cached on the volume. GET /health verifies the speech backend end to end, so it stays unhealthy through the warmup rather than reporting immediate liveness. Full readiness is a generation that returns audio:
Follow the startup with docker logs -f fish-tts.

Make requests

Supported format values are mp3, wav, pcm, and opus. Optional fields include reference_id, mp3_bitrate, sample_rate, latency, and chunk_length. For the lowest time-to-first-audio, stream over WebSocket at ws://<host>:8088/v1/tts/live with the same Authorization and model headers, then send msgpack events: start, one or more text, then stop, and read audio events until finish. The payloads match the hosted WebSocket API.

Latency modes

Set it in the request body as "latency":"balanced", or in the WebSocket start event.

Reference voices

Reference-id requests resolve only from a local archive. Place one zip per voice at /mnt/shared/reference-archives/<reference_id>.zip, containing audio files at the zip root each paired with a same-basename .txt transcript. A named Docker volume has no stable host path, so copy archives in:
Alternatively, bind-mount a host directory at /mnt/shared/reference-archives and drop archives into it directly. Then request with "reference_id":"my-voice".

Authentication and usage

This build records usage to a local, signed, append-only ledger instead of calling a billing service:
  • Any non-empty Authorization: Bearer token is accepted. A missing or empty token returns 401.
  • The token is recorded verbatim as the billing identity, so use a stable, distinct token per tenant. Two tenants sharing a token are indistinguishable in the ledger.
  • The ledger is written under /mnt/shared/offline-billing-ledger/ as signed JSON Lines, one directory per UTC day.
See Offline usage accounting for the record format, verification, and reconciliation.

Persistence

Model weights live in the image, not on the volume. Keep /mnt/shared on persistent storage: without it, every restart pays the full first-start compile again and the ledger is lost. The vocoder engine is specific to the GPU model, so moving to different cards rebuilds it once. If your platform pins persistent storage somewhere other than /mnt/shared, you can relocate the three compile caches with COMPILE_CACHE_DIR, TORCHINDUCTOR_CACHE_DIR, and VQ_CACHE_DIR. Point each at a separate subdirectory that is writable by UID 1000, and keep the /mnt/shared mount either way, because reference voices and the ledger always live there.

Capacity

The single worker admits a bounded number of in-flight requests, set by LIMIT_MODEL_CONCURRENCY (default 32); beyond that, requests queue. The ceiling is bounded by the inference worker’s key-value cache VRAM, so cards with more memory than the 32 GB baseline can run a higher cap. Raise it at launch without rebuilding:
Validate latency and error rate at the new value before committing to it.

Operations

Troubleshooting