ba0ec64ac3
Captures the production Zonos TTS path that the repo was blind to: stock ZONOS2 :1920 engine (stacks/zonos-engine) fronted by zonos-gateway:0.2.0 :8890, reached via the LiteLLM ext-tts alias. Documents the emotion-preset system (neutral/warm/ excited/sad/intense/whisper, the simple preset: caller path), the API, and the measured real-time cost (calibrated steering free at RTF~0.52, cfg1.5 ~0.625 — still realtime). Flags the gateway source (~/zonos-gateway on irv-ml1) as not yet in gitea. Marks stacks/zonos (v0.1 Gradio) dead/superseded. Records the emotion- lever finding (text-priming flat -> native steering works) in persistent memory.
93 lines
4.2 KiB
Markdown
93 lines
4.2 KiB
Markdown
# Zonos
|
||
|
||
> **⚠️ SUPERSEDED / NOT DEPLOYED (2026-07-17).** This stack is Zonos **v0.1**
|
||
> (Gradio UI + a v0.1 SDK adapter) and is **no longer running** anywhere on the
|
||
> fleet. The live Zonos TTS path is **ZONOS2** — see `stacks/zonos-engine`
|
||
> (the `:1920` engine) + `stacks/zonos-gateway` (the `:8890` OpenAI-compatible
|
||
> gateway with the emotion-preset system, reached via the LiteLLM `ext-tts`
|
||
> alias). Kept for history; do not deploy.
|
||
|
||
Zyphra's expressive multilingual open-weight TTS
|
||
([Zyphra/Zonos](https://github.com/Zyphra/Zonos)) — 44 kHz output,
|
||
zero-shot voice cloning, and explicit emotion/conditioning controls —
|
||
served via the **official repo's Gradio interface**.
|
||
|
||
Models ([`Zonos.from_pretrained()`](https://github.com/Zyphra/Zonos)):
|
||
|
||
| Variant | HF repo | Notes |
|
||
|---|---|---|
|
||
| transformer | [Zyphra/Zonos-v0.1-transformer](https://huggingface.co/Zyphra/Zonos-v0.1-transformer) | ~3.6 GB, no special kernels (default) |
|
||
| hybrid | [Zyphra/Zonos-v0.1-hybrid](https://huggingface.co/Zyphra/Zonos-v0.1-hybrid) | Mamba-SSM; needs Ampere+ GPU + extra build deps |
|
||
|
||
**Server:** irv-ml1 (Irvine, WireGuard-only)
|
||
**Ports:** 8199 Gradio eval UI (container 7860) · 8203 REST adapter (container 8000)
|
||
**GPUs:** pins to device 0 (RTX 3090) by default; ~6 GB VRAM
|
||
**Image:** `local/zonos:v1` — built locally from a pinned git SHA of the
|
||
upstream repo via docker buildx's git URL context
|
||
**Upstream:** [Zyphra/Zonos](https://github.com/Zyphra/Zonos) (Apache-2.0),
|
||
trained on 200k+ hours; multilingual EN/JA/ZH/FR/DE
|
||
|
||
## Why this stack exists
|
||
|
||
A different *control surface* from the rest of the bench: Zonos exposes
|
||
**emotion/conditioning sliders** plus pitch/rate conditioning and 44 kHz
|
||
output, where Chatterbox/Dia use inline tags and Fish uses
|
||
natural-language paralinguistic tags. Worth A/B-ing by ear against
|
||
Chatterbox-Turbo (the research that prompted this stack explicitly said
|
||
"benchmark Zonos against Chatterbox before choosing").
|
||
|
||
## Two surfaces: Gradio eval (8199) + REST adapter (8203)
|
||
|
||
The official repo ships a **Gradio WebUI + Python SDK only** — no REST
|
||
endpoint. So this stack runs two services:
|
||
|
||
- **`zonos`** (8199) — upstream Gradio UI, for *auditioning quality by ear*.
|
||
- **`zonos-api`** (8203) — a thin OpenAI-ish adapter we built
|
||
(`adapter/server.py`) exposing `POST /v1/audio/speech` so **asset-engine**
|
||
can route to Zonos like every other TTS in the catalog. Returns a JSON
|
||
envelope `{audio: <base64>, audio_format, seed}` — the `seed` rides back
|
||
so regenerate/fork can pin it (Zonos is the fleet's first seedable TTS).
|
||
|
||
The adapter is built `FROM local/zonos:<tag>` (reuses torch/CUDA/SDK) and
|
||
loads its own copy of the model (~6 GB on top of the Gradio service). Once
|
||
Zonos earns a permanent slot, drop the Gradio service and keep the adapter.
|
||
|
||
The community FastAPI fork ([PR #73](https://github.com/Zyphra/Zonos/pull/73))
|
||
was the alternative; we chose the self-owned adapter over pinning to an
|
||
unmerged fork.
|
||
|
||
### Adapter request (example)
|
||
|
||
```bash
|
||
curl -sS http://10.100.79.3:8203/v1/audio/speech \
|
||
-H 'content-type: application/json' \
|
||
-d '{"input":"Hello from Zonos.","language":"en-us","seed":420}' \
|
||
| python3 -c 'import sys,json,base64; d=json.load(sys.stdin); open("out.wav","wb").write(base64.b64decode(d["audio"])); print("seed",d["seed"])'
|
||
```
|
||
|
||
Cloning: drop a 10–30s WAV in `/worktank/zonos/voices/` and pass its
|
||
filename as `"voice"`. `GET /v1/audio/voices` lists what's available.
|
||
|
||
## Deploy
|
||
|
||
```bash
|
||
# from this workstation (irv-ml1 is WG-only — routes via ana-wg):
|
||
scripts/deploy-stack.sh irv-ml1 zonos
|
||
# then on irv-ml1, first run builds the image from the pinned SHA:
|
||
# docker compose up -d --build
|
||
```
|
||
|
||
Open `http://10.100.79.3:8199/` for the Gradio UI. First boot pulls the
|
||
model (~3.6 GB) into `ZONOS_CACHE_DIR`; the 600 s `start_period` covers
|
||
it.
|
||
|
||
## Notes
|
||
|
||
- **Pin `ZONOS_SHA`** to a full 40-char commit before relying on this —
|
||
`.env.example` ships `main`, which is not reproducible.
|
||
- The upstream image bundles **espeak-ng** (required for Zonos's
|
||
phonemization) via its Dockerfile.
|
||
- `GRADIO_SERVER_NAME=0.0.0.0` is set so the in-container Gradio binds
|
||
all interfaces and the host port-map reaches it. If a future upstream
|
||
hardcodes `server_name`, the API fork above is the cleaner path.
|