Qwen3-TTS VoiceDesign · native Rust + CUDA · DGX Spark

First audio in
94 milliseconds.

Text plus a sentence describing a voice, and the first PCM frame is on the wire before the stock stack has finished thinking. The whole path — the 1.7B talker, its 15-step code predictor, the neural decoder, the scheduler, the HTTP server — is Rust and CUDA. No Python, no PyTorch, no SGLang in the runtime or the image.

$ export QWEN3_TTS_IMAGE=…@sha256:<digest>
$ docker run --gpus device=0 --read-only \
    -p 127.0.0.1:8080:8080 "$QWEN3_TTS_IMAGE"
Time to first audio
94 ms
p95 · stock takes 2.69 s
Peak GPU memory
5.68 GB
stock peaks at 108.90 GB
Languages
10
plus auto-detect
Endurance
200/200
all at natural EOS
Where stock wins
0.50 vs 0.80
aggregate RTF, lower is better

Stock SGLang has better aggregate throughput than this runtime in every profile measured, and it is not close. It gets there by buffering to completion — you hear nothing until all of it exists. That is the trade: 28× sooner to the first frame and 19× less memory, paid for in tokens per second. If you are batching offline, use SGLang.

One DGX Spark, two alternating-order rounds of profiles B1/B3/B6, 2,600 measured requests, 24 warm-ups per cell, no competing CUDA process. Every number here is from that study or from checked JSON evidence in the repo — the paper has the methodology and the limitations.

One paste

Let your agent set it up

You were going to paste it into Claude anyway. The runbook checks you actually have a Spark, makes it resolve the digest from the release instead of grabbing a tag, waits out the warm-up and proves the thing speaks before it says it is done.

Paste into your agent
Set me up with qwen3-tts-native — Qwen3-TTS VoiceDesign serving in native Rust
and CUDA on a DGX Spark. Run this first, then follow it exactly, top to bottom:

    curl -fsSL https://qwen.lukaloehr.com/setup.txt

Ask me its first question before doing anything else. Pin the image by digest,
never by tag, and never print my tokens.
Get started

Two commands

Ah, so you haven’t fallen for the vibe yet. Respect. I still read commands before I run them too.

01

Run it by digest

Needs a DGX Spark (GB10, sm_121, linux/arm64) with Docker and the NVIDIA runtime. The image carries the pinned weights, so there is nothing to download afterwards. Copy the full reference from the current release: a mutable tag, a branch or latest is not a deployment identity, and the runbook refuses one.

# from the release notes, not a tag
$ export QWEN3_TTS_IMAGE=ghcr.io/luka-loehr/
      qwen3-tts-native@sha256:<digest>

$ docker run --rm --gpus device=0 --read-only \
    --cap-drop=ALL -p 127.0.0.1:8080:8080 \
    "$QWEN3_TTS_IMAGE"

Wait for /health/ready. That gate is the model and the full pipeline, not the process — it only opens after a real frame has been pushed through. Cold start is around ten seconds.

02

Describe a voice, get speech

There is no voice name to look up and no sample to upload. You write a sentence about how it should sound, and that is the conditioning. Leave stream out and you get progressive PCM; set it to false for a buffered WAV.

$ curl -X POST localhost:8080/v1/voice-design/speech \
    -H 'Content-Type: application/json' \
    -d '{"text":"Good morning.",
        "voice_description":"A calm adult male voice.",
        "language":"english","stream":false}' \
    -o speech.wav

Streaming responses are multipart/mixed — parse the boundaries, because HTTP DATA frames are not audio packet boundaries. The server does not terminate TLS or authenticate anyone; put it behind a proxy and read SECURITY.md before exposing it.

Scope

VoiceDesign only, on purpose

No voice cloning, no reference audio, no speaker enrollment, no Base or CustomVoice checkpoint, no speech tokenizer. You cannot hand it a recording of someone and get their voice back, and that is a decision rather than a missing feature.

Ten languages are exposed explicitly — Chinese, English, Japanese, Korean, German, French, Russian, Portuguese, Spanish, Italian — plus auto. Anything outside that list is rejected at the boundary. Turkish has no language ID in the pinned checkpoint, so it is not advertised.

Reference

Measured on one Spark

Serving

B1 · nativeTTFA p95 94–96 ms · RTF 0.80
B1 · stock SGLangTTFA p95 2.69–2.70 s · RTF 0.50
B3 · nativeTTFA p95 216 ms · RTF 0.64
B6 · nativeTTFA p95 406 ms · RTF 0.62
Endurance, 200 runsTTFA p95 76.95 ms · RTF 0.734
Ten languages, 24 runsTTFA p95 78.47 ms · RTF 0.751
Audio out24 kHz mono S16LE · 80 ms frames

Runtime

RuntimeRust 1.97 + CUDA 13.0 · no Python
TargetDGX Spark GB10 · sm_121 · arm64
Talker1.7B VoiceDesign + 15-step predictor
Decoderincremental neural speech decoder
Deliverymultipart/mixed progressive PCM
Readinessone real frame warmed before bind

HTTP API

POST /v1/voice-design/speechprogressive PCM, or buffered WAV
GET /v1/capabilitieslanguages, formats, limits
GET /health/readyengine loaded and fully warmed
DELETE /v1/requests/{id}bounded cancellation
GET /metricsprompt-free Prometheus counters
Port8080