03-sep: [videoclub] Buscador interactivo + agentes/skills OpenCode + aviso por voz

This commit is contained in:
juanjo
2026-09-03 20:25:35 +02:00
parent 808fdd1806
commit b1296a0a07
39 changed files with 4917 additions and 40 deletions

122
scripts/aviso_sonoro.py Normal file
View File

@@ -0,0 +1,122 @@
"""
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 <frase> -> sintetiza y reproduce con edge-tts voz es-MX-DaliaNeural
(gratis e ilimitado). Voz preferida del usuario para
respuestas cortas.
toca <frase> -> sintetiza y reproduce con edge-tts (misma voz Dalia)
alarma <frase> -> 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()