// docs / websocket-obs
WebSocket y OBS
LiveAudio levanta un servidor WebSocket local que emite subtítulos en JSON en tiempo real. OBS es el destino integrado mediante el overlay incluido subtitulos_obs.html, pero cualquier cliente HTML o WebSocket en localhost puede conectarse y recibir la misma transmisión.
Detalles del servidor
| Parámetro | Valor |
|---|---|
| Protocolo | WebSocket (ws://) |
| Host | 127.0.0.1 (solo localhost) |
| Puerto | 8765 por defecto, configurable con ws_port |
| Formato | JSON |
| Autenticación | Ninguna — limitado a localhost |
Esquema del payload JSON
{
"id": "1760000000000-12",
"text": "Hola a todos, bienvenidos al stream",
"style": "default",
"created_at": 1760000000.0,
"processed_at": 1760000001.3,
"queue_delay": 0.2,
"total_delay": 1.3,
"latency": 1.1,
"is_replay": false,
"catchup_interval_sec": 0.0
} | Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador estable de la frase dentro de la sesión. |
text | string | Texto transcrito, luego del filtro de blacklist. |
style | string | Estilo visual: default, karaoke, neon, minimal, bold, rgb, typewriter. |
created_at | number | Timestamp de creación del segmento de audio. |
processed_at | number | Timestamp al terminar la transcripción. |
queue_delay | number | Segundos que el audio esperó antes de entrar al motor ASR. |
total_delay | number | Atraso total desde la captura hasta el subtítulo listo (de sub-segundo a ~1 s en un equipo típico). |
latency | number | Segundos que Whisper usó para transcribir el segmento. |
is_replay | boolean | Si es un subtítulo de backlog / catch-up. |
catchup_interval_sec | number | Pacing recomendado entre ítems de backlog en modo auto. |
El overlay de OBS integrado solo consume text y style. Los demás campos son metadata para diagnóstico y control de backlog — útiles si construyes tu propio cliente, ignorables si no.
Estilos de subtítulos
El campo style selecciona uno de siete looks integrados, conmutables desde la pestaña Subtítulos:
| Estilo | Aspecto |
|---|---|
default | Texto blanco sobre fondo negro semitransparente, fade suave de entrada/salida. |
karaoke | Las palabras aparecen escalonadas con animación popIn; amarillo brillante con contorno negro. |
neon | Glow cian, mayúsculas, espaciado amplio. |
minimal | Sin fondo, fade sutil — para streams con diseño propio. |
bold | Texto grueso de alto contraste, animación rápida, presencia fuerte en pantalla. |
rgb | Cada palabra toma un color distinto del arcoíris. |
typewriter | Las palabras se escriben una por una con cursor parpadeante; monoespaciado. |
Política de backlog en OBS
La política de backlog controla solo lo que se muestra en vivo en OBS. Todo lo válido siempre se guarda en disco, sin importar la política.
| Modo | Valor de config | Comportamiento |
|---|---|---|
| Auto | auto | Envía subtítulos frescos más un backlog corto con pacing. Omite lo que supere el atraso máximo. |
| Solo en vivo | live_only | Guarda todo; solo muestra lo que está dentro de subtitle_max_live_delay_sec. |
| Enviar todo | send_all | Envía todo a OBS aunque llegue tarde. |
Seguridad
- Solo localhost — el servidor rechaza cualquier conexión que no sea de
127.0.0.1,::1olocalhost. - No requiere autenticación, porque está limitado a localhost.
- Broadcast — múltiples clientes reciben los mismos mensajes a la vez.
Configurar el Browser Source de OBS
- En OBS, Fuentes → + → Navegador.
- Elige Archivo local y selecciona
subtitulos_obs.html(enliveaudio/assets/). Tamaño 1920×200. - Pon los FPS en
30o60y ubica la fuente en la parte inferior central de la escena. - Desactiva "Apagar la fuente cuando no esté visible" y "Actualizar el navegador cuando la escena se active" — ambas pueden cortar la conexión WebSocket.
- Para un puerto personalizado, configura
ws_portenconfig.json; el HTML de OBS lee?port=XXXXde su URL (default8765).
Comportamiento de la conexión
- Reconexión. Un cliente que pierde la conexión reintenta cada 3 segundos aproximadamente hasta que el servidor vuelve — el overlay incluido ya lo hace por ti.
- Broadcast. Cada cliente conectado recibe cada mensaje. Varios clientes (OBS más una pestaña de depuración) ven el mismo flujo, y un cliente lento no bloquea a los demás.
- Sin backpressure. Con
websockets ≥ 16el servidor usabroadcast(), que reparte sin esperar a ningún cliente en particular.
Construir tu propio cliente
Cualquier cliente WebSocket en localhost puede suscribirse a la misma transmisión que lee OBS. Un cliente mínimo en navegador — ábrelo directamente, o cárgalo como Browser Source en OBS:
<!-- open this file in a browser, or load it as an OBS Browser Source -->
<div id="caption"></div>
<script>
// ?port=XXXX overrides the default; matches ws_port in config.json
const port = new URLSearchParams(location.search).get("port") || "8765";
let ws;
function connect() {
ws = new WebSocket("ws://127.0.0.1:" + port);
ws.onmessage = (e) => {
const msg = JSON.parse(e.data); // the subtitle payload
document.getElementById("caption").textContent = msg.text;
};
// the server only broadcasts — reconnect every 3 s if it drops
ws.onclose = () => setTimeout(connect, 3000);
}
connect();
</script> O un cliente mínimo en Python, para imprimir cada payload a medida que llega (requiere el paquete websockets):
import asyncio, websockets
async def test():
async with websockets.connect("ws://127.0.0.1:8765") as ws:
async for msg in ws:
print(msg)
asyncio.run(test()) Señales de depuración
Abre el overlay en un navegador y presiona F12 → Consola. Estos mensajes indican dónde se traba un overlay que no muestra nada:
| Mensaje en consola | Significado |
|---|---|
Conectado al motor ASR | Conexión exitosa — el WebSocket está activo. |
Desconectado. Reintentando… | No conecta: LiveAudio no está iniciado, el puerto está ocupado, o el ?port= de la URL no coincide con ws_port. |
Error parseando WebSocket | Llegó al overlay un mensaje que no es JSON / no es un dict — el payload no era un objeto de subtítulo válido. |