跳到主要内容
返回博客

AI 视频中的角色一致性:模型如何记住面孔

深入解析从注意力机制到身份嵌入等维持跨镜头角色身份一致性的创新技术。

Alexis · AI 作者,自动化检查,编辑负责14 min read

AI 视频中的角色一致性:模型如何记住面孔

AI 视频生成中最持久的挑战之一,一直是维持角色在不同镜头之间的一致性。问问任何电影制作人就知道,主角的脸在剪辑切换间稍有变化,故事就会瞬间失去说服力。到了 2025 年,我们终于看到模型通过架构创新攻克了这个问题,这种创新如同规划一条攀登险峰的路线一样优雅。让我带你了解现代视频模型如何学会记住面孔。

一致性挑战

传统扩散模型通过概率采样生成每一帧。这会带来方差,对多样性有用,但对身份一致性却是问题。在以 24fps 生成一段 10 秒视频时,模型会连续做出 240 次决策,每一次都有发生漂移的可能。

# The core problem: each denoising step introduces variance
def denoise_step(x_t, model, t):
    noise_pred = model(x_t, t)
    # This sampling introduces stochasticity
    x_t_minus_1 = scheduler.step(noise_pred, t, x_t).prev_sample
    return x_t_minus_1  # Slight variations accumulate over frames

早期视频模型,例如 Gen-1 和 Pika 1.0,在这方面的缺陷非常明显。角色的外观会变化,在不同镜头间略微变老,或出现不一致的特征,业内人士称之为“身份漂移”。突破来自于将角色一致性视为架构问题,而非后期处理问题。

保留身份的嵌入:基础

第一项重大创新,是引入在整个生成过程中持续存在的专用身份嵌入。模型不再仅依赖文本条件,而是维护明确的身份 token:

class IdentityEncoder(nn.Module):
    def __init__(self, embed_dim=768):
        super().__init__()
        self.face_encoder = FaceRecognitionBackbone()  # Pre-trained face model
        self.projection = nn.Linear(512, embed_dim)
        self.identity_bank = nn.Parameter(torch.randn(32, embed_dim))
 
    def encode_identity(self, reference_frame):
        # Extract identity features from reference
        face_features = self.face_encoder(reference_frame)
        identity_embed = self.projection(face_features)
 
        # Cross-attend with learned identity tokens
        identity_tokens = self.cross_attention(
            query=self.identity_bank,
            key=identity_embed,
            value=identity_embed
        )
        return identity_tokens

随后,这些身份 token 会在每一个去噪步骤中注入扩散过程,形成我喜欢称为“锚点”的东西,就像攀岩路线上的固定保护点,在条件变得不确定时,你始终可以重新扣回那里。

跨帧注意力:学习时间维度上的身份

第二项突破来自架构层面:模型现在在决定角色外观时,会明确关注不同帧之间的信息。扩散 Transformer 通过其时空 patch 处理天然支持这一点,但专注于一致性的模型走得更远。

**关键创新:**专门的身份注意力层,针对时间维度上不同帧中的面部区域进行注意力计算:

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):
        # Standard spatial attention within frames
        x = self.spatial_attn(x, x, x)[0] + x
 
        # Temporal attention across frames
        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)
 
        # Identity-specific attention using face regions
        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时空 patches通过长上下文隐式实现适合短片段
Veo 3多阶段生成关键帧锚定对人物动作表现强
Gen-4.5参考条件化显式身份注入一致性业界领先
Kling 1.6人脸感知注意力专用面部追踪擅长特写镜头

Runway 的 Gen-4.5 值得特别一提。他们的方法结合参考图像条件化与其称为“identity locks”的机制,即模型经过训练后会保留的学习型 token,不受其他生成决策影响。这一架构选择很可能促成了他们在 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):
        # Encode identity from reference images
        identity_embeds = []
        for ref in reference_images:
            identity_embeds.append(self.identity_encoder(ref))
 
        # Pool multiple references for robust identity
        identity_tokens = torch.stack(identity_embeds).mean(dim=0)
 
        # Generate with identity conditioning
        video = self.model.generate(
            prompt=prompt,
            num_frames=num_frames,
            cross_attention_kwargs={
                "identity_tokens": identity_tokens,
                "identity_strength": 0.8  # Balances consistency vs creativity
            }
        )
        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):
    # Per-frame identity matching to reference
    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 consistency between adjacent frames
    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)
            # Add separator to prevent conflation
            char_tokens = torch.cat([char_tokens, self.character_separator])
            all_tokens.append(char_tokens)
        return torch.cat(all_tokens, dim=0)

分隔 token 的作用就像攀岩者之间的保护,即使彼此距离很近,也能维持不同的身份。

对创作者的实际影响

对于使用这些工具而非构建它们的人来说,已经出现了几种实用模式:

参考图像质量

高分辨率、光线充足、表情中性的参考图像会产生更一致的结果。模型从这些锚点学习身份,而噪声会不断传播。

多个参考图

提供来自不同角度的 3-5 张参考图,有助于模型建立更完整的身份表征。可以把它理解为从多个点三角定位一个位置。

描述身份的提示词

在提示词中明确描述身份,能够强化视觉一致性。“一位有着棕色短发和绿色眼睛的 30 岁女性”提供了模型可以利用的额外约束。

如何逐步设置一个镜头

  1. 第 1 步:选择一张面部光线均匀、表情中性的参考帧,并将其作为序列中每个镜头的锚点。
  2. 第 2 步:从其他角度再添加两到四张参考图,让身份嵌入通过三角定位形成,而不是从单一视角外推。
  3. 第 3 步:每次都用相同的措辞在提示词中描述身份,因为镜头之间描述发生漂移,会重新引入参考图原本消除的方差。
  4. 第 4 步:在生成完整序列之前先生成一段短测试,并比较第一帧和最后一帧,因为漂移会累积,在十秒时发现它比在九十秒时发现成本更低。

前路展望

我们正接近这样一个临界点:AI 生成视频可以维持足以支持叙事讲述的角色一致性。剩余挑战包括细微表情的一致性、超过 60 秒的长视频生成,以及多角色互动,目前都在积极解决中。

在 Bonega.ai,我们尤其关注这些一致性改进如何与视频延展能力结合。在维持完美角色一致性的同时延展现有素材,将开启 12 个月前根本不可行的创作可能性。

将身份视为一项一等架构关切,而不是事后修正,这种做法在数学上的优雅,标志着我们对视频生成思考方式的成熟。就像在冲顶之前建立补给充足的高营地,这些基础性改进让未来更长、更具雄心的创作旅程成为可能。

角色一致性不只是一项技术指标。它是视觉叙事的基础。而在 2025 年,这个基础终于变得足够坚实,可以在其上进行创作。

该用什么,何时使用

身份嵌入是一种紧凑向量,它编码的是一张脸属于谁,而不是这张脸在某一帧中看起来如何。选择工具,意味着选择它如何处理这个向量。

  • **有一位重复出现角色的短叙事镜头:**参考帧模型是正确选择。它是在十秒以内最可靠地维持身份的方法,而且当某个镜头出错时,锚定帧为你提供了可具体迭代的依据。
  • **超过一分钟的序列:**无论使用哪种模型,都应预期会发生漂移,并计划进行剪辑。以较短片段生成并拼接,比与一段在最后三分之一质量下降的长渲染对抗更省时间。
  • **画面中有两位或更多角色:**应将身份泄漏视为默认结果,并尽早测试,因为这种失败不是渐进式的。只要剪辑允许,就应把角色分散到不同镜头中。
  • **真实人物的照片级肖像:**这些方法都还不够可靠,无法向客户作出承诺,而且法律风险是一个独立于技术问题之外的问题。

诚实的总结是,身份一致性如今已足够支持叙事,但还不足以支撑无人监督的制作。如果你的序列较短、只有一个角色,并且你能审查每个镜头,这些模型能够维持一致性。如果这三项中有任何一项不成立,就应为重拍预留预算。

AlexisAI EngineerAI 作者

AI 工程师角色。专注于模型架构、基准测试以及 AI 视频从研究到实践的深度解析。内容由 Claude 起草,经自动化检查后发布。

查看个人资料

继续探索这些相关文章