Skip to main content

Automated failure-mode QA for text-to-speech systems: structural audio checks, equivalence-aware WER/CER, and ASR-uncertainty quarantine.

Project description

TTSProof

Automated failure-mode QA for text-to-speech systems.

Your TTS pipeline can produce a clip that is empty, half-silent, clipped, stuck in a loop, or three times longer than it should be — and a WER score alone will miss most of it, while plain WER also fails perfectly good audio because the input said 3:30 PM and the transcript said three thirty pee em.

TTSProof runs the checks that catch what actually breaks:

  • Structural audio checks (no model needed): empty/truncated audio, duration explosions, long internal silences, clipping, repeated-chunk loop detection, end-of-clip artifacts. Just numpy + soundfile.
  • Equivalence-aware WER/CER: expected text and ASR transcript are both canonicalized to spoken form (numbers, decimals, dates, clock times, acronyms, single letters) before scoring — so formatting differences don't count as pronunciation errors.
  • ASR-uncertainty quarantine: when audio is structurally clean but ASR disagrees on a very short utterance (a letter, an acronym, "ahh"), the sample is quarantined for human review instead of counted as a failure — because at that length, the ASR is as likely to be wrong as the TTS.

The method was evaluated on a production TTS service — 130 edge cases × 3 voices (390 samples), with a blinded human validation of the quarantine zone — and published as a citable technical report:

An Automated Failure-Mode QA Framework for Neural Text-to-Speech Systems DOI: 10.5281/zenodo.20757553 (CC-BY-4.0)

Install

pip install ttsproof            # structural checks + metrics
pip install "ttsproof[asr]"     # + faster-whisper for pronunciation gating

Quickstart

Check one file (CLI):

ttsproof check output.wav --text "Hello there"

QA a folder of generated audio against a manifest:

# cases.jsonl — one case per line:
# {"id": "case_001", "text": "Meet me at 3:30 PM", "wav": "case_001.wav"}
ttsproof run --manifest cases.jsonl --wav-dir ./audio --out ./reports --asr

You get report.csv + report.json with one verdict per sample: pass / hard_fail / quarantine.

Gate any TTS system in CI (Python):

import ttsproof

def synthesize(text: str) -> bytes:
    ...  # call your TTS engine, return WAV bytes

cases = ttsproof.load_cases_jsonl("edge_cases.jsonl")
rows = ttsproof.qa_synthesize(cases, synthesize, out_dir="qa_audio")
report = ttsproof.write_reports(rows, "qa_reports")
assert report["ok"], report["summary"]

Or check existing audio with three lines:

import ttsproof

report = ttsproof.check_wav("output.wav")          # structural only
print(report.ok, report.errors)

Why "quarantine" instead of pass/fail?

Short utterances are where reference-based TTS systems break — and also where ASR is least reliable. In the published evaluation, a blinded human review of the ASR-uncertain zone found it was a genuine ~45/55 mix of real TTS failures and ASR false-negatives. Treating that zone as "needs human ears" is the honest design: hard failures stay automatic, uncertain shorts get a human, nothing gets silently mislabeled.

What it doesn't do

  • It does not judge naturalness, prosody, or speaker similarity — it catches defects, not aesthetics.
  • ASR-based checks inherit ASR's limits; that is exactly why the quarantine verdict exists.
  • English-first normalization (with Greek letter support); contributions for other languages welcome.

Cite

@techreport{gkilis2026ttsqa,
  author = {Gkilis, Panagiotis},
  title  = {An Automated Failure-Mode QA Framework for Neural Text-to-Speech
            Systems: A Production Case Study on a Reference-Based TTS Service},
  year   = {2026},
  doi    = {10.5281/zenodo.20757553}
}

License

MIT © Panagiotis Gkilis — portfolio · part of the Proof family with BookProof

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ttsproof-0.1.0.tar.gz (19.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ttsproof-0.1.0-py3-none-any.whl (18.8 kB view details)

Uploaded Python 3

File details

Details for the file ttsproof-0.1.0.tar.gz.

File metadata

  • Download URL: ttsproof-0.1.0.tar.gz
  • Upload date:
  • Size: 19.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.10

File hashes

Hashes for ttsproof-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b78e90cc863c622146539a74e0c51b708f470e9cbce7427c6f36a70956ab4662
MD5 96be828bcf76bfe0b54f991e639366fc
BLAKE2b-256 3f884d9d3e2b0e2d8c4633cbef778382242dfdc380bb519c321db87360ea868c

See more details on using hashes here.

File details

Details for the file ttsproof-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ttsproof-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 18.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.10

File hashes

Hashes for ttsproof-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f180d8410d672842f024ed82dc7f12182ac339c7a8e75744d6ef5bb57e4afccf
MD5 a972729a0bf64953054ad77d9db6e01f
BLAKE2b-256 c07c6420e0650ddf9468766bf797d5866d677427b1a42454eb4f38739e9c6a23

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page