OmniVoiceTTS Benchmarks
This directory contains the manual release-engineering benchmarks used to detect performance, memory, speech, and dialogue regressions. They are not unit tests and do not run as part of task test, task validate, task build, or task release.
Benchmark results are comparative. A result is meaningful only when the image or revision, model assets, hardware, driver, runtime settings, workload, and background load are recorded and held constant. Start with the benchmark result index, then use each suite’s DETAILS.md and runs.json for the complete evidence.
Benchmark Suites
| Suite | Official task | Canonical workload | Primary signal |
|---|---|---|---|
| Inference speed | task benchmark-speed |
Three 100-call rounds across all 20 manifest languages | Warmed latency for random, cached-profile, and direct-reference generation |
| CPU memory | task benchmark-memory-cpu |
Six voice modes in fresh memory-constrained CPU containers | Lowest passing container limit and conservative RAM recommendation |
| GPU memory | task benchmark-memory-gpu |
Four voice modes, each warmed independently | PyTorch allocation and whole-device VRAM peaks |
| Speech quality | task benchmark-speech-quality |
Two sentences per judge-supported language, repeated five times | Comparative transcript similarity, repeat consistency, timing, and diagnostics |
| SSML-H reliability | task benchmark-ssml |
One fixed two-speaker dialogue across 20 deterministic seeds | Complete dialogue and final-turn retention |
Canonical Samples
examples/assets/manifest.json is the canonical multilingual text source. Selection is deterministic and follows manifest order; benchmark runners never choose samples randomly.
- The speed suite selects the first two
randomentries for every manifest language and repeats that ordered set until each measured category contains 100 calls. - The speech-quality suite uses the first
cloneentry in each selected language for warm-up, then generates the first tworandomentries five times each with one fixed seed per sentence. - Speech-quality includes only languages accepted by the locked Qwen3-ASR judge. The current canonical workload is 18 languages and 180 measured calls. This filter does not describe OmniVoiceTTS language support.
- Clone and reference scenarios use
examples/original_clone.mp3through its packaged runtime copy at/app/omnivoice/runtime_assets/voices/openai_default_voice.mp3. - The fixed reference transcript is
Hello from OmniVoice. This Docker image includes a browser UI and an HTTP API.
Memory suites use a stable, realistic two-sentence request instead of the multilingual manifest:
This CPU memory benchmark uses a realistic two-sentence request to estimate the RAM needed for local text to speech with common voice modes.
This GPU memory benchmark uses a realistic two-sentence request to measure warmed inference for the voice modes commonly used through the OmniVoiceTTS API.
Both texts remain fixed so memory measurements can be compared between revisions.
Methodology
Warm-up and determinism
Every voice path is warmed independently before its measured calls. Warm-up work is excluded from steady-state measurements and reported separately where useful. Seeds, decoding steps, output format, sample order, and reference audio are fixed by each runner unless an operator explicitly overrides them.
The speed workload uses 24 decoding steps and MP3 output. It performs 10 warm-up calls for each of its three categories before measuring 100 calls per category:
random_voice: no voice prompt or design prompt.predefined_voice: the namedbenchmark_original_clonesaved profile, whose prompt is cached during warm-up.direct_reference_audio: the same reference path is supplied on every request without storing its prompt in the profile cache.
Before the speed suite, create the saved profile benchmark_original_clone in the Voices tab using examples/original_clone.mp3 and the fixed reference transcript above (seed 12345, random seed disabled). The runner checks that this exact profile exists and has a transcript before measuring anything; a missing profile must not silently turn the cached-voice category into voice design. Set SPEED_BENCHMARK_VOICE when intentionally using another prepared profile and record that changed workload in the run comment.
CPU memory
Each CPU scenario runs in a fresh Docker container with equal memory and swap limits. Limits start at 1536 MiB and increase through a fixed practical sequence up to 12 GiB; sub-gigabyte configurations are intentionally not tested. The six paths are random voice, designed voice, direct clone with and without a transcript, and stored voice with and without a transcript.
The reported recommendation adds 512 MiB to the first passing limit and rounds up to a whole GiB. This is operational headroom, not a claim that every host and request length will fit within that amount.
GPU memory
Random voice, designed voice, direct clone, and cached clone are each warmed once and measured for five calls by default. Before a scenario, the runner clears unused CUDA allocator blocks and resets peak counters without unloading the model. It records both PyTorch allocated/reserved memory and nvidia-smi whole-device VRAM.
Qwen3-ASR and unrelated GPU workloads must be stopped for this suite. Whole-device VRAM includes the desktop and every other process, so the dedicated GPU-memory suite is authoritative for clean TTS comparisons.
For a clean-process comparison, restart the TTS container before this suite if previous requests loaded ASR or exercised other models. Preserve the data volume. Clearing allocator blocks or purging/reloading model references is not equivalent to restarting the process; record baseline live allocation as well as peaks. Do not silently mix post-ASR and fresh-process measurements.
Speech quality
The quality runner generates and stages every WAV before transcription begins. Qwen3-ASR is warmed only after the TTS phase, then transcribes the staged files. TTS generation and ASR judging are never interleaved on the shared GPU.
The runner uses 32 decoding steps and fixed per-sentence seeds. Transcript comparison applies Unicode compatibility normalization, case folding, and removal of punctuation and whitespace before calculating exact matches and character similarity. It records repeat consistency, generation time, real-time factor, ASR time, memory diagnostics, and hashes. Non-exact or failed audio is retained under the git-ignored .ai/benchmark-speech-quality directory for listening.
The judge may run on a separate host through the QUALITY_BENCHMARK_ASR_URL task variable (and SSML_BENCHMARK_ASR_URL for dialogue tests). Keep the two phases separate even then. Record the judge deployment/model identity and endpoint in run evidence; a matching public model name alone does not prove identical judge software, weights, or decoding settings. With remote ASR, all local GPU snapshots describe TTS plus desktop consumers, not the remote judge’s VRAM. Do not interpret the ASR-phase baseline/endpoint labels as measurements of remote ASR memory or compare local and remote ASR latency as TTS performance.
Qwen3-ASR is a stable comparative judge, not ground truth. Its transcript can be wrong even when the generated audio is correct. These metrics are intended to reveal changes between equivalent runs; they do not measure objective pronunciation accuracy or replace human listening.
SSML-H reliability
The SSML-H suite generates the fixed Bob and Elisabeth dialogue Are we ready? Yes, all preparations are complete. with 32 decoding steps. It uses 20 fixed seeds; 2717518076 remains first because it reproduced the original missing-final-turn failure. All WAVs are generated before Qwen3-ASR is warmed and transcription begins.
A call passes when its normalized word sequence contains the complete expected dialogue. This suite targets missing turns and truncated final speech, not subjective voice quality.
Controlled Baseline Procedure
- Record the image tag or digest, repository revision, driver, runtime settings, hardware, and intended change in each task’s comment variable.
- Stop unrelated GPU work. Start only OmniVoiceTTS and run
task benchmark-memory-gpu. - Keep that TTS deployment running and run
task benchmark-speed. - Use a fixed remote Qwen3-ASR deployment or start the local judge on port
8000, then runtask benchmark-speech-qualityandtask benchmark-ssml. Override the task’s ASR URL for a remote judge. - Run
task benchmark-memory-cpuseparately. It creates and removes its own constrained CPU containers and takes substantially longer. - Review the generated
BENCHMARKS.md,DETAILS.md, andruns.jsonchanges before committing an official baseline.
Smoke tasks validate harness wiring without appending benchmark history:
task benchmark-speed-smoke
task benchmark-memory-gpu-smoke
task benchmark-speech-quality-smoke
task benchmark-ssml-smoke
Use task benchmark-memory-cpu-smoke only when Docker is available and the additional CPU runtime is acceptable.
Result Files
Each suite follows the same evidence layout:
BENCHMARKS.mdcontains the concise, append-only comparison table.DETAILS.mdcontains methodology notes and human-readable evidence for each run.runs.jsoncontains the structured per-run and per-call measurements.- Local diagnostic audio and temporary artifacts live under
.aiand are not committed.
Do not compare rows collected with different hardware, model assets, decoding parameters, container limits, judge versions, or concurrent workloads. When any of those inputs change, record a new baseline before evaluating later regressions.