Muxer — Statistical Multiplex

TSDuck-based MPEG Transport Stream multiplexer with full PSI/SI support

Multiplexor MPTS & Statmux Híbrido Adaptativo

El mux de Stream Manager ensambla múltiples transmisiones SPTS en una salida MPTS CBR (DVB/IPTV). El Statmux Híbrido Adaptativo combina un relleno CBR base con codificadores VBR equilibrados para una salida de mux constante.

1. Capa de codificador (FFmpeg por transmisión)

Cuando el mux padre tiene statmux habilitado, cada codificador FFmpeg ejecuta VBR con límite: -b:v <promedio> -minrate <min> -maxrate <max> -bufsize <max×2>. El búfer VBV = 2× max proporciona ~2 s de margen de pico. Las transmisiones de statmux también obtienen un desplazamiento de GOP determinístico (-force_key_frames) por stream_id para que los picos de cuadro I no coincidan entre canales.

2. Capa de mux (canalización tsp de TSDuck)

tsp -I null (∞ paquetes NULL a tasa de línea) → -P merge tsp -I ip <stream> (superpone paquetes reales) → -P continuity (alarma de caída) → -P pcradjust --bitrate X (reescribe PCRs) → -P pcrverify --jitter-max 500µs → -P bitrate_monitor (alarma de tasa ±5%) → -P regulate --bitrate X --packet-burst 32 → -O ip <out> --packet-burst 7 --enforce-burst.

3. Capa de salida (UDP)

El plugin regulate emite exactamente mux.bitrate bps en el cable. Las entradas que van rezagadas → paquetes NULL llenan la brecha. Las entradas que se disparan → búfer FIFO interno (4096 paquetes ≈ 0.3 s @ 19 Mbps) lo absorbe. --enforce-burst fuerza 7 paquetes TS por datagrama UDP (1316 B, estándar IPTV).

Tamaño recomendado (Σ mín / promedio / máx vs mux.velocidad de bits)

La barra superior del mux muestra 3 sumas con estado de color. Reglas:

Σ avg ≤ 85 % mux.bitrate — suma de objetivos promedio en todos los canales más audio. Ese es el "presupuesto" del mux. El 15 % de reserva estadística protege contra la coincidencia de picos. Verde ≤ 85 %, ámbar ≤ 100 %, rojo > 100 %.

Σ max ≤ 160 % mux.bitrate — suma de techo de pico. Se permite exceder la capacidad (ese es el punto de statmux — los picos rara vez coinciden). Verde ≤ 160 %, ámbar ≤ 200 %, rojo > 200 % (caídas en pico sostenido).

Σ min ≤ 50 % mux.bitrate — piso del codificador. Un piso seguro asegura que en escenas estáticas el codificador no baje a una calidad innecesariamente baja. Verde ≤ 50 %, ámbar ≤ 90 %, rojo > 90 %.

Ejemplo: 4 canales HD en un mux DVB-T de 19 Mbps

Presupuesto disponible después de PSI/SI/EIT: ~18.5 Mbps. Σ avg = 4 × 4.0 = 16 Mbps (86 % — límite ámbar, reducir un poco más). Σ max = 4 × 6.0 = 24 Mbps (130 % — verde, OK). Σ min = 4 × 3.0 = 12 Mbps (65 % — ámbar, OK). Objetivo: avg ~85 % del presupuesto, max ≤ 160 %.

Diagnósticos y alarmas

Con ≥ 10 alarmas en 60s aparece una notificación flash en la IU del Mux recomendando una reducción de bitrate. El retroceso automático NO está activo — el operador decide.

-P bitrate_monitor --periodic 60 --min/max ±5% — alarma si la tasa real se desvía más allá de ±5 % del objetivo. Significa que regulate está fambrido (murió la entrada).

-P continuity — rastrea los contadores de continuidad TS. Registra una advertencia en cada caída (sobresuscripción, crash de FFmpeg, jitter de NIC).

-P pcrverify --jitter-max 500000 — DVB permite jitter de PCR ≤ 500 µs. Alarma = pcradjust no puede mantener el ritmo o la fuente tiene PCRs rotas.

Fallos y sus causas

Coincidencia de GOP — todos los codificadores emiten fotogramas I simultáneamente, coincidencia de picos. Solución: desplazamiento de GOP (ya activado para statmux, hash(stream_id) mod gop_size).

Pérdida de señal de entrada — un solo canal se pone negro, el mux continúa (gracias a la base -I null). Duración ~3-8 s para reinicio de FFmpeg.

Sobresuscripción (picos sostenidos > capacidad) — bloqueos/ecos de audio ~50-200 ms. Solución: reducir avg del canal un 5-10 % o eliminar un canal.

Deriva de PCR — stutter del STB cada pocos segundos. Solución: pcradjust en la canalización (ya está), vigilar las alarmas pcrverify.

Underrun VBV del STB — el STB pierde sincronización y la recobra (~2-3 s). Solución: bufsize del codificador = 2 × maxrate (ya está), reducir maxrate.

Parámetros de canalización tsp (mux_worker.ex)

--max-input-packets 4096 / --max-flushed-packets 4096 (FIFO interno ≈ 0.3 s @ 19 Mbps). --receive-buffer-size 16777216 (16 MB búfer rcv UDP por entrada). --packet-burst 32 (regulate) / 7 (salida, estándar IPTV). --enforce-burst (cada datagrama UDP tiene exactamente 7 paquetes).

Cálculo empírico de capacidad (CLT)

La insignia `📐 rec X.XM` de la barra superior muestra la capacidad mux recomendada derivada del teorema del límite central. La suma de transmisiones VBR independientes se aproxima a una distribución normal, por lo que Mux = μ_total + z·σ_total + margen. σ_i se estima a partir del rango VBR de cada entrada como (max−min)/4 (asumiendo que el rango cubre ±2σ). El margen = 10% de μ_total compensa la sobrecarga de PSI/SI, la fluctuación del control de tasa del codificador y la correlación de transmisiones que el CLT puro subestima.

Color de la insignia: 🟢 verde = cap ≥ 99.7% rec (conservador) · 🟡 ámbar = entre 99% y 99.7% · 🔴 rojo = cap < 99% (subprovisionado, riesgo de caídas) · 🔵 azul = cap sin establecer.

Puntuación z por objetivo de cobertura: 90% z=1.28 · 95% z=1.65 · 99% z=2.33 · 99.7% z=3.00 (predeterminado) · 99.99% z=3.72 (grado de difusión). La ventana de la insignia enumera todos los niveles; hacer clic aplica la recomendación del 99.7% a mux.bitrate (se requiere reinicio del mux).

σ_eff = σ_total × statmux_factor (statmux_factor = 0.7 cuando Statmux está ON, else 1.0)

Valores recomendados por canal (HD H.264)

Canal HD 1080p25: avg = 4000-5000 kbps, min = avg × 0.75 (~3000-3750), max = avg × 1.5 (~6000-7500). La IU llena automáticamente min/max a partir del avg. La IU de Statmux llena avg a partir del perfil de transcodificador del stream. Canal SD: avg = 2000-2500 kbps. UHD: avg = 12000-18000 kbps.

Statmux Híbrido Adaptativo

El Statmux Híbrido Adaptativo es un mecanismo de tiempo de ejecución que traslada la capacidad no utilizada desde las transmisiones core (protegidas, VBR completo) a las transmisiones equilibradas (sacrificables). "Híbrido" porque dos regímenes distintos de control de tasa se ejecutan lado a lado (relleno CBR core + VBR equilibrado); "adaptativo" porque el enrutador reevalúa una vez por segundo desde una predicción de lookahead de HLS. El operador marca las transmisiones como equilibradas a través de la casilla del lado derecho; el sistema las pre-codifica en tres niveles (HIGH/MED/MIN) y el enrutador intercambia atómicamente el symlink basado en el margen restante después de predecir los picos de core.

Capacidad — cómo se divide la tasa de bits

Capacidad de mux 38 Mbps
  ┌──────────────────────────────────────────────────────────────────┐
  │█████████████████████████████████████████████████████░░░░░░░░░░░░│
  └──────────────────────────────────────────────────────────────────┘
   ◀────── core_max (predicho a partir de 6 segmentos HLS) ─▶◀── equilibrado ──▶
                                                       per_balanced
                                                       = (cap − core_max
                                                          − sobrecarga SI
                                                          − audio) / N

  Ejemplo: cap=38000  core_max=29000  SI=200  audio_total=1280  N_balanced=2
           remaining = 38000 − 29000 − 200 − 1280 = 7520 kbps
           per_balanced_max = 7520 / 2 = 3760 kbps
           clamp(3760, 500, 3000) = 3000 kbps  ← techo para VBR equilibrado

Ganancia práctica (10 transmisiones × 3 Mbps avg, 4 Mbps max)

Sin Statmux Híbrido Adaptativo debes dimensionar el mux para el peor caso Σ max. Con Statmux Híbrido Adaptativo dimensionas alrededor de Σ avg + un búfer estadístico (correlación de difusión ρ=0.15). Ganancia real ~5 Mbps en un mux de 38 Mbps, o +1 canal a la misma capacidad.

CBR puro (codificador fijo)

VBR sin Statmux

Statmux Híbrido Adaptativo ON

Exclusividad URL ↔ Statmux

La anulación de entrada de URL personalizada y Statmux son mutuamente excluyentes. Con Statmux activado, el transcodificador equilibrado depende del HLS del codificador local para controlar la tasa de bits. Una URL externa eludiría ese ciclo de control. La IU aplica esto de ambas formas — la casilla se bloquea cuando hay una combinación conflictiva, y la ventana emergente muestra qué stream está bloqueando.

Canalización (codificador → transcodificador equilibrado → mux ffmpeg → tsp)

┌─────────────────────────┐
          │  Codificador (NVDEC→NVENC)  │ ← Satélite UDP
   STREAM │  /dev/shm/stream_X/h264/│
          │  → muxed.m3u8 + segmentos│
          └────────────┬────────────┘
                       │
              ┌────────┴────────┐
              │                 │
        role="core"        role="balanced"
        (protegido)        (sacrificable)
              │                 │
              │                 ▼
              │     ┌───────────────────────────┐
              │     │  BalancedTranscoder       │
              │     │  ffmpeg p1 NVENC VBR      │
              │     │  -maxrate dinámico         │ ← Enrutador híbrido adaptativo
              │     │  /dev/shm/stream_X_       │   Tick de 1 s (predice a partir de
              │     │   balanced/h264/...m3u8   │   6 segmentos HLS, intercambio
              │     └───────────┬───────────────┘   de enlace simbólico HIGH/MED/MIN)
              │                 │
              ▼                 ▼
          ┌─────────────────────────┐
          │  ffmpeg como mux        │ ← /dev/shm/mux_X/pipe.sh
          │  -f mpegts pipe:1       │
          │  -muxrate <cap>         │
          └────────────┬────────────┘
                       │ tubería shell
                       ▼
          ┌─────────────────────────┐
          │  tsp -I file -          │
          │  continuidad → regular  │
          │  → pcradjust → bitrate_ │
          │     monitor             │
          │  -P nit -P sdt -P inyectar│
          │     (tablas SI DVB)     │
          └────────────┬────────────┘
                       │
                       ▼ Multicast UDP
                  239.x.x.x:1234

Dimensionar min/avg/max VBR de core para statmux

La ganancia estadística solo ocurre cuando los codificadores tienen un amplio rango VBR — cuando max ≈ avg el codificador es efectivamente CBR y el enrutador no tiene nada que redistribuir. Configurar `min/avg/max` por stream para que Σmax esté cómodamente por encima de la capacidad del mux (sobresuscripción = margen para ganancia estadística) mientras Σavg se mantiene cómodamente por debajo.

Ejemplo de trabajo — mux de 38 Mbps, 10 núcleos HD + 2 equilibrados:

  Anterior (bloqueado CBR):       min=2000  avg=3000  max=4000
     Σmax = 10×4000 + 2×7600 = 55200 kbps  (1.45× cap — ganancia pequeña)
     σ_per_stream = (4000−2000)/4 = 500 kbps  (trivial — plano)
     Σ margen estadístico ≈ 1.5 Mbps

  Recomendado (VBR amplio): min=1500  avg=3000  max=6000
     Σmax = 10×6000 + 2×7600 = 75200 kbps  (1.98× cap — ganancia saludable)
     Σavg = 10×3000 + 2×3000 =  36000 kbps  (95% cap — cómodo)
     Σmin = 10×1500 + 2×500  =  16000 kbps  (42% cap — suelo cómodo)
     σ_per_stream = (6000−1500)/4 = 1125 kbps  (significativo)
     Σ margen estadístico ≈ 4 Mbps

  Beneficio real: en escenas de acción, el núcleo alcanza picos de 5-6 Mbps (detalle HD), el
  enrutador reduce los equilibrados al nivel MIN, el total en el cable se mantiene en 38 Mbps.
Rango recomendado por stream de core:

• min  ≈ avg × 0.5  (el codificador puede bajar en escenas estáticas)
• avg  = objetivo nominal por resolución (HD ≈ 3 Mbps, FullHD ≈ 5 Mbps, UHD ≈ 12 Mbps)
• max  ≈ avg × 2.0  (el codificador puede alcanzar en acción — deporte, película de acción)

Guardias de capacidad del mux (deben cumplirse):

• Σ avg core + Σ avg balanced  ≤  mux.bitrate × 0.85   (objetivo cómodo)
• Σ max core + Σ max balanced  ≤  mux.bitrate × 2.0    (ganancia por sobresuscripción)
• Σ min core + Σ min balanced  ≤  mux.bitrate × 0.6    (piso del peor caso)

σ_per_stream = (max − min) / 4  (asume rango ±2σ)
σ_total = √((1−ρ) · Σσ²ᵢ + ρ · (Σσᵢ)²)   ρ = 0.15 típico de difusión
σ_eff = σ_total × 0.7                     (factor de statmux cuando ON)
Mux_99.7% = μ_total + 3 · σ_eff           (mostrado en barra superior 📐 rec)

Consejos y solución de problemas

Al menos 1 stream equilibrado — sin uno, el enrutador Híbrido Adaptativo no tiene nada que comprimir durante los picos, por lo que la ganancia = 0

Los canales de música e información son los mejores candidatos — tolerancia al derrame de tasa de 90 %+

Seguir a través de las entradas de registro `[balance-router]` — muestra `core_max`, `remaining`, transiciones de nivel para cada tick de 1 s

Si `core_max > capacity` (advertencia CORE OVERPEAK en el registro), reducir el número de streams de core o bajar maxrate del codificador

Flujo de trabajo del operador

Agregar streams al mux (la asignación de canal sigue siendo manual)

Alternar Statmux en el encabezado del mux (chip amarillo). Cuando está habilitado, todos los codificadores cambian a VBR y se reinician

Marcar streams sacrificables a través de la casilla naranja del lado derecho — típicamente canales de música/información donde la reducción de tasa es invisible

Listo. El enrutador Híbrido Adaptativo lee una predicción de 6 segmentos HLS de los streams de core cada 1 s e intercambia atómicamente el symlink equilibrado entre los niveles HIGH/MED/MIN

StatMux — multiplexación estadística nativa

The mux runs on a native C NIF (single-host, replaced the old gst_mux.py). Each channel has its own CBR encoder; the NIF demultiplexes them, statistically allocates bitrate by scene complexity, pads with NULL packets to a fixed wire cap, and emits one MPTS UDP multicast. This help describes the current UI: chart, headroom slider, diff gauge, channel cards.

Clase: statmux de retroalimentación en bucle cerrado con anticipación C1 (prealimentación) sobre encoders VBR — principio de statmux de radiodifusión, impulsado desde la complejidad de la fuente.

Arquitectura y flujo de datos

Architecture diagram

UDP multicast SSM, por canal

Codificadores

complejidad de fuente

Retorno

línea propia / Stream

asignador (Σ ≤ pool)

búfer

relleno nulo → CBR

Hilo CBR al cap

anticipar escena compleja antes de la caída

hilo medido — calibración

tasa de bits objetivo

Cada canal funciona en su propia línea hasta el Mux (encoder + conexión de loopback separados), donde todos se fusionan en una línea de multicast MPTS con una tasa de bits exactamente fija. El asignador es el núcleo central (1 GenServer por Mux), ciclo ~0,85 s.

Núcleo: retroalimentación + anticipación C1

El asignador combina dos señales: una predicción a partir de la complejidad de la fuente (anticipación) y el hilo medido (retroalimentación). Esto se aproxima a los statmux de radiodifusión que conocen el coste de un fotograma antes de codificarlo.

C1 mide la complejidad del contenido en el decodificador — lo que va por delante de la salida del encoder según la latencia del pipeline. El cambio relativo de complejidad (correlación r≈0,92 con bits) se aplica a la tasa de bits objetivo en AMBAS direcciones ANTES de que el encoder la produzca: una escena en aumento se pre-asigna (sin caída), una en descenso libera bits antes para otros.

Hilo medido (retroalimentación)

Los bits exactos por Stream emitidos por el Mux (contadores del lado del emisor) calibran el mapeo de complejidad → tasa de bits y mantienen la suma exactamente en el pool. Ancla de referencia real — la predicción C1 no es perfecta (r 0,92), el hilo real posterior lo corrige.

Entregabilidad

La reclamación de un Stream está respaldada por lo que el encoder realmente produce (× margen de pico). Un canal fácil no puede acaparar ancho de banda que no puede usar — lo libera para los que lo necesitan.

Calidad igualada

El objetivo no es igual tasa de bits sino igual calidad — la presión continua mueve bits de canales de alta calidad (QP bajo) hacia los de baja calidad (QP alto).

Redistribución predictiva

Cuando C1 señala la caída de un canal, su ancho de banda se entrega a los demás en el mismo ciclo — aumentan antes de que la caída llegue realmente al hilo.

Per-channel weight = complexity_q12 × max_bps (action scene + higher max ⇒ more bits).

Presupuesto por stream = presupuesto global × peso / Σpesos, límite [min_bps, max_bps], recalculado cada 10 ms.

×headroom % (slider) on the encoder target → Σ real encoder < wire cap ⇒ rings drain empty ⇒ clean video.

Stale-exclusion: a dead input (no receive > 2 s) is dropped from the splitter — its share goes to live channels, not wasted; re-included automatically on recovery.

NULL pad fills the difference to the wire cap (strictly CBR). Encoder feedback: ZMQ complexity → BalanceRouter → set_bitrate.

Hilo CBR: buffer + relleno nulo + cadencia

La salida es un stream CBR exacto al cap configurado. Tres capas lo garantizan:

Buffer permanente ~1 s

La cola de envío mantiene un nivel permanente de ~1 s del hilo que absorbe las caídas de GOP inferiores a un segundo (entre fotogramas I). Verificado por la grabación: 0,5–1 s absorbe el 88–91% de las caídas.

Relleno nulo

Cuando el contenido está por debajo del cap, la diferencia se rellena con paquetes nulos MPEG-TS (PID 0x1FFF). El hilo SIEMPRE alcanza el cap — conforme a DVB.

Cadencia exacta

La salida se cadencia al cap exacto (busy-spin ABSTIME); una sujeción de deuda de 12 ms evita ráfagas de recuperación tras una breve parada → sin jitter de PCR, sin picos sobre el cap.

Bitrate chart (main)

Stacked area — each channel has its colour (matching its card below). Σ of all + NULL pad = wire cap. Switch the time window 10m / 1h / 24h; pills next to it = event counts (CC / PCR / BR / OVF) for the selected window.

Bandas de color

Cada canal tiene un color estable; el grosor = su tasa de bits instantánea. La sobrecarga (PSI/EIT) aparece en gris en la parte inferior, el relleno nulo aparece en blanco texturizado en la parte superior.

Línea de cap / máximo

La línea discontinua en la parte superior = cap configurado (techo del hilo). El contenido + el relleno nulo siempre están por debajo.

Banda nula

La banda blanca punteada en la parte superior = relleno nulo (capacidad libre). Cuanto más delgada, más lleno está el hilo; desaparece con contenido exigente.

Marcas de drop

Marcas rojas en la línea de tiempo = desbordamiento de la cola de envío (drop). Cero en estado estable; ráfagas solo en el arranque/inundación.

Rango (30 s – 30 min)

Los botones cambian la ventana de tiempo al instante (lado cliente), el activo tiene fondo gris. El gráfico acumula 30 min en el navegador.

Información emergente

Al pasar el cursor se muestra la tasa de bits por canal, QP e índice de calidad en ese momento (valor histórico, no en vivo).

cap %

Nivel de regulación del pool actual (pool/(pool−trim)). >100% = sobrepresión (llenando el buffer), <100% = recortando.

Reserva (control deslizante)

Banda de tolerancia por encima del cap — cuánto mantener como reserva nula. 0 = llenar exactamente N; positivo = mayor reserva (más seguro); negativo = ligero sobrellenado.

Búfer (caídas)

El encabezado muestra la utilización de la cola de envío % y los drops acumulados. El botón «limpiar drops» reinicia el contador.

GOP

Longitud de GOP común para todos los canales del Mux (bloqueada en perfiles de vídeo al inicio). El escalonamiento temporal distribuye los fotogramas I en el tiempo para que no colisionen.

VBV

Tamaño del buffer VBV del encoder (ms). Más pequeño aplana los fotogramas I (bueno para canales en movimiento), más grande da un fotograma I más detallado. Predeterminado 850; posible anulación por Stream.

Channel cards (Programs)

The section header has a 'Collapse / Expand all' toggle. Expand a card by clicking it or clicking its colour band in the chart. The left coloured strip with checkbox = channel membership in the mux.

dark = running OK

orange = starting / restarting

gris + atenuado = inactivo/error y casilla DESACTIVADA (desactivado intencionalmente — sin alarma)

red + BLINKING = FAULT — channel is in the mux (checkbox ON) but the stream is down/error

Tablas PSI/SI (conjunto DVB completo)

StatMux genera el conjunto completo de tablas obligatorias MPEG-TS / DVB directamente en el Mux NIF — sin insertador de SI externo. Las tablas se distribuyen uniformemente en el stream para que un STB siempre adquiera PSI/SI rápidamente al sintonizar.

Tabla

PID

Intervalo

Propósito / fuente

EIT ↔ EPG: integración completa

EIT (Event Information Table, PID 0x12) no es estático — está completamente integrado con el sistema EPG de la aplicación. El operador asigna a cada canal del Mux un servicio EPG (eit_epg_service_id), y el Mux genera EIT en vivo a partir de sus eventos programados.

Sizing / recommendations

mux.bitrate = wire CBR cap (typ. 37 Mbps for 12 SD/HD channels).

Σ avg ≲ cap (comfortable target) · Σ max oversubscribed 1.5–2× cap (that is the point of statmux — peaks rarely coincide) · Σ min = worst-case floor.

Set per-stream min/avg/max in Stream → Transcoder profile (auto-syncs to mux_input). Action/sport 8–10 M, news/talking head 1–2 M, min never < 800 k.

The headroom slider is a quick live lever of reserve vs. tightness — no restart.

Relación con los statmux de radiodifusión

Hacemos multiplexación estadística real — redistribución dinámica de bits entre canales VBR que comparten un hilo fijo, con ecualización de calidad. Mecánicamente estamos cerca de los statmux profesionales de cabecera (alineación de cap, buffer de 1 s, relleno nulo, GOP/fotogramas B, anulación de suelo).

Lo que tenemos

Hilo CBR al cap · buffer 1 s · asignación proporcional por Stream · prealimentación de anticipación C1 · ecualización de calidad · redistribución predictiva · relleno nulo · cadencia exacta.

En qué diferimos

Un statmux de radiodifusión usa la estimación de distorsión-tasa del encoder (coste exacto de fotograma, el encoder es esclavo del asignador). Nosotros usamos la complejidad de fuente C1 (r≈0,92) + un encoder VBR que elige su propio QP — una limitación de hardware, no de diseño. Clase: retroalimentación + anticipación en lugar de pura prealimentación.

Solución de problemas

Síntoma

Causa / solución

Channel red and blinking

In the mux (checkbox ON) but stream down/error → check the source/encoder of that stream. Self-recovers once restored.

Lots of NULL / large grey area

Calm content or low headroom — normal (statmux gain). For tighter utilization raise the headroom slider or per-stream max_bps.

Picture freezes / glitches

Headroom too high (rings not draining) → lower the slider to 80–82 %. Watch the diff gauge / NULL.

After restart streams=0 / all NULL

Mux started before the encoders — self-heal automatically reaches 12 within ~30 s (1 s tick retry). No manual action.

Diff gauge stuck at 0 / chart empty

No live samples (mux stopped or encoders not running) — check both the mux and stream status.

Arquitectura (de extremo a extremo)

SAT UDP SSM ─┐
             ├─ gst_encoder.py(K1)  CBR ─ TCP127 ─┐        Complejidad ZMQ
   (por      ├─ gst_encoder.py(K2)  CBR ─ TCP127 ─┤            ▲   │
   canal)     └─ gst_encoder.py(Kn)  CBR ─ TCP127 ─┤            │   ▼
                                                  ▼     BalanceRouter
                                   ┌─────── NIF StatMux ───────┐  │ set_bitrate
                                   │ anillo por entrada (descartar-antiguo) │◄─┘
                                   │ drenaje de 2 pasos (A prio, V)  │
                                   │ asignador: w=cmplx×max    │
                                   │ ×headroom% (deslizador 78-90) │
                                   │ exclusión obsoleta (>2s)     │
                                   │ relleno NULL -> cap CBR del cable  │
                                   │ paso de PCR          │
                                   └────────────┬──────────────┘
                                                ▼
                                   MPTS  Multicast UDP (cap CBR)

gst_encoder.py por canal: entrada SAT UDP SSM → nvh264enc rc-mode=cbr. La tasa de bits es controlada por BalanceRouter a través de set_bitrate. La complejidad de escena (SAD/px) se reporta sobre ZMQ al asignador.

Anillo por entrada (loopback TCP del codificador), drenaje de 2 pasos (prioridad de audio, video completo), asignador proporcional, relleno de NULL exactamente a la capacidad del cable (CBR), paso de PCR desde el codificador.

Un MPTS (PAT/PMT/SDT generados por NIF) → Multicast UDP en la VLAN de salida. El cable es estrictamente CBR a mux.bitrate (relleno de NULL).

Fila 1: ⚠ (problemas de validación) · PNR · nombre en un marco (color = estado).

Fila 2+: min·avg·max kbps · complejidad predicha Δ low/med/high/peak · INPUT LOST · ⚙URL · Mbps del codificador · SID · service_type.

El color del nombre = estado del stream:

Mbps
 37 ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌  <= cap 37.0 Mbit (rojo, techo CBR del cable)
    · · · · · · · · · · · · · · · · ·     <= espacio libre = relleno NULL
    ·· gris · puntos negros · reserva ··       (capacidad no utilizada)
 31 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━  <= margen 85% · 31.5 Mbit (naranja,
    ▓▓▓▓ JOJ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓     los objetivos del codificador apuntan aquí)
    ▒▒▒▒ Markíza ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
    ░░░░ TA3 ░░░░░░░░░░░░░░░░░░░░░░░░░░  <= hacer clic en la banda -> expandir tarjeta
  0 └──────────────────────────────────
        tiempo ->           10m │ 1h │ 24h     CC0 PCR0 BR0 OVF0

Línea roja "cap": techo CBR del cable (mux.bitrate) — NULL rellena hasta aquí.

Línea naranja 'headroom N%': = límite × deslizador de headroom / 100. Los objetivos de set_bitrate del codificador apuntan aquí. Se mueve con el deslizador.

Área gris con puntos negros entre contenido y límite = relleno NULL (reserva no utilizada). Más puntos = más reserva.

Hacer clic en la banda de color de un canal → expande automáticamente la tarjeta de ese canal a continuación.

Programación

MuxEitAdapter lee eventos del sistema EPG por servicio, construye secciones EIT DVB (nombre, hora, duración, descripción, género) y los empaqueta en el PID 0x12. Las versiones de sección se incrementan al cambiar el EPG — el STB recoge la actualización.

El EIT se inyecta directamente en el Mux NIF, de forma uniforme EN el espacio nulo (1 paquete / N salidas + p/f periódicamente) — reemplazando la cascada tsp externa en ráfagas. Pico/promedio ≈ 1,1, sin expulsión de contenido, el cap se mantiene.

Tabla 0x4E — el evento en curso + el siguiente. Inyectado cada ≤2 s para tener «ahora/siguiente» actualizado al instante en el STB.

El Mux regenera periódicamente el EIT .bin desde el EPG (~15 s) — un cambio en la programación del EPG llega al hilo sin reinicio. El encabezado del Mux muestra «EIT ✓» cuando está activo.

Tablas 0x50/0x51 — la programación completa de horas/días por adelantado (segmentos). Distribuida uniformemente en el stream.

Indicador de diferencia (encima del gráfico)

Indicador del flujo real vs cap. Centro = cap (0). Marcador izquierda (verde) = reserva (Σ contenido bajo cap); derecha (rojo) = desbordamiento. En vivo, se mueve en cada tick.

-5 Mbps CAP 37000 kbps +5 Mbps

[#### verde = reserva ####│::: rojo = sobre el cap :::]

^ -3200k

(Σ contenido ~3.2 Mbps bajo el cap = reserva saludable)

Control deslizante de margen (78–90 %, predeterminado 85)

Más bajo (→78): más reserva de NULL, más seguro, menor utilización de la capacidad.

Más alto (→90): mayor utilización de la capacidad, menos NULL.

⚠ ≥88 %: el control deslizante se vuelve amarillo — cerca del techo de congelación de desbordamiento del anillo. Clamp duro 78–90 (no puede alcanzar 100 — guardia contra video congelado).

Asimetría: bajar añade reserva de forma fiable; subir está limitado por el clamp max_bps por stream (el asignador no empujará un canal más allá de su max → seguro).

Controla cuánto de la capacidad apuntan los codificadores: objetivo del codificador = budget × headroom% / 100 (línea naranja en el gráfico). Cambios en vivo (efecto desde el siguiente tick de 10 ms), persistido en SystemConfig.

Pérdida de señal / falla de canal (aislamiento)

Un canal falla (crash del codificador / pérdida de señal) ⇒ el mux sigue funcionando, otros canales no afectados, el cable mantiene la capacidad (NULL absorbe la interrupción), CC=0 en los supervivientes. Los hilos de anillo por entrada son independientes. El canal fallido muestra un nombre rojo parpadeante + insignia INPUT LOST; el codificador se reinicia con supervisión y el canal se recupera automáticamente.

PCR / temporización

PCR y PES PTS/DTS se pasan directamente desde el codificador (dominio de reloj único ⇒ coherente, sin deriva). Jitter residual de PCR ~decenas de ms es inherente (tick de salida de 10 ms + UDP) — el PLL del STB/VLC lo tolera, CC=0. La cumplimiento duro de DVB-S2 para el modulator está fuera del alcance del caso de uso IPTV actual.

CAT — acceso condicional (solo cuando hay codificación / ECM).

EIT — información de eventos (EPG) — del sistema EPG, ver abajo.

NIT — información de red (ID de red, nombre, transport stream).

PAT — lista de programas (mapea PNR → PID de PMT).

PMT — por programa: PIDs de vídeo/audio/PCR, códecs, descriptores.

SDT — nombres de servicio y proveedores (lo que el STB muestra en la lista).

TDT/TOT — hora y fecha + desplazamiento local (reloj del STB).

TSDuck Plugins Used

merge
regulate
pat
pmt
sdt
nit
eitinject
timeref
bitrate_monitor
continuity
psimerge
count