Generation Systems前沿38 分钟P1 · 建议关注

Video Generation

Sora、Hunyuan-Video、Kling、Wan、Movie Gen 与视频生成训练/推理机制。

SoraHunyuanKlingWanMovie Gen
内容来源:ARIS-in-AI-Offer by Ruofeng Yang (杨若峰),许可证 MITImported from commit 7fae0a820348.
本地更新提示复审 2026-06-29

已把 Sora 2、Veo 3.1、Runway Gen-4/4.5 与音频/可控编辑/产品可用性融入原文 TL;DR、时间线、当前 SoTA 表和参考清单。

持续跟踪视频生成模型复核 DiT/时空注意力描述加入长视频一致性与评测

§0 TL;DR Cheat Sheet

💡 7 句话搞定 Video Generation — 2024-2026 视频生成大爆发。一页吃下面试高频要点(详见后文 §1–§11 推导)。

  1. 范式:主流视频生成 = 3D Causal VAE 压缩 + Latent DiT 扩散 / Flow Matching。Sora(2024-02)首次把 Transformer 推到 60s + 高分辨率;Hunyuan-Video / Wan 2.x / Mochi-1 / CogVideoX / Movie Gen / Kling / Veo 2-3.1 / Runway Gen-4/4.5 / Sora 2 都是这一架构家族或产品路线的变体。

  2. 3D Causal VAE:把 H×W×TH \times W \times T 视频压成 h×w×th \times w \times t latent(典型空间下采样 8×8\times、时间下采样 4×4\times)。因果 (causal) 关键:当前帧 latent 不能看未来帧——使训练好的 VAE 同时支持图像(t=1t{=}1)与视频(t>1t{>}1)、并允许后续帧流式 / 自回归生成。

  3. Spacetime Patches (Sora):把视频 latent 切成 pt×ph×pwp_t \times p_h \times p_w 的 3D patch 当 token;像 ViT 但增加了时间维。支持变分辨率 / 变时长 / 变长宽比:直接把不同 shape 的 patch 序列打包到一个 batch(用 mask 区分),无需 resize 到固定尺寸。

  4. 时空 Attention 三大变体:(a) Factorized 2+1D(Latte / OpenSora / AnimateDiff):先 spatial-only,再 temporal-only,复杂度 O(TS2+ST2)O(T \cdot S^2 + S \cdot T^2);(b) Full 3D(Sora / Hunyuan-Video / Mochi):所有 token 互相 attend,复杂度 O((ST)2)O((ST)^2),最贵但效果最好;(c) Window / 稀疏 ST(Wan 2.x / CogVideoX 部分块):滑窗 3D,折中。

  5. MM-DiT for Video (Hunyuan-Video / Mochi):text token 与 video token 同序列做 self-attention(不再用 cross-attn),两个 stream 各自的 QKV 投影 + AdaLN 调制;条件信息在 token-level 直接交互——Hunyuan/Mochi/Wan 把 SD3 image MM-DiT 思路扩展到视频。

  6. Image-to-Video (I2V):主流三招——(i) First-frame concat:把 ref image 编码后沿 channel 拼到 latent;(ii) Cross-attention 注入:ref image token 作 K/V;(iii) AnimateDiff 风格:冻结 T2I 主干,只插入 temporal module。SVD / DynamiCrafter / I2VGen-XL / Wan-I2V 是代表。

  7. 长视频 + 音频 + 可控编辑 是 2026 产品主线:keyframe + interpolation / hierarchical / autoregressive chunks 仍是长视频基础;Sora 2 / Veo 3.1 / Movie Gen 把同步音频或原生音频纳入能力;Runway Gen-4/4.5 强调 reference consistency 和创作控制。评测:VBench 仍常用,但产品可用性还要看 API 是否开放、是否有音频、是否支持 I2V/编辑、多镜头一致性和商用限制。

⚠️ Caveat — 本文中 model-specific 数字(参数量、压缩比、attention 类型)均依据各模型公开 paper / tech report;具体训练 hyperparam 与最终架构以原文为准。

§1 直觉与全景

1.1 为什么视频比图像难

H×W×TH{\times}W{\times}T 视频,pixel 数随 TT 线性增长,token 数(patchify 后)也线性增长。Attention 复杂度二次于 token 数——这意味着在原 pixel 空间做 full 3D attention 对 T16T \ge 16 已经爆炸。所以视频生成的核心工程问题是:

  • 压缩:3D VAE 在空间 + 时间双维度压缩 token 数(典型 8×8×48 \times 8 \times 4
  • 架构:在 latent 上跑 attention(spatiotemporal patterns 是设计点)
  • 生成范式:DDPM / Rectified Flow / FM(v-prediction 主流;SD3-style)

1.2 2024-2026 时间线(按发布顺序)

时间模型出品关键贡献
2023-07 → ICLR'24AnimateDiffGuo et al.T2I 主干 + plug-in motion module,开源 I2V/T2V 鼻祖
2023-11SVDStabilityI2V 开源 baseline;SD2.1 + temporal layers
2024-01LatteMa et al.早期 DiT-Video;factorized spatial+temporal
2024-02SoraOpenAIDiT + spacetime patches + 大规模 caption;闭源
2024-05VeoGoogle DeepMind闭源 1080p / 1 分钟
2024-06KlingKuaishou国产闭源,时长 2 分钟
2024-08CogVideoX (arXiv)Zhipu/THU开源 2B/5B;Expert Transformer + 3D VAE
2024-10Movie GenMeta30B;视频 + 音频联合;DiT + FM
2024-10Mochi-1Genmo10B 开源;AsymmDiT 非对称 MM-DiT
2024-11LTX-VideoLightricks实时(2B);强压缩 VAE + DiT
2024-12Hunyuan-VideoTencent13B 开源 SoTA;3D Causal VAE + MM-DiT + prompt rewriter
2024-12Veo 2Google4K / 2 分钟
2025-02Wan 2.1Alibaba (Team Wan)14B 开源;T2V + I2V 双模
2025-07Wan 2.2Alibaba升级版;MoE expert + 更长时序
2025Runway Gen-4Runwayreference-driven consistency,角色/场景一致性和创作控制
2025-2026Sora 2OpenAI同步音频、物理一致性和 steerability;开发者文档标注 Videos API / Sora 2 video generation models deprecated,计划 2026-09-24 shutdown
2025-2026Veo 3.1Google DeepMindGemini API 主推视频模型,原生音频、720p/1080p/4K 规格和 cinematic control
2026Runway Gen-4.5Runway继续强化视觉保真、运动质量、reference control 与 production workflow
2024-2025OpenSora / OpenSora-PlanHPC-AI / PKU全开源训练栈复刻 Sora pipeline

⚠️ 闭源 vs 开源 — Sora / Veo / Kling / Movie Gen 没放 weights,所有架构细节基于官方 technical report;面试时不要把内部 ablation 当真硬数字,要主动说 "according to their report"。

1.3 整体 pipeline(共性骨架)

Text  --T5/CLIP/MLLM-->  text tokens [B, L_t, D]
Video --3D Causal VAE-->  latent z₁ [B, C, t, h, w] --patchify (p_t×p_h×p_w)--> tokens [B, N_v, D]
                                       │
                              Latent DiT / MM-DiT
                (full 3D / factorized 2+1D / window ST attention)
                              │  Train: regress v_θ(τ, z_τ, text) -> z₁ - z₀ (RF)
                              ↓
                       sampled z₁ --3D Causal VAE Decoder--> Generated video [B, 3, T, H, W]

§2 3D Causal VAE — 视频压缩的基石

2.1 形式化

VAE encoder EE 与 decoder DD

E:R3×T×H×WRC×t×h×w,D:RC×t×h×wR3×T×H×WE: \mathbb{R}^{3 \times T \times H \times W} \to \mathbb{R}^{C \times t \times h \times w}, \quad D: \mathbb{R}^{C \times t \times h \times w} \to \mathbb{R}^{3 \times T \times H \times W}

下采样率 T/t{4,8}T/t \in \{4, 8\}(时间)、H/h,W/w{8,16}H/h, W/w \in \{8, 16\}(空间)。Hunyuan-Video / CogVideoX / Wan 用 4×8×84{\times}8{\times}8,LTX-Video 极限 8×32×32=8192×8{\times}32{\times}32 = 8192\times token 压缩。

潜空间维度 CC 一般 1616(Hunyuan)或 44(OpenSora);越大保留信息越多,但 latent prior 离 N(0,I)\mathcal{N}(0,I) 越远,diffusion 收敛越慢。

2.2 为什么必须 "Causal" — 三个关键收益

3D Causal VAE 三大优势

  • Image / video 同构:当 T=1T=1(单帧)时,causal 3D conv 退化为 2D conv(kernel 在时间维只看历史,但历史为空 → 等价于无时间维)。Encoder 既能压视频也能压图像,图像与视频可以共享同一 latent 空间——这是 Hunyuan-Video / Wan 同时支持 I2V/T2V 的前提。

  • 流式 / 自回归推理:因果保证当前帧 latent 只依赖历史帧,长视频可分 chunk 处理,无需一次性 decode 全部 TT 帧;与 LLM 的 KV cache 同源思路。

  • 训练数据 utilization:图像 + 视频混合训练时,图像可视作 T=1T{=}1 视频;标准 3D VAE 在时间维 kernel 中心要看未来,不能这么做。

2.3 Causal Conv3d 的实现

标准 3D conv 在时间维做 zero padding 时左右各 pad kt/2\lfloor k_t/2 \rfloor(symmetric),这会让 output[t] 依赖 input[t-1], input[t], input[t+1]——泄露未来

Causal 3D conv = 把 padding 全堆到时间左侧(过去方向),右侧(未来)不 pad:

output[t]=τ=0kt1W[τ]input[t(kt1)+τ]\text{output}[t] = \sum_{\tau=0}^{k_t - 1} W[\tau] \cdot \text{input}[t - (k_t - 1) + \tau]

即 output 在时间 tt 只看 [tkt+1,t][t - k_t + 1, t] 这一段历史。空间维仍 symmetric padding(图像问题,无方向)。

⚠️ 下采样的 causal 化 — 时间 stride > 1 的下采样层(如 TT/2T \to T/2)要保证窗口对齐。常见做法:让 stride 在时间维只看历史窗 [t-1, t],输出 t' = t//2。Hunyuan-Video / Mochi 在 paper 里都画了这一层。

2.4 损失函数(与图像 VAE 同骨架)

LVAE=Lrecon+λKLLKL+λLPIPSLLPIPS+λGANLGAN\mathcal{L}_\text{VAE} = \mathcal{L}_\text{recon} + \lambda_\text{KL} \cdot \mathcal{L}_\text{KL} + \lambda_\text{LPIPS} \cdot \mathcal{L}_\text{LPIPS} + \lambda_\text{GAN} \cdot \mathcal{L}_\text{GAN}

视频 VAE 还需要 temporal consistency loss(如相邻帧重建差异 + 光流约束)防闪烁。Hunyuan-Video 用 GAN(PatchGAN 在 spatiotemporal patch 上)+ 3D 感知损失。

2.5 代码:Causal Conv3d 与编码器骨架

import math import torch import torch.nn as nn import torch.nn.functional as F class CausalConv3d(nn.Module): """ 时间维度因果 conv3d. 输入 [B, C_in, T, H, W] -> 输出 [B, C_out, T, H, W](stride=1 时形状不变). 时间 kernel 大小 k_t -> 左侧 pad (k_t-1),右侧不 pad;空间维 symmetric pad. """ def __init__(self, in_ch, out_ch, kernel=(3, 3, 3), stride=(1, 1, 1), dilation=(1, 1, 1)): super().__init__() k_t, k_h, k_w = kernel d_t, d_h, d_w = dilation # 时间维 causal padding(全部堆到左侧) self.t_pad_left = (k_t - 1) * d_t # 空间维 symmetric padding self.h_pad = ((k_h - 1) * d_h) // 2 self.w_pad = ((k_w - 1) * d_w) // 2 # 注意 nn.Conv3d 自带 padding 是 symmetric, 这里手动 pad + 关闭 conv 自带 pad self.conv = nn.Conv3d(in_ch, out_ch, kernel_size=kernel, stride=stride, dilation=dilation, padding=0) def forward(self, x): # x: [B, C, T, H, W] # F.pad order: (W_left, W_right, H_left, H_right, T_left, T_right) x = F.pad(x, (self.w_pad, self.w_pad, self.h_pad, self.h_pad, self.t_pad_left, 0)) # 时间右侧不 pad => 不看未来 return self.conv(x) class CausalResBlock3D(nn.Module): def __init__(self, ch, groups=8): super().__init__() self.norm1 = nn.GroupNorm(groups, ch) self.conv1 = CausalConv3d(ch, ch, kernel=(3, 3, 3)) self.norm2 = nn.GroupNorm(groups, ch) self.conv2 = CausalConv3d(ch, ch, kernel=(3, 3, 3)) def forward(self, x): h = self.conv1(F.silu(self.norm1(x))) h = self.conv2(F.silu(self.norm2(h))) return x + h class CausalVAEEncoder(nn.Module): """ 教学版 3D Causal VAE encoder. 实际 Hunyuan / CogVideoX 用更深的 stack + GAN 判别器. Downsample 用 stride=(2,2,2) 的 CausalConv3d (时间维仍 causal). """ def __init__(self, in_ch=3, base_ch=64, z_ch=16, num_levels=3, blocks_per_level=2): super().__init__() self.in_proj = CausalConv3d(in_ch, base_ch, kernel=(3, 3, 3)) levels, ch = [], base_ch for _ in range(num_levels): blocks = [CausalResBlock3D(ch) for _ in range(blocks_per_level)] blocks.append(CausalConv3d(ch, ch * 2, kernel=(3, 3, 3), stride=(2, 2, 2))) levels.append(nn.Sequential(*blocks)) ch *= 2 self.levels = nn.ModuleList(levels) self.norm_out = nn.GroupNorm(8, ch) self.head = CausalConv3d(ch, 2 * z_ch, kernel=(1, 1, 1)) # mu + logvar def forward(self, x): # 期望 T, H, W 能整除 2^num_levels h = self.in_proj(x) for lvl in self.levels: h = lvl(h) h = F.silu(self.norm_out(h)) return self.head(h).chunk(2, dim=1) # (mu, logvar) @staticmethod def reparameterize(mu, logvar): return mu + torch.exp(0.5 * logvar) * torch.randn_like(mu)

💡 首帧 / chunk boundary 处理(面试加分) — 因果 pad 让首帧时间维"看 0"——VAE 训练时随机扔掉时间起点的 kt1k_t{-}1 帧损失贡献,或者用 anchor padding(首帧复制填充)。Hunyuan-Video 在 paper 里讨论了 chunk-by-chunk 编码时 boundary frame 的一致性问题,工程上常通过 chunked overlapping 解决。

§3 Spacetime Patches (Sora 视角)

3.1 一句话

像 ViT 把图像切 p×pp \times p patch 当 token,Sora 把 视频 latentpt×ph×pwp_t \times p_h \times p_w3D patch 当 token。N=(t/pt)(h/ph)(w/pw)N = (t/p_t) \cdot (h/p_h) \cdot (w/p_w) 个 token 喂给 Transformer。

公式上把一段 latent zRC×t×h×wz \in \mathbb{R}^{C \times t \times h \times w} 重排:

zZRN×(Cptphpw)WprojZRN×Dz \mapsto Z \in \mathbb{R}^{N \times (C \cdot p_t \cdot p_h \cdot p_w)} \xrightarrow{W_\text{proj}} Z' \in \mathbb{R}^{N \times D}

3.2 为什么 patch 化(而非每 voxel 一个 token)

  • token 数缩减ptphpwp_t \cdot p_h \cdot p_w 倍降低 NN,attention 二次成本大幅下降。
  • 局部归纳偏置:每个 patch 内是固定 mlp 投影,类似 conv 的局部融合。
  • 支持变形:不同分辨率 / 时长直接产生不同 NN,模型在 Transformer 内对 NN 不敏感。

3.3 Variable resolution / duration / aspect ratio(Sora 关键贡献)

Sora 不把每段视频 resize 到固定尺寸(如 256×256×16256 \times 256 \times 16)。它把不同 (T,H,W)(T, H, W) 的视频都切成 patch 序列,用 packing(不同样本混到同一 batch 用 segment mask 分离)训练。

实现要点:

  • 位置编码用相对 / 解耦 :space 用 RoPE-2D,time 用 RoPE-1D;不绑死最大长度。
  • Attention mask:同一 batch 内不同 sample 的 token 之间 mask 掉。
  • target aspect ratio token:作为额外条件让模型知道当前生成的是 16:9 还是 9:16。

这一招让 Sora 可以训 / 生成任意比例的视频;后续 Wan-2.x、Hunyuan-Video 都借鉴。

3.4 代码:Spacetime patchify / unpatchify

class SpacetimePatchify(nn.Module): """ 把 video latent [B, C, t, h, w] 切成 3D patch token [B, N, D]. p_t/p_h/p_w 必须能整除 t/h/w(输入时保证). """ def __init__(self, in_ch, patch=(2, 2, 2), embed_dim=1024): super().__init__() self.p_t, self.p_h, self.p_w = patch self.proj = nn.Conv3d( in_ch, embed_dim, kernel_size=(self.p_t, self.p_h, self.p_w), stride=(self.p_t, self.p_h, self.p_w), ) def forward(self, z): # z: [B, C, t, h, w] x = self.proj(z) # [B, D, t/p_t, h/p_h, w/p_w] B, D, tt, hh, ww = x.shape N = tt * hh * ww x = x.flatten(2).transpose(1, 2) # [B, N, D] return x, (tt, hh, ww) class SpacetimeUnpatchify(nn.Module): """ Patchify 的逆操作: [B, N, D] + shape -> [B, C_out, t, h, w] """ def __init__(self, embed_dim, out_ch, patch=(2, 2, 2)): super().__init__() self.p_t, self.p_h, self.p_w = patch self.out_ch = out_ch # 每个 token 解码回 (out_ch * p_t * p_h * p_w) 维 voxel block self.proj = nn.Linear(embed_dim, out_ch * self.p_t * self.p_h * self.p_w) def forward(self, x, grid): # x: [B, N, D], grid = (tt, hh, ww) B, N, D = x.shape tt, hh, ww = grid assert N == tt * hh * ww y = self.proj(x) # [B, N, out_ch * p_t * p_h * p_w] y = y.view(B, tt, hh, ww, self.out_ch, self.p_t, self.p_h, self.p_w) # 把 patch 内坐标拼回原始空间:(tt, p_t) -> T, (hh, p_h) -> H, ... y = y.permute(0, 4, 1, 5, 2, 6, 3, 7).contiguous() return y.view(B, self.out_ch, tt * self.p_t, hh * self.p_h, ww * self.p_w)

⚠️ patch 大小如何选ptp_t 通常 1-2(时间维已被 VAE 压过 4x,不能再压太多),ph=pwp_h = p_w 通常 2。开源模型常用 pt=1,ph=pw=2p_t{=}1, p_h{=}p_w{=}2(Mochi-1 / Hunyuan-Video,配合 4×8×8 latent VAE)。Sora 未公开实现细节,只描述了 "spacetime patches" 概念。

§4 Spatiotemporal Attention 三大变体

4.1 复杂度对比(核心面试题)

定义 S=hw/(phpw)S = h \cdot w / (p_h p_w)(每帧 token 数),Tt=t/ptT_t = t / p_t(时间 token 数),N=STtN = S \cdot T_t

类型公式形式TimeScore memory (vanilla)用在哪
Factorized 2+1DTempAttn(SpatialAttn(x))\text{TempAttn}(\text{SpatialAttn}(x))O(TtS2+STt2)dO(T_t S^2 + S T_t^2) \cdot dO(TtS2+STt2)O(T_t S^2 + S T_t^2)Latte, OpenSora, AnimateDiff
Full 3D STAttnST(xRN×D)\text{Attn}_{\text{ST}}(x \in \mathbb{R}^{N \times D})O(N2d)=O(S2Tt2d)O(N^2 d) = O(S^2 T_t^2 d)O(N2)O(N^2)Hunyuan-Video, Mochi, (Sora 推测)
2+1D + 周期 full大部分块 2+1D, 少量块 full介于两者介于两者OpenSora-Plan, CogVideoX
Window 3D / 稀疏局部 3D windowO(Nw3d)O(N \cdot w^3 d) (ww = window)O(Nw3)O(N \cdot w^3)部分工程实践

💡 核心对比 — Full 3D 是 spacetime token 全交互,表达力最强;Factorized 是先空间后时间两次 attn,强假设 space ⊗ time 可分,但成本低 min(S,Tt)\min(S, T_t) 量级倍。Sora 官方未披露具体 attention 类型,社区基于其 "spacetime patches" 描述普遍推测是 full 3D / 大序列统一 attention(Hunyuan-Video / Mochi 已采用此设计)。

4.2 Factorized 2+1D Attention(Latte / OpenSora)


Input [B, T_t, S, D]
   │
   │  rearrange -> [B*T_t, S, D]
   ↓
SpatialAttn (每帧内 self-attention)    →    [B*T_t, S, D]
   │
   │  rearrange -> [B*S, T_t, D]
   ↓
TempAttn (跨帧 self-attention)         →    [B*S, T_t, D]
   │
   │  rearrange -> [B, T_t, S, D]
   ↓
FFN

强假设:每帧的 spatial relations 与跨帧的 temporal relations 可分离。这是简化但工程上非常好用——多数情况下视频里相邻帧大体相似(temporal "光流" 信息可用 1D attn 抓到),帧内 patch 关系类似图像。

4.3 Full 3D Spatiotemporal Attention(Sora / Hunyuan / Mochi)

直接把 N=STtN = S \cdot T_t 个 token 串成一维序列,标准 self-attention:

Attn(Z)=softmax ⁣(QKdk)V,ZRN×D\text{Attn}(Z) = \text{softmax}\!\left(\frac{Q K^\top}{\sqrt{d_k}}\right) V, \quad Z \in \mathbb{R}^{N \times D}

复杂度 O(N2d)O(N^2 d)NN 在长视频下大:例如 720p × 5s × 24fps 经 4×8×84{\times}8{\times}8 VAE 后 latent shape 约为 30×90×16030 \times 90 \times 160,再做 (1,2,2) patchify 得 N=304580=108000N = 30 \cdot 45 \cdot 80 = 108000 token,N21.17×1010N^2 \approx 1.17 \times 10^{10}所以工程上必须用 FlashAttention v2/v3 + Tensor Parallelism + Sequence Parallelism

4.4 RoPE-3D(位置编码)

视频 token 需要同时编码 (time, height, width) 三维位置。做法 1(解耦):把 dd 维向量切三段,分别对 (t, h, w) 做 RoPE。做法 2(共享):每段都 stack 三种频率的旋转(Hunyuan-Video)。

CogVideoX 用 3D RoPE:把 dd 维 query/key 切成三段 q=[q(t)q(h)q(w)]q = [q^{(t)} \,|\, q^{(h)} \,|\, q^{(w)}](disjoint subspace),三段分别用 (t, h, w) 对应的频率做 1D RoPE 后 concat:

RoPE3D(q,t,h,w)=[Rt(θt)q(t)Rh(θh)q(h)Rw(θw)q(w)]\text{RoPE}_{3D}(q,\, t, h, w) = \big[\, R_t(\theta_t) q^{(t)} \,\big|\, R_h(\theta_h) q^{(h)} \,\big|\, R_w(\theta_w) q^{(w)} \,\big]

实操即三段独立 1D RoPE 拼接(block-diagonal 旋转),自然得到相对时空位置编码。

4.5 代码:Factorized 2+1D 实现

class AxisAttention(nn.Module): """ 沿一个指定轴 (spatial 'S' 或 temporal 'T') 做 self-attention. 输入 [B, T, S, D] -> 输出 [B, T, S, D]. """ def __init__(self, dim, heads, head_dim, axis="S", causal=False): super().__init__() assert axis in ("S", "T") self.heads, self.head_dim, self.axis, self.causal = heads, head_dim, axis, causal self.qkv = nn.Linear(dim, 3 * heads * head_dim, bias=False) self.out = nn.Linear(heads * head_dim, dim, bias=False) def forward(self, x): B, T, S, D = x.shape if self.axis == "S": x_ = x.reshape(B * T, S, D); L_seq = S; merge_batch = T else: # "T": 把 spatial 维 collapse 进 batch, 时间维当 seq x_ = x.permute(0, 2, 1, 3).reshape(B * S, T, D); L_seq = T; merge_batch = S qkv = self.qkv(x_).reshape(-1, L_seq, 3, self.heads, self.head_dim) q, k, v = (t.transpose(1, 2) for t in qkv.unbind(dim=2)) # [B', H, L, d_k] # PyTorch SDPA 自动选 FlashAttention v2/v3 out = F.scaled_dot_product_attention(q, k, v, is_causal=self.causal) out = out.transpose(1, 2).reshape(-1, L_seq, self.heads * self.head_dim) out = self.out(out) if self.axis == "S": return out.reshape(B, T, S, D) else: return out.reshape(B, S, T, D).permute(0, 2, 1, 3) class Factorized2plus1DBlock(nn.Module): """ Latte-style: SpatialAttn -> TempAttn -> FFN. """ def __init__(self, dim, heads, head_dim, mlp_ratio=4.0): super().__init__() self.norm1 = nn.LayerNorm(dim); self.spatial = AxisAttention(dim, heads, head_dim, "S") self.norm2 = nn.LayerNorm(dim); self.temporal = AxisAttention(dim, heads, head_dim, "T") self.norm3 = nn.LayerNorm(dim) hidden = int(dim * mlp_ratio) self.mlp = nn.Sequential(nn.Linear(dim, hidden), nn.GELU(), nn.Linear(hidden, dim)) def forward(self, x): x = x + self.spatial(self.norm1(x)) x = x + self.temporal(self.norm2(x)) x = x + self.mlp(self.norm3(x)) return x

4.6 代码:Full 3D Spatiotemporal Attention(with FlashAttention via SDPA)

class Full3DSpatiotemporalAttention(nn.Module): """ 把 [B, T, S, D] 当作 [B, N, D] 做 self-attention(N = T*S). 使用 PyTorch SDPA, 底层在 H100/A100 上会自动调度 FlashAttention v2/v3. 与 MM-DiT 结合时, text/video token 直接 concat 到这一序列做 attention(见 §5.4). """ def __init__(self, dim, heads, head_dim): super().__init__() self.heads = heads self.head_dim = head_dim self.qkv = nn.Linear(dim, 3 * heads * head_dim, bias=False) self.out = nn.Linear(heads * head_dim, dim, bias=False) def forward(self, x, attn_bias=None): # x: [B, N, D] (调用前先把 T*S flatten) B, N, D = x.shape qkv = self.qkv(x).reshape(B, N, 3, self.heads, self.head_dim) q, k, v = qkv.unbind(dim=2) # [B, N, H, d_k] q, k, v = (t.transpose(1, 2) for t in (q, k, v)) # [B, H, N, d_k] out = F.scaled_dot_product_attention(q, k, v, attn_mask=attn_bias) out = out.transpose(1, 2).reshape(B, N, -1) return self.out(out)

§5 MM-DiT for Video(Hunyuan-Video / Mochi-1 思路)

5.1 从 SD3 MM-DiT 推广到视频

SD3 (Esser et al. 2024) 引入 MM-DiT:把 text token 和 image token concat 到同一序列做 self-attention,两个 stream 各自有独立的 QKV / FFN / AdaLN 参数,但 attention 是同一矩阵:

Z=[ZtextZimg],Attn(Z) shared, FFN per-streamZ = [Z_\text{text} \,|\, Z_\text{img}], \quad \text{Attn}(Z) \text{ shared, FFN per-stream}

视频化 = 把 image stream 换成 video stream(spacetime token),text stream 不变。

5.2 Hunyuan-Video 的 dual-stream → single-stream 设计

Hunyuan-Video tech report 把 DiT 分成两段:

  • Dual-stream blocks(前 N 层):text token 与 video token 在 attention 共享,但 FFN / AdaLN 独立——让两个模态先各自精炼表示。
  • Single-stream blocks(后 M 层):text token 和 video token 完全 share weight,相当于普通 Transformer 处理统一序列。

这与 Mochi-1 的 AsymmDiT 类似(Mochi 让 video stream 比 text stream 宽 4 倍参数,因为视频信息远多于文本)。

5.3 文本编码器(一览)

模型Text encoder备注
Hunyuan-VideoCLIP-L + MLLM (LLaVA 风)MLLM 提供长 prompt + 物体关系
Mochi-1T5-XXL与 SD3 同
Wan 2.1 / 2.2UMT5 (multilingual)支持中英双语
CogVideoXT5-XXL
Sora未公开OpenAI 报告只提到使用 re-captioning 流程

💡 prompt rewriter(Hunyuan-Video / Sora 报告) — 训练数据 caption 通常长且细致,用户 short prompt 与训练分布有 gap。Sora 官方报告提到训练前对视频做 dense re-captioning;Hunyuan-Video 在推理时用 LLM 改写短 prompt 成 dense caption 再喂模型。面试常问"为什么需要 prompt rewriter"——答:训练/推理 caption 分布对齐 + 用户原 prompt 太短。

5.4 代码:MM-DiT video block

class MMDiTVideoBlock(nn.Module): """ Dual-stream MM-DiT block (Hunyuan-Video / Mochi-1 / SD3 style). Text token 与 video token 共享 self-attention 矩阵, 但 QKV / FFN / AdaLN 各自参数. """ def __init__(self, dim, heads, head_dim, mlp_ratio=4.0): super().__init__() self.heads = heads self.head_dim = head_dim self.scale = 1.0 / math.sqrt(head_dim) # 各自的 QKV self.qkv_text = nn.Linear(dim, 3 * heads * head_dim, bias=False) self.qkv_vid = nn.Linear(dim, 3 * heads * head_dim, bias=False) self.out_text = nn.Linear(heads * head_dim, dim, bias=False) self.out_vid = nn.Linear(heads * head_dim, dim, bias=False) # 各自的 FFN hidden = int(dim * mlp_ratio) self.mlp_text = nn.Sequential(nn.Linear(dim, hidden), nn.GELU(), nn.Linear(hidden, dim)) self.mlp_vid = nn.Sequential(nn.Linear(dim, hidden), nn.GELU(), nn.Linear(hidden, dim)) # 各自的 AdaLN(由 timestep + pooled text condition 调制) self.norm_text = nn.LayerNorm(dim, elementwise_affine=False) self.norm_vid = nn.LayerNorm(dim, elementwise_affine=False) self.norm_ff_text = nn.LayerNorm(dim, elementwise_affine=False) self.norm_ff_vid = nn.LayerNorm(dim, elementwise_affine=False) self.cond_text = nn.Linear(dim, 6 * dim) self.cond_vid = nn.Linear(dim, 6 * dim) @staticmethod def _modulate(x, shift, scale): return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1) def _proj_qkv(self, x, qkv_mod): B, L, _ = x.shape qkv = qkv_mod(x).reshape(B, L, 3, self.heads, self.head_dim) q, k, v = qkv.unbind(dim=2) # [B, L, H, d_k] return q.transpose(1, 2), k.transpose(1, 2), v.transpose(1, 2) # [B, H, L, d_k] def forward(self, text, vid, cond): """ text: [B, L_t, D] vid: [B, N_v, D] cond: [B, D] (timestep emb + pooled text) """ # Modulation params st_a, sc_t_a, gt_a, st_m, sc_t_m, gt_m = self.cond_text(F.silu(cond)).chunk(6, dim=-1) sv_a, sc_v_a, gv_a, sv_m, sc_v_m, gv_m = self.cond_vid(F.silu(cond)).chunk(6, dim=-1) # Pre-norm + modulate (各 stream 独立) t = self._modulate(self.norm_text(text), st_a, sc_t_a) v_ = self._modulate(self.norm_vid(vid), sv_a, sc_v_a) # 各 stream 的 QKV (独立参数) qt, kt, vt = self._proj_qkv(t, self.qkv_text) qv, kv, vv = self._proj_qkv(v_, self.qkv_vid) # Concat 两 stream 沿 seq 维一起 self-attention q = torch.cat([qt, qv], dim=2) # [B, H, L_t + N_v, d_k] k = torch.cat([kt, kv], dim=2) v = torch.cat([vt, vv], dim=2) out = F.scaled_dot_product_attention(q, k, v) # [B, H, L_t + N_v, d_k] L_t = text.shape[1] out_t, out_v = out[:, :, :L_t], out[:, :, L_t:] out_t = out_t.transpose(1, 2).reshape(*text.shape[:2], -1) out_v = out_v.transpose(1, 2).reshape(*vid.shape[:2], -1) # Out projection (各 stream) text = text + gt_a.unsqueeze(1) * self.out_text(out_t) vid = vid + gv_a.unsqueeze(1) * self.out_vid(out_v) # FFN (各 stream) text = text + gt_m.unsqueeze(1) * self.mlp_text( self._modulate(self.norm_ff_text(text), st_m, sc_t_m)) vid = vid + gv_m.unsqueeze(1) * self.mlp_vid( self._modulate(self.norm_ff_vid(vid), sv_m, sc_v_m)) return text, vid

5.5 训练目标

主流 = v-prediction 或 rectified flow vector(与 SD3 一致)。给定 video latent x1x_1、噪声 x0x_0、随机 τ[0,1]\tau \in [0, 1](logit-normal 分布更常用):

xτ=(1τ)x0+τx1,uτ=x1x0x_\tau = (1 - \tau) x_0 + \tau\, x_1, \quad u_\tau = x_1 - x_0

L=Eτ,x0,x1,cvθ(τ,xτ,c)uτ2\mathcal{L} = \mathbb{E}_{\tau, x_0, x_1, c} \, \| v_\theta(\tau, x_\tau, c) - u_\tau \|^2

其中 cc 是 text condition(+ optional 图像 / 视频条件)。Hunyuan-Video / Mochi / Wan 都用 RF(与 image 端 SD3 同 paradigm);Sora 未公开但社区推测也是 RF / v-pred 家族。

§6 Image-to-Video (I2V) — 主流三种条件注入

6.1 First-Frame Channel Concat(最简、最常用)

把参考图 IrefI_\text{ref} 编码成 latent zref(0)RC×1×h×wz_\text{ref}^{(0)} \in \mathbb{R}^{C \times 1 \times h \times w}(VAE 在 T=1T{=}1 下退化为 2D 编码),沿 latent 时间维 tt(不是原始帧 TT)做 zero-padded broadcast,并和 noisy latent 沿 channel 维拼接:

z~τ=concatC ⁣(zτ,z~ref,m)R(2C+1)×t×h×w\tilde{z}_\tau = \text{concat}_C\!\left(z_\tau, \, \tilde{z}_\text{ref}, \, m\right) \in \mathbb{R}^{(2C+1) \times t \times h \times w}

其中 z~ref[:,t,:,:]=zref(0)\tilde{z}_\text{ref}[:, t', :, :] = z_\text{ref}^{(0)}tt' 是参考位(一般为 t=0t' = 0),其余位为 0;m{0,1}1×t×h×wm \in \{0, 1\}^{1 \times t \times h \times w} 是同 shape 的 mask channel(参考位为 1,待生成位为 0)。模型第一层 conv 的 in_channels 从 CC 改成 2C+12C + 1

优点:实现简单,与 T2V 主干完全兼容;改一层 conv 就行。缺点:参考信息混在 channel 里,模型要靠 conv 自己提取;远距离帧的引导能力弱。

SVD (Stable Video Diffusion, Blattmann 2023) / DynamiCrafter / I2VGen-XL 都用这套。

6.2 Cross-Attention 注入(细粒度控制)

zrefz_\text{ref} patchify 成 token,作为额外 K/V 注入到 video stream 的 attention:

CrossAttn:Q=zvideo tokens,K,V=[ztext,zref tokens]\text{CrossAttn}: \quad Q = z_\text{video tokens}, \, K, V = [z_\text{text}, z_\text{ref tokens}]

或更复杂——为 ref image 增加独立 cross-attention 层。AnimateDiff 风格的 LoRA tuning 也基本用这条路。

6.3 AnimateDiff 风格 plug-in motion module

AnimateDiff (Guo et al. arXiv 2023-07, ICLR 2024) — 冻结一个 T2I (Stable Diffusion),只插入并训练 temporal motion module(temporal self-attention),就把 T2I 变 T2V。优势:复用 T2I 生态(LoRA / ControlNet);劣势:质量受 base T2I 限制。Motion module 通常插在每个 spatial block 后:[B,T,C,H,W] -> rearrange [B*H*W, T, C] -> temporal self-attn -> back

6.4 代码:first-frame concat I2V

class FirstFrameI2VAdapter(nn.Module): """ 把 ref image latent 沿时间 broadcast + 沿 channel concat 到 noisy latent. 用法: 替换 DiT 的 patchify 输入投影, in_ch 从 C 改为 (2C + 1). """ def __init__(self, latent_ch=16, embed_dim=1024, patch=(1, 2, 2)): super().__init__() self.patch = patch # +1 是 mask channel self.proj = nn.Conv3d( in_channels=2 * latent_ch + 1, out_channels=embed_dim, kernel_size=patch, stride=patch, ) def forward(self, noisy_latent, ref_latent, ref_mask): """ noisy_latent: [B, C, t, h, w] - 加噪 latent ref_latent: [B, C, t, h, w] - 参考帧 latent (待生成位为 0) ref_mask: [B, 1, t, h, w] - 1 = 该位置 (在 t 维) 是参考帧, 0 = 待生成 """ x = torch.cat([noisy_latent, ref_latent, ref_mask], dim=1) # [B, 2C+1, t, h, w] x = self.proj(x) # [B, D, t', h', w'] B, D, tt, hh, ww = x.shape return x.flatten(2).transpose(1, 2), (tt, hh, ww) # [B, N, D]

💡 build ref_latent + mask 的伪代码 — 给定 video latent z_full 和参考帧索引 ref_indices(如 [0] 表示 first-frame I2V),把 z_full[:, :, idx] 拷贝到 ref_latent 同位置、其余位 0,并在 ref_mask 对应位置赋 1。具体实现见 §A.2 video_gen_forward 内部。

6.5 训练时的"noise-only on未来帧" trick

I2V 训练时给参考帧 latent 不加噪(或加极小噪声),待生成帧加正常 τ\tau 噪声。loss 只在待生成帧位置计算。这点在 SVD / Hunyuan-Video I2V variant 中都有提到。

§7 长视频生成(开放问题)

7.1 三大主流路线

路线方法代表缺点
Keyframe + interpolation先生成 KK 个关键帧(远距),再每段插值出中间帧NUWA-XL, Movie Gen 部分 pipeline关键帧 transition 可能不自然
Hierarchical (coarse → fine)先生成 low-fps 低分辨率版本,再 cascade 超分 + 帧插Phenaki, Imagen Video, Sora 部分多阶段累积误差
Autoregressive chunks每次生成 TT 帧 chunk,下一 chunk 以前 chunk 末尾为条件Mochi-1 部分模式, StreamingT2V误差累积 → drift, "loop"

7.2 Sora 的 "duration as condition"

Sora 把 video duration 当成 conditioning(不是固定 TT),训练时把不同时长视频都见过;推理时给定目标时长,生成对应长度 patch 序列。这在公开 report 中只是简短提到。

7.3 Autoregressive Video Generation 兼容性(Causal VAE 派上用场)

由于 3D Causal VAE encoder 不看未来,自然支持 chunk-wise 自回归:encoder 可以一段一段处理。但 DiT 部分要做到自回归还需在 token 维度也加 causal——这是研究方向("VAR for Video" 等)。Hunyuan-Video / Wan 现版本仍是 non-AR diffusion。

7.4 简单的 chunk 自回归伪代码

@torch.no_grad() def chunk_autoregressive(rf_sample_fn, vae, text, num_chunks, chunk_t_lat=4, overlap=1, latent_shape=(16, 60, 90)): """ Chunk-wise 自回归生成长视频伪代码框架. rf_sample_fn(z_init, text, ref_full, ref_mask) -> z_out ——使用 §A.3 的 video_gen_sample 风格, 但接受外部 z_init 与 ref clamp. latent_shape = (C, h_lat, w_lat); 每段 latent 时间长度 = chunk_t_lat. """ chunks = [] ref_latent = None C, hl, wl = latent_shape device = next(vae.parameters()).device for c in range(num_chunks): # 初始 noise z_init = torch.randn(1, C, chunk_t_lat, hl, wl, device=device) # 上一段末尾 overlap 帧当 ref if ref_latent is not None: z_init[:, :, :overlap] = ref_latent[:, :, -overlap:] ref_full = torch.zeros_like(z_init) ref_full[:, :, :overlap] = ref_latent[:, :, -overlap:] ref_mask = torch.zeros(1, 1, chunk_t_lat, hl, wl, device=device) ref_mask[:, :, :overlap] = 1.0 else: ref_full, ref_mask = None, None z = rf_sample_fn(z_init, text, ref_full, ref_mask) # [1, C, chunk_t_lat, h, w] chunks.append(z) ref_latent = z # 拼接 chunks(去重 overlap), VAE decode z_full = torch.cat([chunks[0]] + [c[:, :, overlap:] for c in chunks[1:]], dim=2) return vae.decoder(z_full)

⚠️ drift 问题 — 即使有 overlap,AR 模式下后期 chunk 容易出现内容 drift(人物消失、色调变化)。Movie Gen / Hunyuan 采用全局 attention 一次生成短视频(5-10s)+ 后处理超分时长 trick 而非纯 AR。

§8 控制 / 编辑 / 角色一致性(简表)

任务代表方法注入手段
Camera 控制MotionCtrl (Wang et al. 2023)CMCM: 相机轨迹 R,TR, T 序列 → temporal embedding
Object trajectory 控制MotionCtrl OMCM 模块2D 轨迹点 → spatial heatmap 当 condition
人物动画AnimateAnyone (Hu et al. CVPR 2024)ReferenceNet (sibling SD 主干) + Pose Guider (OpenPose/DWPose) + temporal layers
角色一致IP-Adapter / DreamBooth-styleID embedding 经 cross-attn 注入
局部编辑Mask-guided generation角色 mask + ref image 一同注入

§9 评测:VBench / FVD / CLIPSim-V

VBench (Huang et al. CVPR 2024) — 现 SoTA 标准 — 16 个细粒度维度,分两大类。

  • Video Quality (7 维):Subject Consistency, Background Consistency, Temporal Flickering, Motion Smoothness, Dynamic Degree, Aesthetic Quality, Imaging Quality
  • Video-Condition Consistency (9 维):Object Class, Multiple Objects, Human Action, Color, Spatial Relationship, Scene, Appearance Style, Temporal Style, Overall Consistency

每维有定制 prompt 集 + 自动评测器(GroundingDINO / DOVER / RAFT / CLIP 等),最后给加权综合分。Hunyuan-Video / Mochi / Movie Gen / Sora 等都在 VBench 上自报或被独立测。

FVD (Unterthiner et al. 2018) — FID 推广到视频。生成 / 真实视频分别过一个预训练 video classifier(I3D / VideoMAE / S3D)拿中间层 feature,计算两组分布的 Fréchet 距离:

FVD=μgμr2+Tr ⁣(Σg+Σr2ΣgΣr)\text{FVD} = \|\mu_g - \mu_r\|^2 + \text{Tr}\!\left(\Sigma_g + \Sigma_r - 2\sqrt{\Sigma_g \Sigma_r}\right)

低 FVD = 生成分布更接近真实;缺点:依赖 classifier domain,不反映 text-video alignment。

CLIPSim-V — 每帧取 CLIP image embedding 与 prompt CLIP text embedding 计算余弦:1Ttcos(CLIP-I(ft),CLIP-T(prompt))\frac{1}{T} \sum_t \cos(\text{CLIP-I}(f_t), \text{CLIP-T}(\text{prompt}))。评 text-video 对齐,但忽略时序连贯。

实务:Hunyuan-Video tech report 同时报 VBench + 人评(user study 1-5 likert);Sora / Veo demos 只给定性可视化。面试碰到"你怎么评测"——说 VBench + 人评 + 在 UCF-101 / MSR-VTT 上算 FVD。

§10 复杂度与显存

10.1 Token 数与 attention cost

视频规格VAE 下采样VAE 后 latent shapePatchify (1,2,2) 后 NFull-3D Attn N2N^2
256×256×16256{\times}256{\times}16 (2s, 8fps)4×8×84{\times}8{\times}84×32×324 \times 32 \times 3241616=10244 \cdot 16 \cdot 16 = 1024106\approx 10^6
720p×48720p{\times}48 (2s, 24fps, latent 12×90×16012{\times}90{\times}160)4×8×84{\times}8{\times}812×90×16012 \times 90 \times 160124580=4320012 \cdot 45 \cdot 80 = 432001.9×109\approx 1.9 \times 10^9
1080p×1201080p{\times}120 (5s, 24fps, latent 30×136×24030{\times}136{\times}240)4×8×84{\times}8{\times}830×136×24030 \times 136 \times 2403068120=24480030 \cdot 68 \cdot 120 = 2448006.0×1010\approx 6.0 \times 10^{10}

很快爆。面试常问 "长视频/高分辨率 attention 瓶颈"——答:O(N2)O(N^2) 二次成本 + FlashAttention 也减不了 token 数本质;解法是 factorized / window / cascaded 多阶段。

10.2 显存与 FLOPs 要点

  • Score 矩阵显存:vanilla 是 O(L2)O(L^2);FlashAttention 降到 O(L)O(L) activation
  • KV cache:纯 diffusion 无 AR step,训练时无 KV cache 概念;activation checkpointing + ZeRO-3 是必备
  • 3D Causal VAE 推理:可分 chunk,显存 O(chunkThwC)O(\text{chunk}_T \cdot h \cdot w \cdot C)
  • 训练 FLOPs:13B 模型 per-batch attention FLOPs ≈ 4BN2d4 B N^2 d × layers(B = batch size);Hunyuan-Video 全模型 ≈ 几百到上千 PFLOP / sample 量级,用数千 H100 数月级别训出

§11 与其他生成模型的关系

11.1 Image diffusion vs Video diffusion

维度Image (SD3 / SDXL / FLUX)Video (Hunyuan / Mochi / Wan)
VAE2D VAE, 8×\downarrow 8\times3D Causal VAE, 4×8×8\downarrow 4\times8\times8
Token 数103\sim 10^3 (1024² @ 16²)104105\sim 10^4 - 10^5
AttentionSelf + CrossST (factorized / full 3D) + Cross/MM-DiT
训练 token 量数十亿 image-text pair数千万 video-text pair(视频数据稀缺)
评测FID, CLIPScoreVBench, FVD, CLIPSim-V
主要难点美学 / prompt 跟随时序一致性 / 物理合理性 / 长时长

11.2 Video LLM vs Video Generation vs AR Video

  • Video LLM (VideoChat / Video-LLaVA / NaVit):输入视频,输出文本(理解方向);CLIP/ViViT/VideoMAE feature + LLM
  • Diffusion Video Gen(本文主线):质量高,长视频靠 chunk / hierarchical
  • AR Video (Cosmos-Predict, VAR-Video 系列):视频 token 化 (VQ-VAE / FSQ) + LM 风格生成。优势:天然 streaming + 长视频;劣势:质量目前不如 diffusion
  • Unified (Show-o / Emu3 等 2025 苗头):同时理解 + 生成;视频版本尚未爆发
  • 2024-2025 SoTA 仍以 diffusion 占主流

§12 25 高频面试题

按难度分 3 档:L1 必会(任何 MLE 岗)、L2 进阶(research-oriented)、L3 顶级 lab(diffusion / video specialist)。每题点开看答案要点 + 易踩坑。

L1 必会题(基础 — 任何视频生成相关岗)

Q1. 当下主流视频生成模型的整体 pipeline 是什么?
  • 3D Causal VAE 把视频从 H×W×TH{\times}W{\times}T 压到 h×w×th{\times}w{\times}t latent
  • Latent DiT / MM-DiT 在 latent 空间做扩散 / flow matching
  • Text encoder(T5 / CLIP / MLLM)提供 condition
  • VAE Decoder 把 latent decode 回视频
  • 推理用 ODE/SDE sampler(Euler / Heun / DDIM)从噪声积分到数据

只说 "diffusion + UNet",忘了 latent / 3D / VAE 三件套;或说 pixel-space 跑 attention(早就不可行)。

Q2. 3D Causal VAE 的 "Causal" 是什么意思?为什么必须 causal?
  • 时间维度 conv padding 全堆到左侧(过去),右侧不 pad,不让 current frame 看未来
  • 三大收益:(1) 图像和视频可共享 latent 空间T=1T{=}1 时退化成 2D,图像也能进 encoder),便于 image+video 联合训练;(2) 流式 / 自回归推理,长视频可 chunk-wise 处理;(3) 训练时 image 视为 T=1T{=}1 视频,数据利用率高
  • Hunyuan-Video / Wan / Mochi / CogVideoX 都用 causal 3D VAE

说 "causal 就是 mask 掉未来"——这是表面,关键是为什么有那 3 个工程收益。

Q3. Sora 的 "spacetime patches" 解决了什么问题?
  • 把视频 latent 切 3D patch pt×ph×pwp_t \times p_h \times p_w,每个 patch 是一个 token
  • 支持变 resolution / 变 duration / 变 aspect ratio——不同 shape 视频直接打包到同 batch(用 attention mask 分离)
  • 类似 ViT 但加了时间维;解耦了网络结构与具体输入形状

只说"切 patch",没说核心收益(变形状训练 / 推理)。

Q4. Factorized 2+1D attention 和 Full 3D attention 的复杂度差多少?
  • 记每帧 token 数 SS、时间 token 数 TtT_t、总 token 数 N=STtN = S T_t
  • Factorized 2+1D:spatial O(TtS2)O(T_t S^2) + temporal O(STt2)O(S T_t^2)
  • Full 3DO(N2)=O(S2Tt2)O(N^2) = O(S^2 T_t^2)
  • Full 3D 比 Factorized 多 min(S,Tt)\min(S, T_t)
  • 但 Full 3D 表达力更强(允许 spatial + temporal 联合 pattern)

只比 Full 3D 不算时间项;或忽略两者本质差是"是否假设 space ⊗ time 可分"。

Q5. MM-DiT for video 是怎么注入文本的?
  • Text token 和 video token 拼接到同一序列做 self-attention
  • 每个 stream 各自的 QKV / FFN / AdaLN 参数(dual-stream),但 attention 矩阵共享
  • 对比传统 cross-attention(Q from video, KV from text):MM-DiT 让两个模态在 token 级别对等交互
  • Hunyuan-Video / Mochi 用此架构(video 端);SD3 (Esser et al. 2024) 是 image 端的原始 MM-DiT

说 video 主干 + cross-attn from text——这是 SDXL 风格,MM-DiT 已替代它。

Q6. I2V (Image-to-Video) 最简单的实现是怎样的?
  • 参考图 IrefI_\text{ref} 编码为 latent zrefz_\text{ref}
  • 沿时间维 broadcast,沿 channel 维与 noisy latent 拼接:input channel 从 CC 改成 2C+12C{+}1(加一个 mask channel 标注哪些帧是 ref)
  • 模型其他部分不变;改 patchify 第一层 conv
  • 训练时参考帧不加噪 / 加极小噪,loss 只在待生成帧上算

只说"再喂一张图",没说 concat 在哪 / mask 怎么处理。

Q7. AnimateDiff 的核心思路?
  • 冻结一个 T2I 模型(Stable Diffusion)
  • 插入 + 仅训 temporal motion module(temporal self-attention),插在每个 spatial block 后
  • 优势:直接复用所有 T2I 生态(LoRA, ControlNet, custom checkpoint)
  • 劣势:质量受限于 base T2I 模型;难做长视频

说"用 transformer 替换 UNet"——错,AnimateDiff 是 plug-in,不替换主干。

Q8. VBench 评测什么?与 FVD 有什么区别?
  • VBench (Huang CVPR 2024):16 个细粒度维度(如 Subject Consistency, Motion Smoothness, Object Class, Color, ...),每维用专门 detector / classifier 评分;现 SoTA 视频生成标准
  • FVD (Unterthiner 2018):FID 推广到视频;用 I3D / VideoMAE feature 算两组分布的 Fréchet 距离;单一数字
  • VBench 更解释性强,能定位哪个维度差;FVD 单一但黑盒
  • 实务:两者一起报 + 人评

只听过 FVD 不知道 VBench——2024 后这是大缺口。

Q9. Sora / Hunyuan-Video / Mochi-1 / Kling 哪些开源?
  • 开源:Hunyuan-Video (13B, 2024-12), Mochi-1 (10B, 2024-10), CogVideoX (2B/5B, arXiv 2024-08), OpenSora / OpenSora-Plan, LTX-Video (2B, 2024-11), Wan 2.1/2.2 (14B, 2025), SVD (2023-11)
  • 闭源:Sora (2024-02), Veo / Veo 2 (Google), Kling (Kuaishou 2024-06), Movie Gen (Meta, 30B)
  • 国内开源主力:Hunyuan / Wan / CogVideoX

只记得 Sora 和 SVD——闭源开源都得知道时间线。

Q10. Text encoder 选择:T5 vs CLIP vs MLLM?
  • CLIP-L / G:与图像 latent 对齐好(image-text 联合训练),短文本工作得好,但长 prompt 跟随差
  • T5-XXL:sequence-to-sequence 模型,长 prompt 跟随更好;SD3 / Mochi / CogVideoX 都用
  • MLLM(LLaVA-like):理解 prompt 内物体关系强;Hunyuan-Video 用 CLIP-L + MLLM 双编码器
  • 工程上长 prompt 推理时还会用 prompt rewriter(LLM 改写)补齐 train/test caption 分布差

只说 CLIP——2024 后基本被 T5 / MLLM 替代或并用。

L2 进阶题(research-oriented / 中级岗)

Q11. 推导一下 3D Causal VAE 在 $T{=}1$ 时为什么能"行为上"等价于 2D conv?
  • Causal 3D conv 在时间维 kernel size ktk_t,左 pad kt1k_t - 1,右 pad 0;stride=1。
  • 输入 shape [B,C,1,H,W][B, C, 1, H, W]T=1T{=}1 单帧);经左 pad kt1k_t - 1 后,时间维长度变为 1+(kt1)=kt1 + (k_t - 1) = k_t,前 kt1k_t - 1 个时间位是 padding 0,最后 1 个是真实 frame。
  • Output 时间长度 = (kt+0kt)/1+1=1(k_t + 0 - k_t)/1 + 1 = 1(用 conv 输出长度公式 (Lin+pk)/s+1(L_\text{in} + p - k) / s + 1,其中 Lin=1L_\text{in}=1p=kt1p=k_t-1k=ktk=k_ts=1s=1)。所以只产生一个时间位输出
  • 设时间维权重序列 W0,W1,,Wkt1W_0, W_1, \dots, W_{k_t-1},对该唯一输出位的计算是 τ=0kt1Wτxτ\sum_{\tau=0}^{k_t-1} W_\tau \star x_\tau。但只有 τ=kt1\tau = k_t - 1 对应真实 frame,其余 xτx_\tau 是 padding 0——只有 Wkt1W_{k_t - 1} 这一片时间权重对输出有贡献
  • 结论T=1T{=}1 时整个 causal 3D conv 退化为一个有效的 2D conv(kernel = Wkt1[:,:,:,:]W_{k_t - 1}[:, :, :, :]);其余时间片权重对 image batch "看不到"任何真实输入,相当于在 image path 上不被激活。

工程上:训练时 image 用 T=1T{=}1 batch 走 "2D conv 子集" 路径,无需额外 2D head;这是 Hunyuan-Video / Mochi / CogVideoX 等同时训 image + video 的前提。

把"等价于 2D conv"当成权重物理合并——其实是 padding-0 让其他 time slice 权重对 image 输入不起作用。

Q12. Full 3D attention 与 factorized 2+1D 的表达力差异?(L2/L3 之间)
  • Factorized:先 AttnS\text{Attn}_S 把空间 token 互相 attend (在每帧内),再 AttnT\text{Attn}_T 在时间维做 attention
  • 假设:时空交互是 separable——任意两个时空位置 (t1,s1)(t_1, s_1)(t2,s2)(t_2, s_2) 的关系,可以分解为"先 s1s2s_1 \leftrightarrow s_2t1t_1"再"t1t2t_1 \leftrightarrow t_2s2s_2"两步
  • Full 3D 不假设可分:任意两 token 直接 attention;可学斜向时空 pattern(如 diagonal motion)
  • 数学上:factorized 是 full 3D 的一个严格子集(参数化受限)
  • 实测:full 3D 在 fast motion / 复杂时空 pattern 上更好

只说"full 3D 更准确",不知具体能学到的 pattern 多在哪里(diagonal / non-separable motion)。

Q13. 为什么 video VAE 主流停在 $\downarrow 4{\sim}8 \times 8 \times 8$ 范围?
  • 体素级压缩比 =488=256= 4 \cdot 8 \cdot 8 = 2561:2561{:}256),C=16C=16 latent channel 后净比约 1:481{:}48
  • 更激进(如 LTX-Video 报告的 1:81921{:}8192 总压缩)→ token 数变少但重建质量下降(细节 / 锐度损失)
  • DiT 主干 attention O(N2)O(N^2),所以激进压缩工程友好;但 lost detail 难以恢复
  • 时间下采样 4×4{\times} 是经验上 motion 平滑性可接受的上限——更高时间压缩在快动作场景会出抖动
  • 各家具体配置不同:CogVideoX 用 4×8×84{\times}8{\times}8;Hunyuan-Video 用 4×8×84{\times}8{\times}8;Mochi-1 在时间维更激进(约 6×8×86{\times}8{\times}8,见 Mochi blog);LTX-Video 走极端高压缩 + 实时
  • 即使主架构相同,VAE 选择仍是 active design choice

把所有模型都归到 4×8×84{\times}8{\times}8 同一档——Mochi-1 / LTX-Video 走的是更激进时间压缩。

Q14. logit-normal $t$ 采样在 video FM 训练中为什么有用?
  • SD3 (Esser 2024) 发现 tU[0,1]t \sim \mathcal{U}[0,1] 不最优:中间区域 t0.5t \approx 0.5 的 noise/signal ratio 最难学
  • 改成 t=σ(τ),τN(m,s2)t = \sigma(\tau), \tau \sim \mathcal{N}(m, s^2),让 tt 集中在 0.5 附近
  • 视频中也观察到同样现象(Hunyuan / Mochi 都默认 logit-normal)
  • 直觉:远离 t=0t=0t=1t=1 时模型需要在 mixed noise/signal 上学,正是 hardest 区域

说"loss 加权"——logit-normal 不是 loss reweighting 而是改 tt 采样分布。

Q15. RoPE-3D 怎么编码 (time, height, width)?
  • dd 维 query/key 切成 3 段 q=[q(t)q(h)q(w)]q = [q^{(t)} \,|\, q^{(h)} \,|\, q^{(w)}](disjoint subspace),每段对应 (t, h, w)
  • 每段用 1D RoPE(频率 θd=1/100002k/d\theta_d = 1 / 10000^{2k/d} 类似 Transformer)
  • 结果是 block-diagonal 旋转 concat:RoPE3D(q)=[Rt(θt)q(t)Rh(θh)q(h)Rw(θw)q(w)]\text{RoPE}_{3D}(q) = [R_t(\theta_t) q^{(t)} \,|\, R_h(\theta_h) q^{(h)} \,|\, R_w(\theta_w) q^{(w)}]
  • 对每个 head 独立做;attention 后自然得到相对时空位置信息
  • CogVideoX / Hunyuan-Video 都用类似方案

把它当成 absolute embedding——RoPE 本质是相对位置编码。

Q16. Stable Video Diffusion (SVD) 与 AnimateDiff 的区别?
  • SVD (Blattmann 2023):finetune 整个 SD2.1 UNet,加 temporal layers;I2V 主,14 帧 / 25 帧两版;新模型整体训练
  • AnimateDiff (Guo 2024 ICLR):冻结 SD-T2I,只训 plug-in temporal motion module;T2V 主
  • SVD 质量更好但失去 SD T2I 生态;AnimateDiff 牺牲质量换 plug-and-play
  • 都是 2023 的早期方法,2024 被 DiT-based 大模型超越

只说"两者都是 video diffusion"——区别是 finetune vs plug-in。

Q17. DiT 用 AdaLN 与 cross-attn 的对比?为什么 DiT-Video 也偏好 AdaLN?
  • AdaLN(DiT 默认):把 condition pool 成单向量 cc,预测 LayerNorm 的 scale + shift + gate
  • Cross-attn:condition token 作 K/V, video token 作 Q
  • AdaLN 简单 / 计算少 / 训练稳;但全局 condition——每 token 看到同一个 modulation
  • Cross-attn 允许 token-level 选择性看 condition;token 多时贵
  • MM-DiT(SD3 / Hunyuan / Mochi)实际把两者结合:MM 部分 share attention,AdaLN 调制 norm
  • 单纯 video DiT 用 AdaLN 起家是 Latte / OpenSora 思路;后续被 MM-DiT 取代

把 AdaLN 当过时——MM-DiT 仍内嵌 AdaLN modulation。

Q18. CFG 在视频生成里的特殊点?
  • 与 image 完全同公式:vCFG=vθ()+s(vθ(c)vθ())v_\text{CFG} = v_\theta(\emptyset) + s \cdot (v_\theta(c) - v_\theta(\emptyset))
  • 每帧都做 CFG,所以两倍 forward 成本 ×\times T 帧
  • guidance scale 通常 5-7.5(与 SDXL / SD3 接近)
  • 视频中过大 ss 容易导致帧间闪烁 / 颜色饱和 —— 比图像更敏感
  • 部分实现用 temporal-aware CFG(不同时间步 / 不同帧用不同 ss

说 "CFG 在视频里和图像一样"——通常对,但闪烁更敏感是 video specific。

Q19. Hunyuan-Video 的 dual-stream → single-stream 设计是什么?
  • Dual-stream blocks(前段 layers):text token + video token 共享 attention 矩阵,但 QKV / FFN / AdaLN 各 stream 独立——让两个模态先精炼自己的表征
  • Single-stream blocks(后段 layers):完全 share 参数,相当于 unified Transformer
  • 直觉:早期需要保留模态特异性(text 是 sequential,video 是 spatiotemporal),后期可以统一处理
  • Mochi 的 AsymmDiT 类似思路但更激进——video stream 比 text stream 宽 4 倍

只说"都是 self-attn 同序列"——遗漏了 stream-specific 参数 / 早晚不同的 design。

Q20. Mochi-1 的 AsymmDiT (asymmetric MM-DiT) 是什么?
  • 两个 stream(text / video)的 hidden dim 不一样:video 比 text 宽 4 倍(如 video D=3072D{=}3072 / text D=768D{=}768
  • 直觉:视频信息量远超文本,应分配更多参数给 video stream
  • Attention 时 text 和 video 投影到共同 head dim,做 self-attention
  • FFN 各 stream 独立,按各自宽度
  • 比标准 MM-DiT 用更少 text-side 参数,省显存又不损质量

把 "asymmetric" 当成两个 stream 不交互——错,它们仍同 attention。

L3 顶级 lab 题(深度 — diffusion / video specialist)

Q21. 3D Causal VAE vs 标准 3D VAE:除了 streaming,还有什么本质差别?(必考)
  • 标准 3D VAE:时间 kernel center 对齐,需 symmetric padding,output[t] 依赖 input[t-\lfloor k_t/2 \rfloor \ldots t+\lfloor k_t/2 \rfloor]——看了未来
  • 3D Causal VAE:时间 kernel 因果对齐,左侧 pad kt1k_t - 1,右侧不 pad,output[t] 只依赖 input[t-k_t+1 \ldots t]

本质差别

  • Streaming / 自回归推理:causal 允许 chunk-wise encoding,每来一段视频立即编码;标准 VAE 要等完整 clip 才能算(kernel center 需未来帧)
  • 图像视频同空间:两者 T=1T{=}1 时其实都能"退化到 2D"(zero pad 让其他时间片不起作用),但 causal 设计是"过去全见 + 未来全 0",与训练时大 TT 的子集行为一致;symmetric pad 在 T=1T{=}1 时让 kernel 左右各看 kt/2\lfloor k_t/2 \rfloor 个 padding,行为与训练时 T1T \gg 1 的 boundary 行为不同——一致性更差
  • 训练 + inference 一致性:causal VAE 训练(完整 clip)与推理(AR chunk)共用一套 padding 规则;标准 3D VAE 在 AR chunk 推理时缺右侧未来 frame,需要特殊 pad
  • 与 AR video 兼容:causal 是 AR video 生成 (VAR-Video / Cosmos) 的必要前提
  • 训练数据 utilization:image-only batch 在 causal VAE encoder 里行为与训练时一致;标准 3D VAE 需要 dummy symmetric padding,与正常训练分布有 gap

💡 加分:解释 causal VAE 的 downsample 层怎么做(time stride 2 时仍保 causal);解释训练 batch 里 image + video 混合的 implementation 细节。

只说"causal 是 mask 未来"——这是必要不充分;要展开"为何这件事让生态闭环(image + video 同 stack, AR 兼容, streaming)"。

Q22. 用 spacetime patches 处理任意 resolution / duration / aspect ratio 的工程实现?
  • Patchify token 数 N=(t/pt)(h/ph)(w/pw)N = (t/p_t)(h/p_h)(w/p_w) 随输入 shape 变;Transformer 对 NN 不敏感(self-attn 是 set-like)
  • RoPE-3D:相对位置编码,不与最大长度绑定;任意 (t,h,w)(t, h, w) 三元组都可旋转
  • Packing:一 batch 内 mixed shape sample concat 到同 seq + segment attention mask(同 sample 内可见、跨 sample 屏蔽)+ pad 到 max length
  • Aspect ratio / duration 作为 condition:额外 token / scalar 经 AdaLN 注入,让模型学不同比例的合理构图
  • Sora 首次 production 化;社区复刻见 OpenSora-Plan / OpenSora 1.2+

只说"transformer 不挑长度"——要展开 packing + segment mask + RoPE-3D + aspect ratio condition 这一整套工程组件。

Q23. Factorized 2+1D vs Full 3D attention 复杂度对比的精确公式 + 何时选哪个?
  • 记每帧 spatial token S=(h/ph)(w/pw)S = (h/p_h)(w/p_w),时间 token Tt=t/ptT_t = t/p_t,总 token N=STtN = S T_t
  • Factorized 2+1D
    • Spatial attn (每帧内独立): TtS2dT_t \cdot S^2 \cdot d
    • Temporal attn (每空间位置内独立): STt2dS \cdot T_t^2 \cdot d
    • 合计 O ⁣(d(TtS2+STt2))=O ⁣(dSTt(S+Tt))O\!\left(d \cdot (T_t S^2 + S T_t^2)\right) = O\!\left(d \cdot S T_t (S + T_t)\right)
  • Full 3D: O(dN2)=O ⁣(dS2Tt2)O(d \cdot N^2) = O\!\left(d \cdot S^2 T_t^2\right)
  • 比值 = full / factorized = S2Tt2STt(S+Tt)=STtS+Tt\frac{S^2 T_t^2}{S T_t(S + T_t)} = \frac{S T_t}{S + T_t},等于 min(S,Tt)\min(S, T_t) 量级
  • S103S \approx 10^3(720p latent)、Tt30T_t \approx 30(5s)时:full 比 factorized 贵 30×\approx 30\times(被 min\min 主导)

何时选哪个

  • 算力充足 + 高质量目标:Full 3D(Sora / Hunyuan / Mochi)
  • 预算受限 / 快速迭代:Factorized 2+1D(Latte / OpenSora / AnimateDiff)
  • 质量与速度折中:大部分块 factorized + 几块 full 3D(OpenSora-Plan 思路)
  • 显存敏感时 factorized + recompute 是更经济选择

只给定性回答"full 更贵"——L3 题要给精确公式 + 工程选择 trade-off。

Q24. 长视频 (>30s) 现阶段最 promising 的路线是什么?为什么 chunk AR 容易 drift?
  • Drift 数学解释:每 chunk 从 p(xz^prev)p(x | \hat{z}_\text{prev}) 采样,z^prev\hat{z}_\text{prev} 本身是模型生成(非真实数据),多步条件后误差累积(类似 RNN exposure bias)
  • 缓解:overlap + clamp 已知部分;多帧 ref(不只末尾 1 帧);global learned motif token
  • 更 promising 路线
    • Hierarchical:先生 low-fps keyframe,再 temporal super-resolution 插中间帧
    • Long-context full attention:直接长视频 + sparse / sliding / hierarchical 控制成本
    • Diffusion Forcing 等 hybrid
  • Sora 公开 demo 60s 内部细节未披露;Movie Gen 多阶段 keyframe + interp + super-res

只说"AR drift"——要给具体 drift 数学解释 + 当前 SoTA 应对。

Q25. Hunyuan-Video / Mochi-1 / Wan 都用 Rectified Flow,比 DDPM ε-pred 强在哪?
  • Target 平稳:RF 的 ut=x1x0u_t = x_1 - x_0 给定 (x0,x1)(x_0, x_1) 后是常数,跨 tt 量级变化比 ϵ\epsilon-pred 小
  • 少步采样:path 是直线(理想),少步 ODE 误差小;Reflow 后 1-4 步可生成
  • Loss conditioning 自然:不像 DDPM 需 SNR / VLB / EDM-preconditioning 等显式 reweighting
  • 与 SD3 共享 stack:image / video 同一套 recipe(v-pred + logit-normal tt
  • DDPM ε-pred 需 noise schedule 设计 + 不同 tt 处 target 尺度差大,训练 reweighting 复杂;RF 更"一招吃遍"

只说"RF 路径更直"——要展开训练目标 / 数值稳定性 / sampler 兼容多角度。

§A 附录:完整 from-scratch 视频生成模型骨架

A.1 总体类图


VideoGenModel
├── encoder: CausalVAEEncoder        (3D Causal VAE)
├── decoder: CausalVAEDecoder
├── text_encoder: T5Encoder / MLLM   (frozen)
├── patchify: SpacetimePatchify      (3D patch -> token)
├── unpatchify: SpacetimeUnpatchify
├── time_embed: SinusoidalTimeEmbed  (timestep τ)
├── transformer:
│     ├── MMDiTVideoBlock × N_dual   (dual-stream)
│     └── SingleStreamBlock × N_sing (single-stream)
└── i2v_adapter: FirstFrameI2VAdapter (optional, for I2V mode)

A.2 训练 forward + A.3 Euler RF sampler

def run_dit(model, z, text, tau, ref_full=None, ref_mask=None): """ DiT forward: noisy latent z -> predicted vector field. """ if ref_full is None: tokens, grid = model.patchify(z) else: tokens, grid = model.i2v_adapter(z, ref_full, ref_mask) text_tok = model.text_encoder(text) cond = model.time_embed(tau) + text_tok.mean(dim=1) # [B, D] for blk in model.transformer.dual_stream: text_tok, tokens = blk(text_tok, tokens, cond) for blk in model.transformer.single_stream: cat = torch.cat([text_tok, tokens], dim=1) cat = blk(cat, cond) text_tok, tokens = cat[:, :text_tok.size(1)], cat[:, text_tok.size(1):] return model.unpatchify(tokens, grid) # [B, C, t, h, w] def video_gen_forward(model, video_clean, text, ref_image=None): """ RF v-prediction MSE loss. video_clean: [B,3,T,H,W]; ref_image: optional [B,3,H,W]. """ B = video_clean.size(0); device = video_clean.device mu, logvar = model.encoder(video_clean) z1 = model.encoder.reparameterize(mu, logvar) z0 = torch.randn_like(z1) tau = torch.sigmoid(torch.randn(B, device=device)) # SD3 logit-normal tau_b = tau.view(-1, 1, 1, 1, 1) z_tau = (1 - tau_b) * z0 + tau_b * z1 u_target = z1 - z0 ref_full, ref_mask = None, None if ref_image is not None: mu_r, _ = model.encoder(ref_image.unsqueeze(2)) # 走 T=1 path ref_full = torch.zeros_like(z1); ref_full[:, :, :1] = mu_r ref_mask = torch.zeros(B, 1, *z1.shape[2:], device=device); ref_mask[:, :, :1] = 1.0 # I2V trick: 参考帧保持 clean (不加噪), 训练分布与推理一致 ref_mask_C = ref_mask.expand_as(z_tau).bool() z_tau = torch.where(ref_mask_C, z1, z_tau) v_pred = run_dit(model, z_tau, text, tau, ref_full, ref_mask) # I2V: 只对待生成帧算 loss if ref_mask is not None: gen = (1 - ref_mask).expand_as(v_pred) return ((v_pred - u_target).pow(2) * gen).sum() / gen.sum().clamp(min=1.0) return F.mse_loss(v_pred, u_target) @torch.no_grad() def video_gen_sample(model, text, t_lat=12, h_lat=90, w_lat=160, steps=50, ref_image=None, guidance_scale=6.0, C=16): """ 端到端推理: t_lat/h_lat/w_lat 直接指定 latent 形状(避开 T/4 整除陷阱). """ device = next(model.parameters()).device z = torch.randn(1, C, t_lat, h_lat, w_lat, device=device) ref_full, ref_mask = None, None if ref_image is not None: mu_r, _ = model.encoder(ref_image.unsqueeze(2)) ref_full = torch.zeros_like(z); ref_full[:, :, :1] = mu_r ref_mask = torch.zeros(1, 1, t_lat, h_lat, w_lat, device=device); ref_mask[:, :, :1] = 1.0 # 推理初始即把参考帧位 clamp 到 clean latent (与训练一致), 不然首步 DiT 看到的是 noise z = torch.where(ref_mask.bool().expand_as(z), ref_full, z) taus = torch.linspace(0, 1, steps + 1, device=device) for i in range(steps): tau_i = taus[i].expand(1) v_cond = run_dit(model, z, text, tau_i, ref_full, ref_mask) v_uncond = run_dit(model, z, [""], tau_i, ref_full, ref_mask) v = v_uncond + guidance_scale * (v_cond - v_uncond) z = z + (taus[i + 1] - taus[i]) * v if ref_mask is not None: # I2V: 每步后 clamp 参考帧 z = torch.where(ref_mask.bool().expand_as(z), ref_full, z) return model.decoder(z)

Sanity checks 视频生成模型常做的

  • Reconstruction-only:先 VAE encode 后 decode,PSNR / SSIM / LPIPS 看是否能复原原视频
  • Random latent decode:从 N(0,I)\mathcal{N}(0, I) 采 latent decode,看 VAE 是否退化(应该出"自然 looking" 但语义不一定连贯的视频)
  • Class / prompt overfit:单一 prompt 训练 1000 步看模型能不能 memorize
  • VBench 局部维度:训练中段先评 Subject Consistency / Motion Smoothness 看时序是否稳定
  • CFG sweep:scale = 0/1/3/6/10 看影响(过高会饱和 / 闪烁)

A.4 当前 SoTA 一览

维度当前 SoTA备注
开源最强 T2VHunyuan-Video 13B2024-12,质量逼近闭源
开源 I2VWan 2.2 I2V / Hunyuan-Video I2V中文 prompt 友好
闭源最强Veo 3.1 / Runway Gen-4.5 / Sora 2Sora 2 API 已标注 deprecated,选型要看长期可用性
实时LTX-Video 2BRTX 4090 实时
视频 + 音频Veo 3.1 / Sora 2 / Movie Gen原生或同步音频成为产品级核心能力
控制类Runway Gen-4/4.5 / MotionCtrl / AnimateAnyonereference consistency、人物 / 相机控制、多镜头一致性

Video Generation Quick Reference · 主要参考:Sora technical report (OpenAI 2024), OpenAI Sora 2 / video generation API docs (2026 deprecation note), Google Veo 3.1 Gemini API / DeepMind docs, Runway Gen-4 / Gen-4.5 research pages, Hunyuan-Video tech report (Tencent 2024), Mochi-1 blog (Genmo 2024), CogVideoX (Yang et al. arXiv 2024-08 → ICLR 2025), Wan tech report (Team Wan / Ang Wang et al. arXiv 2025), Movie Gen tech report (Meta 2024), VBench (Huang et al. CVPR 2024), AnimateDiff (Guo et al. arXiv 2023-07 → ICLR 2024), SVD (Blattmann et al. arXiv 2023-11), Latte (Ma et al. arXiv 2024-01 → TMLR 2025), MotionCtrl (Wang et al. 2023 → SIGGRAPH 2024), AnimateAnyone (Hu et al. CVPR 2024), SD3 (Esser et al. ICML 2024)

我的音乐