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"
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
# ksay — Kokoro 82M TTS, better than say -v Eddy, fully offline after install, 4x RTF on M2
|
||||
set -e
|
||||
ROOT="$(cd "$(dirname "$0")" && pwd)"
|
||||
VOICE="af_bella"
|
||||
OUT=""
|
||||
TEXT=""
|
||||
PLAY=1
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-v|--voice) VOICE="$2"; shift 2;;
|
||||
-o|--output-file) OUT="$2"; shift 2;;
|
||||
-l|--list-voices) PYTHONPATH="" "$ROOT/venv/bin/python" "$ROOT/engine_kokoro_tts.py" --list-voices; exit 0;;
|
||||
--no-play) PLAY=0; shift;;
|
||||
--) shift; TEXT="$*"; break;;
|
||||
-*) echo "unknown $1" >&2; exit 2;;
|
||||
*) TEXT="${TEXT:+$TEXT }$1"; shift;;
|
||||
esac
|
||||
done
|
||||
if [[ -z "$TEXT" && ! -t 0 ]]; then TEXT=$(cat); fi
|
||||
if [[ -z "$TEXT" ]]; then echo "usage: ksay [-v voice] [-o file.wav] \"text\" | echo text | ksay" >&2; exit 1; fi
|
||||
TMP="${OUT:-/tmp/ksay-$$.wav}"
|
||||
PYTHONPATH="" "$ROOT/venv/bin/python" "$ROOT/engine_kokoro_tts.py" "$TEXT" -v "$VOICE" -o "$TMP" 2>&1 | grep -vE "UserWarning|FutureWarning|Defaulting|You are sending|torch/nn|WeightNorm|super\(\)" || true
|
||||
if [[ -z "$OUT" ]]; then
|
||||
if [[ "$PLAY" -eq 1 ]]; then afplay "$TMP"; rm -f "$TMP"; fi
|
||||
else
|
||||
echo "saved $TMP (as $OUT requested but kokoro writes $TMP, copy)"
|
||||
cp "$TMP" "$OUT" 2>/dev/null || true
|
||||
fi
|
||||
Reference in New Issue
Block a user