""" aviso_sonoro.py — Reproduce un aviso de voz al terminar una tarea. Uso: python scripts/aviso_sonoro.py [tipo] Tipos: fin (defecto) -> voz de aviso normal ok -> aviso normal error -> aviso normal importante -> voz destacada dalia -> sintetiza y reproduce con edge-tts voz es-MX-DaliaNeural (gratis e ilimitado). Voz preferida del usuario para respuestas cortas. toca -> sintetiza y reproduce con edge-tts (misma voz Dalia) alarma -> sintetiza y reproduce alarma con prioridad alta Reproduccion: usa PowerShell + WPF MediaPlayer (System.Windows.Media.MediaPlayer, PresentationCore), fiable para MP3 en Windows, en modo STA (apartment STA). """ import os import subprocess import sys import tempfile BASE = os.path.dirname(os.path.abspath(__file__)) SND = os.path.join(BASE, "sounds") # Voz por defecto: Dalia (edge-tts, gratis) DEFAULT_VOICE = "es-MX-DaliaNeural" DEFAULT_RATE = "-8%" def reproducir_ps(ruta): """Reproduce un MP3 via PowerShell + WPF MediaPlayer.""" r = ruta.replace("'", "''") ps = ( "Add-Type -AssemblyName PresentationCore; " "Add-Type -AssemblyName WindowsBase; " "$p = New-Object System.Windows.Media.MediaPlayer; " "$p.Open([Uri]'%s'); " "$p.Play(); " "Start-Sleep -Seconds 5; " "$p.Stop(); $p.Close()" % r ) subprocess.run( ["powershell", "-NoProfile", "-STA", "-Command", ps], capture_output=True, timeout=20, ) def sintetizar_dalia(texto, salida=None): """Sintetiza texto con edge-tts (gratis/ilimitado) usando la voz Dalia. Voz preferida del usuario para respuestas cortas de OpenCode.""" import asyncio try: import edge_tts except ImportError: print("[aviso_sonoro] ERROR: no esta instalado edge-tts (pip install edge-tts)") sys.exit(4) if salida is None: salida = os.path.join(SND, "aviso_dalia.mp3") try: asyncio.run(edge_tts.Communicate( texto, DEFAULT_VOICE, rate=DEFAULT_RATE).save(salida)) except Exception as e: print("[aviso_sonoro] ERROR edge-tts: %s" % e) sys.exit(5) reproducir_ps(salida) return salida def sintetizar_voz(texto, voz=None, rate=None, salida=None): """Sintetiza texto con edge-tts usando la voz indicada.""" import asyncio try: import edge_tts except ImportError: print("[aviso_sonoro] ERROR: no esta instalado edge-tts") sys.exit(4) voz = voz or DEFAULT_VOICE rate = rate or DEFAULT_RATE if salida is None: salida = os.path.join(SND, "temporal_voz.mp3") try: asyncio.run(edge_tts.Communicate( texto, voz, rate=rate).save(salida)) except Exception as e: print("[aviso_sonoro] ERROR edge-tts: %s" % e) sys.exit(5) reproducir_ps(salida) return salida def main(): args = sys.argv[1:] if args and args[0] == "dalia": frase = args[1] if len(args) > 1 else "Hola." salida = os.path.join(SND, "aviso_dalia.mp3") rut = sintetizar_dalia(frase, salida) print("[aviso_sonoro] dalia -> %s" % rut) return if args and args[0] == "toca": frase = args[1] if len(args) > 1 else "Aviso." salida = os.path.join(SND, "temporal_toca.mp3") rut = sintetizar_dalia(frase, salida) print("[aviso_sonoro] toca -> %s" % rut) return if args and args[0] == "alarma": frase = args[1] if len(args) > 1 else "Alerta de sistema." salida = os.path.join(SND, "temporal_alarma.mp3") rut = sintetizar_voz(frase, voz="es-ES-AlvaroNeural", rate="-5%", salida=salida) print("[aviso_sonoro] alarma -> %s" % rut) return tipo = args[0] if args else "fin" print("[aviso_sonoro] %s" % tipo) if __name__ == "__main__": main()