Files
whisper-translation/engine_kokoro_tts.py
T
Adolfo Reyna 354cacd417 feat: ksay — Kokoro 82M local TTS replaces say (4x RTF, offline, 9 voices)
- engine_kokoro_tts.py: tts(text, voice, outfile) 0.5s gen 4-5x RTF M2
- ksay: drop-in say replacement, usage: ksay [-v voice] [-o file] "text"
- install-ksay.sh: one-shot setup for macmini (pip + model 310MB + warm)
- voices: af_bella (default), af_heart, am_adam, bf_emma etc
- model ready after: ./install-ksay.sh (pre-downloads hexgrad/Kokoro-82M)
- macmini: git pull gitea main && bash install-ksay.sh && ./ksay "hello"
2026-07-14 13:37:58 -04:00

33 lines
1.3 KiB
Python

"""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])