"""Step 4: speak every segment in every seed of voice.seeds (work/takes/_s.wav). usage: render [--weak] --weak: only the segments pick listed as weak, in voice.extra_seeds Resumable: existing takes are skipped, so after a lexicon change only the changed segments are spoken. """ import json import sys from .config import load from .tts import backend def reference(cfg, ref_id=None): ref_id = ref_id or cfg["voice"]["reference"] refs = {c["id"]: c for c in json.load(open(cfg.w("refs.json"), encoding="utf-8"))} if ref_id not in refs: raise SystemExit(f"reference {ref_id!r} is not in work/refs.json (run refs; see README)") return cfg.w("refs", f"{ref_id}.wav"), refs[ref_id]["text"] def main(): cfg = load() segs = json.load(open(cfg.w("segs.json"), encoding="utf-8")) seeds = cfg["voice"]["seeds"] if "--weak" in sys.argv: weak = set(json.load(open(cfg.w("pick_report.json")))["weak"]) segs = [s for s in segs if s["id"] in weak] seeds = cfg["voice"].get("extra_seeds", []) tts = None for seed in seeds: todo = [(s["acute"], str(cfg.w("takes", f"{s['take']}_s{seed}.wav"))) for s in segs if not cfg.w("takes", f"{s['take']}_s{seed}.wav").exists()] print(f"seed {seed}: {len(todo)} segments to speak", flush=True) if not todo: continue if tts is None: tts = backend(cfg, *reference(cfg)) tts.speak(todo, seed, log=lambda m: print(m, flush=True)) print("RENDER_DONE") if __name__ == "__main__": main()