02-ago: [proyecto] vigilancia - voz por edge-tts + casting a teles Google (pychromecast, enciende la tele en standby) + mensaje hablado limpio para Alexa/TVs
This commit is contained in:
95
vigilancia/voz.py
Normal file
95
vigilancia/voz.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import asyncio
|
||||
import os
|
||||
import socket
|
||||
import threading
|
||||
from http.server import HTTPServer, SimpleHTTPRequestHandler
|
||||
|
||||
import config
|
||||
|
||||
MEDIA_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "voz_media")
|
||||
_server = None
|
||||
|
||||
|
||||
def _ip_lan():
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
try:
|
||||
s.connect(("8.8.8.8", 80))
|
||||
return s.getsockname()[0]
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
def sintetizar(texto, nombre="alerta.mp3"):
|
||||
os.makedirs(MEDIA_DIR, exist_ok=True)
|
||||
ruta = os.path.join(MEDIA_DIR, nombre)
|
||||
try:
|
||||
import edge_tts
|
||||
|
||||
async def _gen():
|
||||
comunicador = edge_tts.Communicate(texto, config.VOZ_EDGE)
|
||||
await comunicador.save(ruta)
|
||||
|
||||
asyncio.run(_gen())
|
||||
return ruta
|
||||
except Exception as e:
|
||||
print(f"[Voz] Error sintetizando: {e}")
|
||||
return None
|
||||
|
||||
|
||||
class _Handler(SimpleHTTPRequestHandler):
|
||||
def __init__(self, *a, **kw):
|
||||
super().__init__(*a, directory=MEDIA_DIR, **kw)
|
||||
|
||||
def log_message(self, *a):
|
||||
pass
|
||||
|
||||
|
||||
def _arrancar_servidor():
|
||||
global _server
|
||||
if _server is not None:
|
||||
return
|
||||
try:
|
||||
_server = HTTPServer(("0.0.0.0", config.GOOGLE_TV_PUERTO), _Handler)
|
||||
threading.Thread(target=_server.serve_forever, daemon=True).start()
|
||||
except Exception as e:
|
||||
print(f"[Voz] No se pudo arrancar el servidor HTTP: {e}")
|
||||
|
||||
|
||||
def reproducir_en_teles(texto):
|
||||
if not config.GOOGLE_TV_ACTIVO:
|
||||
return
|
||||
ruta = sintetizar(texto)
|
||||
if ruta is None:
|
||||
return
|
||||
_arrancar_servidor()
|
||||
if _server is None:
|
||||
return
|
||||
|
||||
url = f"http://{_ip_lan()}:{config.GOOGLE_TV_PUERTO}/{os.path.basename(ruta)}"
|
||||
try:
|
||||
import pychromecast
|
||||
|
||||
chromecasts, browser = pychromecast.get_chromecasts(timeout=8)
|
||||
try:
|
||||
if config.GOOGLE_TV_NOMBRES:
|
||||
objetivos = [c for c in chromecasts
|
||||
if c.cast_info.friendly_name in config.GOOGLE_TV_NOMBRES]
|
||||
else:
|
||||
objetivos = chromecasts
|
||||
|
||||
if not objetivos:
|
||||
print("[Voz] No hay teles Google detectadas")
|
||||
return
|
||||
|
||||
for c in objetivos:
|
||||
try:
|
||||
c.wait(timeout=10)
|
||||
c.media_controller.play_media(url, "audio/mpeg", title=texto[:80])
|
||||
c.media_controller.block_until_active(timeout=10)
|
||||
print(f"[Voz] Reproduciendo en {c.cast_info.friendly_name}")
|
||||
except Exception as e:
|
||||
print(f"[Voz] Error en {c.cast_info.friendly_name}: {e}")
|
||||
finally:
|
||||
pychromecast.discovery.stop_discovery(browser)
|
||||
except Exception as e:
|
||||
print(f"[Voz] Error de casting: {e}")
|
||||
Reference in New Issue
Block a user