[ADDED] Script para interactuar con Claude Code mediante voz
Nuevo script claude_voice.py que permite: - Capturar comandos de voz y convertirlos a texto - Enviar esos comandos a Claude Code - Funcionar en modo continuo o para comandos individuales - Soporte para diferentes idiomas 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
32b049fe65
commit
b74c5e6826
1 changed files with 178 additions and 0 deletions
178
bin/claude_voice.py
Executable file
178
bin/claude_voice.py
Executable file
|
@ -0,0 +1,178 @@
|
|||
#!/usr/bin/env python3
|
||||
# [Script] : claude_voice.py
|
||||
# [Apps] : MRDEVS TOOLS
|
||||
# [Description]: Convierte instrucciones de voz a texto para Claude Code
|
||||
# [Author] : Cortana Rosero One <cortana@rosero.one>
|
||||
# [Generated] : Created by Claude Code (claude-3-7-sonnet-20250219)
|
||||
# [Created] : 2025/03/30 16:45:00
|
||||
# [Modified] : 2025/03/30 16:45:00
|
||||
# [Version] : 1.3.0
|
||||
# [Use Notes] : Instalar dependencias: pip install speechrecognition pydub pyaudio
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import argparse
|
||||
import time
|
||||
import speech_recognition as sr
|
||||
from pydub import AudioSegment
|
||||
from pydub.playback import play
|
||||
|
||||
# Colores para la salida
|
||||
class Colors:
|
||||
PURPLE = '\033[95m'
|
||||
BLUE = '\033[94m'
|
||||
CYAN = '\033[96m'
|
||||
GREEN = '\033[92m'
|
||||
YELLOW = '\033[93m'
|
||||
RED = '\033[91m'
|
||||
BOLD = '\033[1m'
|
||||
UNDERLINE = '\033[4m'
|
||||
END = '\033[0m'
|
||||
|
||||
def play_sound(sound_type):
|
||||
"""Reproduce un sonido para indicar estados"""
|
||||
sounds_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "sounds")
|
||||
if not os.path.exists(sounds_dir):
|
||||
os.makedirs(sounds_dir, exist_ok=True)
|
||||
|
||||
# Usar sonidos predeterminados si existen, o crearlos
|
||||
sound_files = {
|
||||
"start": os.path.join(sounds_dir, "start.mp3"),
|
||||
"stop": os.path.join(sounds_dir, "stop.mp3"),
|
||||
"error": os.path.join(sounds_dir, "error.mp3")
|
||||
}
|
||||
|
||||
# Si no hay archivo de sonido, usar un beep básico
|
||||
try:
|
||||
if os.path.exists(sound_files[sound_type]):
|
||||
sound = AudioSegment.from_file(sound_files[sound_type])
|
||||
play(sound)
|
||||
else:
|
||||
# Frecuencias para diferentes tipos de sonidos
|
||||
if sound_type == "start":
|
||||
print("\a") # Beep básico del sistema
|
||||
elif sound_type == "stop":
|
||||
print("\a")
|
||||
time.sleep(0.1)
|
||||
print("\a")
|
||||
elif sound_type == "error":
|
||||
print("\a")
|
||||
time.sleep(0.1)
|
||||
print("\a")
|
||||
time.sleep(0.1)
|
||||
print("\a")
|
||||
except Exception:
|
||||
# Si hay algún error reproduciendo el sonido, simplemente continuamos
|
||||
pass
|
||||
|
||||
def recognize_speech(language="es-ES"):
|
||||
"""Captura audio del micrófono y lo convierte a texto"""
|
||||
recognizer = sr.Recognizer()
|
||||
|
||||
with sr.Microphone() as source:
|
||||
print(f"{Colors.BLUE}[Claude Voice]{Colors.END} {Colors.YELLOW}Escuchando...{Colors.END} (Presiona Ctrl+C para detener)")
|
||||
play_sound("start")
|
||||
|
||||
# Ajustar para ruido ambiental
|
||||
recognizer.adjust_for_ambient_noise(source, duration=0.5)
|
||||
try:
|
||||
audio = recognizer.listen(source, timeout=10, phrase_time_limit=15)
|
||||
print(f"{Colors.BLUE}[Claude Voice]{Colors.END} {Colors.GREEN}Procesando audio...{Colors.END}")
|
||||
|
||||
# Intentar reconocer usando Google Speech Recognition
|
||||
text = recognizer.recognize_google(audio, language=language)
|
||||
play_sound("stop")
|
||||
return text
|
||||
except sr.UnknownValueError:
|
||||
play_sound("error")
|
||||
print(f"{Colors.RED}No se pudo entender el audio{Colors.END}")
|
||||
return None
|
||||
except sr.RequestError as e:
|
||||
play_sound("error")
|
||||
print(f"{Colors.RED}Error en el servicio de reconocimiento: {e}{Colors.END}")
|
||||
return None
|
||||
except Exception as e:
|
||||
play_sound("error")
|
||||
print(f"{Colors.RED}Error: {e}{Colors.END}")
|
||||
return None
|
||||
|
||||
def send_to_claude(text, silent=False):
|
||||
"""Envía el texto reconocido a Claude Code"""
|
||||
if not text:
|
||||
return False
|
||||
|
||||
if not silent:
|
||||
print(f"{Colors.BLUE}[Claude Voice]{Colors.END} Enviando a Claude Code: {Colors.BOLD}{text}{Colors.END}")
|
||||
|
||||
try:
|
||||
# Usar la ruta de instalación de Claude Code
|
||||
claude_cmd = "claude" if os.system("which claude > /dev/null 2>&1") == 0 else "/usr/local/bin/claude"
|
||||
|
||||
# Enviar el texto como entrada a Claude
|
||||
result = subprocess.run([claude_cmd, text],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
check=False)
|
||||
|
||||
if result.returncode != 0:
|
||||
print(f"{Colors.RED}Error al ejecutar Claude Code: {result.stderr}{Colors.END}")
|
||||
return False
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"{Colors.RED}Error al ejecutar Claude Code: {e}{Colors.END}")
|
||||
return False
|
||||
|
||||
def interactive_mode(language="es-ES", continuous=False):
|
||||
"""Modo interactivo que escucha continuamente comandos de voz"""
|
||||
print(f"{Colors.BLUE}[Claude Voice]{Colors.END} {Colors.GREEN}Modo interactivo iniciado. Di tus instrucciones para Claude Code.{Colors.END}")
|
||||
print(f"{Colors.BLUE}[Claude Voice]{Colors.END} {Colors.YELLOW}Di 'salir' o 'terminar' para finalizar{Colors.END}")
|
||||
|
||||
try:
|
||||
while True:
|
||||
text = recognize_speech(language)
|
||||
|
||||
if text:
|
||||
text = text.strip()
|
||||
print(f"{Colors.BLUE}[Claude Voice]{Colors.END} {Colors.GREEN}Reconocido: {Colors.BOLD}{text}{Colors.END}")
|
||||
|
||||
# Verificar comandos de salida
|
||||
if text.lower() in ["salir", "terminar", "exit", "quit", "goodbye", "bye"]:
|
||||
print(f"{Colors.BLUE}[Claude Voice]{Colors.END} {Colors.YELLOW}Saliendo del modo de voz...{Colors.END}")
|
||||
break
|
||||
|
||||
# Enviar a Claude Code
|
||||
success = send_to_claude(text)
|
||||
|
||||
# Si no es modo continuo, salir después del primer comando exitoso
|
||||
if not continuous and success:
|
||||
break
|
||||
|
||||
# Pausa breve entre reconocimientos
|
||||
if continuous:
|
||||
time.sleep(1)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print(f"\n{Colors.BLUE}[Claude Voice]{Colors.END} {Colors.YELLOW}Modo de voz interrumpido por el usuario{Colors.END}")
|
||||
|
||||
print(f"{Colors.BLUE}[Claude Voice]{Colors.END} {Colors.GREEN}¡Hasta pronto!{Colors.END}")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Claude Code Voice - Convierte voz a texto para Claude Code')
|
||||
parser.add_argument('-l', '--language', default='es-ES', help='Idioma para reconocimiento (ej. es-ES, en-US)')
|
||||
parser.add_argument('-c', '--continuous', action='store_true', help='Modo continuo - escucha constantemente hasta que digas "salir"')
|
||||
parser.add_argument('-t', '--text', help='Texto a enviar directamente (sin reconocimiento de voz)')
|
||||
parser.add_argument('-s', '--silent', action='store_true', help='Modo silencioso - no muestra mensajes extra')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.text:
|
||||
# Modo de texto directo
|
||||
send_to_claude(args.text, args.silent)
|
||||
else:
|
||||
# Modo interactivo con reconocimiento de voz
|
||||
interactive_mode(args.language, args.continuous)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in a new issue