A collection of shell scripts and Gradio UIs for experimenting with qwentts.cpp — a C++ text-to-speech engine powered by the Qwen-Talker model.
Other UIs: Voice Design (TTS) · Custom Voice · Codec · Clone · Chunk Clone
- A local build of qwentts.cpp — tested against
95b4840 - Python 3 virtual environment (
venv/) withgradio>=4.0.0andpython-dotenv ffmpeg(required bychunk-clone.shfor concatenating chunks)- (optional)
google-perftools(libtcmalloc) preloaded by launch scripts for allocation performance
Copy .env.example to .env and edit it:
cp .env.example .envAt minimum, set QWENTTS_PATH to your qwentts.cpp build directory. All other values are sensible defaults.
Launch any Gradio UI with its corresponding launch-*.sh:
| Mode | Launch Script | UI Module | Port |
|---|---|---|---|
| Base | ./launch-base.sh |
ui-base.py |
7861 |
| Voice Design (TTS) | ./launch-tts.sh |
ui-tts.py |
7862 |
| Custom Voice | ./launch-customvoice.sh |
ui-customvoice.py |
7863 |
| Codec (Embeddings) | ./launch-codec.sh |
ui-codec.py |
7864 |
| Clone | ./launch-clone.sh |
ui-clone.py |
7860 |
| Chunk Clone | ./launch-chunk-clone.sh |
ui-chunk-clone.py |
7860 |
Then open http://127.0.0.1:<port> in your browser.
These scripts invoke the qwentts.cpp binaries directly. Model paths and inference flags are read from .env (see Configuration).
| Script | .env Model Var |
What It Does |
|---|---|---|
base.sh |
QWENTTS_BASE_MODEL |
Plain TTS — synthesize text with no voice reference or instruction. Usage: base.sh [prompt.txt] [language] |
tts.sh |
QWENTTS_VOICEDSIGN_MODEL |
Voice Design — describe the desired voice with an instruction string (e.g. "male, warm tone, moderate pace"). Usage: tts.sh [prompt.txt] [language] [instruct] |
customvoice.sh |
QWENTTS_CUSTOMVOICE_MODEL |
Named Speaker — pick from built-in voices (vivian, ryan, serena, etc.). Usage: customvoice.sh [prompt.txt] [language] [speaker] |
clone.sh |
QWENTTS_BASE_MODEL |
Voice Cloning — clone a voice from a reference WAV + transcript text, or from pre-encoded .spk/.rvq embeddings. Usage: clone.sh [ref.wav] [ref.txt] [prompt.txt] [language] |
chunk-clone.sh |
QWENTTS_BASE_MODEL |
Chunked Voice Cloning — splits a long prompt into sentence-bounded chunks, synthesizes each with cloning, then concatenates via ffmpeg. Requires embeddings/<voice>.spk, .rvq, and .txt (transcript). Usage: chunk-clone.sh [voice] [prompt.txt] [language] |
| Script | What It Does |
|---|---|
codec.sh |
Extracts speaker embeddings (.spk) and RVQ codes (.rvq) from a reference WAV, or encodes/decodes .rvq files. Outputs go to embeddings/. Mode controlled by QWENTTS_CODEC_MODE (extract, encode, decode). ~20 seconds of clean speech is enough for a good clone. Usage: codec.sh [input.wav] [output_dir] [speaker_name] |
| Script | What It Does |
|---|---|
server.sh |
Starts the tts-server HTTP API on 127.0.0.1:8000. Uses the customvoice model with auto-detect language. |
Each launch-*.sh sets up the environment (terminal title, LD_PRELOAD for tcmalloc) and runs the corresponding Python UI inside the virtual environment.
All UIs are built with Gradio and act as frontends to their matching shell scripts. They share a common set of advanced options:
- Seed — reproducibility control (-1 = random)
- Temperature / Top-k / Top-p — sampling parameters
- Repetition Penalty — discourages repeated tokens
- Sub-quantizer Temp — codec sub-quantizer temperature
- Output Format — wav16, wav24, or wav32
- Max New Tokens — generation length limit
- Stream by Line — incremental streaming
- Disable Flash Attention / Clamp FP16 — performance toggles
| Module | Backed By | Key Feature |
|---|---|---|
ui-base.py |
base.sh |
Minimal TTS — text + language only |
ui-tts.py |
tts.sh |
Voice design via natural-language instruction |
ui-customvoice.py |
customvoice.sh |
Dropdown to select from built-in named speakers |
ui-codec.py |
codec.sh |
Upload WAV → extract .spk + .rvq embeddings; lists saved embeddings (~20 s of audio is sufficient) |
ui-clone.py |
clone.sh |
Two tabs: (1) upload reference WAV + transcript, (2) pick a pre-encoded voice from embeddings/ |
ui-chunk-clone.py |
chunk-clone.sh |
Upload a long prompt file and reference transcript; the script splits the prompt, synthesizes per chunk with voice cloning, and concatenates the result |
├── .env # local config (git-ignored) — copy from .env.example
├── .env.example # template with defaults and documentation
├── *.sh # shell scripts (drivers + launchers)
├── ui-*.py # Gradio UI modules
├── launch-*.sh # environment setup + UI launchers
├── embeddings/ # stored .spk, .rvq, .txt (transcript), .wav voice profiles (~20 s audio sufficient)
├── outputs/ # chunked synthesis results
├── voices/ # reference voice samples
├── prompts/ # prompt text files
├── venv/ # Python virtual environment
└── requirements.txt # gradio>=4.0.0, python-dotenv
All shared settings live in .env (git-ignored). A template is tracked as .env.example.
| Section | Variables | Purpose |
|---|---|---|
| Paths | QWENTTS_PATH |
Root of your qwentts.cpp build — scripts resolve binaries and models under this path. |
| Model Filenames | QWENTTS_BASE_MODEL, QWENTTS_VOICEDSIGN_MODEL, QWENTTS_CUSTOMVOICE_MODEL, QWENTTS_CODEC_MODEL, QWENTTS_TALKER_MODEL |
Model files resolved as $QWENTTS_PATH/models/$VAR. Change these to swap quantizations (e.g. BF16 → Q4_K_M) without touching any script. |
| Defaults | LANG, SPEAKER, INSTRUCT |
Fallback values for language, named speaker, and voice-design instruction. Override per-invocation via CLI args. Note: LANG must be a recognized language name (e.g. French, English) not a locale like fr_FR.UTF-8. |
| Inference Flags | QWENTTS_SEED, QWENTTS_TEMP, QWENTTS_TOP_K, QWENTTS_TOP_P, QWENTTS_REP_PEN, QWENTTS_SUB_TEMP, QWENTTS_FORMAT, QWENTTS_MAX_NEW |
Shared defaults for all TTS scripts. Override per-command with QWENTTS_TEMP=0.5 ./tts.sh … or from the Gradio UI advanced options. |
| Optional Flags | QWENTTS_GREEDY, QWENTTS_STREAM, QWENTTS_NO_FA, QWENTTS_CLAMP_FP16 |
Leave empty to disable, set to any value to enable. |
| Codec | QWENTTS_CODEC_MODE |
Default mode for codec.sh: extract, encode, or decode. |
A plain env file was chosen over JSON/YAML because shell scripts already use ${VAR:-default} syntax, and per-command overrides (QWENTTS_TEMP=0.5 ./tts.sh) work naturally. Python UIs load it via python-dotenv.
