Skip to content
Bruce's Service
Go back

Stripping XTTS Down to Size: A Single-File Fork of Coqui TTS

Coqui TTS is the reference implementation for XTTS voice cloning, and it’s excellent — if you’re training models. But if all you want is inference — clone a voice, synthesize some text, get a WAV file — you inherit a training framework you’ll never touch: trainer, coqpit, gruut, jamo, g2pkk, bnnumerizer, umap-learn, matplotlib. Over a dozen packages exist purely to support model training and multi-language G2P pipelines that most inference use cases don’t need.

TTS-Clone-Inference is what’s left when you strip that away: the XTTS model and nothing else.

One model, one file

In upstream Coqui TTS, the XTTS model is assembled from half a dozen files spread across the package: TTS/tts/layers/xtts/gpt.py, hifigan_decoder.py, tokenizer.py, stream_generator.py, xtts_manager.py, plus a BaseTTS base class and a Coqpit config system shared across every model type in the framework.

This fork collapses all of it — GPT-2 autoregressive core, HiFi-GAN vocoder, ResNet speaker encoder, BPE tokenizer, Perceiver resampler, and config classes — into two files: xtts.py and utils.py. No Coqpit, no trainer, no dependency on the wider TTS package at all. The model is fully self-contained and portable.

A CLI built for one job

Coqui’s Synthesizer class is a general-purpose dispatcher — it has to handle Tacotron, VITS, Bark, XTTS, vocoder chaining, speaker managers, language managers, and ONNX export, because it serves every model the framework supports.

This fork’s Synthesizer does exactly one thing: run XTTS. The CLI reflects that directness:

python tts_clone_inference/main.py --text "你好世界" --speaker speaker.wav --language zh --output out.wav

No config sprawl, no model-type flags — just text, a reference voice, and an output path.

A feature Coqui doesn’t have: duration matching

Dubbing and voiceover work often needs generated speech to land within a fixed time window — matching a video clip length, a slide timer, a dialogue slot. Coqui TTS has no built-in way to do this.

This fork adds it directly to the CLI:

python tts_clone_inference/main.py --text "..." --speaker speaker.wav --duration 15.0 --output out.wav

Set the target seconds. The tool synthesizes, measures the actual output length, then applies librosa.effects.time_stretch at the exact ratio needed to hit it — or pass --ratio directly if you already know the speed factor you want. It’s a small addition, but it’s the difference between “generates audio” and “generates audio that fits.”

Why this matters

None of this changes what XTTS sounds like — the model weights and architecture are untouched. What changes is what it costs to run it:

  • Fewer dependencies. No gruut, no language toolchains for languages you’re not using, no training-only packages. uv-managed with a full lockfile for reproducible installs.
  • Auditable in one sitting. Two files instead of a scattered package — you can actually read the whole inference path.
  • Built for the actual use case. A CLI for cloning and synthesizing, not a framework surface for training experiments.

If your use case is “point at a reference voice, get audio out” — not “train new TTS models” — this is what that tool looks like once the framework weight is gone.

Repo: github.com/bruceunx/TTS-Clone-Inference