354cacd417
- 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"
30 lines
1.2 KiB
Bash
Executable File
30 lines
1.2 KiB
Bash
Executable File
#!/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
|