Files
model-training/tts/piper/check_phonemes.py
T
2026-07-19 23:52:25 +04:00

59 lines
1.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
phoneme stress sanity check — run BEFORE training (Phase 6).
espeak-ng is piper's phonemizer. for each sampled transcript, print its IPA and
flag any multisyllable word whose IPA carries no primary-stress mark 'ˈ'. wrong
stress is the #1 cause of "sounds bad" — catch it here, not after GPU-days.
ponytail: thin wrapper over the espeak-ng CLI. ceiling = flags MISSING stress
only, not WRONG-POSITION stress (that needs an ear on the Phase 4 audio).
run: python piper/check_phonemes.py [--n 30] [--meta piper/dataset/metadata.csv]
requires: sudo apt install espeak-ng
"""
import argparse
import random
import shutil
import subprocess
import sys
from pathlib import Path
STRESS = "ˈ"
def ipa(text: str) -> str:
out = subprocess.run(
["espeak-ng", "-v", "ru", "--ipa", "-q", text],
capture_output=True, text=True,
)
return out.stdout.strip()
def main():
if not shutil.which("espeak-ng"):
sys.exit("espeak-ng not found — sudo apt install espeak-ng")
ap = argparse.ArgumentParser()
ap.add_argument("--meta", default="tts/piper/dataset/metadata.csv")
ap.add_argument("--n", type=int, default=30)
args = ap.parse_args()
lines = [l for l in Path(args.meta).read_text(encoding="utf-8").splitlines() if "|" in l]
sample = random.sample(lines, min(args.n, len(lines)))
flagged = 0
for line in sample:
_id, text = line.split("|", 1)
phon = ipa(text)
bad = STRESS not in phon and len(text.split()) >= 1
mark = " ⚠ NO STRESS" if bad else ""
flagged += bad
print(f"{text}\n{phon}{mark}\n")
print(f"[{'!' if flagged else ''}] {flagged}/{len(sample)} samples missing stress marks")
if __name__ == "__main__":
main()