Skip to content

Latest commit

 

History

History
229 lines (153 loc) · 4.28 KB

File metadata and controls

229 lines (153 loc) · 4.28 KB

iTTSd

iTTSdinstant 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.

Current performance on the author's RTX 4070 Ti

With the optional qwen3-fast-tts backend:

accepted_to_first_chunk_ms:    ~116 ms
accepted_to_first_playback_ms: ~116 ms

Features

  • Go single-binary daemon: ittsd
  • Local HTTP API for LLMs and scripts
  • Fire-and-forget /speak endpoint
  • 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 backend Qwen3-TTS-12Hz-0.6B-CustomVoice
    • voice: Vivian

Architecture

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

Requirements

Base daemon:

  • Linux
  • Go 1.25+
  • PipeWire tools: pw-play

Qwen backend:

  • NVIDIA GPU with CUDA support
  • Python 3.12 environment
  • torch CUDA wheels
  • faster-qwen3-tts
  • qwen3-tts-server cloned separately

This project is Go-only. It intentionally does not vendor or embed the external Python Qwen backend; iTTSd talks to it over HTTP.

Install quickstart

1. Clone this repo

git clone https://github.com/MircoBlitz/iTTSd.git ~/dev/ittsd
cd ~/dev/ittsd

2. Build

go build -o bin/ittsd ./cmd/ittsd

3. Install user services

./scripts/install-user-service.sh

4. Install the fast Qwen backend

./scripts/setup-qwen3-fast-backend.sh

This clones malaiwah/qwen3-tts-server into:

~/dev/qwen3-tts-server-fast

and installs the Python dependencies into its .venv.

5. Start services

systemctl --user start qwen3-fast-tts.service
systemctl --user start ittsd.service

Enable them at login:

systemctl --user enable qwen3-fast-tts.service ittsd.service

Optional, if you want user services to run without an active graphical login:

loginctl enable-linger "$USER"

Verify

curl http://127.0.0.1:8001/health
curl http://127.0.0.1:8765/health

Expected ittsd response:

{"ok": true}

Speak

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."

Latency test

Run this in a real terminal:

./scripts/latency-test.sh

Press a key when you hear the first audio. The script prints perceived latency and daemon-side latency metrics.

LLM prompt

A ready-to-paste prompt for teaching LLM agents how to use iTTSd is available at:

docs/llm-prompt.md

HTTP API

POST /speak

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"}

GET /job/{id}

Returns job state and timings.

GET /status

Returns current generation/playback state, queue lengths, and known jobs.

GET /voices

Returns the 0.6B preset-only voice list, aliases, and backend model metadata.

GET /health

Health check.

Voice notes

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.

Development

gofmt -w cmd/ittsd/main.go
go build -o bin/ittsd ./cmd/ittsd

Restart the service after rebuild:

systemctl --user restart ittsd.service

Project status

Early prototype, but already useful locally. The API and config flags may still change.

License

MIT. See LICENSE.