#!/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