diff --git a/docs/guia-traduccion-autoservicio-inma-mixbot.md b/docs/guia-traduccion-autoservicio-inma-mixbot.md new file mode 100644 index 0000000..32254c1 --- /dev/null +++ b/docs/guia-traduccion-autoservicio-inma-mixbot.md @@ -0,0 +1,161 @@ +# Guía de traducción (EN/FR/IT/PT) en autoservicio — para Inma / Mixbot + +> **Para quién es este documento:** para Inma y Mixbot, a partir de la conversación del +> 2026-08-31 en Buzz: además del audio ([#222](https://gitea.feadulta.com/rafa/feadulta/issues/222), +> ver `docs/guia-tts-audio-autoservicio-inma-mixbot.md`), Rafa quiere traspasar también la +> traducción. A diferencia del audio, hoy **no hay un issue abierto pidiéndolo** — este +> documento adelanta el trabajo para cuando se dispare. +> +> **Motores autorizados por Rafa (2026-08-31):** un agente local con Haiku desde el propio +> Claude/Cowork de Inma (no la API de pago de Rafa — es otra cuenta, otro caso), o MiniMax +> con el mismo token ya compartido para el audio. **Gemma queda fuera para vosotros**: es un +> modelo local que corre en la GPU del PC de Rafa, no accesible desde fuera. + +--- + +## 0. Antes de nada: esto también tiene un tope bloqueante + +Igual que pasaba con el audio, **hoy no hay forma de decirle a WordPress "esta traducción +va en inglés y es la versión de este post en español"** desde fuera. Ese enlace (idioma + +grupo de traducción) lo gestiona Polylang con dos funciones PHP internas +(`pll_set_post_language`, `pll_save_post_translations`) que **no están expuestas por REST** — +ni siquiera de lectura (el único endpoint que hay, `fea/v1/lang/{id}`, solo lee el idioma, no +permite fijarlo ni enlazar grupos). + +Podéis crear el post traducido por `POST /wp/v2/posts` sin problema (igual que cualquier +artículo), pero **quedaría suelto**: sin idioma asignado y sin enlace Polylang al original en +español, así que el selector de idioma del sitio no lo encontraría y no contaría como "la +traducción EN de este artículo". + +**Esto necesita el mismo tipo de solución que el audio**: un endpoint `fea/v1/crear-traduccion` +(o registrar la taxonomía `language` de Polylang en REST con permisos de administrador) que +haga internamente lo mismo que ya hace `scripts/fea_translate_helper.php::create` en local: +crear el post, `pll_set_post_language($id, $lang)`, y `pll_save_post_translations($grupo)` +enlazándolo con el ES. No lo he encargado todavía — es una pieza más grande que la del audio +(toca la lógica central de multiidioma del sitio) y prefiero que Rafa decida el momento y el +alcance antes de que Codix la construya. Documento aquí el resto del proceso para que, en +cuanto ese hueco se cierre, solo falte la llamada final. + +--- + +## 1. Las reglas de traducción (igual las use vuestro Claude/Haiku o MiniMax) + +Esto es el prompt real que usa el pipeline de Rafa (`scripts/translate_post.py`), verificado +palabra por palabra el 2026-08-31 contra el código — usadlo tal cual, no lo resumáis: + +> Eres un traductor profesional de textos religiosos cristianos (espiritualidad y teología +> católica). Traduce del español al {idioma destino}. REGLAS ESTRICTAS: +> 1. Conserva EXACTAMENTE el marcado HTML (etiquetas y atributos) y los shortcodes entre `[ ]` +> y `{ }`. No los traduzcas ni los reordenes. +> 2. NO traduzcas las referencias bíblicas ni sus abreviaturas (p. ej. "Jn 3, 16", "Isaías 5, +> 1-7", "Mt 5"). Déjalas idénticas. +> 3. Conserva los nombres propios de persona y lugar (salvo exónimos establecidos). +> 4. Glosario fijo: "Fe Adulta" → "Fe Adulta" (en/fr/it/pt, no se traduce); "EFFA" → "EFFA" +> (igual, en los 4 idiomas). +> 5. Traducción FIEL: no resumas, no añadas, no comentes. + +Para el **título**, además: que quede natural en el idioma destino (no lo dejéis en español +salvo que sea un nombre propio o una marca), y si es un modismo, traducid el sentido, no lo +calquéis literal. + +## 2. El "learning" del título — dadle el primer párrafo como contexto + +Esto es lo que pedía Rafa explícitamente documentar. **Aviso de precisión:** este cambio +existe como commit (`4475ebb`, rama `feat/issue-200-title-context`) pero **no está fusionado +a `main`** — verificado el 2026-08-31 comparando el histórico. O sea: si alguna vez volvéis a +usar `scripts/translate_post.py` tal cual desde main, el título se traduce SIN este contexto. +Para vuestro proceso propio (agente Haiku o llamada directa a MiniMax) aplicad la técnica de +todas formas, es la que ya dio mejor resultado en pruebas: + +- **Traducid primero el cuerpo del artículo, el título al final** — necesitáis el cuerpo ya + traducido (o al menos leído) para poder darle contexto al título. +- Al traducir el título, añadid al prompt el **primer párrafo del cuerpo en español** + (recortado a 2000 caracteres), como contexto de significado — no se traduce ni se incluye + literal en la salida, solo ayuda al modelo a entender modismos o dobles sentidos del + título que sin ese contexto salen mal traducidos. +- Instrucción exacta añadida al prompt del título: *"Si es un modismo, interpreta su sentido + según el contexto, no lo calques."* + +## 3. Troceo de artículos largos + +Si usáis MiniMax para traducir (no Haiku, que admite el artículo entero de una vez gracias a +su contexto de 200k), trocead el HTML por párrafos completos (nunca a mitad de una etiqueta) +en bloques de ~5.000 caracteres, y unid las traducciones de cada trozo en el mismo orden. + +## 4. QA — checklist antes de dar una traducción por buena + +Reformulado en REST puro (el script original, `gate_mec2.php`, corre dentro de WP y usa +funciones de Polylang no disponibles desde fuera — pero las comprobaciones sí son igual de +válidas mirando el JSON de cada post por la API): + +Para cada origen ES y cada idioma que hayáis traducido, comparad contra el post ES: + +1. **Cobertura**: los 4 idiomas presentes (o los que toque — Pagola nunca lleva traducción + automática, ver §5). +2. **Estado**: la traducción en `draft` hasta que se revise (salvo que el ES ya esté + `publish` y la carta lo pida — ver `docs/guia-publicacion-carta-inma.md`). +3. **Sin residuos de generación**: buscar literalmente en el `content` devuelto por la API + cadenas como `**`, ``, `<>`, `<<>>`, `<<>>`, + `|||FIN`, o cualquier resto de las marcas del prompt. +4. **Sin alfabetos ajenos**: ningún carácter árabe/cirílico/CJK en el resultado (residuo + típico de generación que se cuela cuando el modelo "piensa" en otro idioma). +5. **Mismo nº de párrafos** que el ES (contar apariciones de ``** que el ES — **es el check que más falla y el más + importante**: en la carta 739, el italiano perdió 15 de 39 enlaces en uno de los trozos + troceados mientras EN/FR salieron bien, y nada posterior lo detecta si no lo comprobáis + aquí. Si hay menos enlaces en la traducción que en el ES, **no la deis por buena**. +7. **Referencias bíblicas equivalentes**: extraer patrones tipo `capítulo,versículo` de + ambos textos y comparar solo capítulo:versículo, **no la abreviatura del libro completa** + (el inglés cambia la coma por dos puntos y traduce el nombre: `Mt 15,21-28` en ES pasa a + `Matthew 15:21-28` en EN — comparar literal daría un falso positivo de "referencia + perdida"). +8. **Título distinto del ES** (salvo portugués, donde algunos nombres propios/citas + coinciden de forma legítima). + +Capa editorial adicional si tenéis acceso a un modelo capaz de juzgar fidelidad (vuestro +Claude/Haiku local sirve para esto): pedidle que lea origen y traducción y devuelva un +veredicto `approve` / `needs_review` / `rewrite` con la cita exacta del problema — descartad +cualquier hallazgo cuya cita no aparezca literal en el texto (evita ediciones basadas en +alucinaciones del propio revisor). + +## 5. Excepciones que no lleváis por la vía automática + +- **Autores que aportan su propia traducción humana** (hoy, Pagola: 4 DOCX por carta, + adjuntos en el issue de la semana) — nunca generéis fallback automático para ellos aunque + falte alguno de los 4 idiomas. +- **Textos litúrgicos enlazados desde la carta** (evangelio, lecturas) — confirmar con Rafa + si entran en el alcance de "todo lo de la carta" o se dejan fuera; ha habido confusión + antes sobre esto (no dar por hecho que "ya deben estar traducidos"). + +## 6. Cómo leer la cuota de MiniMax + +Con el mismo token que ya tenéis para el audio: + +```bash +curl -s https://api.minimax.io/v1/token_plan/remains \ + -H "Authorization: Bearer " -H "Content-Type: application/json" +``` + +Del JSON de respuesta: +- `base_resp.status_code` debe ser `0` (cualquier otro valor es error de cuenta/plan, ver + `base_resp.status_msg`). +- `model_remains` es una lista por modelo. El de texto/traducción es el que tiene + `model_name == "general"`; los de audio son los `speech-2.8-*` que ya usáis para TTS. +- De cada entrada: `current_interval_remaining_percent` (cuánto queda de la ventana de 5h + que se resetea sola — `end_time` es cuándo) y `current_weekly_remaining_percent` / + `weekly_end_time` (la ventana semanal, más amplia). Restad a 100 para saber "cuánto habéis + gastado" si preferís verlo así. + +Igual que con el audio: un HTTP 200 no es garantía de cuota — cuando `t2a_v2` o el endpoint +de traducción devuelvan `base_resp.status_code=2056` (plan agotado) o `1039` (límite de +ritmo), parad y reintentad más tarde, no machaquéis la API. + +## 7. Qué falta para que esto sea autoservicio de verdad + +- **Bloqueante (§0):** endpoint o mecanismo para fijar idioma + enlazar grupo Polylang de + cada traducción — sin esto podéis generar el texto pero no "engancharlo" al sitio como + traducción real, igual que pasaba con el audio antes del #222. +- Decisión pendiente de Rafa (no la resuelvo yo aquí): si vuestro agente de traducción va a + tener acceso de shell/SSH al WordPress (como tenía Hermes) o va a ser puramente REST como + el resto de vuestro trabajo — cambia bastante el diseño del endpoint que haría falta. diff --git a/docs/guia-tts-audio-autoservicio-inma-mixbot.md b/docs/guia-tts-audio-autoservicio-inma-mixbot.md new file mode 100644 index 0000000..3b20a08 --- /dev/null +++ b/docs/guia-tts-audio-autoservicio-inma-mixbot.md @@ -0,0 +1,268 @@ +# Guía de generación de audio (TTS) en autoservicio — para Inma / Mixbot + +> **Para quién es este documento:** para Inma y Mixbot, a partir del traspaso pedido por +> Rafa (issue [#222](https://gitea.feadulta.com/rafa/feadulta/issues/222)): dejar de pedirle +> el audio a Hermes y generarlo y subirlo vosotros mismos, con vuestro propio token de MiniMax. +> +> **Estado a 2026-08-31:** completo y **desplegado en producción**. El endpoint +> `fea/v1/subir-audio` (PR [#224](https://gitea.feadulta.com/rafa/feadulta/pulls/224)) ya está +> en prod y verificado de extremo a extremo por Claudix con una subida real. El punto 1 del +> #222 queda cerrado — ver §6 para la llamada real. +> +> Este documento sustituye, para el caso de uso "Inma/Mixbot generan directamente", a la +> sección 4 de `docs/guia-tts-traduccion-inma.md` (que describe el flujo antiguo vía Hermes +> ejecutando `scripts/tts_produce.py` en el PC de Rafa). Ese flujo sigue existiendo como +> alternativa si alguna vez hace falta que Hermes lo dispare, pero deja de ser el camino +> principal. + +--- + +## 1. Por qué este documento existe + +La generación de audio con MiniMax no es "coger el texto del artículo y pedirle un mp3". +El resultado suena mal (entonación cortada, pausas artificiales o inexistentes, sección de +cabecera/firma leída en voz alta) si no se prepara el texto antes. Todo lo de abajo salió de +prueba y error real sobre cartas ya publicadas — no es una recomendación genérica de MiniMax, +es la receta que ya suena bien en producción. Seguidla tal cual, no la simplifiquéis. + +## 2. La cuenta y las voces + +- **Endpoint:** `https://api.minimax.io/v1/t2a_v2` (modelo de síntesis). +- **Modelo:** `speech-2.8-hd` (calidad) o `speech-2.8-turbo` (más barato, para pruebas). +- **Voces clonadas por autor** (issue #152 — solo estos autores usan su propia voz; el resto + cae a la voz por defecto): + + | Autor | WP user_id | `voice_id` | + |---|---:|---| + | Fray Marcos | 382 | `FrayMarcosFeadulta2026` | + | José Antonio Pagola | 383 | `PagolaFeadulta2026` | + | José Luis Sicre | 774 | `SicreFeadulta2026` | + | José Arregi | 386 | `ArregiFeadulta2026` | + +- **Voz por defecto (resto de autores):** confirmar con Rafa cuál es la vigente antes de + arrancar — hay más de una en la cuenta (`NicoFeadulta2026` y una más reciente, + `nico_feadulta_es_20260802`) y usar la que no toca es un error fácil de cometer sin verlo + (issue #189, todavía sin cerrar del todo). **No deis por hecho ninguna de las dos sin + preguntar primero.** +- Un autor nuevo sin voz clonada = voz por defecto. Clonar una voz nueva requiere el + procedimiento del #152 (audio limpio 2-5 min, sin música de fondo) — no es autoservicio + desde este documento, es un paso aparte. + +## 3. Preparar el texto (la parte que importa) + +Partiendo del **HTML del artículo en español** (el campo `content` que devuelve +`GET /wp-json/wp/v2/posts/{id}?context=edit`), en este orden exacto: + +### 3.1 Limpiar el HTML a texto plano por párrafos + +1. Sustituir `

`, `
`/`
` y ``…`` por un salto de línea. +2. Quitar el resto de etiquetas HTML. +3. Quitar shortcodes `[...]` (multimedia, cajas, etc. — no se locutan). +4. Decodificar entidades HTML (`á` → `á`, etc.). +5. Separar en párrafos por línea, colapsar espacios múltiples, descartar líneas de 1 + carácter o menos (restos de saltos vacíos). + +### 3.2 Cortar la firma final del autor + +Los artículos suelen terminar con una línea corta tipo `José Antonio Pagola` o +`Fray Marcos` — hay que **conservar esa línea y cortar todo lo que venga después** +(enlaces, notas, anexos), porque eso sí sobra en el audio. + +Cómo detectarla (mirando desde el final del artículo hacia atrás, no desde el principio): +un párrafo cuenta como firma si tiene entre 2 y 6 palabras, ninguna palabra supera lo +razonable para un nombre propio, no contiene dígitos ni `:`, `;`, `http`, `www.`, `@`, y +cada palabra empieza en mayúscula (se permiten minúsculas para conectores como "de", "del", +"la", "las", "los", "y", "e"). **Importante:** solo cuenta como firma si hay al menos 200 +caracteres de contenido real *antes* de ese párrafo — si no, podéis confundir un encabezado +inicial corto (p. ej. `"CORPUS (A)"`, `"DOMINGO XI (A)"`) con la firma y cortar el artículo +entero por error. Buscad la firma desde el final, quedaos con el primer párrafo (contando +desde atrás) que cumpla la condición, y descartad todo lo posterior. + +### 3.3 Expandir abreviaturas bíblicas + +MiniMax lee mal `Mt 5, 1-12`. Antes de generar el audio, expandir el nombre del libro +cuando la abreviatura va seguida de un número (cita bíblica): `Mt` → `Mateo`, `Mc` → `Marcos`, +`Lc` → `Lucas`, `Jn` → `Juan`, `Rom`/`Rm` → `Romanos`, etc. Hay un listado largo de ~70 +abreviaturas en `scripts/minimax_tts.py::expand_bible_abbreviations` (repo `joomla-migration`) +— reutilizadlo tal cual en vez de rehacer la lista a mano, es fácil dejarse alguna. + +### 3.4 Insertar pausas — el hallazgo central de este documento + +MiniMax soporta marcas de pausa literales dentro del texto: `<#0.3#>` inserta 0,3 s de +silencio en ese punto exacto. Sin estas marcas el audio suena corrido y sin respiración; +poniendo una pausa fija igual en todos los puntos suena robótico. La receta que sí funciona +es **pausa proporcional a la longitud de la frase que se acaba de cerrar**: + +- Tras cada fin de frase (`.`, `!`, `?`, `…`), calcular el nº de palabras de esa frase: + - frase corta (< 6 palabras) → pausa **0,1 s** + - frase media (6-12 palabras) → pausa **0,2 s** + - frase larga (> 12 palabras) → pausa **0,3 s** + (umbrales configurables, pero estos son los que ya suenan bien; no hace falta tocarlos) +- Entre párrafos (allí donde había una línea en blanco en el original) → pausa fija de + **0,7 s**, más larga que cualquier pausa de frase — es lo que hace que el oído perciba el + cambio de idea/tema. +- La última pausa de frase de cada párrafo se descarta (queda sustituida por la del + párrafo, que ya es más larga — poner las dos seguidas suena a silencio muerto). +- **Todo bloque (título, párrafo) que no termine en signo de puntuación se cierra con un + punto antes de generar el audio.** Sin esto, MiniMax deja la entonación "abierta" en el + aire al final de un título o frase cortada — se nota mucho y es fácil no darse cuenta en + texto pero sí al oído. + +Ejemplo de transformación (simplificado): + +``` +Entrada: "Jesús les dijo esto. Y añadió una frase mucho más larga sobre lo que significaba + seguirle de verdad en el día a día.\n\nOtro párrafo distinto." + +Salida: "Jesús les dijo esto. <#0.1#> Y añadió una frase mucho más larga sobre lo que + significaba seguirle de verdad en el día a día. <#0.7#> Otro párrafo distinto." +``` + +(la frase corta cerró con 0,1s pero esa marca se sustituye por la de párrafo 0,7s al ser la +última del bloque; la larga, al no ser la última del párrafo, habría llevado 0,3s si hubiera +seguido más texto en el mismo párrafo). + +Referencia de implementación exacta (por si hay dudas de un caso concreto): +`scripts/minimax_tts.py::add_pauses` + `_sent_pause` + `ensure_terminal_punctuation`. + +### 3.5 Trocear si el texto es largo + +MiniMax limita cada petición a 10.000 caracteres; dejamos margen porque las marcas de pausa +también cuentan, así que **el límite práctico es 8.000 caracteres por petición**. Cartas +largas hay que trocearlas: + +- Cortar **solo por los puntos donde ya hay una marca de pausa** (nunca a mitad de frase). +- Entre petición y petición, **esperar 35 segundos** — es el límite de ritmo (TPM) de la + cuenta MiniMax; sin esta espera, la segunda petición puede fallar aunque quede cuota. +- Los fragmentos de audio resultantes se concatenan con `ffmpeg` (`concat` a nivel de audio, + sin recodificar más de lo necesario) para producir un único mp3 final. + +## 4. Llamar a la API + +``` +POST https://api.minimax.io/v1/t2a_v2 +Authorization: Bearer +Content-Type: application/json + +{ + "model": "speech-2.8-hd", + "text": " ya insertadas>", + "voice_setting": {"voice_id": "", "speed": 1.0, "vol": 1.0, "pitch": 0}, + "audio_setting": {"sample_rate": 32000, "bitrate": 128000, "format": "mp3", "channel": 1}, + "language_boost": "Spanish" +} +``` + +La respuesta trae el audio en `data.audio` como **hexadecimal**, no base64 — decodificarlo a +bytes antes de escribir el mp3. + +### Errores de cuota — no reintentéis en bucle + +Si `data.audio` viene vacío, mirad `base_resp.status_code`: + +- **`2056`** = cuota del plan agotada (se resetea con el tiempo, horas). +- **`1039`** = límite de ritmo por minuto (TPM) — bajad la cadencia, no lo repitáis al + segundo siguiente. + +Un HTTP 200 **no significa que haya audio** — hay que mirar siempre el `base_resp` del +cuerpo. Ante cualquiera de estos dos códigos: **parad y reintentad más tarde**, no +machaquéis la API en bucle esperando que cambie. + +**Cómo comprobar la cuota disponible antes de lanzar una tanda** (importante si vais a +procesar el backlog histórico del #188 además de la carta semanal, para repartir bien las +ventanas de 5h): + +```bash +curl -s https://api.minimax.io/v1/token_plan/remains \ + -H "Authorization: Bearer " -H "Content-Type: application/json" +``` + +Buscad en `model_remains` la entrada cuyo `model_name` sea el modelo que vayáis a usar +(`speech-2.8-hd`/`speech-2.8-turbo`). Cada entrada trae +`current_interval_remaining_percent` (lo que queda de la ventana de 5h, y `end_time` de +cuándo se resetea) y `current_weekly_remaining_percent`/`weekly_end_time` (la ventana +semanal). Con eso podéis calcular cuántos audios caben antes de la próxima ventana y +programar el resto para la siguiente, en vez de descubrirlo con un `2056` a mitad de tanda. + +## 5. Acabado del audio (opcional pero es lo que suena en producción) + +El pipeline actual aplica dos retoques más al mp3 antes de darlo por bueno — no son +obligatorios para que el audio "funcione", pero sí para que suene igual que el resto del +catálogo ya publicado: + +1. **Ruido de confort:** una capa de ruido marrón muy suave (`amplitude=0.004`, filtrado + paso-alto 120 Hz / paso-bajo 3800 Hz) mezclada con el audio entero. Sin esto, los + silencios de las pausas `<#…#>` contrastan de forma audible con el suelo de ruido del + habla generada — se nota como un "hueco" en vez de una pausa natural. +2. **Fade in/out:** entrada suave de 0,08 s y salida de 0,5 s en los últimos 0,5 s del + audio, para evitar un corte brusco ("bump") al final. + +Receta `ffmpeg` exacta usada hoy (referencia: `scripts/minimax_tts.py::t2a`, líneas finales): + +```bash +ffmpeg -y -i entrada.mp3 -filter_complex \ + "anoisesrc=color=brown:amplitude=0.004:sample_rate=32000[n];\ + [n]highpass=f=120,lowpass=f=3800[nf];\ + [0:a][nf]amix=inputs=2:duration=first:dropout_transition=0:normalize=0[m];\ + [m]afade=t=in:st=0:d=0.08,afade=t=out:st=:d=0.5[a]" \ + -map "[a]" -b:a 128k salida.mp3 +``` + +Si vuestro entorno de generación no tiene `ffmpeg` disponible, generad el audio igual sin +este paso y avisad a Rafa/Claudix — es preferible subir un audio sin el acabado a no subir +nada, pero que quede constancia de que ese paso se saltó (para que quien revise sepa por qué +suena ligeramente distinto al resto). + +## 6. Subir el resultado al artículo + +El endpoint que faltaba ya está desplegado en producción (#224), con el mismo patrón que +`fea/v1/subir-avatar` (#175) que ya usáis: + +``` +POST https://www.feadulta.com/wp-json/fea/v1/subir-audio +Authorization: Basic (o el header equivalente que useis) +Content-Type: multipart/form-data + +post_id= +audio= +voice_id= +``` + +Respuesta (`201`): + +```json +{ + "post_id": 56785, + "audio_url": "https://www.feadulta.com/wp-content/uploads/tts/56785.mp3", + "voice_id": "NicoFeadulta2026", + "sha256": "", + "previous_audio": {"url": null, "voice": null, "done": null, "sha256": null, "error": null} +} +``` + +`previous_audio` trae el estado de antes de vuestra subida (o todo `null` si el post no tenía +audio) — guardadlo si vais a reemplazar un audio ya publicado, por si hay que deshacer. + +**Límite real: 25 MiB por fichero** (`upload_max_filesize`/`post_max_size` del servidor, y el +propio endpoint valida lo mismo con un mensaje claro). Los audios de la carta semanal rondan +5-6 MB, así que hay margen — pero si algún artículo muy largo genera un mp3 más grande, +avisad en vez de forzarlo: el límite se fijó a propósito en 25 MiB (no en los 256 MiB que se +había propuesto al principio) porque el caso de 198 MB del #212/#190 era un error de +generación a corregir, no un tamaño a soportar. + +Solo admite `.mp3`/`audio/mpeg` — mismo nivel de permiso que el resto de endpoints `fea/v1` +de escritura (vuestro usuario Editor/Administrator). Verificado por Claudix el 2026-08-31 con +una subida real de extremo a extremo contra prod (post desechable, borrado después). + +## 7. Lo que NO cambia con este traspaso + +- Las traducciones (EN/FR/IT/PT) siguen, de momento, por el camino de siempre + (`docs/guia-tts-traduccion-inma.md`, motor Gemma/MiniMax vía Hermes) — este documento + cubre solo audio. Si el traspaso de traducciones también avanza, hará falta un documento + equivalente a este (y probablemente el mismo tipo de hueco de REST para enlazar las + traducciones vía Polylang) — no asumáis que ya está resuelto por analogía con el audio. +- El backlog histórico de TTS (issue #188, ~1.700 audios pendientes) es un problema aparte + de mucho más volumen que la carta semanal (~15-20/semana). Si el traspaso del #222 incluye + también ese backlog, es una decisión de Rafa que hay que confirmar explícitamente antes de + empezar — no arranquéis el backlog solo porque ya tengáis el mecanismo funcionando para la + carta semanal. diff --git a/docs/guia-tts-traduccion-inma.md b/docs/guia-tts-traduccion-inma.md index dfdaa18..f6b686e 100644 --- a/docs/guia-tts-traduccion-inma.md +++ b/docs/guia-tts-traduccion-inma.md @@ -8,6 +8,19 @@ > audio solo al publicar — esa automatización es la propuesta abierta > [issue #23](https://gitea.feadulta.com/rafa/feadulta/issues/23), sin implementar. Todo lo de > abajo es un proceso que **hay que pedir**, hoy solo ejecutable en el servidor/PC de Rafa. +> +> **Actualización 2026-08-31 (issue [#222](https://gitea.feadulta.com/rafa/feadulta/issues/222)):** +> el **audio (TTS)** deja de depender de Hermes — Inma/Mixbot lo generan y suben con su propio +> token de MiniMax. La §4 de abajo describe el flujo viejo (Hermes ejecutando +> `scripts/tts_produce.py` en el PC de Rafa); para el flujo nuevo de autoservicio, con la receta +> exacta de preparación de texto y pausas, usar +> **`docs/guia-tts-audio-autoservicio-inma-mixbot.md`**. Rafa confirmó el mismo día que las +> **traducciones** van también hacia autoservicio (agente local con Haiku desde el Claude de +> Inma, o MiniMax con el mismo token) aunque todavía sin un issue como el #222 que lo dispare +> — ver **`docs/guia-traduccion-autoservicio-inma-mixbot.md`** para las reglas, el QA y el +> hueco de infraestructura equivalente (falta enlazar idioma/grupo Polylang por REST). La §3 +> de abajo sigue describiendo el flujo viejo vía Hermes, todavía válido mientras no se cierre +> ese hueco. ---