Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 09:05:52 +08:00
commit db12a906d2
62 changed files with 27669 additions and 0 deletions

114
hooks/utils/tts/elevenlabs_mcp.py Executable file
View File

@@ -0,0 +1,114 @@
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.8"
# dependencies = [
# "python-dotenv",
# ]
# ///
import os
import sys
import json
import subprocess
from pathlib import Path
from dotenv import load_dotenv
def main():
"""
ElevenLabs MCP TTS Script
Uses ElevenLabs MCP server for high-quality text-to-speech via Claude Code.
Accepts optional text prompt as command-line argument.
Usage:
- ./elevenlabs_mcp.py # Uses default text
- ./elevenlabs_mcp.py "Your custom text" # Uses provided text
Features:
- Integration with Claude Code MCP
- Automatic voice selection
- High-quality voice synthesis via ElevenLabs API
- Optimized for hook usage (quick, reliable)
"""
# Load environment variables
load_dotenv()
try:
print("🎙️ ElevenLabs MCP TTS")
print("=" * 25)
# Get text from command line argument or use default
if len(sys.argv) > 1:
text = " ".join(sys.argv[1:]) # Join all arguments as text
else:
text = "Task completed successfully!"
print(f"🎯 Text: {text}")
print("🔊 Generating and playing via MCP...")
try:
# Use Claude Code CLI to invoke ElevenLabs MCP
# This assumes the ElevenLabs MCP server is configured in Claude Code
claude_cmd = [
"claude", "mcp", "call", "ElevenLabs", "text_to_speech",
"--text", text,
"--voice_name", "Adam", # Default voice
"--model_id", "eleven_turbo_v2_5", # Fast model
"--output_directory", str(Path.home() / "Desktop"),
"--speed", "1.0",
"--stability", "0.5",
"--similarity_boost", "0.75"
]
# Try to run the Claude MCP command
result = subprocess.run(
claude_cmd,
capture_output=True,
text=True,
timeout=15 # 15-second timeout for TTS generation
)
if result.returncode == 0:
print("✅ TTS generated and played via MCP!")
# Try to play the generated audio file
# Look for recently created audio files on Desktop
desktop = Path.home() / "Desktop"
audio_files = list(desktop.glob("*.mp3"))
if audio_files:
# Find the most recent audio file
latest_audio = max(audio_files, key=lambda f: f.stat().st_mtime)
# Try to play with system default audio player
if sys.platform == "darwin": # macOS
subprocess.run(["afplay", str(latest_audio)], capture_output=True)
elif sys.platform == "linux": # Linux
subprocess.run(["aplay", str(latest_audio)], capture_output=True)
elif sys.platform == "win32": # Windows
subprocess.run(["start", str(latest_audio)], shell=True, capture_output=True)
print("🎵 Audio playback attempted")
else:
print("⚠️ Audio file not found on Desktop")
else:
print(f"❌ MCP Error: {result.stderr}")
# Fall back to simple notification
print("🔔 TTS via MCP failed - task completion noted")
except subprocess.TimeoutExpired:
print("⏰ MCP TTS timed out - continuing...")
except FileNotFoundError:
print("❌ Claude CLI not found - MCP TTS unavailable")
except Exception as e:
print(f"❌ MCP Error: {e}")
except Exception as e:
print(f"❌ Unexpected error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,83 @@
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.8"
# dependencies = [
# "elevenlabs",
# "python-dotenv",
# ]
# ///
import os
import sys
from pathlib import Path
from dotenv import load_dotenv
def main():
"""
ElevenLabs Turbo v2.5 TTS Script
Uses ElevenLabs' Turbo v2.5 model for fast, high-quality text-to-speech.
Accepts optional text prompt as command-line argument.
Usage:
- ./elevenlabs_tts.py # Uses default text
- ./elevenlabs_tts.py "Your custom text" # Uses provided text
Features:
- Fast generation (optimized for real-time use)
- High-quality voice synthesis
- Stable production model
- Cost-effective for high-volume usage
"""
# Load environment variables
load_dotenv()
# Get API key from environment
api_key = os.getenv('ELEVENLABS_API_KEY')
if not api_key:
print("❌ Error: ELEVENLABS_API_KEY not found in environment variables", file=sys.stderr)
print("Please add your ElevenLabs API key to .env file:", file=sys.stderr)
print("ELEVENLABS_API_KEY=your_api_key_here", file=sys.stderr)
sys.exit(1)
try:
from elevenlabs.client import ElevenLabs
from elevenlabs.play import play
# Initialize client
elevenlabs = ElevenLabs(api_key=api_key)
# Get text from command line argument or use default
if len(sys.argv) > 1:
text = " ".join(sys.argv[1:]) # Join all arguments as text
else:
text = "Task completed successfully."
try:
# Generate and play audio directly
audio = elevenlabs.text_to_speech.convert(
text=text,
voice_id="EXAVITQu4vr4xnSDxMaL", # Sarah voice
model_id="eleven_turbo_v2_5",
output_format="mp3_44100_128",
)
play(audio)
except Exception as e:
print(f"❌ Error: {e}", file=sys.stderr)
sys.exit(1)
except ImportError:
print("❌ Error: elevenlabs package not installed", file=sys.stderr)
print("This script uses UV to auto-install dependencies.", file=sys.stderr)
print("Make sure UV is installed: https://docs.astral.sh/uv/", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"❌ Unexpected error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()

93
hooks/utils/tts/local_tts.py Executable file
View File

@@ -0,0 +1,93 @@
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.8"
# dependencies = [
# "pyttsx3",
# ]
# ///
import sys
import random
import os
def main():
"""
Local TTS Script (pyttsx3)
Uses pyttsx3 for offline text-to-speech synthesis.
Accepts optional text prompt as command-line argument.
Usage:
- ./local_tts.py # Uses default text
- ./local_tts.py "Your custom text" # Uses provided text
Features:
- Offline TTS (no API key required)
- Cross-platform compatibility
- Configurable voice settings
- Immediate audio playback
- Engineer name personalization support
"""
try:
import pyttsx3
# Initialize TTS engine
engine = pyttsx3.init()
# Configure engine settings
engine.setProperty('rate', 180) # Speech rate (words per minute)
engine.setProperty('volume', 0.9) # Volume (0.0 to 1.0)
print("🎙️ Local TTS")
print("=" * 12)
# Get text from command line argument or use default
if len(sys.argv) > 1:
text = " ".join(sys.argv[1:]) # Join all arguments as text
else:
# Default completion messages with engineer name support
engineer_name = os.getenv("ENGINEER_NAME", "").strip()
if engineer_name and random.random() < 0.3: # 30% chance to use name
personalized_messages = [
f"{engineer_name}, all set!",
f"Ready for you, {engineer_name}!",
f"Complete, {engineer_name}!",
f"{engineer_name}, we're done!",
f"Task finished, {engineer_name}!"
]
text = random.choice(personalized_messages)
else:
completion_messages = [
"Work complete!",
"All done!",
"Task finished!",
"Job complete!",
"Ready for next task!",
"Ready for your next move!",
"All set!"
]
text = random.choice(completion_messages)
print(f"🎯 Text: {text}")
print("🔊 Speaking...")
# Speak the text
engine.say(text)
engine.runAndWait()
print("✅ Playback complete!")
except ImportError:
print("❌ Error: pyttsx3 package not installed")
print("This script uses UV to auto-install dependencies.")
sys.exit(1)
except Exception as e:
print(f"❌ Error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()

109
hooks/utils/tts/openai_tts.py Executable file
View File

@@ -0,0 +1,109 @@
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.8"
# dependencies = [
# "openai",
# "python-dotenv",
# ]
# ///
import os
import sys
import asyncio
from pathlib import Path
from dotenv import load_dotenv
async def main():
"""
OpenAI TTS Script
Uses OpenAI's TTS model for high-quality text-to-speech.
Accepts optional text prompt as command-line argument.
Usage:
- ./openai_tts.py # Uses default text
- ./openai_tts.py "Your custom text" # Uses provided text
Features:
- OpenAI TTS-1 model (fast and reliable)
- Nova voice (engaging and warm)
- Direct audio streaming and playback
- Optimized for hook usage
"""
# Load environment variables
load_dotenv()
# Get API key from environment
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
print("❌ Error: OPENAI_API_KEY not found in environment variables")
sys.exit(1)
try:
from openai import AsyncOpenAI
# Initialize OpenAI client
openai = AsyncOpenAI(api_key=api_key)
print("🎙️ OpenAI TTS")
print("=" * 15)
# Get text from command line argument or use default
if len(sys.argv) > 1:
text = " ".join(sys.argv[1:]) # Join all arguments as text
else:
text = "Task completed successfully!"
print(f"🎯 Text: {text}")
print("🔊 Generating audio...")
try:
# Generate audio using OpenAI TTS
response = await openai.audio.speech.create(
model="tts-1",
voice="nova",
input=text,
response_format="mp3",
)
# Save to temporary file
audio_file = Path.home() / "Desktop" / "tts_completion.mp3"
with open(audio_file, "wb") as f:
async for chunk in response.iter_bytes():
f.write(chunk)
print("🎵 Playing audio...")
# Play the audio file
import subprocess
if sys.platform == "darwin": # macOS
subprocess.run(["afplay", str(audio_file)], capture_output=True)
elif sys.platform == "linux": # Linux
subprocess.run(["aplay", str(audio_file)], capture_output=True)
elif sys.platform == "win32": # Windows
subprocess.run(["start", str(audio_file)], shell=True, capture_output=True)
print("✅ Playback complete!")
# Clean up the temporary file
try:
audio_file.unlink()
except:
pass
except Exception as e:
print(f"❌ Error: {e}")
except ImportError as e:
print("❌ Error: Required package not installed")
print("This script uses UV to auto-install dependencies.")
sys.exit(1)
except Exception as e:
print(f"❌ Unexpected error: {e}")
sys.exit(1)
if __name__ == "__main__":
asyncio.run(main())