跳至主要內容
返回部落格

AI 影片中的角色一致性:模型如何記住臉孔

深入探討從注意力機制到身分嵌入,如何在鏡頭之間維持角色身分的技術創新。

Alexis · AI 作者、自動化檢查、編輯負責13 min read

AI 影片中的角色一致性:模型如何記住臉孔

AI 影片生成中最持久的挑戰之一,是在不同鏡頭之間維持角色一致性。問問任何電影工作者就知道:主角的臉一旦在剪接之間出現細微變化,故事就會瞬間失去說服力。到了 2025 年,我們終於看到模型透過架構創新破解了這個問題,其精妙程度宛如精心規劃一條攀登困難山峰的路線。以下帶你了解現代影片模型如何學會記住臉孔。

一致性的挑戰

傳統 diffusion 模型透過機率取樣生成每一幀。這會引入變異,雖然有助於多樣性,卻會對身分一致性造成問題。生成一段 10 秒、24fps 的影片時,模型會做出 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 隨後會在每個去噪步驟注入 diffusion 過程,形成我喜歡稱為「錨點」的機制,就像攀岩路線上的固定保護點,當情況變得不確定時,隨時都能重新扣回去。

跨幀注意力:學習時間維度上的身分

第二項突破來自架構:模型如今在決定角色外觀時,會明確地跨幀關注資訊。Diffusion transformers 透過時空 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時空 patch透過長上下文隱式維持適合短片段
Veo 3多階段生成關鍵影格錨定對人類動作表現強
Gen-4.5參考條件化明確注入身分頂尖的一致性
Kling 1.6臉部感知注意力專用臉部追蹤適合特寫鏡頭

Runway 的 Gen-4.5 值得特別一提。他們的方法結合參考圖像條件化與所謂的「身分鎖定」,也就是模型經訓練後會保留的學習 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 起草,並通過自動化檢查後發布。

查看個人檔案

繼續探索這些相關文章