Wideo z awatarem wydaje się wiarygodne tylko wtedy, gdy wygląd osoby pozostaje spójny w czasie. Gdy twarz się przesuwa, zmieniają się zęby, rozjeżdża się synchronizacja ust albo ruch nagle się resetuje między ujęciami, ludzie natychmiast to zauważają. Ma to jeszcze większe znaczenie w przypadku awatarów niż przy wielu innych zadaniach generowania wideo, ponieważ widz ogląda konkretną osobę mówiącą, często z bliska i przez dłuższy czas.
We współczesnym świecie generowania wideo czas trwania wciąż pozostaje jednym z najbardziej widocznych ograniczeń. Wiele modeli i produktów udostępnia generowanie w formie klipu o stałej długości — kilku sekund, a niewiele systemów potrafi wygenerować materiał dłuższy niż kilka minut. W przypadku produktów z awatarami to ograniczenie bezpośrednio wpływa na przepływy pracy klientów. Klienci potrzebują dłuższych, spójnych scen/filmów do szkoleń wideo, prezentacji sprzedażowych, demonstracji produktów, edukacji, wsparcia oraz agentów, którzy powinni mówić tak długo, aż zadanie zostanie wykonane, a jednocześnie oczekują szybkiego podglądu, aby móc iterować nad promptami, ruchem i scenariuszem.
W HeyGen przełożyło się to na trzy konkretne wymagania:
- Spójność w długich scenach. Awatar musi zachowywać tożsamość, synchronizację ruchu ust, mimikę oraz ciągłość ruchu nie tylko w jednym krótkim klipie, ale w wielu fragmentach wygenerowanego wideo.
- Brak stałego limitu czasu trwaniaGenerowanie może trwać dziesięć sekund, dziesięć minut lub mieć formę nieograniczonej czasowo sesji na żywo.
- Szybki podgląd, generowanie w czasie rzeczywistym lub szybciej niż w czasie rzeczywistymSystem powinien szybko rozpocząć tworzenie klatek i nawet umożliwiać strumieniowe przesyłanie generowanych klatek, gdy wnioskowanie wciąż trwa.
Ten wpis omawia framework wnioskowania, który zbudowaliśmy, aby spełnić te wymagania.
Podstawowa architektura modelu
Framework opiera się na modelach generowania wideo awatarów HeyGen — rodzinach Avatar IV i Avatar V. Na wysokim poziomie model przyjmuje obraz/wideo referencyjne, dźwięk sterujący oraz opcjonalne warunki tekstowe lub sceniczne, a następnie generuje wideo tego awatara mówiącego z odpowiednią tożsamością, mimiką i ruchem.
Główny model generatywny to Diffusion Transformer (DiT) trenowany z wykorzystaniem flow matching. Zamiast kompresować postać do małego wektora tożsamości, model warunkowany jest bogatymi tokenami referencyjnymi, dzięki czemu może zachować detale kluczowe dla awatarów: kształt twarzy, zęby, teksturę skóry, ruch ust, styl gestykulacji oraz rytm mówienia.
Ścieżka wnioskowania produkcyjnego składa się z trzech głównych etapów:
- Generowanie wideo z dźwięku. Podstawowy model DiT generuje niskorozdzielcze latentne reprezentacje wideo na podstawie referencyjnej tożsamości, cech audio oraz sygnałów warunkujących. Ten etap koncentruje się na ruchu, synchronizacji ust z dźwiękiem i spójności czasowej.
- Superrozdzielczość z uwzględnieniem tożsamościDrugi model przekształca te latentne reprezentacje w obraz o wysokiej rozdzielczości, ze szczególnym naciskiem na obszary, na które ludzie są najbardziej wrażliwi na artefakty, zwłaszcza twarz i usta.
- Strumieniowe dekodowanie VAE. Dekoder VAE przekształca wysokorozdzielcze latentne reprezentacje na klatki RGB kawałek po kawałku, dzięki czemu klatki mogą być emitowane, zanim cały film zostanie ukończony.
Aby generować długie filmy, system przetwarza dane w segmentach. Podczas gdy pierwszy segment opiera się całkowicie na statycznym odniesieniu, kolejne segmenty wykorzystują dane graniczne z poprzednich fragmentów. Dzięki temu awatar może kontynuować naturalną wypowiedź bez resetowania swojej postawy ani tożsamości od zera.
Strumieniowy framework i pętla potokowa
Aby umożliwić wykonywanie zadań w oparciu o fragmenty danych, framework inferencyjny wykorzystuje modułową, trójwarstwową architekturę, która działa na zlokalizowanych przedziałach czasowych i zwalnia zasoby natychmiast po przetworzeniu danego fragmentu.
- Moduł: Obejmuje konkretny model i jego punkt kontrolny (np. A2V DiT, Super-Resolution DiT, komponenty VAE, enkodery tekstu/dźwięku).
- Etap: typowa jednostka wykonawcza, która koordynuje jeden lub więcej modułów (np. generowanie kontekstu, superrozdzielczość).
- Potok przetwarzania: Graf wykonawczy, który łączy etapy, zarządza współdzielonym stanem i koordynuje tryby wykonywania strumieniowego lub wsadowego.
Faza inicjalizacji koduje referencyjną tożsamość do przestrzeni latentnej raz na każde żądanie. Następnie potok wykonuje ciągłą pętlę przez pozostałe etapy, aż do wyczerpania wejściowego strumienia audio:

- Generowanie kontekstu: Przekształca napływające segmenty audio w cechy, łączy je z tekstem lub warunkami sceny i przygotowuje docelowe tensory szumu.
- Audio-to-Video: Wykonuje wieloetapowe przejście dyfuzyjne, aby wygenerować niskorozdzielcze latentne reprezentacje. Na tym etapie bieżący fragment jest warunkowany klatkami granicznymi poprzedniego fragmentu, aby zachować ciągłość ruchu.
- Super-rozdzielczość: Skaluje latenty ruchu do pełnej rozdzielczości w jednym kroku, priorytetyzując szczegóły przestrzenne na twarzy.
- VAE Decode-and-Publish: Dekoduje wysokorozdzielcze latentne reprezentacje do klatek RGB i zapisuje je bezpośrednio do enkodera wyjściowego (H.264 / AAC) w celu natychmiastowego przechowywania lub odtwarzania na żywo.
Ciągłość na granicach i spójność segmentów
Generowanie wideo w oddzielnych segmentach wprowadza potencjalne nieciągłości na granicach. Framework ogranicza ten problem, wykorzystując dwa odrębne typy segmentów:
- Segmenty N: segmenty, które generują główną oś czasu awatara.
- I Chunks (Interpolacja): segmenty zaprojektowane w celu wygładzenia przejść między kolejnymi fragmentami N.
Sekwencja wykonywania jest zorganizowana w następujący sposób:
N0 -> N1 -> I0 -> N2 -> I1 -> N3 -> I2 -> ...
Fragment I jest generowany dopiero po zakończeniu poprzedzającego i następującego po nim fragmentu N. Wykorzystuje on ostatnią klatkę poprzedniego fragmentu N oraz wczesną klatkę bieżącego fragmentu N jako klatki kotwiczące do obliczenia ruchu przejściowego. Po wygenerowaniu zbędne przewidywania dla klatek kotwiczących są odrzucane, pozostawiając jedynie płynnie zinterpolowane przejście. Ten mechanizm ogranicza wymagane okno kontekstu, jednocześnie zachowując spójność czasową.
Stała ilość pamięci w czasie trwania
Tradycyjny potok wideo gromadzi latentne reprezentacje, zdekodowane klatki oraz kontekst uwagi w trakcie działania, przez co zużycie pamięci GPU rośnie liniowo wraz z długością wideo.
Aby umożliwić otwartą, nieograniczoną generację, ten framework utrzymuje ściśle kontrolowany stan kroczący. System zachowuje jedynie statyczne warunki referencyjne oraz minimalny zestaw tensorów kotwiczących wymaganych do przejść między fragmentami. Wszystkie pośrednie zasoby — w tym cechy audio, tensory szumu, wewnętrzne aktywacje i surowe klatki RGB — są usuwane z pamięci natychmiast po zdekodowaniu i zapisaniu danego fragmentu.
W rezultacie szczytowy profil wykorzystania pamięci GPU pozostaje niezmienny, niezależnie od tego, czy generowany jest krótki klip, czy dłuższa sekwencja; zużycie zasobów skaluje się wraz z określonym rozmiarem fragmentu, a nie z całkowitym czasem trwania sesji.
Etapy ładowania/zwalniania w ramach potoku przetwarzania
Każde żądanie jest przetwarzane na węźle z 8 GPU. Używamy FSDP do podziału parametrów dużych modeli między GPU. Każdy rank posiada tylko część wag, zbiera parametry potrzebne do obliczeń, a następnie ponownie je zwalnia. To właśnie dzięki temu wiele dużych modeli — bazowy DiT, DiT do super-rozdzielczości, enkoder tekstu, enkoder audio oraz VAE — może zmieścić się na jednym węźle.
Istnieje pewien kompromis. FSDP wprowadza narzut komunikacyjny podczas wnioskowania, ponieważ parametry muszą być zbierane w trakcie przejść w przód. Używamy kombinacji technik, aby ukryć ten narzut i utrzymywać współlokowane modele poza GPU, gdy nie są używane:
- Prefetching w przód. Operacja AllGather dla parametrów następnego bloku jest uruchamiana z wyprzedzeniem i wykonywana równolegle z obliczeniami bieżącego bloku, co ukrywa opóźnienie zbierania na krytycznej ścieżce.
- Leniwe odszardowywanie na poziomie bloków z CPU. Gdy model jest przywracany z przypiętej pamięci CPU, nie ładujemy z wyprzedzeniem pełnego zestawu wag. Każdy blok transformera jest odszardowywany (kopiowanie z hosta na urządzenie + AllGather) tuż przed swoim przejściem w przód, dzięki czemu transfer H2D bloku n+1 nakłada się na obliczenia wykonywane dla bloku n.
- Przenoszenie obciążenia na przypiętą pamięć CPU między etapami. Parametry modelu, który w danej chwili nie jest uruchomiony, są przechowywane w przypiętej pamięci CPU, dzięki czemu współdzielone modele (bazowy DiT, DiT do super‑rozdzielczości, enkoder tekstu, enkoder audio, VAE) nie muszą jednocześnie trzymać swoich wag w pamięci GPU. To właśnie przypięta pamięć sprawia, że kopiowanie H2D jest na tyle szybkie, by nakładać się w czasie z obliczeniami.
- Rozmieszczanie procesów z uwzględnieniem NUMA. Każdy proces jest przypięty do tego samego węzła NUMA co przypisany mu GPU, dzięki czemu transfery CPU↔GPU działają z pełną przepustowością PCIe/NVLink, bez przechodzenia przez międzygniazdowe połączenie międzyprocesorowe.
Przełączanie modeli między etapami w czasie poniżej 10 ms
Praktyczną korzyścią z opisanych powyżej technik jest to, że przekazywanie GPU z modelu jednego etapu do modelu kolejnego — na przykład z A2V DiT do Super-Resolution DiT albo z SR DiT do dekodera VAE — jest w praktyce darmowe. Ponieważ model wychodzący jest asynchronicznie wyładowywany z pamięci, a pierwszy blok modelu wchodzącego jest rozszardowywany dokładnie na czas, zarówno kopiowanie H2D, jak i operacja AllGather są ukryte za obliczeniami, które i tak już trwają. Od końca do końca obserwowalny narzut na pojedyncze przełączenie jest mniejszy niż 10 ms — zdecydowanie poniżej budżetu jednej klatki przy naszych docelowych liczbach klatek na sekundę. W praktyce to właśnie umożliwia pętli strumieniowego potoku (Context Gen → A2V → SR → VAE Decode-and-Publish) przechodzenie przez kilka dużych modeli na fragment bez tego, by samo przełączanie modeli stało się wąskim gardłem.
Publikowanie strumieniowe w czasie rzeczywistym
Aby model był wystarczająco szybki do strumieniowania w czasie rzeczywistym, przeprowadziliśmy wiele optymalizacji wnioskowania, zapoznaj się z https://www.heygen.com/research/avatar-v-inference aby uzyskać więcej szczegółów na ten temat.
Gdy potok zaczyna emitować wideo kawałek po kawałku w czasie rzeczywistym, strumieniowe dostarczanie staje się naturalnym rozszerzeniem wnioskowania, a nie osobnym etapem przetwarzania końcowego.
W przypadku ścieżki transmisji na żywo w stylu broadcastowym publikujemy generowane klatki w Amazon Kinesis Video Streams (KVS). KVS jest zazwyczaj omawiany w kontekście kamer, urządzeń IoT i przesyłanych materiałów wideo. W naszym przypadku „kamerą” jest sam pipeline inferencyjny: klatki są tworzone przez model, natychmiast kodowane i wysyłane do KVS jako transmisja na żywo.
Moduł zapisu wyjściowego odbiera zdekodowane klatki RGB ze strumieniowego VAE i przekazuje je do potoku GStreamer. Wideo jest kodowane w H.264, a dźwięk w AAC, po czym oba strumienie są wysyłane do kvssink, czyli modułu wyjściowego producenta KVS. Stamtąd widzowie mogą odtwarzać sesję jako transmisję na żywo, jeszcze w trakcie jej generowania.
Wyniki i wnioski
Framework zmienił generowanie Avatarów IV i V z renderowania w stałej scenie na otwartą, strumieniową generację. Najważniejszy rezultat jest prosty: usunęliśmy ograniczenia długości sceny dla Avatarów IV i V. Dla generowania Avatara IV w czasie rzeczywistym osiągnęliśmy czas do wyświetlenia pierwszej klatki poniżej 5 sekund oraz generowanie z prędkością ponad 27 klatek na sekundę dla wideo Avatar IV w rozdzielczości 720p — szybciej niż odtwarzanie w czasie rzeczywistym.