Cómo evitar que tu stream ABR haga ping-pong entre bitrates

Este artículo ha sido traducido del inglés con la ayuda de IA. Leer el original

Cómo diseñar una escalera de transcodificación que no vuelva locos a los algoritmos ABR

Si has pasado algo de tiempo observando la reproducción HLS en condiciones reales, lo has visto: el stream sigue rebotando entre dos renditions. Arriba, abajo, arriba, abajo. El espectador ve un cambio constante de calidad, a veces cada pocos segundos. Es peor que quedarse en una rendition inferior todo el tiempo. Al menos un stream estable en 720p parece intencional. Un stream que oscila entre 720p y 1080p cada 10 segundos parece roto.

La causa raíz es casi siempre la misma: la escalera de codificación tiene renditions demasiado cercanas en bitrate, o la diferencia de calidad entre peldaños no justifica el salto en ancho de banda. El algoritmo ABR del lado del cliente no puede decidirse, porque la diferencia entre "puedo permitirme esto" y "no puedo permitirme esto" es mínima.

Veamos cómo solucionar esto correctamente.

La prueba de cordura de bits por píxel

Antes de todo, necesitas entender lo que los bits por píxel (BPP) te dicen sobre tu escalera. Es la métrica más simple para evaluar si un bitrate determinado realmente tiene sentido para una resolución dada.

La fórmula es directa:

BPP = bitrate / (width × height × framerate)

Por ejemplo, un stream de 1920×1080 a 4500 kbps y 30 fps:

BPP = 4,500,000 / (1920 × 1080 × 30) = 0.072

¿Por qué importa esto? Porque el BPP te indica la densidad de compresión en cada peldaño. Si dos peldaños adyacentes de tu escalera tienen valores de BPP muy similares, el espectador no verá una diferencia de calidad significativa — pero el algoritmo ABR seguirá intentando cambiar entre ellos. Así es como terminas con un comportamiento de ping-pong.

Una escalera bien diseñada debe tener una curva de BPP descendente a medida que la resolución aumenta. Esto refleja una propiedad real de los códecs de vídeo: son más eficientes a resoluciones más altas. Necesitas menos bits por píxel en 1080p para lograr la misma calidad percibida que en 480p. Si tu BPP es plano o inconsistente entre peldaños, algo está mal.

La "Regla del 0.70" es una referencia práctica aquí. La idea es que cuando duplicas la cantidad de píxeles (por ejemplo, al pasar de 720p a 1080p), deberías aplicar aproximadamente 0.70× el BPP de la resolución inferior. Es una heurística, no una ley, pero te da una forma rápida de detectar anomalías. Si graficas los valores de BPP de tu escalera y un peldaño destaca claramente — demasiado alto o demasiado bajo comparado con sus vecinos — ese peldaño causará problemas.

La conclusión: no elijas simplemente bitrates que parezcan números redondos bonitos. Calcula el BPP para cada peldaño y asegúrate de que la curva tenga sentido. Si dos peldaños adyacentes están a un 15-20% de diferencia en BPP, el espectador no los distinguirá, pero la heurística ABR perderá tiempo cambiando entre ellos.

Espaciado de bitrates: la regla del factor 1.5×

No existe un estándar universal, pero una recomendación de ingeniería común es mantener al menos un ratio de 1.5× entre peldaños de bitrate adyacentes. Algunas implementaciones llevan este ratio a 2×.

¿Por qué? Porque los algoritmos ABR usan la estimación de ancho de banda para decidir qué rendition elegir. La estimación tiene un intervalo de confianza — nunca es exacta. Si dos renditions están a 2,5 Mbps y 3,0 Mbps, el BWE puede fácilmente oscilar por encima y por debajo de 3,0 Mbps en una conexión ligeramente variable, causando cambios constantes. Si en cambio el salto es de 2,0 Mbps a 4,0 Mbps, el algoritmo necesita un cambio de ancho de banda mucho más significativo para activar un cambio. El resultado: una reproducción más estable.

Aquí hay un ejemplo concreto. Supongamos que tienes una escalera limpia de cuatro peldaños:

Resolución Bitrate BPP (30fps) Ratio con el anterior
480×270400 kbps0.103
960×5402000 kbps0.1295.0×
1280×7202800 kbps0.1011.4×
1920×10804500 kbps0.0721.6×

A primera vista parece razonable — cuatro resoluciones, bitrates crecientes. Pero mira el salto 540p→720p: de 2000 kbps a 2800 kbps. Eso es solo un ratio de 1.4×. En cualquier conexión que oscile alrededor de 2,5–3 Mbps (que es la mayoría de las conexiones móviles), el BWE cruzará constantemente ese umbral. Arriba, abajo, arriba, abajo. El espectador ve un cambio de resolución cada pocos segmentos.

Y aquí está el otro problema: el BPP en realidad baja de 0,129 a 540p a 0,101 a 720p. Así que el espectador obtiene más píxeles pero menos datos por píxel. Dependiendo del contenido, la rendition de 720p podría no verse significativamente mejor que la de 540p — has añadido resolución pero perdido margen de compresión. El algoritmo ABR está cambiando para nada.

Una mejor versión de esta escalera subiría el bitrate de 720p y ajustaría el de 540p a la baja:

Resolución Bitrate BPP (30fps) Ratio con el anterior
480×270400 kbps0.103
960×5401500 kbps0.0963.75×
1280×7203000 kbps0.1092.0×
1920×10805800 kbps0.0931.93×

Ahora el salto 540p→720p es un ratio limpio de 2×. El BWE necesita duplicarse antes de que el reproductor siquiera considere subir de calidad. Y el BPP en realidad aumenta de 0,096 a 0,109, lo que significa que el peldaño 720p ofrece tanto más píxeles como mejor calidad de compresión — el espectador ve una mejora real. El salto 720p→1080p a 1,93× es igualmente sólido, y el BPP baja solo ligeramente a 0,093, que es la ganancia de eficiencia esperada a resoluciones más altas.

Verificación rendition por rendition: prueba de reproducción individual

Aquí hay algo que rara vez veo hacer a los equipos, pero es crítico: reproducir cada rendition individualmente y ver todo el contenido completo.

Suena obvio, pero la mayoría de la gente solo prueba el ABR como un stream multi-variante completo. Nunca aíslan una sola rendition y la reproducen de principio a fin. Cuando lo haces, detectas problemas que el comportamiento ABR oculta:

  • Una rendition que hace buffering incluso a su propio bitrate declarado (porque el BANDWIDTH declarado en la playlist es demasiado bajo comparado con el bitrate pico real)
  • Una rendition donde el codificador tuvo dificultades y produjo artefactos visibles en ciertas escenas
  • Una rendition donde el framerate cae o tartamudea porque la combinación resolución/bitrate es demasiado exigente para el decodificador del dispositivo objetivo

Para probar esto, puedes forzar la reproducción de una sola rendition de varias formas:

Con la página de demo de hls.js: Carga tu stream multi-variante, luego en el menú desplegable del selector de calidad, fija manualmente cada nivel uno por uno. La demo de hls.js en hlsjs.video-dev.org/demo/ expone todos los niveles de calidad y te permite anular el ABR. Reproduce cada uno durante al menos unos minutos de contenido representativo. Observa los frames perdidos en la pestaña «Buffer & Statistics».

Con AVPlayer en plataformas Apple: Usa preferredPeakBitRate y preferredMaximumResolution en AVPlayerItem para restringir la reproducción a una sola rendition. O incluso más simple: crea una playlist de prueba que solo incluya una variante.

Con ffprobe o mediainfo: Antes de reproducir nada, verifica las estadísticas reales de bitrate de cada rendition. El valor de BANDWIDTH en tu playlist master debe considerar el pico, no solo el promedio. Si tu codificación VBR tiene picos un 40% por encima del promedio, tu BANDWIDTH declarado debe reflejarlo.

Si una sola rendition no puede reproducirse sin problemas a su propio bitrate declarado, absolutamente causará problemas en modo ABR. El algoritmo ABR selecciona esa rendition pensando que tiene suficiente ancho de banda, luego encuentra un pico VBR, se detiene, baja de nivel, se recupera, selecciona esa rendition de nuevo — ping-pong.

Duración de los segmentos: el reloj de conmutación del ABR

Hay otro factor que la gente tiende a pasar por alto: la duración de los segmentos controla directamente con qué frecuencia el algoritmo ABR puede tomar una decisión. Cada límite de segmento es un punto de conmutación potencial. Así que si usas segmentos de 2 segundos, el reproductor puede reevaluar y cambiar hasta 30 veces por minuto. Con segmentos de 6 segundos, eso baja a 10 veces por minuto. Con segmentos de 10 segundos, solo 6.

Esto importa mucho cuando tu escalera ya tiene un espaciado de bitrate ajustado. Segmentos cortos combinados con peldaños de bitrate cercanos es la peor combinación — estás dando al algoritmo ABR el máximo de oportunidades para hacer cambios marginales que el espectador no necesita ver.

Por el contrario, segmentos más largos actúan como un amortiguador natural contra la oscilación. Incluso si la estimación de ancho de banda fluctúa, el reproductor tiene que comprometerse con su rendition actual durante toda la duración del segmento que acaba de descargar. Para cuando llega el siguiente punto de decisión, el BWE puede haberse estabilizado.

La especificación HLS no exige una duración específica, pero las directrices de Apple recomiendan un objetivo de 6 segundos. En la práctica:

  • Segmentos de 2 segundos: tienen sentido para live de baja latencia donde el inicio rápido y la adaptación rápida son críticos. Pero necesitas una escalera bien espaciada para evitar el cambio constante.
  • Segmentos de 6 segundos: son un buen valor predeterminado para VOD y live estándar. Dan al algoritmo ABR suficiente tiempo para construir una estimación de ancho de banda fiable entre decisiones.
  • Segmentos de 10 segundos: muy estables pero lentos para adaptarse. Si el ancho de banda cae bruscamente, el reproductor queda atrapado descargando un segmento de alto bitrate que puede no ser capaz de terminar a tiempo.

También hay una sutileza con la codificación VBR: la varianza de bitrate dentro de un segmento aumenta con la duración del segmento. Un segmento de 10 segundos de una transición de escena — pasando de un plano estático a una secuencia de acción — puede tener una fluctuación de bitrate masiva internamente. Si el BANDWIDTH declarado en la playlist coincide con el promedio general pero no con los picos por segmento, el algoritmo ABR se lleva una sorpresa. Los segmentos más cortos tienden a tener bitrates por segmento más consistentes, lo que hace que el BWE sea más preciso.

En resumen: si estás viendo oscilación y el espaciado de tu escalera parece correcto, verifica la duración de tus segmentos. Pasar de 4 segundos a 6 segundos podría ser todo lo que necesitas para calmar las cosas.

Usar Network Link Conditioner para simular condiciones reales

Probar el ABR en una conexión de fibra estable de 100 Mbps es inútil. Necesitas simular condiciones del mundo real, y Network Link Conditioner de Apple es la mejor herramienta para esto en macOS.

Lo obtienes del paquete Additional Tools for Xcode de Apple: en Xcode, ve a Xcode > Open Developer Tool > More Developer Tools, lo que te lleva a la página de descargas para desarrolladores de Apple. Busca «Additional Tools for Xcode», descarga el DMG para tu versión de Xcode, ábrelo, y en la carpeta Hardware encontrarás Network Link Conditioner.prefPane. Haz doble clic para instalarlo. Luego aparece como un panel en Ajustes del Sistema (o Preferencias del Sistema en versiones anteriores de macOS). Te permite definir perfiles de ancho de banda con velocidad, latencia, tasa de pérdida de paquetes y retardo DNS específicos.

Crea perfiles personalizados que importan:

  • 4G mediocre: 8 Mbps de bajada / 2 Mbps de subida, 80ms RTT, 1% de pérdida de paquetes
  • WiFi deficiente: 3 Mbps de bajada / 1 Mbps de subida, 150ms RTT, 3% de pérdida de paquetes
  • Transicional: Comienza a 15 Mbps, cambia manualmente a 2 Mbps durante la reproducción

Esta última prueba es la definitiva. Si tu escalera está bien diseñada, el reproductor debería bajar suavemente a una rendition inferior en unos segundos y quedarse ahí. Si empieza a oscilar entre dos renditions, tus peldaños están demasiado cerca en la frontera de ancho de banda.

En dispositivos iOS, Network Link Conditioner está disponible a través de los ajustes de Desarrollador (actívalo en Ajustes > Desarrollador después de conectar el dispositivo a Xcode).

El objetivo de estas pruebas no es simplemente «¿hace buffering?» — es «¿el stream se estabiliza en una rendition y se queda ahí?». Una buena experiencia ABR es aquella donde los cambios son raros y decisivos. El espectador ve el cambio de calidad una vez, y luego se estabiliza.

Usar AVMetrics de Apple para monitorear los cambios en producción

A partir de iOS 18, Apple introdujo la API AVMetrics en AVFoundation. Esto es un cambio radical para monitorear el comportamiento ABR en el campo.

El tipo de evento clave para nuestro propósito es el evento de cambio de variante. Cada vez que AVPlayer cambia entre variantes HLS, obtienes un evento de métricas que te dice desde qué cambió, hacia qué cambió, y los detalles de la rendition de medios. También obtienes eventos de bloqueo cuando el reproductor hace rebuffering, y un evento de resumen al final de la sesión con los KPI generales.

Aquí está el patrón en Swift:

let playerItem: AVPlayerItem = // your configured item

let switchMetrics = playerItem.metrics(
    forType: AVMetricPlayerItemVariantSwitchEvent.self
)
let stallMetrics = playerItem.metrics(
    forType: AVMetricPlayerItemStallEvent.self
)

for await (event, _) in switchMetrics.chronologicalMerge(with: stallMetrics) {
    switch event {
    case let switchEvent as AVMetricPlayerItemVariantSwitchEvent:
        // Log: from variant, to variant, timestamp
        await analytics.logSwitch(switchEvent)
    case let stallEvent as AVMetricPlayerItemStallEvent:
        // Log: stall duration, variant at time of stall
        await analytics.logStall(stallEvent)
    default:
        break
    }
}

Lo que debes buscar en tus análisis:

  • Frecuencia de cambio: Si la sesión promedio tiene más de 3-4 cambios por minuto, tu escalera tiene problemas. Los streams saludables cambian quizás una o dos veces por sesión, típicamente al inicio.
  • Patrones de oscilación: Dos renditions que siguen alternándose — señal clásica de peldaños demasiado cercanos.
  • Bloqueos correlacionados con subidas de calidad: Si los bloqueos ocurren justo después de cambiar a una rendition superior, tus declaraciones de BANDWIDTH en la playlist son demasiado bajas.

Para la WWDC 2025, Apple expandió AVMetrics para incluir información de rendition de medios en los eventos de cambio de variante, facilitando ver exactamente qué pistas de audio/vídeo/subtítulos estaban activas durante el cambio.

Si no estás en plataformas Apple, datos similares se pueden recopilar desde hls.js a través de los eventos LEVEL_SWITCHED y FRAG_BUFFERED. Los mismos principios aplican.

Experimentar con hls.js: ajustar el comportamiento ABR

La página de demo de hls.js (hlsjs.video-dev.org/demo/) es la mejor herramienta gratuita para experimentar con el comportamiento de conmutación ABR en la web. Carga tu stream HLS y usa los paneles «Real-time metrics» y «Buffer & Statistics» para observar qué sucede.

Parámetros clave de hls.js para experimentar:

  • abrEwmaFastVoD y abrEwmaSlowVoD: Estos controlan la media móvil ponderada exponencialmente (EWMA) para la estimación de ancho de banda. Valores más bajos hacen que el reproductor reaccione más rápido a los cambios de ancho de banda (cambio más agresivo). Valores más altos lo hacen más conservador (cambio más lento, más estable). Si estás viendo demasiados cambios, intenta aumentar estos valores.
  • abrBandWidthFactor (predeterminado: 0.95) y abrBandWidthUpFactor (predeterminado: 0.7): Estos son márgenes de seguridad. El reproductor selecciona una rendition cuyo bitrate está por debajo de estimatedBandwidth × factor. El factor de subida es deliberadamente más bajo — el reproductor es más conservador para subir que para bajar de calidad. Si tu escalera tiene espaciado ajustado, podrías querer bajar abrBandWidthUpFactor a 0.6 para reducir la oscilación.
  • abrMaxWithRealBitrate (predeterminado: false): Cuando está habilitado, el controlador ABR usa el bitrate real medido de los segmentos descargados en lugar del BANDWIDTH declarado en la playlist. Esto es particularmente útil si tus bitrates declarados son inexactos.

Pero aquí está la cuestión: si necesitas ajustar mucho estos parámetros para obtener una reproducción estable, tu escalera probablemente esté mal diseñada. Estos controles son para ajuste fino. La escalera de codificación en sí es el fundamento. Una escalera bien espaciada funciona bien con los ajustes ABR predeterminados en cualquier reproductor.

Recomendaciones prácticas

Si tuviera que resumir esto en una checklist:

  1. Calcula el BPP para cada peldaño de tu escalera. Asegúrate de que disminuye a medida que la resolución aumenta. Elimina o ajusta cualquier peldaño donde el BPP esté dentro del 15% de su vecino.
  2. Mantén al menos un ratio de bitrate de 1.5× entre peldaños adyacentes. Prefiere 2× cuando sea posible, especialmente en la mitad inferior de la escalera donde la fluctuación de ancho de banda tiene mayor impacto.
  3. Prueba cada rendition de forma aislada. Fuerza la reproducción de una sola variante y mira contenido representativo de principio a fin. Si no puede reproducirse sin problemas por sí sola, no lo hará en ABR.
  4. Usa Network Link Conditioner para simular caídas de ancho de banda. El stream debería estabilizarse en una rendition rápidamente y quedarse ahí.
  5. Verifica la duración de tus segmentos. Si estás en 2–4 segundos y ves oscilación, prueba 6 segundos. Los segmentos más largos reducen naturalmente la frecuencia de cambio al darle al BWE más tiempo para estabilizarse entre decisiones.
  6. Instrumenta tu reproductor. Usa AVMetrics en Apple, eventos de hls.js en la web. Rastrea la frecuencia de cambio por sesión. Si las sesiones promedian más de un puñado de cambios fuera de la fase de inicio, investiga.
  7. No confíes solo en el BANDWIDTH declarado. Usa abrMaxWithRealBitrate en hls.js o verifica con ffprobe que tus picos VBR no excedan el valor declarado.
  8. Menos peldaños suele ser mejor. Una escalera de 5 peldaños con renditions bien espaciadas superará a una escalera de 10 peldaños donde la mitad de los peldaños están demasiado juntos. El espectador no necesita 12 niveles de calidad. Necesita 4 o 5 que se vean significativamente diferentes y se reproduzcan de forma fiable.

El objetivo del ABR es que sea invisible. El espectador no debería notar que está funcionando. Si lo nota, algo está mal — y nueve de cada diez veces, es la escalera.

Referencias:

¿Necesitas ayuda con tu proyecto de streaming?

Este artículo fue escrito por profesionales experimentados disponibles en iReplay.tv. Ya sea que necesites experiencia en streaming, HLS, hls.js—nuestra red de especialistas puede dar vida a tu proyecto.

Contratar un profesional →