Skill: bewareofddog/beware-piper-tts (version 1.0.1)

--- name: piper-tts description: Local text-to-speech using Piper for voice message delivery. Use when the user asks for voice responses, audio messages, TTS, text-to-speech, voice notes, or wants to hear something spoken aloud. Converts text to speech locally (no cloud APIs, no cost, no latency) and delivers as voice messages on Telegram, Discord, or any channel supporting audio. --- # Piper TTS — Local Voice Messages Generate voice messages using [Piper](https://github.com/rhasspy/piper), a fast local TTS engine. Zero cloud calls, zero cost, zero API keys. ## Setup If Piper is not installed, run the setup script: ```bash scripts/setup-piper.sh ``` This installs `piper-tts` via pip and downloads a default voice (`en_US-kusal-medium`). ## Generating Voice Messages Use `scripts/piper-speak.sh` to generate and deliver voice: ```bash scripts/piper-speak.sh "<text>" [voice] ``` - `text`: The text to speak (required) - `voice`: Piper voice name (default: `en_US-kusal-medium`) The script outputs an MP3 path. Include it in your reply as: ``` [[audio_as_voice]] MEDIA:<path-to-mp3> ``` This delivers the audio as a native voice message on supported channels (Telegram, Discord, etc.). ## Example Workflow 1. User asks: "Tell me a joke as audio" 2. Run: `scripts/piper-speak.sh "Why do programmers prefer dark mode? Because light attracts bugs!"` 3. Get MP3 path from output 4. Reply with `[[audio_as_voice]]` + `MEDIA:<path>` ## Available Voices After setup, download additional voices: ```bash scripts/setup-piper.sh --voice en_US-ryan-high scripts/setup-piper.sh --voice en_GB-northern_english_male-medium ``` Popular voices: - `en_US-kusal-medium` — Clear male voice (default, recommended) - `en_US-ryan-high` — High quality US male - `en_US-hfc_male-medium` — US male - [REDACTED_SECRET] — British male - Browse all: https://huggingface.co/rhasspy/piper-voices ## Important Notes - **Speed**: Local generation is ~0.5-1s. Much faster than cloud TTS. - **No API keys**: Works completely offline after setup. - **Platform**: macOS (Apple Silicon + Intel), Linux. Requires Python 3.9+. - **Do NOT** set `messages.tts.auto: "always"` in OpenClaw config — it makes every response slow. Keep TTS on-demand.

path: scripts/piper-speak.sh
content: #!/usr/bin/env bash
set -euo pipefail

# Piper Speak — Generate voice audio for OpenClaw delivery
# Usage: piper-speak.sh "<text>" [voice]
# Output: MP3 path ready for [[audio_as_voice]] delivery

TEXT="${1:?Usage: piper-speak.sh \"<text>\" [voice]}"
VOICE="${2:-en_US-kusal-medium}"
VOICES_DIR="${PIPER_VOICES_DIR:-$HOME/.local/share/piper-voices}"

# Also check common locations
if [[ ! -f "$VOICES_DIR/${VOICE}.onnx" ]]; then
  for alt_dir in "$HOME/Documents/resources/piper-voices" "/usr/share/piper-voices"; do
    if [[ -f "$alt_dir/${VOICE}.onnx" ]]; then
      VOICES_DIR="$alt_dir"
      break
    fi
  done
fi

if [[ ! -f "$VOICES_DIR/${VOICE}.onnx" ]]; then
  echo "❌ Voice not found: $VOICE" >&2
  echo "   Run: setup-piper.sh --voice $VOICE" >&2
  exit 1
fi

# Output to temp directory (OpenClaw media delivery compatible)
OUT_DIR="${TMPDIR:-/tmp}/tts-piper"
mkdir -p "$OUT_DIR"
OUT_WAV="$OUT_DIR/voice-$(date +%s%N | cut -c1-13).wav"
OUT_MP3="${OUT_WAV%.wav}.mp3"

# Generate speech
echo "$TEXT" | python3 -m piper --data-dir "$VOICES_DIR" -m "$VOICE" -f "$OUT_WAV" 2>/dev/null

# Convert to MP3
ffmpeg -y -loglevel error -i "$OUT_WAV" -codec:a libmp3lame -qscale:a 4 "$OUT_MP3"

# Cleanup WAV
rm -f "$OUT_WAV"

# Output MP3 path (agent copies this into reply)
echo "$OUT_MP3"


path: scripts/setup-piper.sh
content: #!/usr/bin/env bash
set -euo pipefail

# Piper TTS Setup — installs piper-tts and downloads voices
# Usage: setup-piper.sh [--voice <voice-name>] [--voices-dir <path>]

VOICES_DIR="${PIPER_VOICES_DIR:-$HOME/.local/share/piper-voices}"
VOICE=""
HF_BASE="https://huggingface.co/rhasspy/piper-voices/resolve/main/en"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --voice) VOICE="$2"; shift 2 ;;
    --voices-dir) VOICES_DIR="$2"; shift 2 ;;
    *) echo "Unknown arg: $1"; exit 1 ;;
  esac
done

mkdir -p "$VOICES_DIR"

# Install piper-tts if not present
if ! python3 -m piper --help &>/dev/null; then
  echo "📦 Installing piper-tts..."
  pip3 install piper-tts
  echo "✅ piper-tts installed"
else
  echo "✅ piper-tts already installed"
fi

# Install ffmpeg if not present (needed for MP3 conversion)
if ! command -v ffmpeg &>/dev/null; then
  echo "📦 Installing ffmpeg..."
  if command -v brew &>/dev/null; then
    brew install ffmpeg
  elif command -v apt-get &>/dev/null; then
    sudo apt-get install -y ffmpeg
  else
    echo "⚠️  Please install ffmpeg manually"
    exit 1
  fi
  echo "✅ ffmpeg installed"
else
  echo "✅ ffmpeg already installed"
fi

# Download voice
download_voice() {
  local voice_name="$1"
  local onnx_file="$VOICES_DIR/${voice_name}.onnx"
  
  if [[ -f "$onnx_file" ]]; then
    echo "✅ Voice already downloaded: $voice_name"
    return 0
  fi

  # Parse voice name: en_US-kusal-medium → en/en_US/kusal/medium
  local lang_region="${voice_name%%-*}"          # en_US
  local rest="${voice_name#*-}"                   # kusal-medium
  local speaker="${rest%-*}"                      # kusal
  local quality="${rest##*-}"                     # medium
  local lang="${lang_region%%_*}"                 # en

  local base_url="${HF_BASE}/${lang_region}/${speaker}/${quality}"
  
  echo "📥 Downloading voice: $voice_name..."
  curl -L -o "$onnx_file" "${base_url}/${voice_name}.onnx"
  curl -L -o "${onnx_file}.json" "${base_url}/${voice_name}.onnx.json"
  echo "✅ Voice downloaded: $voice_name ($(du -h "$onnx_file" | cut -f1))"
}

if [[ -n "$VOICE" ]]; then
  download_voice "$VOICE"
else
  # Default voice
  download_voice "en_US-kusal-medium"
fi

echo ""
echo "🎤 Piper TTS ready!"
echo "   Voices dir: $VOICES_DIR"
echo "   Generate speech: piper-speak.sh \"Hello world!\""


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (MEDIUM)