make_samples.py
| 1 | """Rebuild voices/*.pt and samples/*_clone.wav from samples/*_ref.wav. |
| 2 | |
| 3 | pip install inno-kokoro && python make_samples.py |
| 4 | |
| 5 | The pack name already sitting next to each reference sets the accent: af_/am_ render American, bf_/bm_ British. |
| 6 | Every clone is the same TEST_TEXT passage, so the samples table stays comparable across voices. |
| 7 | """ |
| 8 | |
| 9 | import glob |
| 10 | import os |
| 11 | |
| 12 | import soundfile as sf |
| 13 | import torch |
| 14 | from inno_kokoro.enroll import SR_KOKORO, TEST_TEXT, Tuner, enroll, read |
| 15 | from kokoro import KPipeline |
| 16 | |
| 17 | PACKS = {os.path.basename(p).split("_", 1)[1][:-3]: os.path.basename(p)[:-3] for p in glob.glob("voices/*.pt")} |
| 18 | |
| 19 | |
| 20 | def main(): |
| 21 | tuner = Tuner(device="cuda" if torch.cuda.is_available() else "cpu") |
| 22 | pipes = {} |
| 23 | for ref in sorted(glob.glob("samples/*_ref.wav")): |
| 24 | key = os.path.basename(ref)[: -len("_ref.wav")] |
| 25 | name = PACKS[key.replace("_", "")] |
| 26 | pack, weights = enroll(*read(ref), tuner) |
| 27 | pack_path = f"voices/{name}.pt" |
| 28 | torch.save(pack, pack_path) |
| 29 | pipe = pipes.setdefault(name[0], KPipeline(lang_code=name[0])) |
| 30 | out = torch.cat([r.audio for r in pipe(TEST_TEXT, voice=pack_path)]) |
| 31 | sf.write(f"samples/{key}_clone.wav", out.cpu().numpy(), SR_KOKORO) |
| 32 | blend = " ".join(f"{k}:{v:.2f}" for k, v in sorted(weights.items(), key=lambda kv: -kv[1])) |
| 33 | print(f"{name:24s} {len(out) / SR_KOKORO:5.1f}s {blend}") |
| 34 | |
| 35 | |
| 36 | if __name__ == "__main__": |
| 37 | main() |
| 38 | |