tts-bench
A modern, batteries-included evaluation library for open-source and API-based TTS models.
tts-bench is a passion project that may become useful for anyone who wants to evaluate Text-to-Speech models and compare them with each other. There are a few models available right now by default but the beauty of it is that it is very easy to add your model to the mix. It is by no means a complete project and it is still growing. All the contributions are welcome (Please look into CONTRIBUTING.md for the ways to contribute or even just use the tool and give me a feedback on what you would want to see on it).
pip install tts-bench
Optional Dependencies
Some metrics require packages not available on PyPI and must be installed manually:
| Metric | Package | Install command |
|---|---|---|
utmos |
UTMOSv2 | pip install git+https://github.com/sarulab-speech/UTMOSv2.git |
Why tts-bench?
Evaluating TTS models is surprisingly painful. You either write one-off scripts per model, cobble together separate tools for each metric, or rely on benchmarks that are years out of date. tts-bench is trying to fix that:
- One interface for all models — open-source (Kokoro, XTTS, YourTTS, VITS) and soon to be added API-based (ElevenLabs, OpenAI) share the same evaluation API. You can even add your own very eaily
- Pick your metrics — choose from a growing library of intelligibility, naturalness, speaker, and signal metrics
- Human-readable output — an HTML report with inline audio playback so you can hear the differences, not just read numbers
Quickstart
Evaluate a single model
from tts_bench.benchmark import Benchmark
from tts_bench.report import generate_report
bench = Benchmark(
model_names=["kokoro"],
metric_names=["wer", "utmos"],
output_dir="output",
)
texts = [
"The quick brown fox jumps over the lazy dog.",
"Call 1-800-555-0199 to speak with an agent.",
"Dr. Smith confirmed the diagnosis: type 2 diabetes.",
]
results = bench.run(texts)
generate_report(results, "output")
Compare two models side by side
from tts_bench.benchmark import Benchmark
from tts_bench.report import generate_report
bench = Benchmark(
model_names=["kokoro", "vits"],
metric_names=["wer", "cer", "utmosv2", "speaker_similarity"],
output_dir="output",
)
with open("my_eval_texts.txt") as f:
texts = [line for line in f.read().splitlines() if line.strip()]
results = bench.run(texts)
generate_report(results, "output")
Run from the command line
tts-bench run --models kokoro vits --metrics wer utmosv2 speaker_similarity --input texts.txt --output-dir output
Metrics
tts-bench takes a metrics= argument everywhere. Pass a list of metric keys to run only what you need. Below is the full catalogue, organized by category.
Intelligibility
These metrics measure whether the model actually says what you asked it to say.
| Key | Metric | What it measures | Reference needed? | Status |
|---|---|---|---|---|
wer |
Word Error Rate | Word-level transcription accuracy via Whisper ASR | No | ✅ |
cer |
Character Error Rate | Character-level transcription accuracy via Whisper ASR | No | ✅ |
ttscore_int |
TTScore-Int | Reference-free intelligibility via discrete speech token prediction | No | 🔜 |
Naturalness & Perceived Quality
These metrics estimate how natural and pleasant the speech sounds, without needing human listeners.
| Key | Metric | What it measures | Reference needed? | Status |
|---|---|---|---|---|
utmosv2 |
UTMOSv2 | Improved MOS predictor, stronger on modern systems | No | ✅ |
dnsmos |
DNSMOS | Microsoft's non-intrusive MOS predictor | No | ✅ |
nisqa |
NISQA-MOS | Non-intrusive speech quality assessment | No | 🔜 |
squim_mos |
SQUIM-MOS | Torchaudio's MOS predictor, grounded by non-matching reference | Optional | 🔜 |
ttsds2 |
TTSDS2 | Distributional quality score across prosody, speaker, and intelligibility — strongest correlation with human MOS of any automatic metric | No | 🔜 |
Prosody
These metrics measure the expressiveness, rhythm, and pitch characteristics of the output.
| Key | Metric | What it measures | Reference needed? | Status |
|---|---|---|---|---|
pitch_rmse |
F0 RMSE | Pitch contour error vs. reference speech | Yes | 🔜 |
duration_error |
Duration Prediction Error | Phoneme/word duration accuracy vs. reference | Yes | 🔜 |
prosody_diversity |
Prosody Diversity Score | Whether the model produces varied prosody across different inputs (not flat/robotic) | No | 🔜 |
ttscore_pro |
TTScore-Pro | Reference-free prosody evaluation via pitch token prediction | No | 🔜 |
speechbertscore |
SpeechBERTScore | Reference-aware evaluation leveraging NLP-style embedding comparison | Yes | 🔜 |
Speaker & Voice
These metrics are most relevant for voice cloning and zero-shot TTS scenarios.
| Key | Metric | What it measures | Reference needed? | Status |
|---|---|---|---|---|
speaker_similarity |
Speaker Similarity (ECAPA-TDNN) | Cosine similarity between output and reference speaker embeddings | Yes | ✅ |
speaker_sim_xvec |
Speaker Similarity (x-vector) | x-vector based speaker similarity | Yes | 🔜 |
speaker_sim_rawnet |
Speaker Similarity (RawNet3) | RawNet3-based speaker similarity | Yes | 🔜 |
Signal Quality
These are classical signal-level metrics, useful for reference-based comparisons or when ground truth audio is available.
| Key | Metric | What it measures | Reference needed? | Status |
|---|---|---|---|---|
mcd |
Mel-Cepstral Distortion | Spectral distance between synthetic and reference audio | Yes | 🔜 |
pesq |
PESQ | Perceptual evaluation of speech quality, widely used in telecom | Yes | 🔜 |
stoi |
STOI | Short-time objective intelligibility (0–100%) | Yes | 🔜 |
estoi |
ESTOI | Extended STOI, better for low-intelligibility conditions | Yes | 🔜 |
Robustness (Stress Testing)
| Key | Metric | What it measures | Reference needed? | Status |
|---|---|---|---|---|
stress_pass_rate |
Stress Pass Rate | Aggregate pass rate across the built-in stress suite | No | ✅ |
Stress-Test Suite
The built-in stress-test suite is a curated set of inputs that commonly break TTS models in practice. You can use it as-is, extend it, or bring your own.
| Suite name | Category | Status |
|---|---|---|
stress_test |
Full stress test | ✅ |
stress_light |
Lightweight stress test | ✅ |
stress_numbers |
Numbers & currency | 🔜 |
stress_abbreviations |
Abbreviations & acronyms | 🔜 |
stress_foreign |
Foreign words & names | 🔜 |
stress_punctuation |
Heavy punctuation | 🔜 |
stress_long |
Long-form text | 🔜 |
stress_repetition |
Repeated phrases | 🔜 |
stress_homophones |
Homophones & ambiguous spelling | 🔜 |
from tts_bench.benchmark import Benchmark
from tts_bench.report import generate_report
from tts_bench.suites import load_suite
# Use the built-in suite
texts = load_suite("stress_test")
# Or provide your own text file via --input on the CLI,
# or read it manually:
with open("my_suite.txt") as f:
texts = [line for line in f.read().splitlines() if line.strip()]
bench = Benchmark(model_names=["kokoro"], metric_names=["wer", "utmosv2"], output_dir="output")
results = bench.run(texts)
generate_report(results, "output")
Custom Models
You can benchmark any TTS model — not just the built-in ones — by subclassing BaseTTSModel and passing your class directly to evaluate or compare.
How a custom model file should look
# my_model.py
import numpy as np
from tts_bench.models import BaseTTSModel
class MyCustomModel(BaseTTSModel):
sample_rate = 22050 # output sample rate in Hz
def __init__(self, **kwargs):
super().__init__()
# load your model weights / initialize your API client here
def synthesize(self, text: str, **kwargs) -> tuple[np.ndarray, int]:
"""
Must return a tuple of (audio_samples, sample_rate).
audio_samples — 1-D float32 numpy array of PCM audio.
sample_rate — integer sample rate in Hz.
"""
# replace with your actual synthesis call
samples = np.zeros(self.sample_rate * 1, dtype=np.float32)
return samples, self.sample_rate
Rules:
- Subclass
tts_bench.models.BaseTTSModel. - Set the
sample_rateclass attribute to match your model's output. - Implement
synthesize(text, **kwargs)and return(np.ndarray, int). - Optionally override
load_to_device()/unload_from_device()if your model uses PyTorch and you want automatic GPU memory management during multi-model runs.
Usage
from tts_bench.benchmark import Benchmark
from tts_bench.report import generate_report
# Evaluate a single custom model
bench = Benchmark(
model_names=["MyCustomModel"],
metric_names=["wer", "utmosv2"],
output_dir="output",
custom_model_paths=["my_model.py::MyCustomModel"],
)
results = bench.run([
"The quick brown fox jumps over the lazy dog.",
"She has a PhD from MIT.",
])
generate_report(results, "output")
# Compare a custom model against a built-in one
bench = Benchmark(
model_names=["MyCustomModel", "kokoro"],
metric_names=["wer", "cer", "utmosv2", "speaker_similarity"],
output_dir="output",
custom_model_paths=["my_model.py::MyCustomModel"],
)
with open("eval_texts.txt") as f:
texts = [line for line in f.read().splitlines() if line.strip()]
results = bench.run(texts)
generate_report(results, "output")
You can also use a custom model from the CLI with --custom-model <file>::<ClassName>:
tts-bench run \
--custom-model my_model.py::SilentModel \
--models SilentModel \
--metrics wer utmos \
--suit stress_test \
--output-dir output
--custom-model registers the class from the given file, and --models then refers to it by class name alongside any built-in model keys.
Supported Models
System requirement:
espeak-ngmust be installed before using any local model.
- Ubuntu/Debian:
sudo apt-get install espeak-ng- macOS:
brew install espeak-ng- Windows:
winget install espeak-ng
Open-Source (local inference)
| Model | Key | Character | Status |
|---|---|---|---|
| Kokoro-82M | kokoro |
Lightweight, modern, Apache 2.0 | ✅ Supported |
| XTTS v2 | xtts |
Multilingual (17 langs), voice cloning | ✅ Supported |
| YourTTS | yourtts |
Zero-shot voice cloning from 3s clip | ✅ Supported |
| VITS (VCTK) | vits |
Deterministic, 109 English speakers | ✅ Supported |
| Parler TTS | parler |
Prompted style control | 🔜 Coming soon |
| StyleTTS2 | styletts2 |
High naturalness, style transfer | 🔜 Coming soon |
| FishAudio | fish |
Realistic voice cloning | 🔜 Coming soon |
| CosyVoice | cosyvoice |
Multilingual, instruction-following TTS | 🔜 Coming soon |
| IndexTTS | indextts |
High-fidelity zero-shot voice cloning | 🔜 Coming soon |
XTTS, YourTTS, and VITS are all available via the coqui-tts package. Kokoro uses the kokoro package.
API-based
| Provider | Key | Status |
|---|---|---|
| ElevenLabs | elevenlabs |
🔜 Coming soon |
| OpenAI TTS | openai |
🔜 Coming soon |
| Cartesia | cartesia |
🔜 Coming soon |
| Gemini TTS | gemini |
🔜 Coming soon |
Want a model added? Open an issue.
Installation
Requires Python 3.11+.
pip install tts-bench
or
git clone https://github.com/amhajavi/tts-bench.git
cd tts-bench
uv sync
Contributing
Contributions are very welcome — especially new model adapters, metrics, and stress-test inputs.
See CONTRIBUTING.md for guidelines.
Roadmap
- ElevenLabs, Gemini, Cartesia, and OpenAI TTS adapters
- Hallucination detection metric (repeated/dropped words)
- Automated app builder for subjective scoring
- Multilingual stress-test suite
- ...
License
MIT
Metadata
Release files for tts-bench 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tts_bench-0.1.1.tar.gz | 304.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tts_bench-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 332.3 kB
Release files / tts_bench-0.1.1.tar.gz
| Download URL | tts_bench-0.1.1.tar.gz |
|---|---|
| Size | 304.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d4f5d8f0884a2f9501574954e38d9b9b6cec77699cbedfb6d6e047b7831153ff
|
|
BLAKE2b-256 checksum How to use checksums |
c362caf2f5435d116fd2871a5a6b3726c80e910c21768cfecb4cefd9f5c9cbc5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / tts_bench-0.1.1-py3-none-any.whl
| Download URL | tts_bench-0.1.1-py3-none-any.whl |
|---|---|
| Size | 27.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c5463ffa0d62bd5a157c04c6b19e005767cce473f6955ff0e02f735acb29335e
|
|
BLAKE2b-256 checksum How to use checksums |
501a9c813bebbee1210304ab6bf6ba977b62725714513355399e1251e634f5a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|