Commit inicial: gr-locutor (Locutor IA - GRP)
Locuciones de radio con voz IA local (XTTS-v2) integradas a G Radio Player: interfaz Rust/GTK4 de configuración, motor de generación y enriquecimiento de texto en Python, daemon de monitoreo que dispara locuciones sin pausar playlist-refill. Requiere radio-player >= 0.4.11.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
# Arquitectura del Locutor Automático IA
|
||||
|
||||
## Componentes instalados
|
||||
|
||||
| Ruta | Rol |
|
||||
|---|---|
|
||||
| `~/.gradio/locutor-venv/` | Entorno virtual Python con el motor XTTS-v2 (torch, coqui-tts, transformers) |
|
||||
| `~/.gradio/locutor-venv/gr-locutor.sh` | Wrapper: `gr-locutor.sh "texto" [nombre]` → genera un MP3 |
|
||||
| `~/.gradio/data/locutor-ia/generar.py` | Script real de síntesis (llamado por el wrapper) |
|
||||
| `~/.gradio/data/locutor-ia/referencia/voz_referencia.wav` | Voz de referencia activa (genérica de GRP o la de la estación) |
|
||||
| `~/.gradio/data/locutor-ia/salida/` | MP3 generados |
|
||||
| `~/.gradio/data/locutor-ia/scripts/enriquecer-locucion.py` | Genera el texto: metadata ID3 + Wikipedia + MusicBrainz |
|
||||
| `~/.gradio/data/locutor-ia/scripts/generar-intro.sh` | Orquesta: texto enriquecido → `gr-locutor.sh` |
|
||||
| `~/.gradio/data/locutor-ia/scripts/monitor-locuciones.py` | Daemon: mantiene 3 locuciones listas en `playlist4` |
|
||||
| `~/.gradio/data/locutor-ia/scripts/start-monitor.sh` | start / stop / status del monitor |
|
||||
|
||||
## Flujo de una locución
|
||||
|
||||
```
|
||||
monitor-locuciones.py detecta que faltan locuciones en la ventana
|
||||
└── generar-intro.sh "/ruta/tema.mp3"
|
||||
├── enriquecer-locucion.py → texto (metadata + Wikipedia + MusicBrainz)
|
||||
└── gr-locutor.sh "texto" → generar.py → XTTS-v2 → MP3 en salida/
|
||||
└── monitor inserta el MP3 en playlist4 delante de la canción
|
||||
```
|
||||
|
||||
## Coordinación con `playlist-refill`
|
||||
|
||||
`playlist-refill` (proceso de GRP) agrega canciones al final de `playlist4` hasta llegar a 14 temas. Si corre a la vez que el monitor inserta locuciones, puede haber una carrera (leer-generar-escribir tarda varios segundos, y mientras tanto el player puede haber consumido temas).
|
||||
|
||||
Solución ya implementada: `monitor-locuciones.py` crea `~/.gradio/data/tmp/pause_refill` al iniciar (GRP ya respeta este archivo — es el mismo mecanismo del botón "Automático" de la UI) y lo borra al detenerse. **No hace falta ninguna acción manual** — `start-monitor.sh start/stop` lo maneja solo.
|
||||
|
||||
## Bandera de habilitación
|
||||
|
||||
`~/.gradio/data/tmp/locutor_auto` (`1`/`0`) — se controla desde el diálogo de Configuración de GRP ("Locutor Automático"). El monitor y el generador no deberían correr si está en `0`.
|
||||
|
||||
## Rendimiento medido (texto de referencia ~10s de audio)
|
||||
|
||||
| Máquina | Generar | Cargar modelo (1 vez) |
|
||||
|---|---|---|
|
||||
| Escritorio con GPU NVIDIA | ~2s | ~10s |
|
||||
| Escritorio CPU (20 hilos, sin GPU) | ~29s | ~10s |
|
||||
| RPi5 real (CPU, sin GPU) | ~104s | ~120s |
|
||||
|
||||
Todos entran en el margen de una canción de 3-4 minutos. La recomendación es **no correr el generador en la misma máquina que reproduce en vivo** salvo que tenga GPU o de sobra de RAM/CPU — en el RPi5 se midió presión real de memoria (swap) al generar en aislamiento.
|
||||
@@ -0,0 +1,44 @@
|
||||
# Formato de la locución enriquecida
|
||||
|
||||
Generado por `scripts/enriquecer-locucion.py`. Cada locución tiene 3 partes:
|
||||
|
||||
```
|
||||
{OPENER}, {TEMA}, {INFO ENRIQUECIDA}
|
||||
```
|
||||
|
||||
Y opcionalmente (50% de las veces) un **cierre** con el nombre de la emisora (leído de `gradio.config`, no hardcodeado) y un saludo según la hora del día.
|
||||
|
||||
## 1. Opener (aleatorio, uno de tres)
|
||||
|
||||
- **Curiosidad del país** (si MusicBrainz devuelve país de origen): *"¿Sabías que {país} es conocido por {dato}?"*
|
||||
- **Consejo ecológico**: *"Recuerda: {consejo}."* (banco fijo de frases sobre reducir huella de carbono)
|
||||
- **Dato turístico del país**: *"{País} ofrece {dato turístico}."*
|
||||
|
||||
## 2. Tema (siempre presente)
|
||||
|
||||
```
|
||||
"Escuchas {título} de {artista}"
|
||||
```
|
||||
|
||||
## 3. Info enriquecida
|
||||
|
||||
Según los datos disponibles: año de grabación, género, país de lanzamiento, y un dato de Wikipedia (1-2 oraciones) sobre el artista o la canción.
|
||||
|
||||
## 4. Cierre opcional (~50%)
|
||||
|
||||
```
|
||||
"Estás en sintonía con {nombre de la radio}. {saludo según hora}"
|
||||
```
|
||||
|
||||
El nombre de la radio se lee de `~/.gradio/data/tmp/gradio.config` (línea 3, campo `station_name`) — **nunca lo hardcodees**, cada estación tiene el suyo.
|
||||
|
||||
## Ejemplo completo
|
||||
|
||||
> "¿Sabías que México es el país con más patrimonios de la humanidad en América Latina? Escuchas Muriendo Lento de Moderatto con Belinda, un tema pop lanzado en México en 2007. Estás en sintonía con Radio Ejemplo. ¡Buenos días!"
|
||||
|
||||
## Fuentes de datos
|
||||
|
||||
- **Metadata ID3**: `mutagen` (título, artista, año, género) — si el archivo no tiene tags, se infiere del nombre `Artista - Título.mp3`.
|
||||
- **Wikipedia** (`es.wikipedia.org`): dato curioso, solo si hay artículo en español; si no, se omite (nunca se usa inglés).
|
||||
- **MusicBrainz**: país y año de lanzamiento.
|
||||
- **Caché**: `~/.gradio/data/tmp/locuciones_cache.json` — evita repetir consultas online del mismo artista/tema. Borrarlo fuerza consultas frescas.
|
||||
Reference in New Issue
Block a user