# services.yaml — canonical catalog of inference services on irv-ml1 # # THIS IS A FIRST-CLASS CONTRACT. External consumers depend on the # shape and contents of this file. See CATALOG-CONTRACT.md alongside # for: schema reference, change-management policy, sync workflow for # downstream consumers, and known consumers list. # # Drives form generators that auto-render UIs against the inference # services. Each entry produces one form (from `fields:`) and one # response renderer (dispatched on `response.type`). The field-type # vocabulary and response-type vocabulary are closed sets — see the # JSON Schema at services.schema.json or the contract doc. # # `catalog_version`: bump when the SCHEMA changes (a field type added, # a required field removed, etc). Per-service `version:` bumps when a # specific service's parameter shape changes. Both let downstream # consumers detect drift. catalog_version: 1 services: - id: kokoro name: Kokoro 82M TTS description: > Lowest-latency English TTS (82M params, fp16). ~300ms TTFA, 35–100x realtime, 60+ built-in voices in 8 languages. Voice mixing via inline weights. OpenAI-compatible /v1/audio/speech. category: tts version: 3 host: irv-ml1 lifecycle: stack: kokoro vram_gb: 2 gpu_device_id: null endpoint: http://10.100.79.3:8193/v1/audio/speech method: POST content_type: application/json model: id: hexgrad/Kokoro-82M revision: null image: ghcr.io/remsky/kokoro-fastapi-gpu:v0.2.4-master fields: - name: input type: textarea label: Text required: true max_length: 5000 - name: voice type: select label: Voice source_url: http://10.100.79.3:8193/v1/audio/voices source_jsonpath: $.voices[*] default: af_heart description: > 60+ built-in voices. Default `af_heart` is the only A-rated voice per upstream VOICES.md (also the kokoro-fastapi container's own default). Custom blends: af_bella(2)+af_aoede(1) syntax for weighted mixing. Persistent custom voices via playbooks/blend-kokoro-voice.yaml. - name: response_format type: select options: [wav, mp3, opus, flac, pcm] default: wav - name: speed type: slider label: Speed required: false min: 0.25 max: 4.0 step: 0.05 default: 1.0 description: Playback speed multiplier. 1.0 is natural. - name: volume_multiplier type: slider label: Volume required: false min: 0.5 max: 2.0 step: 0.05 default: 1.0 description: > Output gain. Useful for level-matching against music beds. Upstream is unbounded; UI bounds (0.5–2.0) are a sensible default — override the slider client-side if you need extremes. - name: lang_code type: text label: Language code required: false description: > Optional language hint (e.g. "a" for American English). When unset, kokoro infers from the first letter of the voice name. Set when text contains code-switching kokoro guesses wrong on. - name: stream type: bool default: false description: Phrase-by-phrase streaming via chunked HTTP. response: type: audio mime_from_field: response_format reproducibility: seedable: false deterministic: true notes: > No seed parameter. Model fully deterministic (no sampling); identical params always produce identical bytes. Image tag is mutable; pin to digest for v3 reproducibility audit. estimated_latency: cold_start_s: 2 warm_per_unit: "~300ms TTFA, 35–100x realtime" license: Apache-2.0 notes: | Voice mixing: voice="name1(w1)+name2(w2)+..." normalizes weights. Custom voices persist at /worktank/kokoro/user_voices (bind-mounted). v2 (2026-05-11): added speed, volume_multiplier, lang_code per kokoro's OpenAPI surface. - id: kokoro-captioned name: Kokoro Captioned Speech description: > Kokoro TTS with word-level timestamps returned alongside the audio. For subtitle generation and video sync. Same model as `kokoro`; separate catalog entry because the wire shape is a JSON envelope carrying base64-encoded audio plus a structured timestamps array. category: tts version: 2 status: ready host: irv-ml1 endpoint: http://10.100.79.3:8193/dev/captioned_speech method: POST content_type: application/json model: id: hexgrad/Kokoro-82M revision: null image: ghcr.io/remsky/kokoro-fastapi-gpu:v0.2.4-master fields: - name: input type: textarea label: Text required: true max_length: 5000 - name: voice type: select label: Voice source_url: http://10.100.79.3:8193/v1/audio/voices source_jsonpath: $.voices[*] default: af_heart - name: response_format type: select options: [wav, mp3, opus, flac, pcm] default: wav - name: speed type: slider label: Speed required: false min: 0.25 max: 4.0 step: 0.05 default: 1.0 - name: lang_code type: text label: Language code required: false response: # Stays in the closed type vocabulary: from a renderer-dispatch # standpoint this IS audio. The audio_field/audio_format_field/ # timestamps_field decomposition tells consumers how to extract # those parts from the JSON envelope wire shape — added to the # catalog schema in 2026-05 specifically to support response # shapes like this one without extending the type vocab. type: audio audio_field: audio audio_format_field: audio_format timestamps_field: timestamps reproducibility: seedable: false deterministic: true notes: > Same determinism story as kokoro proper. Verified wire shape (2026-05-11 against live API): { "audio": "", "audio_format": "audio/wav" (or matching response_format), "timestamps": [{"word": str, "start_time": float, "end_time": float}, ...] } Consumer base64-decodes `audio` to play; `timestamps` drives subtitle/karaoke UI. The response decomposition fields above encode this so the renderer doesn't need per-service-id branches. estimated_latency: cold_start_s: 2 warm_per_unit: "~same as kokoro proper, plus minor overhead for timestamp emission" license: Apache-2.0 notes: | `return_timestamps` and `stream` upstream params deliberately omitted from the catalog: timestamps must be on for this endpoint to be meaningful, and streaming + JSON-with-base64 don't compose. `download_format` / `return_download_link` skipped — same as kokoro proper. status: experimental until the consumer's audio-with-timestamps renderer ships. Once present, flip to status: ready. - id: chatterbox name: Chatterbox TTS description: > Resemble AI's low-latency English TTS (Chatterbox-Turbo, 350M, ~75ms TTFB, 6× realtime). 28 built-in predefined voices + zero-shot cloning from a 5–30s reference. Inline paralinguistic tags, plus Resemble's signature exaggeration / cfg_weight emotion + pacing control. category: tts version: 2 status: ready host: irv-ml1 lifecycle: stack: chatterbox vram_gb: 4 gpu_device_id: 0 endpoint: http://10.100.79.3:8196/tts method: POST content_type: application/json model: id: ResembleAI/chatterbox-turbo revision: null image: devnen/Chatterbox-TTS-Server:latest section_groups: - id: basic label: Text & voice - id: sampling label: Expression & sampling hint: Resemble's neutral defaults (exaggeration 0.5 / cfg_weight 0.5). Raise exaggeration or lower cfg_weight for drama. - id: advanced label: Advanced fields: - name: text type: textarea label: Text (with optional [tags]) section: basic required: true max_length: 5000 description: > Inline paralinguistic tags honored by Turbo: [laugh] [chuckle] [sigh] [gasp] [cough] [clear throat] [sniff] [groan] [shush]. Best results when a physical tag is paired with surrounding emotional context. - name: voice_mode type: select label: Voice mode section: basic options: [predefined, clone] default: predefined description: > `predefined` -> a built-in voice (predefined_voice_id below). `clone` -> a reference clip (reference_audio_filename). predefined is the out-of-box default; the empty/"undefined" case is avoided by defaulting the voice below. - name: predefined_voice_id type: select label: Voice (built-in) section: basic optional: true default: "Emily.wav" source_url: http://10.100.79.3:8196/get_predefined_voices source_jsonpath: $[*].filename description: > Required when voice_mode=predefined. 28 built-in voices staged in the devnen image (Abigail, Adrian, Alexander, Alice, Austin, Axel, Connor, Cora, Elena, Eli, Emily, Everett, Gabriel, Gianna, Henry, Ian, Jade, Jeremiah, Jordan, Julian, Layla, Leonardo, Michael, Miles, Olivia, Ryan, Taylor, Thomas — each .wav). Default Emily.wav is the server's own default_voice_id. Verified live via /get_predefined_voices. - name: reference_audio_filename type: select label: Voice (clone reference) section: basic optional: true source_url: http://10.100.79.3:8196/get_reference_files source_jsonpath: $[*] description: > Required when voice_mode=clone. 5–30s clean WAV (16 kHz+ mono) under /worktank/chatterbox/reference_audio/; upload via the server's /upload_reference. Match the clip's language to `language` to avoid accent transfer (or set cfg_weight=0). - name: exaggeration type: slider section: sampling min: 0.25 max: 2.0 step: 0.05 default: 0.5 description: > Emotional intensity. Resemble's docs: 0.5 "works well for most prompts across all languages"; ~0.7+ for dramatic delivery (which also speeds speech up). NOTE: the devnen server *ships* 1.3 (tuned for its theatrical demo presets) — 0.5 is the general-use value and the catalog default; the shipped 1.3 is the likely cause of over-acted/unstable output. - name: cfg_weight type: slider section: sampling min: 0.0 max: 1.0 step: 0.05 default: 0.5 description: > Pacing / prompt adherence (Resemble default 0.5). Lower to ~0.3 to slow delivery, for fast/intense reference speakers, or alongside a raised exaggeration for drama; 0 effectively disables guidance (useful to reduce reference-accent transfer). - name: temperature type: slider section: sampling min: 0.05 max: 2.0 step: 0.05 default: 0.8 description: Sampling temperature; lower = steadier. Server + Resemble default 0.8. - name: speed_factor type: slider section: sampling min: 0.5 max: 2.0 step: 0.05 default: 1.0 description: Post-hoc playback speed. Server default 1.0. - name: seed type: number section: sampling required: false default: 0 description: 0 = random; a fixed integer repeats the same take. - name: output_format type: select section: basic options: [wav, opus, mp3] default: wav description: 24 kHz. Live-verified enum (wav/opus/mp3). - name: language type: text section: advanced required: false default: en description: > Language override. Base Turbo is English; the multilingual variant (23 languages, via the stack .env) honors other codes. Leave `en`. - name: split_text type: bool section: advanced default: true description: Auto-split long text into chunks. - name: chunk_size type: slider section: advanced min: 100 max: 1000 step: 10 default: 120 description: Target chunk length in chars when splitting (server default 120). response: type: audio mime_from_field: output_format reproducibility: seedable: true deterministic: false seed_field: seed notes: > /tts exposes `seed` (0=random); a fixed seed + identical params repeats a take. Temperature-sampled → not guaranteed byte-exact, and Resemble's PerTh watermark is applied unconditionally. (Prior catalog claimed no seed support — corrected against the live OpenAPI 2026-06-01.) estimated_latency: cold_start_s: 3 warm_per_unit: "~75ms TTFB, 6× realtime" license: MIT notes: | Routes to the devnen wrapper's richer /tts (full control surface: exaggeration / cfg_weight / temperature / speed_factor / seed / voice_mode) instead of the thin OpenAI /v1/audio/speech, which exposes NONE of the emotion knobs — that omission was why prior output was poor. Same wrapper author as the `dia` stack; identical predefined/clone voice model. Defaults sourced from Resemble's README (exaggeration + cfg_weight = 0.5) and the server's generation_defaults (temperature 0.8, speed 1.0, seed 0), read live 2026-06-01; the server's shipped exaggeration 1.3 is demo-tuned and deliberately NOT adopted. Python 3.10 only (wrapper hardcoding); multilingual (23-language) variant available via the stack .env. - id: index-tts name: IndexTTS-2 description: > Bilibili's emotion-controllable zero-shot TTS. Disentangled emotion control (timbre from one reference, emotion from another). 22050 Hz fixed output. category: tts version: 1 status: down host: irv-ml1 lifecycle: stack: index-tts vram_gb: 6 gpu_device_id: null endpoint: http://10.100.79.3:8192/v1/audio/speech method: POST content_type: application/json model: id: IndexTeam/IndexTTS-2 revision: null image: local/index-tts:v2 fields: - name: input type: textarea label: Text required: true max_length: 5000 - name: voice type: select label: Speaker Voice description: .wav in /worktank/index-tts/voices/. 5–30s clean clips. - name: response_format type: select options: [wav] default: wav description: 22050 Hz PCM_16 mono only; no negotiation. - name: stream type: bool default: false description: > Segment-level streaming (~120 tokens). Streaming WAV uses placeholder data-length (0xFFFFFFFF); browsers fine, strict parsers may complain. - name: emotion_voice type: select label: Emotion Reference Voice optional: true description: .wav in /worktank/index-tts/emotions/. - name: emotion_vector type: json label: Emotion Vector optional: true description: > 8 floats [happy, angry, sad, afraid, disgusted, melancholic, surprised, calm], each 0.0–1.0. - name: emotion_text type: textarea label: Emotion Description (free text) optional: true - name: emotion_alpha type: slider min: 0.0 max: 1.0 default: 1.0 label: Emotion Strength response: type: audio mime: audio/wav reproducibility: seedable: false deterministic: true notes: > No seed. 22050 Hz hardcoded — resample in caller if 24/48 kHz needed. Precedence if multiple emotion sources: emotion_voice > vector > text. estimated_latency: cold_start_s: 5 warm_per_unit: "segment-latency streaming" license: "Custom Bilibili (free at small scale; commercial tier 100M MAU)" notes: | Three-way mutual-exclusion among emotion_voice / emotion_vector / emotion_text; precedence as above. UI should expose this as a single picker. - id: qwen3-tts name: Qwen3-TTS 1.7B description: > Alibaba's open English-first TTS (Apache 2.0). 10 languages, 97ms TTFB, instruction-driven emotion, voice cloning. category: tts version: 2 status: down host: irv-ml1 lifecycle: stack: qwen3-tts vram_gb: 16 gpu_device_id: null endpoint: http://10.100.79.3:8191/v1/audio/speech method: POST content_type: application/json model: id: Qwen/Qwen3-TTS-12Hz-1.7B revision: null image: local/qwen3-tts:v2 fields: - name: model type: select options: [Qwen/Qwen3-TTS-12Hz-1.7B, Qwen/Qwen3-TTS-12Hz-0.6B-Base] default: Qwen/Qwen3-TTS-12Hz-1.7B - name: input type: textarea label: Text required: true max_length: 5000 - name: voice type: select label: Voice source_url: http://10.100.79.3:8191/v1/voices source_jsonpath: $.voices[*].id default: vivian options: - vivian - serena - uncle_fu - ryan - aiden - ono_anna - sohee - eric - dylan - alloy - echo - fable - nova - onyx - shimmer description: > Wrapper ships 9 Qwen presets (vivian/serena/uncle_fu/ryan/aiden/ ono_anna/sohee/eric/dylan) + 6 OpenAI-compat aliases (alloy/echo/ fable/nova/onyx/shimmer) — verified live 2026-05-12 against /v1/voices. Default `vivian` matches the wrapper's OpenAPI default (case-normalized; the Qwen3-TTS blog cites "Vivian" with caps). For cloning: clone: where is a profile dir under /worktank/qwen3-tts/voices/profiles/. Create via /voice-studio web UI or manually (meta.json + reference.wav). The 17-preset list cited in the Qwen3-TTS upstream blog (Cherry/Ethan/Chelsie/...) differs from what this wrapper exposes — the wrapper is the source of truth. - name: instructions type: textarea label: Emotion/Style Instructions optional: true description: > Natural-language directive (e.g. "speak with cold contempt"). English instructions verified working ~2026-04. - name: response_format type: select options: [wav, mp3, pcm] default: wav response: type: audio mime_from_field: response_format reproducibility: seedable: false deterministic: true estimated_latency: cold_start_s: 5 warm_per_unit: "~97ms TTFB" license: Apache-2.0 notes: | Voice cloning shape differs from CosyVoice: profile-based, not voice-id-based. - id: cosyvoice name: CosyVoice 3 (Multilingual) description: > FunAudioLLM's multilingual expressive TTS. 18+ Chinese dialects + 8 other langs. English prosody not ElevenLabs-grade — use Qwen3-TTS for English. category: tts version: 1 status: down host: irv-ml1 lifecycle: stack: cosyvoice vram_gb: 4 gpu_device_id: null endpoint: http://10.100.79.3:8190/v1/audio/speech method: POST content_type: application/json model: id: FunAudioLLM/Fun-CosyVoice3-0.5B-2512 revision: null image: neosun/cosyvoice:v1.3.2 fields: - name: model type: select options: [cosyvoice-v3, cosyvoice-v2] default: cosyvoice-v3 - name: input type: textarea label: Text (with optional XML emotion tags) required: true max_length: 5000 description: > For English: use XML tags , , , , , etc. NOT the instruct field — English instruct values get vocalized literally (upstream bug). - name: voice type: select label: Voice (cloned only — no presets) description: > Create via POST /v1/voices/create (multipart with reference audio ≤30s). Reference must be 16kHz mono ≤30s; longer = AssertionError. - name: response_format type: select options: [wav] default: wav - name: speed type: slider min: 0.5 max: 2.0 default: 1.0 response: type: audio mime: audio/wav reproducibility: seedable: false deterministic: true notes: > Reference audio MUST be ≤30s (16kHz mono). instruct field broken for English. estimated_latency: cold_start_s: 5 warm_per_unit: "~150ms TTFB streaming" license: Apache-2.0 notes: | GOTCHA: instruct field is Chinese-context only — UI should hide it for English or surface a strong warning. - id: fish-s2 name: Fish Audio S2-Pro description: > Fishaudio's richest-paralinguistic English TTS (15,000+ inline tags). Trained 10M+ hours, dual-AR. Released March 2026. Heavy: ~240s compile warmup on cold start, ~realtime throughput once warm. category: tts version: 6 host: irv-ml1 lifecycle: stack: fish-s2 vram_gb: 24 gpu_device_id: 1 endpoint: http://10.100.79.3:8195/v1/tts method: POST content_type: application/json model: id: fishaudio/s2-pro revision: null image: local/fish-s2:v1 section_groups: - id: basic label: Text & output - id: sampling label: Sampling & latency hint: fish-speech ServeTTSRequest defaults. Lower temperature/top_p for steadier reads; latency=balanced for lower latency. - id: advanced label: Advanced & voice cloning fields: - name: text type: textarea label: Text (with optional [tags]) section: basic required: true max_length: 5000 description: > Inline tags: [laugh] [whispers] [super happy] [sigh] [excited] [heavy breathing] [angry] [sleepy] [crying] [surprise] ... (15,000+). Upstream best-practice: physical tags like [whispers] feel flat without emotional context — pair with an emotion tag. Example: `[excited] Welcome back! [whisper] I have a secret. [laugh] Just kidding.` - name: format type: select section: basic options: [wav, mp3, opus] default: wav description: > Output container (upstream also accepts raw `pcm`, omitted here). wav + mp3 verified live 2026-06-01. - name: temperature type: slider section: sampling min: 0.1 max: 1.0 step: 0.05 default: 0.8 description: Sampling temperature; lower = steadier. fish-speech default 0.8. - name: top_p type: slider section: sampling min: 0.1 max: 1.0 step: 0.05 default: 0.8 description: Nucleus sampling cutoff. fish-speech default 0.8. - name: repetition_penalty type: slider section: sampling min: 0.9 max: 2.0 step: 0.05 default: 1.1 description: > Penalizes repeats; raise if you hear stutters/loops. fish-speech default 1.1. - name: latency type: select section: sampling options: [normal, balanced] default: normal description: > `balanced` trades a little quality for lower latency — useful given S2-Pro's ~realtime throughput. fish-speech default `normal`. - name: seed type: number section: sampling required: false description: Omit for a random seed; a fixed integer repeats a take. - name: reference_id type: select label: Voice section: basic optional: true default: "Emily" options: - Abigail - Adrian - Alexander - Alice - Austin - Axel - Beatrice - Eleanor - Imogen - Connor - Cora - Elena - Eli - Emily - Everett - Gabriel - Gianna - glados - Henry - Ian - Jade - Jeremiah - Jordan - Julian - Layla - Leonardo - Michael - Miles - Olivia - Ryan - Taylor - Thomas description: > Voice = a staged clone reference picked by name (THE working voice path on this build; verified live 2026-06-01). 32 voices staged in /worktank/fish-s2/references/: 28 from the dia library + glados + 3 British-female VCTK voices (Beatrice/Eleanor/Imogen). Default Emily. Subtle British (Southern-England) female accents: Imogen (VCTK p225), Eleanor (p228), Beatrice (p229) — consenting VCTK volunteers (CC BY 4.0), NOT modeled on or representing any public figure. Other female: Abigail, Alice, Cora, Elena, Emily, Gianna, Jade, Layla, Olivia, glados. Resolves to .wav + optional .txt transcript; blank = model default/random speaker. To add: drop a clean 5–15s WAV into the references dir + add the name here. (No /voices API → static list; a list-endpoint is the durable fix — see notes.) - name: references type: json label: Custom clone (inline base64) section: advanced optional: true description: > Power-use: zero-shot clone from a reference NOT in the staged library — array of {audio: , text: "transcript"}. IMPORTANT: `audio` must be base64 bytes, NOT a filesystem path (a path returns HTTP 500 on this build). For staged voices use `reference_id`. - name: max_new_tokens type: number section: advanced required: false default: 1024 description: Max audio tokens per chunk. fish-speech default 1024. - name: chunk_length type: slider section: advanced min: 100 max: 1000 step: 10 default: 200 description: Target chunk length in chars when splitting. fish-speech default 200. - name: normalize type: bool section: advanced default: true description: Text normalization (numbers, punctuation). fish-speech default on. - name: use_memory_cache type: select section: advanced options: ["off", "on"] default: "off" description: > `on` caches the reference encoding to speed up repeated calls with the same voice. fish-speech default off. response: type: audio mime_from_field: format reproducibility: seedable: true deterministic: false seed_field: seed notes: > /v1/tts exposes `seed` (omit = random); a fixed seed repeats a take. Temperature/top_p sampled → not guaranteed byte-exact. (Prior catalog claimed no seed support — corrected against the upstream ServeTTSRequest schema + a live generation 2026-06-01.) estimated_latency: cold_start_s: 240 warm_per_unit: "~realtime throughput on the A6000 (heavy). latency=balanced trades quality for lower latency." license: "Research-only (Fishaudio terms; non-commercial)" license_warning: | Research/internal only. Not clear for commercial use. Same flag as Voxtral and SAO — UI must surface when output destined for products. notes: | NOT OpenAI-compatible: only /v1/tts (no /v1/audio/voices, /v1/models, or /openapi.json). Voice discovery is manual (host filesystem). Full control surface (temperature/top_p/repetition_penalty/latency/seed/format + the cloning fields) sourced from fish-speech's ServeTTSRequest schema and verified live 2026-06-01; prior catalog exposed only text + references. HEAVY: ~240s torch.compile warmup measured on cold start; budget the wait. - id: kyutai-tts name: Kyutai TTS 1.6B EN/FR description: > Kyutai's bilingual streaming TTS (1.6B, 2.5M hours). Heritage from Mimi codec + Moshi dialogue framework. OpenAI-compat HTTP wrapper over Rust streaming core. category: tts version: 2 status: down host: irv-ml1 lifecycle: stack: kyutai-tts vram_gb: 6 gpu_device_id: 0 endpoint: http://10.100.79.3:8198/v1/audio/speech method: POST content_type: application/json model: id: kyutai/tts-1.6b-en_fr revision: null image: local/kyutai-tts:v1 fields: - name: model type: select options: [tts-1.6b-en_fr] default: tts-1.6b-en_fr - name: input type: textarea label: Text required: true max_length: 5000 - name: voice type: text label: Voice (HF-relative path) default: unmute-prod-website/default_voice.wav description: > Path relative to the `kyutai/tts-voices` HF repo, cached on irv-ml1 at /worktank/kyutai-tts/hf_cache. NillPointer wrapper does NOT expose /v1/audio/voices (404; only /health + POST /v1/audio/speech are wired) — voices are specified by path. Default `unmute-prod-website/default_voice.wav` is upstream's named-default. Categories available locally (count): vctk/* (212, CC BY 4.0 — commercial-safe) ears/* (306) voice-donations/* (291, mixed) expresso/* (103, CC BY-NC — research-only) cml-tts/* (70) unmute-prod-website/* (6, incl. default) alba-mackenna/* (4) For commercial paths, prefer a vctk/* voice (e.g., `vctk/p225_023_mic1.wav`). Full repo: https://huggingface.co/kyutai/tts-voices - name: response_format type: select options: [wav, mp3, pcm] default: wav - name: stream type: bool default: false response: type: audio mime_from_field: response_format reproducibility: seedable: false deterministic: true notes: > Wrapper adds Python overhead vs Kyutai's bare 220ms claim. Voice list is filesystem-discovered, not API-exposed — the NillPointer wrapper only wires /health + /v1/audio/speech. estimated_latency: cold_start_s: 4 warm_per_unit: "~220–400ms TTFB (with wrapper)" license: "TBD (Kyutai — verify)" - id: vibevoice name: VibeVoice 1.5B (Long-form) description: > Microsoft's diffusion-based long-form multi-speaker TTS. Multi-minute scripts with speaker switching. Not for low-latency single-line use. category: tts version: 3 host: irv-ml1 lifecycle: stack: vibevoice vram_gb: 20 gpu_device_id: 1 endpoint: http://10.100.79.3:8194/v1/audio/speech method: POST content_type: application/json model: id: microsoft/VibeVoice-1.5B revision: null image: local/vibevoice:v1 fields: - name: model type: select options: [tts-1, tts-1-hd, vibevoice] default: tts-1 description: > OpenAI-compatibility aliases all map to VibeVoice internally. Wire default is tts-1 (verified against /openapi.json). - name: input type: textarea label: "Text (or Speaker N: ... script)" required: true description: > Single-speaker: plain text. Multi-speaker: "Speaker 0: ...\nSpeaker 1: ..." via /v1/vibevoice/generate (extended endpoint). - name: voice type: select label: Voice default: en-Alice_woman description: > Default `en-Alice_woman` matches the upstream model card's stated default voice. Foot-gun: Alice has been observed to insert intro-BGM for openers like "Welcome to ..." — flip to en-Maya_woman if BGM artifacts are unwanted. OpenAI presets (compat aliases): alloy, echo, fable, onyx, nova, shimmer. VibeVoice presets: en-Alice_woman, en-Carter_man, en-Frank_man, en-Mary_woman_bgm, en-Maya_woman, in-Samuel_man, zh-Anchen_man_bgm, zh-Bowen_man, zh-Xinran_woman. The `_bgm`-suffixed voices were trained with background music intentionally — avoid for clean speech. Custom: drop WAV/MP3/FLAC/M4A into /worktank/vibevoice/voices/, restart container. Voice cloning training NOT released by Microsoft. options: - alloy - echo - fable - onyx - nova - shimmer - en-Alice_woman - en-Carter_man - en-Frank_man - en-Mary_woman_bgm - en-Maya_woman - in-Samuel_man - zh-Anchen_man_bgm - zh-Bowen_man - zh-Xinran_woman - name: response_format type: select options: [wav, mp3, opus, flac, pcm] default: mp3 description: > Wire default is mp3 (verified /openapi.json). All five values confirmed by exercising the endpoint 2026-05-11; aac and m4a fail with 500 despite OpenAPI not enforcing an enum, so excluded. - name: stream type: bool default: false description: Single-shot endpoint doesn't stream; segment-level on multi-speaker. response: type: audio mime_from_field: response_format reproducibility: seedable: false deterministic: true estimated_latency: cold_start_s: 8 warm_per_unit: "30–60s first generation; segment-based after" license: MIT notes: | flash_attention_2 default; sdpa fallback. 7B variant (rsxdalv/VibeVoice-Large, ~18GB) needs int8 for <10GB VRAM. - id: voxtral name: Voxtral 4B TTS description: > Mistral AI's 4B multilingual streaming TTS (CC BY-NC — research/internal only). 8 languages, 70ms model latency, 9.7× realtime. Served via vLLM-Omni. category: tts version: 2 status: down host: irv-ml1 lifecycle: stack: voxtral vram_gb: 12 gpu_device_id: 1 endpoint: http://10.100.79.3:8197/v1/audio/speech method: POST content_type: application/json model: id: mistralai/Voxtral-4B-TTS-2603 revision: null image: vllm/vllm-omni:v0.18.0 fields: - name: model type: select options: [mistralai/Voxtral-4B-TTS-2603] default: mistralai/Voxtral-4B-TTS-2603 - name: input type: textarea label: Text required: true max_length: 5000 - name: voice type: select label: Voice source_url: http://10.100.79.3:8197/v1/audio/voices default: neutral_female options: - neutral_female - neutral_male - casual_female - casual_male - cheerful_female - ar_male - de_female - de_male - es_female - es_male - fr_female - fr_male - hi_female - hi_male - it_female - it_male - nl_female - nl_male - pt_female - pt_male description: > Native Voxtral presets — vLLM-Omni does NOT translate OpenAI aliases (verified 2026-05-12 live against /v1/audio/voices). Naming shape is `_` for English (neutral_*, casual_*, cheerful_*) and `_` for non-English. Default `neutral_female` matches Mistral docs' stated default. The full list above was captured live from the running container; uploaded user voices appear in /v1/audio/voices under `uploaded_voices`. - name: response_format type: select options: [wav, mp3, pcm] default: wav - name: stream type: bool default: false response: type: audio mime_from_field: response_format reproducibility: seedable: false deterministic: true notes: vLLM-Omni v0.18.0+ required (first Voxtral-aware release, 2026-03-29). estimated_latency: cold_start_s: 6 warm_per_unit: "~70ms model latency, 9.7× realtime" license: "CC BY-NC (Mistral) — non-commercial only" license_warning: | NOT clear for commercial use. UI must surface this when output destined for products. Use Kokoro/Chatterbox/Fish/IndexTTS/Qwen3/CosyVoice for commercial paths. - id: parakeet name: Parakeet TDT (ASR) description: > NVIDIA Parakeet-TDT 0.6B (int8 ONNX, ~400MB) via sherpa-onnx. Transcription only. category: asr version: 1 host: irv-ml1 lifecycle: stack: parakeet vram_gb: 2 gpu_device_id: null endpoint: http://10.100.79.3:8765/transcribe method: POST content_type: multipart/form-data model: id: nvidia/parakeet-tdt-v2-en-int8 revision: null image: local/parakeet:sherpa-onnx-v2 fields: - name: file type: file label: Audio File required: true accepted_types: [audio/wav, audio/mp3, audio/flac, audio/ogg] response: type: text output_field: text reproducibility: seedable: false deterministic: true estimated_latency: cold_start_s: 1 warm_per_unit: "~realtime" license: "Proprietary (NVIDIA model) + Apache-2.0 (sherpa-onnx)" notes: | Aliased at /v1/audio/transcriptions for OpenAI compat. v3 model (25 languages) available via env-only change. - id: stable-audio-open name: Stable Audio Open 1.0 (SFX) description: > Stability AI's text-to-audio diffusion. SFX/foley/ambience only — NOT music. Max 47s clips. Seeded, fully deterministic. category: sfx version: 2 host: irv-ml1 lifecycle: stack: stable-audio-open vram_gb: 6 gpu_device_id: 1 endpoint: http://10.100.79.3:8211/v1/audio/sfx method: POST content_type: application/json model: id: stabilityai/stable-audio-open-1.0 revision: null image: local/stable-audio-open:v1 fields: - name: prompt type: textarea label: Prompt required: true description: > Description of the audio to generate. Per diffusers Tips section, descriptive multi-element prompts produce better results than terse ones — `"melodic techno with a fast beat and synths, 128 BPM"` is stronger than `"techno"`. Other canonical examples from the model card: `"128 BPM tech house drum loop"`, `"the sound of a hammer hitting a wooden surface"`. - name: negative_prompt type: textarea label: Negative Prompt default: "low quality, average quality" description: > Official diffusers-docs recommendation. `"low quality, average quality"` (lowercase, comma-separated) per the Stable Audio pipeline's Tips section — was `"Low quality."` in v0, fixed in v1. - name: duration type: slider min: 0.5 max: 47.0 default: 10.0 label: Duration (seconds) - name: steps type: slider min: 10 max: 300 default: 100 label: Diffusion Steps - name: cfg_scale type: slider min: 0.0 max: 20.0 default: 7.0 label: CFG Scale - name: seed type: number label: Seed optional: true response: type: audio mime: audio/wav reproducibility: seedable: true seed_field: seed deterministic: true notes: > Identical seed+prompt+steps+cfg = bit-identical bytes. Wrapper serializes concurrent requests via asyncio.Lock (StableAudioPipeline not reentrant). estimated_latency: cold_start_s: 3 warm_per_unit: "~30–60s per 10s clip" license: "Stability AI Community (non-commercial)" license_warning: | Non-commercial only. Same flag as Voxtral for commercial paths. - id: ace-step name: ACE-Step 1.5 (Music) description: > Apache-2.0 hybrid diffusion+LLM music generation. Multi-minute lyric-aware songs with vocals + instrumentation. category: music version: 5 host: irv-ml1 lifecycle: stack: ace-step vram_gb: 16 gpu_device_id: 1 endpoint: http://10.100.79.3:8210/generate method: POST content_type: application/json model: id: ace-step/ACE-Step revision: main image: local/ace-step:v1 section_groups: - id: basic label: Basic hint: "Prompt + lyrics + duration. The 80% case." - id: generation label: Generation hint: "Sampler steps, guidance, scheduler, seed." - id: conditioning label: Conditioning hint: "ERG flags, OSS schedule, guidance shape." - id: a2a label: "Audio → Audio" hint: "Generate from a reference clip." - id: lora label: LoRA hint: "Adapter weights." - id: output label: Output hint: "Format and device." fields: - name: prompt type: textarea label: Musical Prompt required: true section: basic description: > Style/mood/instrumentation as a comma-separated tag string. The upstream Gradio UI ships pre-filled with: `"funk, pop, soul, rock, melodic, guitar, drums, bass, keyboard, percussion, 105 BPM, energetic, upbeat, groovy, vibrant, dynamic"` — same shape works well here. Shorter examples: `"uplifting pop with synth leads"`, `"lo-fi hip-hop beat with vinyl crackle"`. - name: lyrics type: textarea label: Lyrics required: true default: "" section: basic description: > Required by the upstream Pydantic model (`lyrics: str`) but empty string is a valid value (instrumental). Default '' so the inference client always sends a string. - name: audio_duration type: slider min: 5.0 max: 240.0 default: 30.0 label: Duration (seconds) section: basic description: > Upstream caps at 240s (the model's training horizon). Lower bound 5s is our choice — upstream uses -1 as a "random duration" sentinel which is hostile UX for a slider. Default 30s also kept (upstream uses -1; explicit 30 is the better first-time-user experience). - name: infer_step type: number default: 60 label: Inference Steps section: generation description: > Upstream Gradio default is 60 (matches benchmark numbers in the README). Lower values (20-30) are useful for "preview" passes; higher (80-100) marginal returns. - name: guidance_scale type: slider min: 0.0 max: 30.0 default: 15.0 section: generation - name: scheduler_type type: select options: [euler, heun, pingpong] default: euler section: generation description: > Flow-matching scheduler. `euler` is the canonical default; `heun` trades 2x compute for higher-order accuracy; `pingpong` is a specialized noise-bouncing variant. - name: cfg_type type: select options: [apg, cfg, cfg_star] default: apg section: generation description: > Classifier-free guidance variant. Upstream Gradio default is `apg` (adaptive projected guidance); `cfg` is the standard SD-style formulation; `cfg_star` is an advanced alternative. See the upstream pipeline source for trade-offs. - name: omega_scale type: slider min: -10.0 max: 30.0 default: 10.0 section: generation description: > Upstream technically allows [-100, 100] but values that wide are unusable as a slider. UI-bounded to [-10, 30] which covers the typical zone with headroom. Hit the API directly for extremes. - name: actual_seeds type: json label: Seeds (empty = random) default: [] section: generation description: > Empty list = wrapper sends empty string to pipeline = pipeline picks a random seed per batch element. Explicit seeds (e.g. [42] or [42, 137, 9999]) for reproducibility. REPRODUCIBILITY GAP (queued for follow-up): the pipeline returns the chosen seed in its result dict, but our wrapper currently throws it away. Assets generated with the default `[]` cannot currently be regenerated. Workaround: set actual_seeds explicitly when reproducibility matters. Wrapper enhancement to surface random-resolved seeds via X-Actual-Seeds header + a catalog schema field for header→accessory capture is the planned fix. - name: guidance_interval type: slider min: 0.0 max: 1.0 default: 0.5 section: conditioning - name: guidance_interval_decay type: slider min: 0.0 max: 1.0 default: 0.0 section: conditioning description: > Upstream Gradio default is 0.0 (no decay). Catalog v4 had this at 1.0 (full decay) — wrong; produced under-conditioned outputs. - name: min_guidance_scale type: slider min: 0.0 max: 20.0 default: 3.0 section: conditioning description: > Upstream technically allows up to 200; UI-bounded to 20 (covers the typical zone). Hit the API directly for extremes. - name: use_erg_tag type: bool default: true section: conditioning - name: use_erg_lyric type: bool default: false section: conditioning - name: use_erg_diffusion type: bool default: true section: conditioning - name: oss_steps type: json default: [] section: conditioning - name: guidance_scale_text type: slider min: 0.0 max: 10.0 default: 0.0 section: conditioning - name: guidance_scale_lyric type: slider min: 0.0 max: 10.0 default: 0.0 section: conditioning - name: audio2audio_enable type: bool default: false section: a2a - name: ref_audio_strength type: slider min: 0.0 max: 1.0 default: 0.5 section: a2a - name: ref_audio_input type: text label: Reference Audio Path optional: true section: a2a - name: lora_name_or_path type: text label: LoRA Repo/Path optional: true section: lora - name: lora_weight type: slider min: -3.0 max: 3.0 default: 1.0 section: lora description: > Negative weights are legitimate (apply the LoRA in inverse). Upstream Gradio range adopted verbatim. - name: audio_format type: select options: [wav, mp3, flac] default: wav section: output - name: bf16 type: bool default: true section: output - name: torch_compile type: bool default: false section: output - name: device_id type: number default: 0 label: GPU Device Index section: output - name: checkpoint_path type: text label: Checkpoint Path required: true default: /app/checkpoints section: output description: > Required by the upstream wrapper (`infer-api.py:29`, no default in the Pydantic model). The container always mounts checkpoints at /app/checkpoints, so the catalog default works out-of-the-box. Only override if you've mounted an alternate checkpoint path. Wrapper-side cleanup queued — once the upstream model defaults this, the catalog field will become optional or be dropped entirely. response: # As of wrapper version that ships with image local/ace-step:v1 # post 2026-05-11, /generate streams audio bytes inline with # Content-Type set from the audio_format request field. The # in-container output_path is exposed via X-Output-Path header # for log correlation but is no longer load-bearing. type: audio mime_from_field: audio_format reproducibility: seedable: true deterministic: true notes: > actual_seeds parameter exposed; identical seeds + params = identical audio. Local infer-api.py patches upstream's broken 24-arg pipeline signature (v2: was 18 in upstream — caused crashes with audio_duration in `format` slot) AND inline-streams the generated audio bytes (v4: was returning a JSON path reference to a file inside the container, which was unreachable from outside). REPRODUCIBILITY GAP (v5): default `actual_seeds: []` triggers random seed selection inside the pipeline. The chosen seed IS available in the pipeline's return dict (`actual_seeds` key) but our wrapper doesn't capture or surface it — so default-defaulted assets cannot be regenerated bit-exact. Set actual_seeds explicitly when reproducibility is required. Wrapper enhancement to surface chosen seeds via response header + a catalog schema for header→accessory capture is queued. estimated_latency: cold_start_s: 30 warm_per_unit: "~10–60s depending on audio_duration + infer_step" license: Apache-2.0 notes: | 27-field surface — UI must do progressive disclosure (basic/advanced). Gradio UI fallback: docker exec -it ace-step python3 acestep/gui.py. - id: comfyui name: ComfyUI (workflow engine — catalog-deferred) description: > Node-based diffusion workflow engine. Native API is workflow JSON DAG, not form fields. Catalog-deferred until per-asset-type workflow templates are defined and a wrapper maps form inputs to template node parameters. category: image status: catalog-deferred version: 1 host: irv-ml1 endpoint: http://10.100.79.3:8188 method: WebSocket + POST content_type: application/json model: id: "various (SD, SDXL, Flux, ControlNet, LoRA, upscalers)" revision: null image: mmartial/comfyui-nvidia-docker:ubuntu24_cuda12.8-20260312 response: type: image mime: image/png reproducibility: seedable: true deterministic: true notes: > Seed is a workflow node parameter. Reproducibility requires persisting full workflow JSON + seed alongside the asset. license: GPL-3.0 notes: | To bring into the catalog: define workflow templates per asset-type (portrait, landscape, sfx-thumbnail, ...), build a wrapper that does form-field-to-node-parameter substitution, submit via POST /prompt, poll /history. Until then, expose ComfyUI as an external link in the UI. User state at /worktank/comfyui/basedir/. # Dia2 runs as TWO fixed-model instances: the devnen wrapper is # single-model and IGNORES the OpenAI `model` field (serves whatever # checkpoint is loaded), so the only way to offer both Dia2 models to # asset-engine as real per-request choices is one endpoint per model. # Both live in the `dia` stack (one compose, two services); `compose up` # starts both. The legacy Dia 1.6B entry was retired 2026-05-31 in favor # of these — drop the old `dia` tile when re-vendoring. - id: dia2-2b name: Dia2 2B (High Quality) description: > Nari Labs' Dia2 dialogue TTS, 2B high-quality checkpoint — multi-speaker turn-taking in one pass with [S1]/[S2] speaker tags and nonverbals (laughs)/(coughs)/(sighs). 24 kHz. Served via devnen/Dia-TTS-Server. category: tts version: 2 status: ready host: irv-ml1 lifecycle: stack: dia vram_gb: 8 gpu_device_id: 0 endpoint: http://10.100.79.3:8200/tts method: POST content_type: application/json model: id: nari-labs/Dia2-2B revision: null image: local/dia:v2 section_groups: - id: basic label: Text & voice - id: sampling label: Sampling hint: Wrapper-canonical Dia2 defaults; lower temperature/cfg for steadier output. - id: advanced label: Advanced fields: - name: text type: textarea label: Text ([S1]/[S2] dialogue + nonverbals) section: basic required: true max_length: 5000 default: "[S1] Hello Dia2!" # canonical: nari-labs/dia2 README usage example description: > [S1]/[S2] tags mark speaker turns; nonverbals like (laughs), (coughs), (sighs), (clears throat) go inline. - name: voice_mode type: select label: Voice mode section: basic options: [clone, single_s1, single_s2, dialogue] default: clone description: > Defaults to `clone` -> a stable predefined voice (clone_reference_filename below, default Abigail.wav). The unconditioned modes (single_s1/s2, dialogue) sample a RANDOM speaker each call (gender varies) — pick one only if you want that. NOTE: voice_mode=clone REQUIRES a real clone_reference_filename; an empty/"undefined" value 404s. - name: clone_reference_filename type: select label: Voice (clone reference) section: basic optional: true default: "Abigail.wav" source_url: http://10.100.79.3:8200/get_reference_files source_jsonpath: $[*] description: > Required when voice_mode=clone. Lists the reference_audio library — 43 curated voices (singles + [S1]/[S2] dialogue pairs like Abigail_Taylor.wav) staged there from the image's /app/voices, plus any you upload. Pins voice/gender deterministically. - name: transcript type: textarea label: Reference transcript section: advanced optional: true description: > Optional transcript of a custom clone reference (overrides its local .txt sidecar). Leave blank for predefined voices. - name: output_format type: select section: basic options: [opus, wav] default: opus description: 24 kHz (Dia2). - name: cfg_scale type: slider section: sampling min: 1.0 max: 5.0 step: 0.1 default: 3.0 description: Classifier-free guidance scale (wrapper default 3.0). - name: temperature type: slider section: sampling min: 0.1 max: 1.5 step: 0.05 default: 1.3 description: Sampling temperature; lower = steadier (wrapper default 1.3). - name: top_p type: slider section: sampling min: 0.1 max: 1.0 step: 0.01 default: 0.95 - name: cfg_filter_top_k type: number section: sampling required: false default: 35 description: Top-k filter for CFG guidance (1–100; wrapper default 35). - name: speed_factor type: slider section: sampling min: 0.5 max: 2.0 step: 0.01 default: 0.94 description: Playback speed (wrapper canonical default 0.94). - name: seed type: number section: sampling required: false default: -1 description: -1 = random; a fixed integer repeats the same take. - name: split_text type: bool section: advanced default: true description: Auto-split long text into chunks. - name: chunk_size type: slider section: advanced min: 100 max: 1000 step: 10 default: 300 description: Target chunk length in chars when splitting (wrapper default 300). - name: max_tokens type: number section: advanced required: false description: Max audio tokens per chunk; omit to use the model's internal default. response: type: audio mime_from_field: output_format reproducibility: seedable: true deterministic: false notes: > Per the dia2 README, voices vary per generation unless anchored — set voice_mode=clone + a clone_reference_filename for a stable voice/gender. seed (-1=random) repeats a take but doesn't choose the voice; temperature-sampled, not byte-exact; raw bytes -> no seed_field. All field defaults are the wrapper's CustomTTSRequest Pydantic blessed values. estimated_latency: cold_start_s: 30 warm_per_unit: "dialogue one-pass; ~realtime on the 3090" license: "Apache-2.0 (Dia2 weights); MIT (devnen wrapper)" notes: | Routes to the wrapper's richer /tts endpoint (full control surface: cfg_scale/temperature/top_p/cfg_filter_top_k/voice_mode/clone) rather than the OpenAI /v1/audio/speech. One of two fixed-model instances in the `dia` stack; sibling dia2-1b (:8202). `docker compose up` starts BOTH (~8 GB here; budget both if gating the whole stack). Image local/dia:v2 (see stacks/dia/dia2-image/). Verified end-to-end 2026-05-31. - id: dia2-1b name: Dia2 1B (Streaming) description: > Nari Labs' Dia2 dialogue TTS, 1B streaming checkpoint — same [S1]/[S2] dialogue + nonverbals as dia2-2b, lower latency / lighter weight. 24 kHz. Served via devnen/Dia-TTS-Server. category: tts version: 2 status: ready host: irv-ml1 lifecycle: stack: dia vram_gb: 5 gpu_device_id: 0 endpoint: http://10.100.79.3:8202/tts method: POST content_type: application/json model: id: nari-labs/Dia2-1B revision: null image: local/dia:v2 section_groups: - id: basic label: Text & voice - id: sampling label: Sampling hint: Wrapper-canonical Dia2 defaults; lower temperature/cfg for steadier output. - id: advanced label: Advanced fields: - name: text type: textarea label: Text ([S1]/[S2] dialogue + nonverbals) section: basic required: true max_length: 5000 default: "[S1] Hello Dia2!" # canonical: nari-labs/dia2 README usage example description: > [S1]/[S2] tags mark speaker turns; nonverbals like (laughs), (coughs), (sighs), (clears throat) go inline. - name: voice_mode type: select label: Voice mode section: basic options: [clone, single_s1, single_s2, dialogue] default: clone description: > Defaults to `clone` -> a stable predefined voice (clone_reference_filename below, default Abigail.wav). The unconditioned modes (single_s1/s2, dialogue) sample a RANDOM speaker each call (gender varies) — pick one only if you want that. NOTE: voice_mode=clone REQUIRES a real clone_reference_filename; an empty/"undefined" value 404s. - name: clone_reference_filename type: select label: Voice (clone reference) section: basic optional: true default: "Abigail.wav" source_url: http://10.100.79.3:8202/get_reference_files source_jsonpath: $[*] description: > Required when voice_mode=clone. Lists the reference_audio library — 43 curated voices (singles + [S1]/[S2] dialogue pairs like Abigail_Taylor.wav) staged there from the image's /app/voices, plus any you upload. Pins voice/gender deterministically. - name: transcript type: textarea label: Reference transcript section: advanced optional: true description: > Optional transcript of a custom clone reference (overrides its local .txt sidecar). Leave blank for predefined voices. - name: output_format type: select section: basic options: [opus, wav] default: opus description: 24 kHz (Dia2). - name: cfg_scale type: slider section: sampling min: 1.0 max: 5.0 step: 0.1 default: 3.0 description: Classifier-free guidance scale (wrapper default 3.0). - name: temperature type: slider section: sampling min: 0.1 max: 1.5 step: 0.05 default: 1.3 description: Sampling temperature; lower = steadier (wrapper default 1.3). - name: top_p type: slider section: sampling min: 0.1 max: 1.0 step: 0.01 default: 0.95 - name: cfg_filter_top_k type: number section: sampling required: false default: 35 description: Top-k filter for CFG guidance (1–100; wrapper default 35). - name: speed_factor type: slider section: sampling min: 0.5 max: 2.0 step: 0.01 default: 0.94 description: Playback speed (wrapper canonical default 0.94). - name: seed type: number section: sampling required: false default: -1 description: -1 = random; a fixed integer repeats the same take. - name: split_text type: bool section: advanced default: true description: Auto-split long text into chunks. - name: chunk_size type: slider section: advanced min: 100 max: 1000 step: 10 default: 300 description: Target chunk length in chars when splitting (wrapper default 300). - name: max_tokens type: number section: advanced required: false description: Max audio tokens per chunk; omit to use the model's internal default. response: type: audio mime_from_field: output_format reproducibility: seedable: true deterministic: false notes: > Same story as dia2-2b: voices vary per generation unless anchored (voice_mode=clone + clone_reference_filename); temperature-sampled, not byte-exact; raw bytes -> no seed_field. Defaults are the wrapper's CustomTTSRequest Pydantic blessed values. estimated_latency: cold_start_s: 30 warm_per_unit: "streaming; lower latency than dia2-2b" license: "Apache-2.0 (Dia2 weights); MIT (devnen wrapper)" notes: | Routes to the wrapper's richer /tts endpoint (same control surface as dia2-2b). Sibling of dia2-2b in the same `dia` stack (see its notes for the single-model-per-endpoint rationale + both-start-together caveat). Image local/dia:v2. Verified end-to-end 2026-05-31. - id: zonos name: Zonos-v0.1 TTS description: > Zyphra's expressive multilingual open-weight TTS (Apache-2.0) — 44 kHz, zero-shot voice cloning from a 10–30s clip, and an 8-axis emotion vector plus pitch/rate/fmax conditioning. First genuinely seedable TTS in the fleet: the adapter returns the seed so regenerate/fork can pin it. category: tts version: 1 status: down host: irv-ml1 lifecycle: stack: zonos # Adapter alone (~6 GB). NOTE: the zonos stack currently ships TWO # services (the Gradio eval UI + this adapter); if orchestration does a # whole-stack `compose up` it loads the model twice (~12 GB). Target the # zonos-api service, or drop the Gradio service at promotion. vram_gb: 6 gpu_device_id: 0 endpoint: http://10.100.79.3:8203/v1/audio/speech method: POST content_type: application/json model: id: Zyphra/Zonos-v0.1-transformer revision: null image: local/zonos-api:v1 section_groups: - id: text label: Text - id: voice label: Voice - id: expression label: Expression hint: Conditioning knobs; leave emotion blank to keep it unconditional. - id: generation label: Generation fields: - name: input type: textarea label: Text to synthesize section: text required: true max_length: 500 default: "Zonos uses eSpeak for text to phoneme conversion!" # canonical: upstream gradio_interface.py default description: eSpeak-phonemized. Upstream Gradio caps the box at ~500 chars. - name: language type: select label: Language code section: text default: en-us # eSpeak code list is large; these are the documented multilingual # set. The adapter accepts any code in zonos.supported_language_codes. options: [en-us, ja, cmn, fr-fr, de] description: Any eSpeak code Zonos supports; 400 on an unknown code. - name: voice type: select label: Clone voice (optional) section: voice optional: true source_url: http://10.100.79.3:8203/v1/audio/voices source_jsonpath: $.voices[*] description: > Reference clip filename under /worktank/zonos/voices/ (10–30s clean WAV). Omit for Zonos's default unconditioned voice. - name: response_format type: select section: generation options: [wav, flac] default: wav description: 44.1 kHz. Both lossless (libsndfile); no mp3/opus in v1. - name: emotion type: json label: Emotion vector (optional) section: expression optional: true description: > 8 floats 0.0–1.0 [happy, sad, disgust, fear, surprise, anger, other, neutral]. Omit to leave emotion unconditional (the Gradio default; upstream warns the sliders are finicky and can destabilize output). - name: speaking_rate type: slider section: expression min: 5.0 max: 30.0 step: 0.5 default: 15.0 - name: pitch_std type: slider label: Pitch std section: expression min: 0.0 max: 300.0 step: 1 default: 45.0 - name: fmax type: slider label: Fmax (Hz) section: expression min: 0 max: 24000 step: 1 default: 24000 - name: cfg_scale type: slider label: CFG scale section: generation min: 1.0 max: 5.0 step: 0.1 default: 2.0 - name: seed type: number section: generation optional: true description: Omit for a random seed; the seed used is returned in the envelope. response: # JSON envelope (like kokoro-captioned) so the seed rides back with the # audio. Adapter returns: {audio: , # audio_format: "audio/wav"|"audio/flac", seed: }. type: audio audio_field: audio audio_format_field: audio_format reproducibility: seedable: true deterministic: true seed_field: seed notes: > torch.manual_seed(seed); the adapter echoes the seed it used in the envelope's `seed` key. Same seed + params + GPU → byte-stable in practice; cross-GPU (3090 vs A6000) may differ at bf16. Wire shape is defined by the adapter (stacks/zonos/adapter/server.py) — verify against the live endpoint at deploy per CATALOG-CONTRACT. estimated_latency: cold_start_s: 30 warm_per_unit: "~2x realtime on the 3090 (transformer variant)" license: Apache-2.0 notes: | Served via a thin OpenAI-ish FastAPI adapter (stacks/zonos/adapter/) in front of the Zonos Python SDK — upstream ships only Gradio + SDK, no REST. Transformer variant only (mamba-ssm absent → no hybrid). Fields read from upstream gradio_interface.py (2026-05-31), the CATALOG-CONTRACT blessed source for defaults/ranges. Adapter not yet deployed/verified — flip to ready (or experimental) after the first successful generation through 8203. # Reproducibility audit — answers per service: (a) seedable, (b) model # deterministic without seed, (c) image tag mutable (security/reproducibility risk). reproducibility_audit: - service: kokoro seedable: false model_deterministic: true image_tag_mutable: true notes: ":v0.2.4-master is mutable; pin to digest for v3." - service: kokoro-captioned seedable: false model_deterministic: true image_tag_mutable: true notes: "Same image as kokoro proper; same mutability story. Response carries timestamps." - service: chatterbox seedable: true model_deterministic: false image_tag_mutable: true notes: "/tts exposes seed (0=random); temperature-sampled, not byte-exact. PerTh watermark unconditional (Resemble policy). image :latest is mutable — pin a digest/SHA for true repro." - service: index-tts seedable: false model_deterministic: true image_tag_mutable: false notes: "22050 Hz hardcoded — caller must resample." - service: qwen3-tts seedable: false model_deterministic: true image_tag_mutable: false - service: cosyvoice seedable: false model_deterministic: true image_tag_mutable: false notes: "instruct field broken for English; XML tags only." - service: fish-s2 seedable: true model_deterministic: false image_tag_mutable: false notes: "/v1/tts exposes seed (omit=random); temperature/top_p sampled, not byte-exact. Research-only license — non-commercial." - service: kyutai-tts seedable: false model_deterministic: true image_tag_mutable: false - service: vibevoice seedable: false model_deterministic: true image_tag_mutable: false notes: "Voice cloning training not released." - service: voxtral seedable: false model_deterministic: true image_tag_mutable: false notes: "CC BY-NC — non-commercial." - service: parakeet seedable: false model_deterministic: true image_tag_mutable: false - service: stable-audio-open seedable: true model_deterministic: true image_tag_mutable: false notes: "Wrapper serializes concurrent requests (StableAudioPipeline not reentrant)." - service: ace-step seedable: true model_deterministic: true image_tag_mutable: false notes: "Local infer-api.py patches upstream's broken pipeline signature." - service: comfyui seedable: true model_deterministic: true image_tag_mutable: false notes: "Reproducibility requires persisting full workflow JSON + seed." - service: dia2-2b seedable: true model_deterministic: false image_tag_mutable: false notes: "Dia2 2B, temperature-sampled (seed gives consistent prosody, not byte-exact). local/dia:v2 (derived; upstream wrapper SHA not pinned)." - service: dia2-1b seedable: true model_deterministic: false image_tag_mutable: false notes: "Dia2 1B streaming; same determinism story as dia2-2b. local/dia:v2." - service: zonos seedable: true model_deterministic: true image_tag_mutable: false notes: "Adapter echoes the seed used (reproducibility.seed_field=seed). Byte-stable same-GPU; bf16 may drift cross-GPU. local/zonos-api:v1 built FROM local/zonos (pin ZONOS_SHA for true repro)."