Kamila 口播线 · 设计确认稿 · 2026-07-08
画外有个提问的声音,Kamila 只在自己说话的段落对口型;记者问话时她在镜头前听。老的平文本口播原样保留,一行行为都不变。
下单的东西(payload)里多一个可选的结构化台词字段。有它,走采访体;没有它,和今天一模一样。老模板、老单、存量行为零影响。
关键取舍:分流只发生在入口一处,老路径整块代码不碰。新模式出问题最多影响采访体订单,伤不到存量口播。
新字段长这样(和 hook 广告线已有的台词形状同构,上游好实现):
// 采访体下单(新,可选)
"shots": [{
"scene": "冰场边的采访角,Kamila 坐在镜头前",
"lines": [
{"speaker": "vo", "line_ru": "Камила, как вы это делаете?"}, // 记者,画外
{"speaker": "kamila", "line_ru": "Честно говоря, всё просто..."}, // 本人,对口型
{"speaker": "vo", "line_ru": "..."},
{"speaker": "kamila", "line_ru": "..."}
]
}]
// 老口播下单(完全不变)
"shots": [{ "scene": "...", "dialogue_ru": "整段平文本..." }]
你点的核心:话外音不对口型,但时间必须准。做法是延续这条线验证过的铁律 ——声音是主时钟。每段台词先做 TTS(她的声线 / 记者声线),量出真实时长,按顺序累加(段间留 0.4s 换气),这就是唯一的时间轴。音轨、画面、字幕三条轨都从同一个钟上取偏移,对齐是结构保证的,不存在"拼完再对"。
看虚线:话外音第二问的起点 12.6s,在音轨、画面、字幕三条轨上是同一个数——因为它们都是从"前面各段实测时长 + 换气间隔"累加出来的,不是三条轨各算各的。口型崩那次的教训(duration 写死 ≠ TTS 时长)在这里天然不会复发。
| 面 | 改动 | 说明 |
|---|---|---|
talking_head.py | 加采访体分支 | 入口分流 + 分段 TTS + 听镜生成 + 时间轴铺轨;老分支代码不碰 |
prompts/ | 新增 1 个听镜模板 | "她在听"的表演提示词;现有口播模板不动 |
| recipe 资产 | 加 1 个记者声线 | 固定的沉稳画外音声线(Fish 参考),第一版不给用户选 |
| workflow 定义 | 声明 lines 可选字段 | 发新 test snapshot,老字段不动 |
| Mai 上游 | 脚本层支持"谁说的" | 跟用户确认台词时标 speaker;方案你点头后我再去跟 mai-cc 对 |
| 不动 | — | 老平文本路径、Fish/lipsync/拼接机制、hook 广告线、prod 别名(kvo=5fe8d649 冻结) |
要你拍的两个小点(都有默认,不拍就按默认走):