igerry commited on
Commit
5f569e2
·
verified ·
1 Parent(s): 8fc3d92

Upload comfy/custom_nodes/ComfyUI-IndexTTS2/audition_klaus.py with huggingface_hub

Browse files
comfy/custom_nodes/ComfyUI-IndexTTS2/audition_klaus.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """audition_klaus.py — single-fragment IndexTTS-2 audition for the Web UI's
3
+ 歪果仁 mode试听 button.
4
+
5
+ Loads IndexTTS-2 once, runs ONE infer with klaus_lexicon mangling on the
6
+ provided text, writes a single FLAC. Sibling to render_klaus_episode.py but
7
+ single-fragment + no concat / atempo / sidecar — the Web UI just needs a
8
+ ~6-second self-introduction sample to preview the voice.
9
+
10
+ Cold-start ~4 min (model load); warm ~3-5 s. The Web UI cache-by-name keeps
11
+ this cost paid only once per voice — see voice_workshop.audition_indextts.
12
+
13
+ Usage (server-side):
14
+ cd /root/IndexTTS2
15
+ .venv/bin/python audition_klaus.py \
16
+ --ref-wav refs/web/<voice>.flac \
17
+ --text "嗨,你好呀!我是 Klaus..." \
18
+ --output /root/ComfyUI/output/voice_audition/klaus_audition_klaus_NNN.flac
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import argparse
24
+ import sys
25
+ import time
26
+ from pathlib import Path
27
+
28
+ sys.path.insert(0, str(Path(__file__).parent))
29
+ import klaus_lexicon # noqa: E402
30
+
31
+ from indextts.infer_v2 import IndexTTS2 # noqa: E402
32
+
33
+ # Same locked-in profile as render_klaus_episode.py — keeps the audition
34
+ # faithful to what the actual render will sound like.
35
+ LEXICON_PROFILE = dict(
36
+ tone_4to1_prob=0.95,
37
+ tone_3to2_prob=0.95,
38
+ retroflex_loss_prob=0.0,
39
+ u_prob=0.0,
40
+ )
41
+
42
+
43
+ def main() -> int:
44
+ ap = argparse.ArgumentParser(description=__doc__.split("\n")[0])
45
+ ap.add_argument("--ref-wav", required=True, help="path to spk_audio_prompt (relative to cwd or absolute)")
46
+ ap.add_argument("--text", required=True, help="self-intro text to speak")
47
+ ap.add_argument("--output", required=True, help="final .flac path")
48
+ ap.add_argument("--seed", type=int, default=42)
49
+ args = ap.parse_args()
50
+
51
+ if not Path(args.ref_wav).exists():
52
+ sys.exit(f"REF missing: {args.ref_wav} (cwd={Path.cwd()})")
53
+
54
+ print(">> loading IndexTTS2…", flush=True)
55
+ t0 = time.perf_counter()
56
+ tts = IndexTTS2(cfg_path="checkpoints/config.yaml", model_dir="checkpoints", use_fp16=True)
57
+ print(f">> loaded in {time.perf_counter()-t0:.1f}s on {tts.device}", flush=True)
58
+
59
+ mangled, stats = klaus_lexicon.transform(args.text, seed=args.seed, **LEXICON_PROFILE)
60
+ rate = stats["overrides_emitted"] / max(stats["total_han"], 1)
61
+ print(f">> mangled ({rate:.0%} override): {mangled}", flush=True)
62
+
63
+ Path(args.output).parent.mkdir(parents=True, exist_ok=True)
64
+ t0 = time.perf_counter()
65
+ tts.infer(spk_audio_prompt=args.ref_wav, text=mangled, output_path=args.output, verbose=False)
66
+ print(f">> done in {time.perf_counter()-t0:.1f}s -> {args.output}", flush=True)
67
+ return 0
68
+
69
+
70
+ if __name__ == "__main__":
71
+ sys.exit(main())