Avatar video only feels believable if the person stays consistent over time. When the face drifts, the teeth change, the lip sync slips, or the motion resets between clips, people notice immediately. This matters more for avatars than for many other video generation tasks because the viewer is watching a specific person speak, often at close range, for a long time.
In today's video generation world, duration is still one of the most visible limitations. Many models and products expose generation as a fixed-length clip — a few seconds, with few systems able to generate more than a few minutes. For avatar products, that limit shows up directly in customer workflows. Customers want longer consistent scenes/videos for training videos, sales demos, product walkthroughs, education, support, and agents that should keep talking until the task is done, and also they want fast preview to iterate on prompts, motion and script.
At Heygen, that translated into three concrete requirements:
- Consistencia en escenas largas. El avatar tiene que conservar la identidad, el lip-sync, la expresión y la continuidad del movimiento no solo en un clip corto, sino a lo largo de muchos fragmentos de video generado.
- No fixed duration cap. A generation might be ten seconds, ten minutes, or an open-ended realtime session.
- Vista previa rápida, generación en tiempo real o más rápida que en tiempo real. El sistema debe empezar a producir cuadros rápidamente e incluso permitir transmitir en streaming los cuadros generados mientras la inferencia sigue en curso.
This post walks through the inference framework we built to meet those requirements.
The Underlying Model Architecture
El framework está construido sobre los modelos de generación de videos con avatar de HeyGen — las familias Avatar IV y Avatar V. A grandes rasgos, el modelo toma una imagen/video de referencia, el audio guía y, de forma opcional, texto o condiciones de escena, y luego genera un video de ese avatar hablando con la identidad, expresión y movimiento correctos.
The core generation model is a Diffusion Transformer, or DiT, trained with flow matching. Instead of compressing the person into a small identity embedding, the model conditions on rich reference tokens so it can preserve details that matter for avatars: face shape, teeth, skin texture, mouth movement, gesture style, and speaking rhythm.
La ruta de inferencia en producción tiene tres etapas principales:
- Audio-to-video generation. A base DiT generates low-resolution video latents from the reference identity, audio features, and conditioning signals. This stage focuses on motion, lip sync, and temporal coherence.
- Súper resolución consciente de la identidad. Un segundo modelo refina esos latentes para generar una salida en alta resolución, poniendo especial atención en las zonas donde las personas son más sensibles a los artefactos, especialmente la cara y la boca.
- Decodificación VAE en streamingUn decodificador VAE convierte los latentes de alta resolución en cuadros RGB por partes, para que los cuadros se puedan emitir antes de que el video completo esté listo.
Para generar videos largos, el sistema procesa los datos en bloques. Mientras que el primer bloque depende por completo de la referencia estática, los bloques siguientes usan datos de los límites de los segmentos anteriores. Esto permite que el avatar siga hablando de forma natural sin reiniciar su postura ni su identidad desde cero.
El framework de streaming y el ciclo de la canalización
Para adaptarse a la ejecución por bloques, el framework de inferencia usa una arquitectura modular de tres niveles que opera en ventanas de tiempo localizadas y libera los recursos inmediatamente después de que se procesa cada bloque.
- Módulo: un contenedor alrededor de un modelo específico y su checkpoint (por ejemplo, A2V DiT, Super-Resolution DiT, componentes VAE, codificadores de texto/audio).
- Etapa: una unidad de ejecución tipada que coordina uno o más módulos (por ejemplo, generación de contexto, super-resolución).
- Pipeline: El grafo de ejecución que conecta las etapas entre sí, administra el estado compartido y coordina los modos de ejecución en streaming o por lotes.
La fase de inicialización codifica la identidad de referencia en latentes una vez por cada solicitud. Luego, el pipeline ejecuta un ciclo continuo a través de las etapas restantes hasta que se agota el flujo de audio de entrada:

- Generación de contexto: Convierte los segmentos de audio entrantes en características, los combina con texto o condicionamiento de escena y prepara los tensores de ruido objetivo.
- Audio a video: Ejecuta un proceso de difusión en múltiples pasos para generar latentes de baja resolución. Esta etapa condiciona el fragmento actual con los cuadros límite del fragmento anterior para mantener la continuidad del movimiento.
- Súper resolución: aumenta la resolución de los latentes de movimiento a resolución completa en un solo paso, priorizando el detalle espacial en el rostro.
- VAE Decode-and-Publish: decodifica los latentes de alta resolución en cuadros RGB y los envía directamente al codificador de salida (H.264 / AAC) para guardarlos de inmediato o reproducirlos en vivo.
Continuidad de bordes y consistencia entre segmentos
Generar video en segmentos distintos introduce posibles discontinuidades en los límites. El framework mitiga esto utilizando dos clasificaciones de bloques diferentes:
- N Chunks: segmentos que generan la línea de tiempo principal del avatar.
- I Chunks (Interpolación): segmentos diseñados para suavizar las transiciones entre N chunks secuenciales.
La secuencia de ejecución está estructurada de la siguiente manera:
N0 -> N1 -> I0 -> N2 -> I1 -> N3 -> I2 -> ...
Un bloque I se genera solo después de que se completan los bloques N anteriores y posteriores. Usa el cuadro final del bloque N previo y un cuadro temprano del bloque N actual como cuadros ancla para calcular el movimiento de transición. Después de la generación, se descartan las predicciones de ancla redundantes, dejando solo la transición suavemente interpolada. Este mecanismo limita la ventana de contexto necesaria mientras preserva la consistencia temporal.
Memoria constante durante toda la duración
Una canalización de video convencional acumula latentes, cuadros decodificados y contexto de atención durante la ejecución, lo que provoca que el consumo de memoria de la GPU aumente de forma lineal con la duración del video.
Para permitir una generación abierta, este framework mantiene un estado continuo estricto. El sistema conserva solo la referencia estática de condicionamiento y un conjunto mínimo de tensores ancla necesarios para las transiciones entre bloques. Todos los recursos intermedios —incluyendo características de audio, tensores de ruido, activaciones internas y cuadros RGB sin procesar— se eliminan de la memoria inmediatamente después de que un bloque se decodifica y se escribe.
Como resultado, el perfil máximo de memoria de la GPU se mantiene constante tanto si se genera un clip corto como una secuencia extendida; el uso de recursos escala con el tamaño de bloque definido en lugar de la duración total de la sesión.
Etapas de carga y descarga dentro del pipeline
Cada solicitud se ejecuta en un nodo con 8 GPU. Usamos FSDP para dividir en fragmentos los parámetros de modelos grandes entre las GPU. Cada rango posee solo una fracción de los pesos, reúne los parámetros que necesita para un cálculo y luego los libera de nuevo. Esto es lo que permite que varios modelos grandes —el DiT base, el DiT de superresolución, el codificador de texto, el codificador de audio y el VAE— quepan en un solo nodo.
Hay una compensación. FSDP introduce sobrecarga de comunicación durante la inferencia porque es necesario reunir los parámetros durante las pasadas hacia adelante. Usamos una combinación de técnicas para ocultar esa sobrecarga y mantener los modelos ubicados en el mismo nodo fuera de la GPU cuando no se están usando:
- Prefetching hacia adelante. El AllGather de los parámetros del siguiente bloque se lanza por adelantado y se superpone con el cómputo del bloque actual, ocultando la latencia de recopilación en la ruta crítica.
- Desfragmentación perezosa por bloque desde la CPU. Cuando un modelo se trae de vuelta desde la memoria de CPU fijada, no cargamos todo el conjunto de pesos por adelantado. Cada bloque del transformador se desfragmenta (copia de host a dispositivo + AllGather) justo antes de su pasada hacia adelante, de modo que la transferencia H2D del bloque n+1 se superpone con el cómputo del bloque n.
- Descarga en CPU fijada entre etapas. Los parámetros de un modelo que no se está ejecutando en ese momento se mantienen en memoria de CPU fijada, de modo que los modelos ubicados en el mismo servidor (DiT base, DiT de super resolución, codificador de texto, codificador de audio, VAE) no necesitan tener todos sus pesos en la GPU al mismo tiempo. La memoria fijada es lo que hace que las copias H2D sean lo suficientemente rápidas como para solaparse con el cómputo.
- Asignación de procesos con reconocimiento de NUMA. Cada proceso se fija al mismo nodo NUMA que su GPU asignada, para que las transferencias CPU↔GPU se realicen al ancho de banda completo de PCIe/NVLink sin cruzar el interconector entre sockets.
Cambio de modelo entre etapas en menos de 10 ms
El beneficio práctico de las técnicas anteriores es que pasar la GPU del modelo de una etapa al de la siguiente —por ejemplo, A2V DiT → Super-Resolution DiT, o SR DiT → VAE decoder— es prácticamente gratis. Como el modelo saliente se descarga de forma asíncrona y el primer bloque del modelo entrante se desfragmenta justo a tiempo, tanto la copia H2D como el AllGather quedan ocultos detrás del cómputo que ya se está ejecutando. De punta a punta, la sobrecarga observable por cada cambio de modelo es menor a 10 ms —muy por debajo del presupuesto de un solo cuadro a nuestras tasas de cuadros objetivo. En concreto, esto es lo que permite que el ciclo del pipeline de streaming (Context Gen → A2V → SR → VAE Decode-and-Publish) recorra varios modelos grandes por chunk sin que el intercambio de modelo se vuelva nunca el cuello de botella.
Publicación en streaming en tiempo real
Para que el modelo sea lo suficientemente rápido para transmitir en tiempo real, hicimos muchas optimizaciones de inferencia; consulta https://www.heygen.com/research/avatar-v-inference para ver más detalles sobre esta parte.
Una vez que el pipeline emite el video por partes en tiempo real, la entrega por streaming se vuelve una extensión natural de la inferencia en lugar de un paso de posprocesamiento separado.
Para la ruta en tiempo real de tipo transmisión, publicamos los cuadros generados en Amazon Kinesis Video Streams (KVS). Normalmente se habla de KVS en el contexto de cámaras, dispositivos IoT y medios cargados. En nuestro caso, la “cámara” es el propio flujo de inferencia: los cuadros son creados por el modelo, codificados de inmediato y enviados a KVS como una transmisión en vivo.
El escritor de salida recibe cuadros RGB decodificados del VAE de streaming y los envía a un flujo de trabajo de GStreamer. El video se codifica en H.264 y el audio en AAC, luego ambas pistas se envían a kvssink, el sink productor de KVS. A partir de ahí, las personas pueden reproducir la sesión como una transmisión en vivo mientras todavía se está generando.
Resultados y aprendizajes
El framework cambió la generación de Avatar IV y Avatar V de un renderizado de escenas fijas a una generación continua y abierta por streaming. El resultado más importante es sencillo: eliminamos los límites de duración de escena para Avatar IV y Avatar V. Para la generación en tiempo real de Avatar IV, logramos un tiempo hasta el primer cuadro de menos de 5 segundos y una generación de más de 27 cuadros por segundo para videos Avatar IV en 720p, más rápido que la reproducción en tiempo real.