Согласованность персонажей в AI-видео: как модели запоминают лица
Технический разбор инноваций, сохраняющих идентичность персонажа между сценами, от механизмов внимания до эмбеддингов идентичности.

Одной из самых устойчивых проблем генерации AI-видео было сохранение согласованности персонажей между сценами. Спросите любого режиссера: история разваливается в тот момент, когда лицо главного героя едва заметно меняется между монтажными склейками. В 2025 году мы наконец увидели, как модели решили эту проблему с помощью архитектурных инноваций, столь же элегантных, как хорошо спланированный маршрут на сложную вершину. Давайте разберем, как современные видеомодели учатся запоминать лица.
Проблема согласованности
Традиционные диффузионные модели генерируют каждый кадр с помощью вероятностного сэмплирования. Это вносит вариативность, полезную для разнообразия, но проблемную для идентичности. При генерации 10-секундного видео в 24fps модель принимает 240 последовательных решений, и каждое из них создает возможность для дрейфа.
# Основная проблема: каждый шаг денойзинга вносит вариативность
def denoise_step(x_t, model, t):
noise_pred = model(x_t, t)
# Это сэмплирование вносит стохастичность
x_t_minus_1 = scheduler.step(noise_pred, t, x_t).prev_sample
return x_t_minus_1 # Небольшие различия накапливаются между кадрамиРанние видеомодели, такие как Gen-1 и Pika 1.0, заметно страдали от этого. Внешность персонажей менялась, они немного старели между сценами или приобретали несогласованные черты, это практики называли "дрейфом идентичности". Прорыв произошел, когда согласованность персонажа стали рассматривать не как проблему постобработки, а как архитектурную задачу.
Эмбеддинги, сохраняющие идентичность: основа
Первой крупной инновацией стало введение выделенных эмбеддингов идентичности, сохраняющихся на протяжении процесса генерации. Вместо опоры исключительно на текстовую обусловленность модели теперь поддерживают явные токены идентичности:
class IdentityEncoder(nn.Module):
def __init__(self, embed_dim=768):
super().__init__()
self.face_encoder = FaceRecognitionBackbone() # Предобученная модель лиц
self.projection = nn.Linear(512, embed_dim)
self.identity_bank = nn.Parameter(torch.randn(32, embed_dim))
def encode_identity(self, reference_frame):
# Извлечение признаков идентичности из референса
face_features = self.face_encoder(reference_frame)
identity_embed = self.projection(face_features)
# Кросс-внимание с обучаемыми токенами идентичности
identity_tokens = self.cross_attention(
query=self.identity_bank,
key=identity_embed,
value=identity_embed
)
return identity_tokensЗатем эти токены идентичности внедряются в диффузионный процесс на каждом шаге денойзинга, создавая то, что мне нравится считать "якорными точками", как стационарные точки страховки на альпинистском маршруте, к которым всегда можно пристегнуться, когда условия становятся неопределенными.
Межкадровое внимание: обучение временной идентичности
Второй прорыв был архитектурным: теперь модели явно учитывают информацию между кадрами, принимая решения о внешности персонажа. Диффузионные трансформеры естественным образом поддерживают это благодаря обработке пространственно-временных патчей, но модели, сфокусированные на согласованности, идут дальше.
Ключевая инновация: выделенные слои внимания к идентичности, специально анализирующие области лица во временном измерении:
class IdentityAwareAttention(nn.Module):
def __init__(self, dim, num_heads=8):
super().__init__()
self.spatial_attn = nn.MultiheadAttention(dim, num_heads)
self.temporal_attn = nn.MultiheadAttention(dim, num_heads)
self.identity_attn = nn.MultiheadAttention(dim, num_heads)
def forward(self, x, identity_tokens, face_masks):
# Стандартное пространственное внимание внутри кадров
x = self.spatial_attn(x, x, x)[0] + x
# Временное внимание между кадрами
x = rearrange(x, '(b t) n d -> (b n) t d', t=num_frames)
x = self.temporal_attn(x, x, x)[0] + x
x = rearrange(x, '(b n) t d -> (b t) n d', n=num_patches)
# Внимание, специфичное для идентичности, с использованием областей лица
face_tokens = x * face_masks.unsqueeze(-1)
x = self.identity_attn(
query=x,
key=identity_tokens,
value=identity_tokens
)[0] + x
return xЭтот механизм тройного внимания, объединяющий пространственное, временное и специфичное для идентичности внимание, позволяет модели принимать решения о внешности, явно опираясь и на установленную идентичность, и на предыдущие кадры.
Сравнение подходов современных моделей
Крупные платформы генерации видео реализовали согласованность персонажей по-разному:
| Модель | Подход | Метод согласованности | Эффективность |
|---|---|---|---|
| Sora 2 | Пространственно-временные патчи | Неявно через длинный контекст | Хорошо для коротких клипов |
| Veo 3 | Многоэтапная генерация | Привязка к ключевым кадрам | Сильно для движения людей |
| Gen-4.5 | Обусловленность референсами | Явное внедрение идентичности | Лучшая в классе согласованность |
| Kling 1.6 | Внимание к лицу | Выделенное отслеживание лица | Сильно для крупных планов |
Gen-4.5 от Runway заслуживает здесь особого упоминания. Их подход сочетает обусловленность референсным изображением с тем, что они называют "замками идентичности", обучаемыми токенами, которые модель обучена сохранять независимо от других генеративных решений. Этот архитектурный выбор, вероятно, способствовал их доминированию в Video Arena.
Парадигма референсного кадра
Значительным сдвигом в 2025 году стал переход к генерации, обусловленной референсами. Вместо создания персонажей исключительно по текстовым описаниям модели теперь принимают референсные изображения, задающие каноничную внешность:
class ReferenceConditionedGenerator:
def __init__(self, base_model, identity_encoder):
self.model = base_model
self.identity_encoder = identity_encoder
def generate(self, prompt, reference_images, num_frames=120):
# Кодирование идентичности по референсным изображениям
identity_embeds = []
for ref in reference_images:
identity_embeds.append(self.identity_encoder(ref))
# Объединение нескольких референсов для устойчивой идентичности
identity_tokens = torch.stack(identity_embeds).mean(dim=0)
# Генерация с обусловленностью идентичностью
video = self.model.generate(
prompt=prompt,
num_frames=num_frames,
cross_attention_kwargs={
"identity_tokens": identity_tokens,
"identity_strength": 0.8 # Баланс согласованности и креативности
}
)
return videoПараметр identity_strength представляет важный компромисс. Если он слишком высок, модель становится негибкой и не может показывать естественные вариации выражений. Если слишком низок, возвращается дрейф. Поиск оптимального значения, обычно около 0.7-0.85, это отчасти искусство, отчасти наука.
Функции потерь для сохранения идентичности
Обучение таких систем требует специализированных функций потерь, которые явно штрафуют дрейф идентичности:
Потеря сохранения идентичности:
L_identity = ||f(G(z, c)) - f(x_ref)||² + λ_temporal * Σ_t ||f(v_t) - f(v_{t+1})||²Здесь f представляет предобученный энкодер распознавания лиц, G является генератором, а v_t представляет сгенерированные кадры. Первый член гарантирует, что сгенерированные лица соответствуют референсам, второй штрафует различия между соседними кадрами.
def identity_preservation_loss(generated_video, reference_faces, face_encoder):
# Покадровое сопоставление идентичности с референсом
frame_losses = []
for frame in generated_video:
face_embed = face_encoder(frame)
ref_embed = face_encoder(reference_faces).mean(dim=0)
frame_losses.append(F.mse_loss(face_embed, ref_embed))
reference_loss = torch.stack(frame_losses).mean()
# Временная согласованность между соседними кадрами
temporal_losses = []
for i in range(len(generated_video) - 1):
curr_embed = face_encoder(generated_video[i])
next_embed = face_encoder(generated_video[i + 1])
temporal_losses.append(F.mse_loss(curr_embed, next_embed))
temporal_loss = torch.stack(temporal_losses).mean()
return reference_loss + 0.5 * temporal_lossСценарии с несколькими персонажами: более сложная проблема
Согласованность одного персонажа в значительной степени решена. Сценарии с несколькими персонажами, в которых нужно одновременно поддерживать несколько разных идентичностей, остаются сложной задачей. Механизмы внимания могут смешивать идентичности, что приводит к перетеканию черт между персонажами.
Современные подходы используют отдельные банки идентичности:
class MultiCharacterIdentityBank:
def __init__(self, max_characters=8, embed_dim=768):
self.banks = nn.ModuleList([
IdentityBank(embed_dim) for _ in range(max_characters)
])
self.character_separator = nn.Parameter(torch.randn(1, embed_dim))
def encode_multiple(self, character_references):
all_tokens = []
for idx, refs in enumerate(character_references):
char_tokens = self.banks[idx].encode(refs)
# Добавление разделителя для предотвращения смешения
char_tokens = torch.cat([char_tokens, self.character_separator])
all_tokens.append(char_tokens)
return torch.cat(all_tokens, dim=0)Токены-разделители действуют как страховочные станции между альпинистами, сохраняя разные идентичности даже при работе на близком расстоянии.
Практические последствия для создателей
Для тех, кто использует эти инструменты, а не создает их, сформировалось несколько практических подходов:
Качество референсного изображения
Референсные изображения с более высоким разрешением, хорошим освещением и нейтральным выражением лица дают более согласованные результаты. Модель обучается идентичности по этим якорям, а шум распространяется дальше.
Несколько референсов
Предоставление 3-5 референсных изображений под разными углами помогает модели построить более полное представление идентичности. Это похоже на определение позиции по нескольким точкам.
Промпты, описывающие идентичность
Явные описания идентичности в промптах усиливают визуальную согласованность. "30-летняя женщина с короткими каштановыми волосами и зелеными глазами" дает дополнительные ограничения, которые модель может использовать.
Как настроить сцену, шаг за шагом
- Шаг 1: выберите один референсный кадр, где лицо освещено равномерно, а выражение нейтрально, и оставьте его якорем для каждого кадра в последовательности.
- Шаг 2: добавьте еще от двух до четырех референсов с других ракурсов, чтобы эмбеддинг идентичности формировался триангуляцией, а не экстраполировался из одного вида.
- Шаг 3: каждый раз описывайте идентичность в промпте одними и теми же словами, поскольку описание, меняющееся между сценами, вновь вносит вариативность, которую убрали референсы.
- Шаг 4: сгенерируйте короткий тест перед полной последовательностью и сравните первый и последний кадры, поскольку дрейф накапливается, и его дешевле обнаружить на десяти секундах, чем на девяноста.
Дальнейший путь
Мы приближаемся к порогу, при котором сгенерированное AI-видео может сохранять согласованность персонажа, достаточную для повествовательного сторителлинга. Оставшиеся проблемы, включая согласованность тонких выражений лица, генерацию длинных форматов свыше 60 секунд и взаимодействие нескольких персонажей, активно решаются.
В Bonega.ai нас особенно интересует, как эти улучшения согласованности интегрируются с возможностями расширения видео. Способность расширять существующий видеоматериал, сохраняя идеальную согласованность персонажа, открывает творческие возможности, которые просто не были реализуемы 12 месяцев назад.
Математическая элегантность подхода, в котором идентичность рассматривается как первоклассная архитектурная задача, а не как постфактум-коррекция, знаменует зрелость нашего мышления о генерации видео. Как создание хорошо оснащенного высотного лагеря перед штурмом вершины, эти фундаментальные улучшения делают возможными более долгие и амбициозные творческие путешествия впереди.
Согласованность персонажа не просто техническая метрика. Это основа визуального повествования. И в 2025 году эта основа наконец стала достаточно прочной, чтобы на ней строить.
Что использовать и когда
Эмбеддинг идентичности - это компактный вектор, который кодирует, кому принадлежит лицо, а не то, как оно выглядело в одном кадре, и выбор инструмента означает выбор того, как он работает с этим вектором.
- Короткие повествовательные сцены с одним повторяющимся персонажем: модель с референсным кадром будет правильным выбором. Это подход, который наиболее надежно удерживает идентичность в роликах до десяти секунд, а якорный кадр дает конкретную опору для итераций, когда дубль идет не так.
- Последовательности длиннее минуты: ожидайте дрейфа независимо от модели и планируйте монтажные склейки. Генерация более короткими сегментами и их соединение требует меньше времени, чем борьба с одним длинным рендером, качество которого ухудшается в последней трети.
- Два или более персонажа в кадре: считайте утечку идентичности результатом по умолчанию и тестируйте ее заранее, поскольку сбой происходит не постепенно. Разделяйте персонажей между сценами везде, где это позволяет монтаж.
- Фотореалистичное сходство с реальным человеком: ни один из этих методов недостаточно надежен, чтобы обещать его клиенту, а юридические риски являются отдельной проблемой от технической.
Честный вывод таков: идентичность теперь решена достаточно хорошо для сторителлинга, но еще недостаточно хорошо для производства без контроля. Если ваша последовательность короткая, с одним персонажем и вы можете проверить каждую сцену, эти модели справятся. Если хотя бы одно из этих трех условий не выполняется, заложите бюджет на пересъемки.



