This commit is contained in:
john 2025-09-11 10:56:08 +02:00
commit b3990ae6b9

78
say.zsh Executable file
View file

@ -0,0 +1,78 @@
#!/bin/env zsh
voices_dir=/usr/share/piper-voices
voice="$voices_dir/en/en_US/ryan/high/en_US-ryan-high.onnx"
parse_voice() {
emulate -L zsh
local query="$1" chosen
[[ -n "$query" ]] || { echo "voice query required" >&2; exit 2; }
chosen=$(
jq -r --arg root "$voices_dir" '
to_entries
| .[].value.files
| keys[]
| select(endswith(".onnx"))
| if startswith("/") then . else "\($root)/\(.)" end
' "$voices_dir/voices.json" \
| fzf --filter="$query" \
| head -n1
)
[[ -n "$chosen" ]] || { echo "no matching voice for: $query" >&2; exit 4; }
voice="$chosen"
}
list_voices() {
jq -r 'keys[]' $voices_dir/voices.json
}
print_help() {
echo "Usage: say [options] <text | ->"
echo "Options:"
echo " -h, --help Show this help message and exit"
echo " -v, --voice <voice> Set voice"
echo " -l, --list List available voices and exit"
}
do_say() {
echo "$voice" >&2
emulate -L zsh
{ [[ $# -eq 0 ]] && cat || echo "$@"; } \
| piper-tts --model "$voice" --output_raw 2>/dev/null \
| aplay -r 22050 -f S16_LE -t raw - 2>/dev/null
}
opts=$(getopt -o hv:l --long help,voice:,list -n "$0" -- "$@") || exit 5
eval set -- "$opts"
while true; do
case "$1" in
-h|--help)
print_help
exit 0
;;
-v|--voice)
parse_voice "$2"
shift 2
;;
-l|--list)
list_voices
exit 0
;;
--)
shift
break
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
do_say "$@"