iTTSd — instant Text-To-Speech daemon — is a local, LLM-friendly TTS router written in Go.
It accepts non-blocking HTTP speech requests, queues them so voices never overlap, and plays audio locally through PipeWire. For low latency it can use a streaming Qwen3 backend (faster-qwen3-tts) that starts playback from raw PCM chunks instead of waiting for full WAV generation.
With the optional qwen3-fast-tts backend:
accepted_to_first_chunk_ms: ~116 ms
accepted_to_first_playback_ms: ~116 ms
- Go single-binary daemon:
ittsd - Local HTTP API for LLMs and scripts
- Fire-and-forget
/speakendpoint - FIFO queue: multiple LLM messages do not speak over each other
- Token-level PCM streaming via
faster-qwen3-tts - Fallback external streaming Qwen backend
- PipeWire playback via
pw-play - Systemd user services
- Latency test script
- Tested defaults for Qwen3-TTS CustomVoice:
- model:
custom-0.6b/ fast backendQwen3-TTS-12Hz-0.6B-CustomVoice - voice:
Vivian
- model:
Recommended fast path:
LLM / curl
→ ittsd :8765
→ queued job
→ qwen3-fast-tts :8001 /v1/audio/speech/pcm-stream
→ raw 24 kHz mono s16 PCM
→ pw-play --raw
Base daemon:
- Linux
- Go 1.25+
- PipeWire tools:
pw-play
Qwen backend:
- NVIDIA GPU with CUDA support
- Python 3.12 environment
torchCUDA wheelsfaster-qwen3-ttsqwen3-tts-servercloned separately
This project is Go-only. It intentionally does not vendor or embed the external Python Qwen backend; iTTSd talks to it over HTTP.
git clone https://github.com/MircoBlitz/iTTSd.git ~/dev/ittsd
cd ~/dev/ittsdgo build -o bin/ittsd ./cmd/ittsd./scripts/install-user-service.sh./scripts/setup-qwen3-fast-backend.shThis clones malaiwah/qwen3-tts-server into:
~/dev/qwen3-tts-server-fast
and installs the Python dependencies into its .venv.
systemctl --user start qwen3-fast-tts.service
systemctl --user start ittsd.serviceEnable them at login:
systemctl --user enable qwen3-fast-tts.service ittsd.serviceOptional, if you want user services to run without an active graphical login:
loginctl enable-linger "$USER"curl http://127.0.0.1:8001/health
curl http://127.0.0.1:8765/healthExpected ittsd response:
{"ok": true}curl -s http://127.0.0.1:8765/speak \
-H 'Content-Type: application/json' \
-d '{"text":"Hello from Vivian. This is iTTSd speaking locally.","lang":"en","voice":"Vivian"}'Or:
./scripts/speak.sh "Hello from Vivian. This is iTTSd speaking locally."Run this in a real terminal:
./scripts/latency-test.shPress a key when you hear the first audio. The script prints perceived latency and daemon-side latency metrics.
A ready-to-paste prompt for teaching LLM agents how to use iTTSd is available at:
docs/llm-prompt.md
Queue speech and return immediately.
Request:
{
"text": "Hallo. Hello.",
"lang": "auto",
"voice": "Vivian",
"model": "custom-0.6b",
"tempo": 1.15,
"instruct": "optional style instruction"
}Response:
{"job_id":"abc123","status":"queued"}Returns job state and timings.
Returns current generation/playback state, queue lengths, and known jobs.
Returns the 0.6B preset-only voice list, aliases, and backend model metadata.
Health check.
Tested Qwen 0.6B preset voices:
Serena,Vivian,Aiden,Dylan,Eric,Ryan,Ono_Anna,Sohee,Uncle_Fu- Custom cvoices are intentionally not exposed but possible.
gofmt -w cmd/ittsd/main.go
go build -o bin/ittsd ./cmd/ittsdRestart the service after rebuild:
systemctl --user restart ittsd.serviceEarly prototype, but already useful locally. The API and config flags may still change.
MIT. See LICENSE.