Ditto 技术解读把 talking head diffusion 从像素潜空间挪到运动空间Ditto 这篇工作最有意思的地方不是又做了一个音频驱动数字人而是它把问题拆得很干净扩散模型负责生成运动渲染器负责把运动落到具体身份上。这个分工看起来朴素但它直接绕开了很多 talking head diffusion 过去绕不开的问题比如 VAE latent 太重、可控性弱、推理慢以及生成结果只能靠重采样碰运气。论文全名是《Ditto: Motion-Space Diffusion for Controllable Realtime Talking Head Synthesis》Ant Group 团队在 2024 年 11 月放出 arXiv2025 年 7 月 README 更新显示被 ACM MM 2025 接收。项目已经开源推理代码、Hugging Face 模型后续也放出了 PyTorch 模型和训练分支。对想复现或者做后续研究的人来说这比 VASA-1 那类不开源系统友好很多。这篇文章主要讲清楚四件事Ditto 的 motion space 到底是什么为什么它比直接在 VAE latent 里做扩散更适合实时 talking head条件信号和训练策略怎么补 LivePortrait motion 表征的坑最后看实验数字时应该看哪些不该被哪些指标带偏。一句话概括 DittoDitto 用 LivePortrait 类似的运动抽取器把人脸运动表示成 identity-agnostic 的 keypoint deformation、head rotation 和 translation再训练一个 conditional Diffusion Transformer 从音频和控制信号生成这组运动参数。生成出来的运动参数交给 one-shot renderer 渲染回视频。换句话说它不是让扩散模型直接学“下一帧长什么样”而是让模型学“脸应该怎么动”。这一步把纹理、身份、背景这些对运动生成没那么必要的信息先剥掉扩散模型看到的是低维、可控、和人脸语义有一定对应关系的运动空间。一个简化流程如下输入音频 单张参考图 │ ├─ HuBERT 提取音频特征 │ ├─ Motion Extractor 从参考图取 canonical keypoints / 初始 motion │ ├─ Conditional DiT 在 motion space 里生成 m {δ, R, t} │ └─ Face Renderer 使用参考身份外观 生成 motion 渲染视频这个设计的核心收益有两个。第一motion 表征比视频 VAE latent 小得多扩散生成更轻。第二motion 表征里有旋转、平移、局部 deformation 这些可以操作的量所以 gaze、pose、emotion、局部幅度限制都更容易接进去。为什么不要直接在视频 latent 里扩散EMO、EchoMimic、Hallo、Hallo2 这类方法把 diffusion 带进了 talking head一般会比早期 GAN/landmark 方法更自然表情细节、头部节奏、说话时的非口型运动都更丰富。但代价也很明显推理慢而且生成结果的控制粒度有限。论文指出常见 latent diffusion 的 VAE latent 对 talking head 来说有两个不合适的地方。它同时混着纹理和运动扩散模型要学的东西太多它又是隐式空间很难直接对应到“眼睛张开一点”“头往右转一点”“嘴部幅度别太夸张”这样的控制。Ditto 的判断是既然 talking head 的身份外观可以由渲染器保留扩散模型就没必要反复生成纹理。把运动拿出来单独建模才是更贴近任务结构的选择。论文中的 motion 表征来自 LivePortrait 系列的 motion extractor。对一帧图像模型提取 canonical keypointsccc、expression deformationδ\deltaδ、head rotationRRR和 translationttt。最终交给扩散模型预测的是m{δ,R,t} m \{\delta, R, t\}m{δ,R,t}渲染阶段再用参考图的身份信息和生成的 motion 组合出隐式 3D keypointsx^crefR^δ^t^ \hat{x} c_{ref}\hat{R} \hat{\delta} \hat{t}x^cref​R^δ^t^然后 renderer 根据参考外观特征和这些 keypoints 合成帧。这里的关键不是公式复杂而是责任边界清楚DiT 学运动分布renderer 负责 photorealistic synthesis。Conditional DiT音频只是条件之一如果只看标题容易误以为 Ditto 就是“音频到 motion 的 diffusion”。实际实现里音频只是条件信号的一部分。作者给 DiT 塞了多种条件HuBERT 音频特征aaa、canonical keypointscrefc_{ref}cref​、emotion labelsss、eye stateeee、reference initial motionmrefm_{ref}mref​。这些条件解决的是不同问题条件信号作用HuBERT audio featureaaa提供口型和语音节奏的主要驱动canonical keypointscrefc_{ref}cref​让生成 motion 适配目标身份的脸型几何emotion labelsss给表情一个显式控制入口避免全靠音频猜表情eye stateeee控制眨眼和视线这些和音频相关性很弱initial motionmrefm_{ref}mref​保持片段间连续性也能把长序列拉回指定状态这里有一个容易忽略但很重要的点Ditto 没有假设 LivePortrait 的 motion 表征已经完全去身份化。论文明确说即使是 LivePortrait也很难完全 disentangle motion 和 identity。因此作者把 canonical keypoints 作为 identity feature 输入 DiT让生成的运动适配目标脸而不是强行要求运动空间天然纯净。这其实是比较务实的工程判断。很多论文会把“identity-agnostic representation”写得很理想但真实系统里总会残留身份信息。Ditto 的做法是承认这个残留然后用条件建模去补偿。训练策略motion space 小了但并不自动好学motion space 降低了扩散学习难度但它也带来新问题。不同 motion 分量的幅度、频率、和音频相关性都不一样。嘴唇、眼睛、头部姿态、表情 deformation 不能用同一套 loss 权重粗暴处理。Ditto 做了几件比较有针对性的事情。第一是 horizontal flip。真实视频里的头部朝向分布不一定平衡如果训练集里某些朝向更多motion extractor 提取出的运动也会带偏。论文用水平翻转增强让 audio-to-motion 的对应关系在左右方向上更平衡。第二是 adaptive loss weights。作者把 motion representation 按控制区域分组根据不同组在训练中 loss 下降情况动态调权。直觉上嘴部和头部不是同一种运动统一 MSE 很容易让某些分量学得快、某些分量学崩。第三是 temporal loss。除了 DDPM 风格的去噪目标作者还回归 motion 的一阶和二阶导数约束速度和加速度LLdLtLini L L_d L_t L_{ini}LLd​Lt​Lini​其中LtL_tLt​关注 motion 的 temporal stabilityLiniL_{ini}Lini​让生成片段的起始 motion 和参考初始 motion 对齐。这个设计是为了避免片段生成在长视频里慢慢漂移。从 ablation 看这些细节不是装饰。Table 4 里去掉 emotion label 后Talk9 上 FID 从 17.254 变成 23.036FVD 从 219.368 变成 324.078去掉 adaptive loss weights 后FVD 直接恶化到 588.821Sync-C 也从 8.069 掉到 0.289。这个结果说明 Ditto 的质量不只是来自“换了 motion space”训练怎么处理不同 motion 分量同样关键。控制能力来自 motion 语义映射Ditto 的控制不是在 prompt 层面说“高兴一点”这么粗。它在 motion deformation 上建立了更接近 blendshape 的操作方式。论文把 expression deformation 视为 63 维向量也就是 21 个隐式 3D keypoints 的x,y,zx,y,zx,y,z坐标。作者对每一维加小的正负偏移再观察渲染后哪个面部区域变化。结果发现一些维度能相对清楚地对应到局部动作比如第 34 维控制右眼开合第 58 维类似 ARKit 里的 jaw open。这带来两类控制Regional control: 限制某些局部区域的运动 Magnitude control: 限制 deformation 幅度减少夸张表情或局部 artifact论文里比较典型的例子是 gaze correction。早期测试中生成的 gaze 会和 head pose 绑定头一动眼神也跟着漂角色很难稳定看向镜头。作者录制了一个模板视频让演员平滑转头但保持眼睛看镜头、表情恒定然后拟合 head pose variation 到 gaze-related deformation 的映射δeK(Re)\delta_e K(R_e)δe​K(Re​)。推理时用这个映射修正 gaze让眼神和头部姿态解耦。这个点对交互式 avatar 很实际。口型对齐只是底线眼神乱飘会让人立刻觉得不对劲。Ditto 把 gaze 当成可修正 motion而不是寄希望于 diffusion 一次生成完美结果这个思路更适合产品化。实时性Ditto 真正在优化端到端链路很多 talking head 论文说自己快其实只报某个模块的速度。Ditto 的实时性部分比较具体它同时优化了 audio feature extraction、motion generation、video synthesis还报告了 RTF 和 FFD。RTF 是 Real-Time Factor小于 1 才能跑得比实时更快。FFD 是 First-Frame Delay交互场景里越低越好。论文里的几个关键数字设置RTFFFDtalking-head offline0.635-talking-head online0.895385msfull-body offline0.648-full-body online0.914392ms模块级别上Audio2Feat 单步 23msMotion DiT 62msFace Rendering 15ms对应 RTF 分别是 0.115、0.310、0.375。论文测试环境是 12-core Intel Xeon Platinum 8369B CPU、1 张 NVIDIA A100 GPU 和 100G 内存。它能做到这个速度主要靠几层优化叠加HuBERT 做 streaming audio feature extraction用 KV cache 和 causal mask 处理很短音频片段DiT 推理从 50 步降到 10 步motion DiT 和 renderer 都转 TensorRT视频输出时 CPU 侧 FFmpeg 可以并行压缩。Table 1 里也能看到速度差距。Talk9 上EchoMimic 的 RTF 是 35.528Hallo 是 53.082Hallo2 是 56.838Ditto-s10 是 0.635。也就是说传统 diffusion talking head 在这个测试里比实时慢几十倍而 Ditto 进入了在线交互可用的区间。实验怎么读别只盯着 FIDDitto 在 Talk9 和 HDTF100 上都报了定量指标。Talk9 上Ditto-s50 / Ditto-s10 的 FID 分别是 17.254 / 17.060FVD 是 219.368 / 231.182CSIM 是 0.864 / 0.861Sync-C 是 8.069 / 8.111Sync-D 是 7.114 / 7.291RTF 是 2.121 / 0.635。这里最值得看的不是 s50 比 s10 略好而是 s10 在质量基本接近的情况下把 RTF 压到了 1 以下。实时系统里50 步 diffusion 如果跑不动指标再好也很难进交互链路。HDTF100 上Ditto 的 FVD 是 134.640优于 EchoMimic 的 532.733、Hallo 的 366.066、Hallo2 的 239.517Sync-C 是 8.939也高于这些 baseline。这个结果支持作者的主张motion space diffusion 对口型和时序一致性都有帮助。用户研究更有意思。10 名参与者、5 组 image-audio 输入、每种方法生成 5 个 driving clips然后成对比较。Ditto 在 visual quality 和 lip synchronization 上胜出比例最高分别是 84.0% 和 80.7%。但在 naturalness of facial expressions and head movement 上Ditto 是 48.7%低于 Hallo2 的 59.3%。作者也承认motion representation 会削弱一些高频运动信息。这点很关键。Ditto 不是“所有维度都赢”。它在实时性、可控性、口型和稳定性上很强但 motion space 的压缩也可能损失细微自然度。对研究来说这反而给后续工作留出了清晰方向如何在保持可控和实时的同时把高频微表情和头部自然运动补回来。复现和工程使用注意点官方 README 给出的测试环境是 CentOS 7.2、A100、Python 3.10、TensorRT 8.6.1。推理分支已经提供 TensorRT 模型路径大致如下checkpoints/ ├── ditto_cfg/ │ ├── v0.4_hubert_cfg_trt.pkl │ └── v0.4_hubert_cfg_trt_online.pkl ├── ditto_onnx/ └── ditto_trt_Ampere_Plus/基本推理命令是python inference.py\--data_root./checkpoints/ditto_trt_Ampere_Plus\--cfg_pkl./checkpoints/ditto_cfg/v0.4_hubert_cfg_trt.pkl\--audio_path./example/audio.wav\--source_path./example/image.png\--output_path./tmp/result.mp4如果 GPU 不支持官方提供的 Ampere_Plus TensorRT engine需要从 ONNX 重新转换python scripts/cvt_onnx_to_trt.py\--onnx_dir./checkpoints/ditto_onnx\--trt_dir./checkpoints/ditto_trt_customREADME 还给了 PyTorch 模型路径方便二次开发。但如果目标是实时推理TensorRT 仍然是主线。训练代码在train分支官方也提醒它可能和论文版本略有差异这种差异复现实验时要记下来。我会特别注意三件事。第一Ditto 的强项依赖 LivePortrait 风格 renderer。如果你换 renderermotion space 的语义和 artifact 分布都会变不能假设论文结论自动迁移。第二实时数字是在 A100 TensorRT 下测出来的。消费级 GPU、不同 TensorRT 版本、不同分辨率都会影响 RTF 和 FFD。尤其 online streaming 里 inter-segment overlap 会抬高 RTF不能只用 offline 输出速度估计交互延迟。第三Ditto 的控制接口很适合接产品逻辑比如 gaze lock、head pose bound、mouth-open clamp、局部 deformation 限幅。但这些控制如果调得太硬也可能让动作变僵。真正要落地最好把这些参数暴露成可调策略而不是固定 magic number。和 LivePortrait、VASA-1 的关系Ditto 很像站在两个系统之间LivePortrait 给它 motion extractor 和 renderer 的基础VASA-1 给它“在 motion/appearance disentangled space 里训练 DiT”的方向。但 Ditto 更偏开源可复现也更强调控制。LivePortrait 本身适合做图像驱动、姿态/表情迁移和编辑但它不是一个完整的 audio-to-motion diffusion system。Ditto 借它的 motion space把音频到人脸运动这部分补上。VASA-1 展示了实时 talking face 的潜力但论文里用的是更隐式的 motion representation而且没有公开代码后续研究很难直接沿着它改。Ditto 的 explicit motion space 和开源实现使它更像一个可接续的研究基座。如果要给 Ditto 一个定位我会说它不是追求端到端视频扩散的“更大模型”而是把 talking head 重新拆成了可生成、可控制、可渲染的几个环节。这种拆法没那么炫但很有工程生命力。局限motion space 不是免费午餐Ditto 的局限也来自它的优点。motion space 越 compact推理越快控制越容易但如果这个空间表达不了某些高频细节模型也生成不出来。用户研究里 naturalness 指标不如 Hallo2论文解释为 motion representation attenuating high-frequency motion information。这个说法可信。另一个问题是控制语义仍然是半经验的。通过逐维 offset 观察渲染结果可以找到一些局部对应关系但这和标准化 blendshape 还不一样。不同 renderer、不同训练版本、不同人脸风格下这些维度的语义稳定性还需要更多验证。再就是数据规模。论文训练用了约 50 小时广播场景视频、330 个 identities。这个规模对学术 paper 不小但对泛化到任意人像、任意语言、任意拍摄条件的产品来说仍然有限。尤其唱歌、夸张表演、侧脸、大幅身体动作这类 case可能需要更专门的数据和控制策略。结语Ditto 的价值在于它把 talking head diffusion 的瓶颈从“生成视频帧”改写成了“生成可渲染的运动”。这让实时性和可控性第一次变得很像同一个设计目标而不是互相牺牲。如果你关心数字人、音频驱动头像、实时 avatar 或者 gesture/face generationDitto 值得认真读。它给出的不是一个完美终点而是一条很清楚的路线motion representation 要足够轻语义要足够可控renderer 要足够稳最后再让 diffusion 去补运动分布。后续工作真正难的地方大概就是在这条线上把自然度和微表情补回来。参考资料Li Tianqi, Zheng Ruobing, Yang Minghui, Chen Jingdong, Yang Ming. 《Ditto: Motion-Space Diffusion for Controllable Realtime Talking Head Synthesis》, arXiv:2411.19509v3, 2025-04-30. https://arxiv.org/abs/2411.19509Ditto project page, Ant Group / Digital Avatar. https://digital-avatar.github.io/ai/Ditto/antgroup/ditto-talkinghead GitHub README. https://github.com/antgroup/ditto-talkingheaddigital-avatar/ditto-talkinghead Hugging Face model repository. https://huggingface.co/digital-avatar/ditto-talkinghead