From 9708eede717a64d24b0abfff0cb9cc565620958b Mon Sep 17 00:00:00 2001 From: mARTin-B78 Date: Sat, 30 May 2026 14:31:25 +0200 Subject: [PATCH] refactor: consolidate Docker files into docker/ and merge streaming repo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move full 4-service compose config/docker-compose.yml → docker/docker-compose.yml - Move single-service quickstart docker-compose.yml → docker/docker-compose.simple.yml - Replace private /home/sparky paths with /path/to/ placeholders in docker/docker-compose.yml - Merge martinb78/qwen3-tts-streaming-dgx-spark into martinb78/faster-qwen3-tts-dgx-spark:streaming tag - Update all image references: v4 → latest, streaming image → :streaming tag - Update README and DOCKERHUB_STREAMING.md to reflect new structure Co-Authored-By: Claude Sonnet 4.6 --- DOCKERHUB_STREAMING.md | 112 ++++++++++++++++++ README.md | 37 +++--- .../docker-compose.simple.yml | 6 +- {config => docker}/docker-compose.yml | 37 +++--- 4 files changed, 156 insertions(+), 36 deletions(-) create mode 100644 DOCKERHUB_STREAMING.md rename docker-compose.yml => docker/docker-compose.simple.yml (88%) rename {config => docker}/docker-compose.yml (76%) diff --git a/DOCKERHUB_STREAMING.md b/DOCKERHUB_STREAMING.md new file mode 100644 index 0000000..e449fee --- /dev/null +++ b/DOCKERHUB_STREAMING.md @@ -0,0 +1,112 @@ +# Qwen3-TTS Streaming — DGX Spark (GB10) + +Low-latency, OpenAI-compatible streaming TTS server for the **NVIDIA DGX Spark GB10** +(ARM64 / SM 121 / CUDA 13), powered by [faster-qwen3-tts](https://github.com/andimarafioti/faster-qwen3-tts) +with CUDA graph acceleration. + +Streams WAV audio chunks to the client while generation is still running — +first audio arrives in under a second for typical sentences. + +Part of a four-backend TTS stack documented on the NVIDIA Developer Forum: +[Three times (VoiceClone | VoiceDesign | CustomVoice) — Faster-Qwen3-TTS for NVIDIA DGX Spark (GB10)](https://forums.developer.nvidia.com/t/three-times-voiceclone-voicedesign-customvoice-faster-qwen3-tts-for-nvidia-dgx-spark-gb10/370530) + +--- + +## Quick start + +```bash +docker run -d \ + --runtime nvidia \ + --name qwen3-tts-streaming \ + -p 8023:8000 \ + -e NVIDIA_VISIBLE_DEVICES=all \ + -v /path/to/Qwen3-TTS-12Hz-1.7B-Base:/models/Qwen3-TTS:ro \ + -v /path/to/faster-qwen3-tts/config:/config:rw \ + -v /path/to/active_voices:/voices:ro \ + martinb78/faster-qwen3-tts-dgx-spark:streaming \ + /bin/bash -c " + python3 /config/generate_voices.py && + python3 /config/run_server.py + --model /models/Qwen3-TTS + --voices /config/voices.json + --port 8000 + --max-seq-len 4096 + " +``` + +Check it's running: + +```bash +curl http://localhost:8023/health +``` + +--- + +## Voice configuration + +Create a `voices.json` in your config directory. Each entry maps a voice ID to a +reference audio file and transcript: + +```json +{ + "william": { + "ref_audio": "/voices/william.wav", + "ref_text": "The quick brown fox jumps over the lazy dog.", + "language": "English", + "temperature": 0.75, + "top_k": 40, + "top_p": 0.85 + }, + "natasha": { + "ref_audio": "/voices/natasha.wav", + "ref_text": "She sells seashells by the seashore.", + "language": "English" + } +} +``` + +`temperature`, `top_k`, and `top_p` are optional — defaults are `0.8 / 50 / 0.9`. + +--- + +## API + +OpenAI-compatible `/v1/audio/speech`: + +```bash +curl http://localhost:8023/v1/audio/speech \ + -H "Content-Type: application/json" \ + -d '{"model": "tts-1", "input": "Hello world!", "voice": "william", "response_format": "wav"}' \ + --output speech.wav +``` + +| Endpoint | Method | Description | +|---|---|---| +| `/v1/audio/speech` | POST | Generate speech (WAV / PCM / MP3) | +| `/v1/models` | GET | List available voice IDs | +| `/v1/audio/voices` | GET | Voice list (OpenWebUI fallback) | +| `/speakers` | GET | Voice list (SillyTavern) | +| `/health` | GET | Liveness check | + +Works with **OpenWebUI**, **SillyTavern**, **llama-swap**, and any OpenAI-compatible client. + +--- + +## Requirements + +- NVIDIA DGX Spark GB10 or another ARM64 system with CUDA 13 +- CUDA driver 580+ +- Docker + NVIDIA Container Toolkit +- [Qwen3-TTS-12Hz-1.7B-Base](https://huggingface.co/Qwen/Qwen3-TTS-12Hz-1.7B-Base) weights downloaded locally + +--- + +## Related images + +| Image | Description | +|---|---| +| `martinb78/faster-qwen3-tts-dgx-spark:latest` / `:v5` | VoiceClone, VoiceDesign, and CustomVoice backends | +| `martinb78/faster-qwen3-tts-dgx-spark:streaming` | This tag — streaming VoiceClone | + +Full four-backend `docker-compose` setup in `docker/docker-compose.yml` and detailed documentation on GitHub and the +[NVIDIA Developer Forum](https://forums.developer.nvidia.com/t/three-times-voiceclone-voicedesign-customvoice-faster-qwen3-tts-for-nvidia-dgx-spark-gb10/370530). diff --git a/README.md b/README.md index 21bdbc4..793bc60 100644 --- a/README.md +++ b/README.md @@ -8,17 +8,17 @@ This repo packages the DGX Spark fixes plus four OpenAI-compatible TTS backends: | Backend | Port | Image | Voice source | |---|---:|---|---| -| VoiceClone | `8020` | `martinb78/faster-qwen3-tts-dgx-spark:v5` | Reference audio plus transcript | -| VoiceDesign | `8021` | `martinb78/faster-qwen3-tts-dgx-spark:v5` | Text prompt describes the voice; no reference needed | -| CustomVoice | `8022` | `martinb78/faster-qwen3-tts-dgx-spark:v5` | Separate CustomVoice model variant | -| Streaming | `8023` | `martinb78/qwen3-tts-streaming-dgx-spark:latest` | Same voices as `8020`, but streams WAV chunks while generating | +| VoiceClone | `8020` | `martinb78/faster-qwen3-tts-dgx-spark:latest` | Reference audio plus transcript | +| VoiceDesign | `8021` | `martinb78/faster-qwen3-tts-dgx-spark:latest` | Text prompt describes the voice; no reference needed | +| CustomVoice | `8022` | `martinb78/faster-qwen3-tts-dgx-spark:latest` | Separate CustomVoice model variant | +| Streaming | `8023` | `martinb78/faster-qwen3-tts-dgx-spark:streaming` | Same voices as `8020`, but streams WAV chunks while generating | All four backends expose the OpenAI `/v1/audio/speech` contract and work with **OpenWebUI**, **SillyTavern**, **llama-swap**, `curl`, or any OpenAI-compatible client. -Both Docker images are published and publicly available: +One Docker image covers all four backends: -- `martinb78/faster-qwen3-tts-dgx-spark:v5` - used by VoiceClone, VoiceDesign, and CustomVoice. -- `martinb78/qwen3-tts-streaming-dgx-spark:latest` - used by the streaming service. +- `martinb78/faster-qwen3-tts-dgx-spark:v5` (or `:latest`) — VoiceClone, VoiceDesign, and CustomVoice. +- `martinb78/faster-qwen3-tts-dgx-spark:streaming` — streaming VoiceClone. ## What this solves @@ -31,7 +31,7 @@ The DGX Spark GB10 has a unique ARM64 Grace CPU plus Blackwell GPU stack (SM 121 ## Quick start: VoiceClone only -Use the root `docker-compose.yml` when you only need voice cloning on port `8020`. +Use `docker/docker-compose.simple.yml` when you only need voice cloning on port `8020`. ```bash docker pull martinb78/faster-qwen3-tts-dgx-spark:latest @@ -39,11 +39,9 @@ docker pull martinb78/faster-qwen3-tts-dgx-spark:latest mkdir -p models huggingface-cli download Qwen/Qwen3-TTS-12Hz-1.7B-Base --local-dir ./models/Qwen3-TTS -cp .env.example .env -# Edit .env and set MODEL_PATH to your local Qwen3-TTS-12Hz-1.7B-Base directory. - # Add reference audio and transcripts to config/speakers/ first. -docker compose up -d +cd docker +MODEL_PATH=/path/to/Qwen3-TTS-12Hz-1.7B-Base docker compose -f docker-compose.simple.yml up -d ``` Build the image locally instead of pulling Docker Hub: @@ -66,7 +64,7 @@ curl http://localhost:8020/health ## Full stack: VoiceClone, VoiceDesign, CustomVoice, Streaming -Use `config/docker-compose.yml` when you want all four OpenAI-compatible backends side by side: +Use `docker/docker-compose.yml` when you want all four OpenAI-compatible backends side by side: ```text 8020 -> VoiceClone (/v1/audio/speech, reference audio) @@ -83,21 +81,21 @@ huggingface-cli download Qwen/Qwen3-TTS-12Hz-1.7B-VoiceDesign --local-dir /path/ huggingface-cli download Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice --local-dir /path/to/Qwen3-TTS-12Hz-1.7B-CustomVoice ``` -2. Edit `config/docker-compose.yml` and adjust the volume paths for your machine: +2. Edit `docker/docker-compose.yml` and adjust the volume paths for your machine: ```yaml volumes: - /path/to/Qwen3-TTS-12Hz-1.7B-Base:/models/Qwen3-TTS:ro - /path/to/Qwen3-TTS-12Hz-1.7B-VoiceDesign:/models/Qwen3-TTS-VoiceDesign:ro - /path/to/Qwen3-TTS-12Hz-1.7B-CustomVoice:/models/Qwen3-TTS-CustomVoice:ro - - /path/to/this/repo/config:/config:rw + - /path/to/faster-qwen3-tts/config:/config:rw ``` 3. Make sure the external Docker network exists, then start the stack: ```bash docker network create dgx_net 2>/dev/null || true -cd config +cd docker docker compose up -d ``` @@ -338,6 +336,13 @@ The first request after container startup can be slower because CUDA graph captu ## Changelog +### v6 — 2026-05-30 +**Consolidate Docker files into `docker/` folder** + +- Moved full 4-service compose from `config/docker-compose.yml` → `docker/docker-compose.yml` +- Moved single-service quickstart from root `docker-compose.yml` → `docker/docker-compose.simple.yml` +- Consolidated streaming image into `martinb78/faster-qwen3-tts-dgx-spark:streaming` tag; removed separate `qwen3-tts-streaming-dgx-spark` repository + ### v5 — 2026-05-30 **Fix: voice drifts and gender changes on long paragraphs (VoiceClone)** diff --git a/docker-compose.yml b/docker/docker-compose.simple.yml similarity index 88% rename from docker-compose.yml rename to docker/docker-compose.simple.yml index 43ec30c..eae93e0 100644 --- a/docker-compose.yml +++ b/docker/docker-compose.simple.yml @@ -12,11 +12,11 @@ services: - "8020:8000" volumes: # Mount your local Qwen3-TTS model (download first, see README) - - ${MODEL_PATH:-./models/Qwen3-TTS}:/models/Qwen3-TTS:ro + - ${MODEL_PATH:-../models/Qwen3-TTS}:/models/Qwen3-TTS:ro # Config directory (voices.json generated on startup) - - ./config:/config:rw + - ../config:/config:rw # Speaker reference audio files - - ./config/speakers:/voices:ro + - ../config/speakers:/voices:ro command: > /bin/bash -c " python3 /config/generate_voices.py && diff --git a/config/docker-compose.yml b/docker/docker-compose.yml similarity index 76% rename from config/docker-compose.yml rename to docker/docker-compose.yml index 2dc4f78..4e59373 100644 --- a/config/docker-compose.yml +++ b/docker/docker-compose.yml @@ -7,9 +7,12 @@ # 8022 -> CustomVoice model # 8023 -> Low-latency streaming voice clone endpoint # -# Voice files: -# The voice clone and streaming services scan active voices from: -# /home/sparky/Projekte/TTS_Voices/active_voices +# Before starting: adjust the volume paths below to match your setup. +# - /path/to/Qwen3-TTS-12Hz-1.7B-Base -> local Qwen3-TTS base model +# - /path/to/Qwen3-TTS-12Hz-1.7B-VoiceDesign -> local VoiceDesign model +# - /path/to/Qwen3-TTS-12Hz-1.7B-CustomVoice -> local CustomVoice model +# - /path/to/faster-qwen3-tts/config -> this repo's config directory +# - /path/to/active_voices -> directory with reference .wav files # # Portainer note: # Set HF_TOKEN in the stack environment if the models ever need Hugging Face access. @@ -18,7 +21,7 @@ services: # Standard voice cloning backend used by TTS Voice Creator and other OpenAI-compatible clients. faster-qwen3-tts-voiceclone: - image: martinb78/faster-qwen3-tts-dgx-spark:v4 + image: martinb78/faster-qwen3-tts-dgx-spark:latest container_name: faster-qwen3-tts-voiceclone restart: unless-stopped runtime: nvidia @@ -28,9 +31,9 @@ services: ports: - "8020:8000" volumes: - - /home/sparky/LLMs/vllm/Alibaba/Qwen3-TTS-12Hz-1.7B-Base:/models/Qwen3-TTS:ro - - /home/sparky/Docker/faster-qwen3-tts/config:/config:rw - - /home/sparky/Projekte/TTS_Voices/active_voices:/voices:ro + - /path/to/Qwen3-TTS-12Hz-1.7B-Base:/models/Qwen3-TTS:ro + - /path/to/faster-qwen3-tts/config:/config:rw + - /path/to/active_voices:/voices:ro command: > /bin/bash -c " python3 /config/generate_voices.py && @@ -52,7 +55,7 @@ services: # VoiceDesign backend: creates speech from a descriptive voice prompt instead of a reference clip. faster-qwen3-tts-voicedesign: - image: martinb78/faster-qwen3-tts-dgx-spark:v4 + image: martinb78/faster-qwen3-tts-dgx-spark:latest container_name: faster-qwen3-tts-voicedesign restart: unless-stopped runtime: nvidia @@ -62,8 +65,8 @@ services: ports: - "8021:8000" volumes: - - /home/sparky/LLMs/vllm/Alibaba/Qwen3-TTS-12Hz-1.7B-VoiceDesign:/models/Qwen3-TTS-VoiceDesign:ro - - /home/sparky/Docker/faster-qwen3-tts/config:/config:rw + - /path/to/Qwen3-TTS-12Hz-1.7B-VoiceDesign:/models/Qwen3-TTS-VoiceDesign:ro + - /path/to/faster-qwen3-tts/config:/config:rw command: > /bin/bash -c " python3 /config/run_voicedesign_server.py @@ -84,7 +87,7 @@ services: # CustomVoice backend: keeps the separate CustomVoice model available on port 8022. faster-qwen3-tts-customvoice: - image: martinb78/faster-qwen3-tts-dgx-spark:v4 + image: martinb78/faster-qwen3-tts-dgx-spark:latest container_name: faster-qwen3-tts-customvoice restart: unless-stopped runtime: nvidia @@ -94,8 +97,8 @@ services: ports: - "8022:8000" volumes: - - /home/sparky/LLMs/vllm/Alibaba/Qwen3-TTS-12Hz-1.7B-CustomVoice:/models/Qwen3-TTS-CustomVoice:ro - - /home/sparky/Docker/faster-qwen3-tts/config:/config:rw + - /path/to/Qwen3-TTS-12Hz-1.7B-CustomVoice:/models/Qwen3-TTS-CustomVoice:ro + - /path/to/faster-qwen3-tts/config:/config:rw command: > /bin/bash -c " python3 /config/run_customvoice_server.py @@ -116,7 +119,7 @@ services: # Streaming voice clone backend: same active voices as 8020, but streams WAV chunks while generating. faster-qwen3-tts-streaming: - image: martinb78/qwen3-tts-streaming-dgx-spark:latest + image: martinb78/faster-qwen3-tts-dgx-spark:streaming container_name: faster-qwen3-tts-streaming restart: unless-stopped runtime: nvidia @@ -131,9 +134,9 @@ services: ports: - "8023:8000" volumes: - - /home/sparky/LLMs/vllm/Alibaba/Qwen3-TTS-12Hz-1.7B-Base:/models/Qwen3-TTS:ro - - /home/sparky/Docker/faster-qwen3-tts/config:/config:rw - - /home/sparky/Projekte/TTS_Voices/active_voices:/voices:ro + - /path/to/Qwen3-TTS-12Hz-1.7B-Base:/models/Qwen3-TTS:ro + - /path/to/faster-qwen3-tts/config:/config:rw + - /path/to/active_voices:/voices:ro command: > /bin/bash -c " python3 /config/generate_voices.py &&