Add voice assistant convenience scripts

- enable-voice.sh: One-command setup for voice assistant
- Automatic prerequisite checking (Poetry, piper-tts, voice models)
- Voice model download with progress indicators
- Server startup with health testing
- Auto-generates disable-voice.sh for cleanup

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-17 14:56:28 +02:00
parent 572434d42e
commit 16081ec85e

231
scripts/enable-voice.sh Executable file
View File

@@ -0,0 +1,231 @@
#!/bin/bash
# Enable Voice Mode - Start voice server and configure voice-mode
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
HOMELAB_ROOT="$(dirname "$SCRIPT_DIR")"
VOICE_SERVER_DIR="$HOMELAB_ROOT/voice-server"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
check_prerequisites() {
log_info "Checking prerequisites..."
# Check if poetry is installed
if ! command -v poetry &> /dev/null; then
log_error "Poetry is not installed. Please install it first:"
log_error "curl -sSL https://install.python-poetry.org | python3 -"
exit 1
fi
# Check if piper-tts is installed
if ! command -v piper-tts &> /dev/null; then
log_error "piper-tts is not installed. Please install it first:"
log_error "yay -S piper-tts"
exit 1
fi
# Check if voice server directory exists
if [[ ! -d "$VOICE_SERVER_DIR" ]]; then
log_error "Voice server directory not found: $VOICE_SERVER_DIR"
exit 1
fi
# Check if voice models exist
VOICES_DIR="$HOME/.local/share/piper-voices"
RYAN_MODEL="$VOICES_DIR/en_US-ryan-medium.onnx"
if [[ ! -f "$RYAN_MODEL" ]]; then
log_warn "Ryan voice model not found: $RYAN_MODEL"
log_info "Downloading voice models..."
mkdir -p "$VOICES_DIR"
cd "$VOICES_DIR"
log_info "Downloading Ryan voice (male US English)..."
wget -q --show-progress \
"https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/ryan/medium/en_US-ryan-medium.onnx" \
"https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/ryan/medium/en_US-ryan-medium.onnx.json"
log_info "Voice models downloaded successfully"
fi
log_info "Prerequisites check completed"
}
setup_voice_server() {
log_info "Setting up voice server..."
cd "$VOICE_SERVER_DIR"
# Install dependencies if needed
if [[ ! -d ".venv" ]] || ! poetry check &> /dev/null; then
log_info "Installing voice server dependencies..."
poetry install --only=main
fi
log_info "Voice server setup completed"
}
start_voice_server() {
log_info "Starting voice server..."
cd "$VOICE_SERVER_DIR"
# Check if server is already running
if curl -s http://127.0.0.1:8880/health > /dev/null 2>&1; then
log_warn "Voice server is already running on port 8880"
return 0
fi
# Start server in background
log_info "Starting voice server on http://127.0.0.1:8880"
poetry run voice-server &
SERVER_PID=$!
# Save PID for cleanup
echo $SERVER_PID > /tmp/voice-server.pid
# Wait for server to start
log_info "Waiting for server to start..."
for i in {1..30}; do
if curl -s http://127.0.0.1:8880/health > /dev/null 2>&1; then
log_info "Voice server started successfully (PID: $SERVER_PID)"
return 0
fi
sleep 1
done
log_error "Failed to start voice server"
exit 1
}
test_voice_server() {
log_info "Testing voice server..."
# Test health endpoint
if ! curl -s http://127.0.0.1:8880/health | grep -q "healthy"; then
log_error "Voice server health check failed"
exit 1
fi
# Test TTS endpoint
if ! curl -s -X POST "http://127.0.0.1:8880/v1/audio/speech" \
-H "Content-Type: application/json" \
-d '{"input": "Voice server test", "voice": "ryan"}' \
--output /tmp/voice-test.wav > /dev/null 2>&1; then
log_error "Voice server TTS test failed"
exit 1
fi
# Check if audio file was created
if [[ ! -f "/tmp/voice-test.wav" ]] || [[ ! -s "/tmp/voice-test.wav" ]]; then
log_error "Generated audio file is invalid"
exit 1
fi
rm -f /tmp/voice-test.wav
log_info "Voice server test completed successfully"
}
show_usage() {
log_info "Voice mode is now enabled!"
echo
echo "Server Details:"
echo " URL: http://127.0.0.1:8880"
echo " Health: http://127.0.0.1:8880/health"
echo " API Docs: http://127.0.0.1:8880/docs"
echo
echo "Available commands:"
echo " # Test TTS"
echo " curl -X POST 'http://127.0.0.1:8880/v1/audio/speech' \\"
echo " -H 'Content-Type: application/json' \\"
echo " -d '{\"input\": \"Hello world!\", \"voice\": \"ryan\"}' \\"
echo " --output test.wav"
echo
echo " # Stop server"
echo " $SCRIPT_DIR/disable-voice.sh"
echo
echo " # View server logs"
echo " tail -f $VOICE_SERVER_DIR/voice-server.log"
echo
log_info "You can now use voice commands in Claude Code!"
}
create_disable_script() {
cat > "$SCRIPT_DIR/disable-voice.sh" << 'EOF'
#!/bin/bash
# Disable Voice Mode - Stop voice server
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
if [[ -f "/tmp/voice-server.pid" ]]; then
PID=$(cat /tmp/voice-server.pid)
if kill -0 "$PID" 2>/dev/null; then
log_info "Stopping voice server (PID: $PID)..."
kill "$PID"
rm -f /tmp/voice-server.pid
log_info "Voice server stopped"
else
log_error "Voice server process not found"
rm -f /tmp/voice-server.pid
fi
else
log_error "Voice server PID file not found"
fi
# Also try to kill any remaining voice-server processes
pkill -f "voice-server" && log_info "Cleaned up remaining voice-server processes"
log_info "Voice mode disabled"
EOF
chmod +x "$SCRIPT_DIR/disable-voice.sh"
}
main() {
log_info "Enabling Voice Mode for Claude Code..."
check_prerequisites
setup_voice_server
start_voice_server
test_voice_server
create_disable_script
show_usage
}
# Handle cleanup on exit
cleanup() {
if [[ -n "${SERVER_PID:-}" ]]; then
log_info "Cleaning up..."
kill "$SERVER_PID" 2>/dev/null || true
fi
}
trap cleanup EXIT
main "$@"