"""engine_kokoro_tts.py — Kokoro 82M local TTS, drop-in say replacement, 4x RTF, offline""" from __future__ import annotations import argparse from kokoro import KPipeline import soundfile as sf VOICES=["af_bella","af_heart","af_sarah","af_nova","af_sky","bf_emma","bf_isabella","am_adam","am_michael"] _cache={} def get_pipe(lang='a'): if lang not in _cache: _cache[lang]=KPipeline(lang_code=lang) return _cache[lang] def tts(text, voice="af_bella", outfile="/tmp/kokoro_out.wav"): pipe=get_pipe('a') for _,_,audio in pipe(text, voice=voice): sf.write(outfile, audio, 24000) return outfile if __name__=="__main__": ap=argparse.ArgumentParser(description="Kokoro 82M TTS — better than say -v Eddy") ap.add_argument("text", nargs="?", default="Hello world, this is Kokoro eighty two M on Mac") ap.add_argument("-v","--voice", default="af_bella", help="voice: af_bella, af_heart, am_adam etc") ap.add_argument("-o","--out", default="/tmp/kokoro_out.wav") ap.add_argument("--list-voices", action="store_true") ap.add_argument("--play", action="store_true") a=ap.parse_args() if a.list_voices: print("\n".join(VOICES)); raise SystemExit out=tts(a.text, voice=a.voice, outfile=a.out) print(f"wrote {out}") if a.play: import subprocess; subprocess.run(["afplay", out])