# -*- coding: utf-8 -*- """QA on the finished MP4: extracts the audio already mixed with the music, cuts it by the timeline and transcribes it. It proves the voice is intelligible over the bed, not just that the loose WAV was fine.""" import json, os, subprocess, sys from difflib import SequenceMatcher ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, os.path.join(ROOT, "scripts")) from narration import SCRIPTS from verify import norm from gen_audio import transcribe LIMIT = 0.88 def main(names): worst = [] for name in names: mp4 = os.path.join(ROOT, "out", f"{name}.mp4") tl = json.load(open(os.path.join(ROOT, "out", f"{name}_timeline.json"))) segs = json.load(open(os.path.join(ROOT, "audio", name, "segments.json")))["segments"] work = os.path.join(ROOT, "tmp", name + "_fin") os.makedirs(work, exist_ok=True) integer = os.path.join(work, "todo.wav") subprocess.run(["ffmpeg", "-v", "error", "-y", "-i", mp4, "-vn", "-ac", "1", "-ar", "16000", integer], check=True) chunks = [] for bt in tl["beats"]: p = os.path.join(work, f"{bt['i']:02d}.wav") subprocess.run(["ffmpeg", "-v", "error", "-y", "-ss", f"{bt['start']:.3f}", "-t", f"{segs[bt['i']]['dur'] + 0.25:.3f}", "-i", integer, "-c", "copy", p], check=True) chunks.append(p) tr = transcribe(chunks, work) print(f"\n=== {name} (mezcla final) ===") for bt, p in zip(tl["beats"], chunks): i = bt["i"] got = tr[p] r = SequenceMatcher(None, norm(segs[i]["tts"]), norm(got)).ratio() if r < LIMIT: worst.append((name, i, r)) print(f" {i:02d} {'OK ' if r >= LIMIT else 'REV'} {r:.2f} | {got}") print("\n>> a revisar:", worst if worst else "nada") if __name__ == "__main__": main(sys.argv[1:] or list(SCRIPTS))