El EPG no es un campo, es una integración

Cuando alguien nuevo en operación de IPTV escucha "EPG" (Electronic Program Guide) piensa en algo simple: una lista de programas con hora de inicio y fin, mostrada debajo de cada canal. En la práctica, el EPG es el punto donde convergen todas las fuentes de captación de una cabecera —satélite, terrestre, feeds de terceros— cada una con su propio formato, su propia frecuencia de actualización y, casi siempre, su propia zona horaria de origen. La señal de video se valida con un número (bitrate, SNR, lock). El EPG se valida solo mirándolo, canal por canal, franja por franja.

En una cabecera con captación satelital (Canal+ Caribe) y terrestre (TDT Francia) con failover entre ambas, ya descrita en un post anterior sobre arquitectura multi-nodo, el EPG no puede tratarse como un adjunto de la señal. Es una pieza de infraestructura separada, con su propio pipeline, sus propios fallos y su propio monitoreo.

XMLTV: el formato que todo el mundo asume que entiende

La práctica estándar en TVHeadend, Stalker y la enorme mayoría de portales IPTV es consumir la guía en formato XMLTV: un XML con dos tipos de nodo, <channel> (definición del canal) y <programme> (un bloque de programación con inicio, fin y metadata). Un fragmento típico:

<channel id="canalplus.caribe">
  <display-name>Canal+ Caribe</display-name>
</channel>

<programme start="20260805190000 -0400" stop="20260805200000 -0400" channel="canalplus.caribe">
  <title lang="fr">Journal de 19h</title>
  <desc lang="fr">Actualités du jour.</desc>
</programme>

El detalle que casi nadie lee la primera vez: el timestamp de start y stop incluye el offset de zona horaria (-0400) explícitamente. Eso es exactamente lo que hace que el formato funcione entre fuentes distintas — y exactamente lo que se rompe cuando un grabber o un script intermedio normaliza mal ese offset antes de reinyectarlo al sistema.

De dónde sale el EPG real: grabbers, no adivinanzas

El EPG no lo genera TVHeadend ni Flussonic por sí solos — alguien tiene que traerlo desde una fuente externa (el sitio del operador, un feed de terceros, o el propio broadcast si el operador incrusta EIT/EPG en el stream). En una operación real, tres patrones conviven:

Detalle que importa

EIT y grabber externo casi nunca deben mezclarse para el mismo canal sin una regla de prioridad clara. Si ambos alimentan el mismo channel id en TVHeadend sin coordinación, se producen programas duplicados o solapados en la guía — visualmente esto se traduce en un STB mostrando dos "ahora" distintos para el mismo canal.

El problema real: mapear channel ID entre mundos que no se hablan

Cada fuente de EPG nombra sus canales a su manera. El EIT embebido identifica el canal por su service_id dentro del mux. Un grabber externo suele usar un slug propio (canalplus.caribe, cplus-caribe-fr, lo que el mantenedor del script haya elegido). El feed de un proveedor tercero trae su propio catálogo de IDs, distinto a ambos. Ninguno de los tres, por defecto, coincide con el channel number lógico que usa el portal Stalker para mostrarle el canal al STB.

El trabajo real de integración de EPG es, en el fondo, mantener una tabla de mapeo estable entre estos identificadores y el canal lógico interno. Cuando esa tabla no existe o se deja desactualizada:

La regla operativa que aplicamos: el mapeo vive en un solo lugar versionado (no en la configuración dispersa de cada herramienta), y cualquier cambio de fuente de EPG para un canal pasa primero por actualizar esa tabla, después por la configuración de TVHeadend o del portal.

Zona horaria: el bug que no se ve hasta que alguien se queja

En el post sobre arquitectura multi-nodo mencionamos el ajuste de zona horaria por canal como "el detalle que casi nadie maneja". Aquí es donde ese detalle se vuelve mecánico y hay que ejecutarlo bien:

  1. La fuente trae su propia hora local. Un feed de TDT Francia entrega horarios en hora de Europa Central; un feed satelital para audiencia caribeña puede entregar en UTC o en la hora local del operador de origen. Ninguno de los dos coincide, por defecto, con la zona horaria del televidente final en Estados Unidos.
  2. El offset del XMLTV es la fuente de verdad, no una suposición. Como el formato incluye el offset explícito en cada timestamp, la conversión correcta es tomar ese offset literal y convertirlo a la zona horaria de destino — nunca asumir que "el feed ya viene en la hora que necesito" sin verificarlo contra el offset real del XML.
  3. DST (horario de verano) rompe conversiones fijas. Un offset de conversión hardcodeado (por ejemplo, "restar 5 horas siempre") funciona la mitad del año y falla la otra mitad, porque Europa y Estados Unidos no cambian de horario de verano el mismo fin de semana. El síntoma clásico: durante dos o tres semanas al año, el EPG de un canal aparece corrido una hora exacta, hasta que alguien reporta que "el programa de las 8 empezó a las 7".
Lección operativa

La conversión de zona horaria del EPG nunca debe hacerse con un offset fijo calculado a mano. Hay que resolverla con una librería de zonas horarias con reglas DST reales (tipo tz database / IANA), aplicada por canal según la zona horaria de origen del feed y la zona horaria de destino de la audiencia — que pueden no coincidir con la ubicación física del servidor que procesa el EPG.

Frecuencia de actualización y ventanas de sincronización

No toda la guía necesita actualizarse con la misma urgencia. En la práctica conviene separar:

Sincronizar estas tres capas con la misma cadencia (por ejemplo, regenerar todo el XMLTV completo cada 15 minutos) desperdicia ciclos y aumenta la ventana de riesgo de que un grabber falle a mitad de descarga y deje el portal sin "ahora/después" durante ese ciclo. Separar la cadencia por tipo de dato reduce ese riesgo.

EPG en el portal Stalker: lo que el STB realmente necesita

Los STB MAG que consumen un portal Stalker no piden el XMLTV completo — el portal lo procesa y expone un API propio que el STB consulta bajo demanda: programación del canal actual, del canal siguiente en el zapeo, y la ventana de tiempo que el usuario tenga abierta en la guía. Dos consecuencias prácticas:

Fallos más comunes en producción

1. "Ahora/después" congelado

El grabber se ejecuta, pero silenciosamente falla a mitad de descarga (timeout de red, cambio de estructura HTML en el sitio origen si el grabber hace scraping) y deja el XMLTV anterior sin sobrescribir. El síntoma es una guía que parece funcionar pero muestra la programación de ayer. La mitigación real es comparar el timestamp de generación del XMLTV contra la hora actual y alertar si supera un umbral, no solo revisar si el cron "corrió" — un cron que corre y falla adentro sigue reportando éxito si nadie valida el contenido resultante.

2. Desfase de una hora durante transición DST

Ya descrito arriba: offsets hardcodeados que ignoran las reglas reales de horario de verano. Se detecta comparando, dos semanas antes de cada transición DST relevante (tanto la de origen como la de destino), un programa conocido contra la hora real de transmisión.

3. Programas duplicados o solapados

Cuando EIT embebido y grabber externo alimentan el mismo canal sin regla de prioridad, ambos escriben bloques de programación para la misma franja horaria. El portal o TVHeadend terminan mostrando dos programas simultáneos superpuestos en la guía. La solución no es técnica sino de proceso: una sola fuente autoritativa por canal, documentada, sin fallback silencioso a una segunda fuente que también esté activa.

4. Canal sin programación tras cambio de proveedor de grabber

Un grabber comunitario deja de mantenerse o cambia su convención de channel id, y el mapeo interno no se actualiza. El canal sigue transmitiendo video con normalidad; el EPG para ese canal específico simplemente desaparece. Vale la pena monitorear activamente "canales con cero programas en las próximas N horas" como una alerta separada del monitoreo de bitrate — son fallas completamente independientes.

Checklist antes de dar por lista la capa de EPG

Cierre

El EPG rara vez es la razón por la que se pierde un cliente en el primer mes, pero es una de las razones más comunes por las que un cliente se queja después de que "todo funciona". La señal de video es binaria: está o no está. La guía de programación falla en grados —un canal sin datos, un desfase de una hora, un duplicado— y esos grados son precisamente los que un monitoreo mal diseñado no detecta. Tratarla como una integración propia, con su propio pipeline y su propio monitoreo, es lo que separa una cabecera que "se ve bien en la demo" de una que sigue funcionando bien seis meses después, cuando cambia de horario de verano o el operador reubica un canal sin avisar.

Si estás evaluando montar o auditar la capa de EPG de una plataforma IPTV/OTT, hablemos.