Diga olá ao Avatar V, o avatar mais realista já criado. Crie o seu gratuitamente

By Jiajun Zhao, Pedram Haqiqi

Um vídeo de avatar só parece convincente se a pessoa se mantiver consistente ao longo do tempo. Quando o rosto se desloca, os dentes mudam, a sincronização labial falha ou o movimento é reiniciado entre os clipes, as pessoas percebem na hora. Isso é ainda mais importante para avatares do que para muitas outras tarefas de geração de vídeo, porque o espectador está assistindo a uma pessoa específica falar, muitas vezes de perto, por um longo período.

No cenário atual de geração de vídeos, a duração ainda é uma das limitações mais visíveis. Muitos modelos e produtos oferecem a geração como um clipe de duração fixa — alguns segundos, com poucos sistemas conseguindo gerar mais do que alguns minutos. Para produtos de avatar, esse limite aparece diretamente nos fluxos de trabalho dos clientes. Eles querem cenas/vídeos mais longos e consistentes para treinamentos em vídeo, demonstrações de vendas, apresentações de produto, educação, suporte e agentes que devem continuar falando até a tarefa ser concluída, e também querem uma pré-visualização rápida para iterar em prompts, movimentos e roteiro.

Na HeyGen, isso se traduziu em três requisitos concretos:

  1. Consistência em cenas longas. O avatar precisa preservar a identidade, a sincronização labial, a expressão e a continuidade dos movimentos não apenas em um clipe curto, mas ao longo de vários trechos de vídeo gerado.
  2. Sem limite fixo de duraçãoUma geração pode ter dez segundos, dez minutos ou ser uma sessão em tempo real sem duração definida.
  3. Pré-visualização rápida, geração em tempo real ou mais rápida que o tempo realO sistema deve começar a produzir quadros rapidamente e até permitir o streaming dos quadros gerados enquanto a inferência ainda estiver em andamento.

Este artigo apresenta em detalhes a estrutura de inferência que desenvolvemos para atender a esses requisitos.

A Arquitetura Subjacente do Modelo

A estrutura é baseada nos modelos de geração de vídeos com avatar da HeyGen — das famílias Avatar IV e Avatar V. Em um nível alto, o modelo recebe uma imagem/vídeo de referência, um áudio guia e, opcionalmente, texto ou condicionamento de cena, e então gera um vídeo desse avatar falando com a identidade, expressão e movimento corretos.

O modelo principal de geração é um Diffusion Transformer, ou DiT, treinado com flow matching. Em vez de comprimir a pessoa em um pequeno embedding de identidade, o modelo é condicionado por tokens de referência ricos, para que consiga preservar detalhes importantes para avatares: formato do rosto, dentes, textura da pele, movimento da boca, estilo de gestos e ritmo de fala.

O fluxo de inferência em produção possui três etapas principais:

  1. Geração de áudio para vídeo. Um modelo DiT básico gera latentes de vídeo em baixa resolução a partir da identidade de referência, de recursos de áudio e de sinais de condicionamento. Esta etapa foca em movimento, sincronização labial e coerência temporal.
  2. Super-resolução sensível à identidade. Um segundo modelo refina esses latentes em uma saída de alta resolução, com atenção especial às regiões em que as pessoas são mais sensíveis a artefatos, especialmente o rosto e a boca.
  3. Decodificação VAE em streamingUm decodificador VAE converte latentes de alta resolução em quadros RGB, pedaço por pedaço, permitindo que os quadros sejam emitidos antes que o vídeo completo esteja pronto.

Para gerar vídeos longos, o sistema processa os dados em blocos. Enquanto o primeiro bloco depende inteiramente da referência estática, os blocos seguintes usam dados de borda dos segmentos anteriores. Isso permite que o avatar continue falando de forma natural, sem precisar redefinir sua postura ou identidade do zero.

A Estrutura de Streaming e o Loop de Pipeline

Para viabilizar a execução baseada em blocos, o framework de inferência utiliza uma arquitetura modular em três camadas, que opera em janelas de tempo localizadas e libera os recursos imediatamente após o processamento de cada bloco.

  • Módulo: Um invólucro em torno de um modelo específico e seu checkpoint (por exemplo, A2V DiT, Super-Resolution DiT, componentes de VAE, codificadores de texto/áudio).
  • Estágio: uma unidade de execução tipada que coordena um ou mais módulos (por exemplo, geração de contexto, super-resolução).
  • Pipeline: o grafo de execução que conecta os estágios, gerencia o estado compartilhado e coordena os modos de execução em streaming ou em lote.

A fase de inicialização codifica a identidade de referência em latentes uma vez por solicitação. Em seguida, o pipeline executa um loop contínuo pelas etapas restantes até que o fluxo de áudio de entrada seja esgotado:

Fluxograma de um pipeline de inferência de avatar em streaming, processando entradas de imagem/vídeo, áudio e texto por estágios como codificação, geração de contexto e super-resolução, com um loop baseado em blocos, para produzir um arquivo de saída gerado.
  • Geração de Contexto: Converte os segmentos de áudio recebidos em recursos, combina-os com texto ou condicionamento de cena e prepara os tensores de ruído de destino.
  • Áudio para Vídeo: Executa uma passagem de difusão em múltiplas etapas para produzir latentes de baixa resolução. Nesta fase, o trecho atual é condicionado pelos quadros de borda do trecho anterior para manter a continuidade do movimento.
  • Super-Resolution: aumenta a escala dos latentes de movimento para resolução total em uma única etapa, priorizando os detalhes espaciais no rosto.
  • VAE Decodificar e Publicar: Decodifica os latentes em alta resolução em quadros RGB e os envia diretamente para o codificador de saída (H.264 / AAC) para armazenamento imediato ou reprodução ao vivo.

Continuidade de Fronteira e Consistência entre Blocos

Gerar vídeo em segmentos distintos introduz possíveis descontinuidades nas bordas. O framework mitiga isso utilizando duas classificações distintas de blocos:

  • N Chunks: Segmentos que geram a linha do tempo principal do avatar.
  • I Chunks (Interpolação): Segmentos projetados para suavizar as transições entre N Chunks sequenciais.

A sequência de execução é estruturada da seguinte forma:

N0 -> N1 -> I0 -> N2 -> I1 -> N3 -> I2 -> ...

Um bloco I é gerado apenas depois que seus blocos N anterior e seguinte são concluídos. Ele usa o quadro final do bloco N anterior e um quadro inicial do bloco N atual como quadros âncora para calcular o movimento de transição. Após a geração, as previsões de âncora redundantes são descartadas, restando apenas a transição suavemente interpolada. Esse mecanismo limita a janela de contexto necessária, preservando a consistência temporal.

Memória constante ao longo da duração

Um pipeline de vídeo convencional acumula latentes, quadros decodificados e contexto de atenção durante a execução, fazendo com que o consumo de memória da GPU aumente linearmente com a duração do vídeo.

Para viabilizar a geração aberta, este framework mantém um estado contínuo rigoroso. O sistema preserva apenas o condicionamento de referência estático e um conjunto mínimo de tensores âncora necessários para as transições entre blocos. Todos os ativos intermediários — incluindo recursos de áudio, tensores de ruído, ativações internas e quadros RGB brutos — são removidos da memória imediatamente após cada bloco ser decodificado e gravado.

Como resultado, o pico de uso de memória da GPU permanece constante, seja ao gerar um clipe curto ou uma sequência longa; a utilização de recursos escala com o tamanho do bloco definido, e não com a duração total da sessão.

Estágios de carregamento/descarregamento dentro do pipeline

Cada requisição é executada em um nó com 8 GPUs. Usamos FSDP para fragmentar os parâmetros de modelos grandes entre as GPUs. Cada rank possui apenas uma fração dos pesos, reúne os parâmetros de que precisa para um cálculo e depois os libera novamente. É isso que permite que vários modelos grandes — o DiT base, o DiT de super‑resolução, o codificador de texto, o codificador de áudio e o VAE — caibam em um único nó.

Existe um trade-off. O FSDP introduz uma sobrecarga de comunicação durante a inferência, porque os parâmetros precisam ser reunidos durante as passagens de forward. Usamos uma combinação de técnicas para ocultar essa sobrecarga e manter os modelos co-localizados fora da GPU quando não estão em uso:

  • Pré-busca no forward. O AllGather dos parâmetros do próximo bloco é disparado com antecedência e sobreposto ao cálculo do bloco atual, ocultando a latência da coleta no caminho crítico.
  • Desfragmentação preguiçosa por bloco a partir da CPU. Quando um modelo é trazido de volta da memória fixada (pinned) da CPU, não carregamos antecipadamente todo o conjunto de pesos. Cada bloco do transformer é desfragmentado (cópia host‑para‑dispositivo + AllGather) imediatamente antes de sua passagem forward, de modo que a transferência H2D do bloco n+1 se sobrepõe ao cálculo do bloco n.
  • Descarregamento em CPU fixada entre estágios. Os parâmetros de um modelo que não está sendo executado no momento são mantidos em memória de CPU fixada (pinned), de modo que modelos co-localizados (DiT base, DiT de super-resolução, codificador de texto, codificador de áudio, VAE) não precisem manter todos os seus pesos na GPU ao mesmo tempo. É a memória fixada que torna as cópias H2D rápidas o suficiente para sobrepor com o processamento.
  • Alocação de processos ciente de NUMA. Cada processo é fixado ao mesmo nó NUMA que sua GPU designada, de modo que as transferências CPU↔GPU ocorram na largura de banda máxima de PCIe/NVLink, sem atravessar o interconector entre soquetes.

Troca de modelo em menos de 10 ms entre estágios

O ganho prático das técnicas acima é que passar a GPU do modelo de uma etapa para o da próxima — por exemplo, A2V DiT → Super-Resolution DiT, ou SR DiT → VAE decoder — é, na prática, gratuito. Como o modelo que está saindo é descarregado de forma assíncrona e o primeiro bloco do modelo que está entrando é desfragmentado (unsharded) exatamente no momento necessário, tanto a cópia H2D quanto o AllGather ficam ocultos atrás de computações que já estão em execução. De ponta a ponta, a sobrecarga observável por troca fica abaixo de 10 ms — bem abaixo do orçamento de um único frame nas taxas de quadros que temos como alvo. Em termos concretos, é isso que permite que o loop do pipeline de streaming (Context Gen → A2V → SR → VAE Decode-and-Publish) percorra vários modelos grandes por chunk sem que a própria troca de modelo se torne o gargalo.

Publicação de streaming em tempo real

Para tornar o modelo rápido o suficiente para transmitir em tempo real, fizemos diversas otimizações de inferência; consulte https://www.heygen.com/research/avatar-v-inference para mais detalhes sobre esta parte.

Quando o pipeline passa a emitir o vídeo em tempo real, pedaço por pedaço, a entrega via streaming se torna uma extensão natural da inferência, em vez de uma etapa separada de pós-processamento.

Para o caminho em tempo real no estilo transmissão, publicamos os frames gerados no Amazon Kinesis Video Streams (KVS). O KVS geralmente é mencionado no contexto de câmeras, dispositivos IoT e mídias enviadas por upload. No nosso caso, a “câmera” é o próprio pipeline de inferência: os frames são criados pelo modelo, codificados imediatamente e enviados ao KVS como uma transmissão ao vivo.

O gravador de saída recebe quadros RGB decodificados do VAE de streaming e os envia para um pipeline do GStreamer. O vídeo é codificado em H.264 e o áudio em AAC, então ambas as faixas são enviadas para o kvssink, o sink produtor do KVS. A partir daí, os espectadores podem reproduzir a sessão como uma transmissão ao vivo enquanto ela ainda está sendo gerada.

Resultados e aprendizados

O framework mudou a geração dos Avatares IV e V de renderização em cenas fixas para geração em streaming aberta. O resultado mais importante é simples: removemos os limites de duração de cena para os Avatares IV e V. Para a geração em tempo real do Avatar IV, alcançamos um tempo até o primeiro frame de menos de 5 segundos e geração a mais de 27 quadros por segundo para vídeos do Avatar IV em 720p — mais rápido do que a reprodução em tempo real.