48 lines
1.6 KiB
Bash
Executable file
48 lines
1.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Script Name: speak
|
|
# Description: Text-to-speech with ElevenLabs/Piper/espeak support
|
|
# Source: Enhanced from https://evanhahn.com/scripts-i-wrote-that-i-use-all-the-time/
|
|
# Usage: echo "text" | speak
|
|
# speak < file.txt
|
|
# cat README.md | speak
|
|
|
|
# Strip markdown if pandoc is available
|
|
if command -v pandoc &>/dev/null; then
|
|
text=$(pandoc -f commonmark -t plain --wrap=preserve)
|
|
else
|
|
text=$(cat)
|
|
fi
|
|
|
|
# Try voice systems in order of preference:
|
|
# 1. ElevenLabs (best quality, requires API)
|
|
# 2. Piper (good quality, local)
|
|
# 3. espeak-ng (fallback)
|
|
# 4. say (macOS)
|
|
|
|
if command -v elevenlabs &>/dev/null && [[ -n "${ELEVENLABS_API_KEY:-}" ]]; then
|
|
# Use ElevenLabs (highest quality)
|
|
echo "$text" | elevenlabs tts --voice "Adam" --play
|
|
elif command -v piper &>/dev/null; then
|
|
# Use Piper (good local TTS)
|
|
# Look for installed voice models
|
|
piper_voice_dir="$HOME/.local/share/piper/voices"
|
|
if [[ -f "$piper_voice_dir/en_US-amy-medium.onnx" ]]; then
|
|
echo "$text" | piper --model "$piper_voice_dir/en_US-amy-medium.onnx" --output-raw | aplay -r 22050 -f S16_LE -t raw -
|
|
else
|
|
echo "Error: Piper voice model not found at $piper_voice_dir" >&2
|
|
echo "Download with: piper --download-dir $piper_voice_dir --download en_US-amy-medium" >&2
|
|
exit 1
|
|
fi
|
|
elif hash espeak-ng 2>/dev/null; then
|
|
# Use espeak-ng (basic but reliable)
|
|
echo "$text" | espeak-ng
|
|
elif hash say 2>/dev/null; then
|
|
# Use macOS say
|
|
echo "$text" | say
|
|
else
|
|
echo "Error: No TTS program found" >&2
|
|
echo "Install one of: piper, espeak-ng, or set ELEVENLABS_API_KEY" >&2
|
|
exit 1
|
|
fi
|