视频片段生成(静态到片段,然后唇形同步)
概述
一个完成的静态图像会通过图像到视频模型变成4-9秒的片段。然后,如果有角色在屏幕上说话,唇形同步模型会将其嘴部动作重新与你的对话对齐。你无法直接观看结果:通过提取的帧(scripts/take_sheet.py和查看视频技能)判断每个片段,并让人类对运动有最终决定权。
要求: Python 3(仅stdlib)和 ffmpeg/ffprobe。密钥放在环境变量中:GEMINI_API_KEY(一个Google AI Studio密钥;图像范围的密钥可用,GEMINI_IMAGE_API_KEY作为后备读取)用于Omni,FAL_KEY(与fal显示完全一样的完整密钥)用于唇形同步。切勿打印它们。
选择模型
| 模型 | 访问途径 | 用途 | 备注 |
|---|---|---|---|
Gemini Omni Flash 1.1 (gemini-omni-1.1-flash) | Google Interactions API,AI Studio密钥 | 默认用于插图、动漫和卡通静态图像;也在一个逼真静态图像上测试过(一次测试) | 保持艺术风格和面部;任何输入比例(如2:3的静态图像可以干净地变成9:16,因此无需先外扩或裁剪);720p 9:16或16:9;同步,每个片段约25-35秒;添加自己的音频(请静音) |
| Veo 3.1 / Veo 3.1 Fast | Gemini API,图像作为起始帧 | 逼真静态图像 | 未在我们的运行中使用;使用前请先查看当前文档 |
| Seedance 2.5 | ElevenLabs Flows,或直接ByteDance | 替代外观 | 尝试时需要账户批准 |
| ElevenLabs Flows内的任何模型 | ElevenLabs API | 一把钥匙用于所有 | API访问需要Pro计划(402 paid_plan_required)和密钥的image_video_generation权限(没有则返回401);其中的Omni仅限应用内 |
对于唇形同步,Sync 3 on fal (fal-ai/sync-lipsync/v3) 是默认选项。它使用视频到视频方式工作,因此保持片段的运动,仅重新调整嘴部动作。比较和价格:references/providers.md。
为静态图像制作动画
python3 <this-skill-dir>/scripts/omni_generate.py jobs.json clips/ [--takes 3] [--only S05]
{"base": "将这幅静态图像以其原样赋予生命:相同的艺术风格、调色板、光线和布局,每个角色保持其面部、头发、体型和衣服。自然、流畅的运动。屏幕上没有文字,没有对话气泡,没有新角色,一个连续镜头。",
"jobs": {"S05": {"image": "panels/p05.png",
"prompt": "[0-3秒] 穿着红色夹克的女人拿起手机并兴奋地说话。[3-6秒] 穿着绿色连帽衫的朋友靠在沙发上大笑。摄像机缓慢推进。"}}}
如何编写提示词(完整指南及示例见 references/gemini-omni.md):
- 每秒时间轴,每个括号内一个节拍。片段运行时长大约与时间轴相同。
- 通过衣着描述人物,永远不要用名字:模型不知道“Dana”是谁。
- 对将要唇形同步的人说“说话”,这样嘴部已经会动。
- 固定不允许改变的部分:“摄像机保持静止”、“左墙上只有一个窗户”、“恰好一个兜帽身影”、“她的手平放在桌子上”。每个固定点都来自真实的失败案例(见
references/failure-modes.md)。
在使用前审查每个片段
python3 <this-skill-dir>/scripts/take_sheet.py sheet review/S09.jpg clips/S09_t1.mp4 clips/S09_t2.mp4 clips/S09_t3.mp4 --times 0.3,1,2,3,4,5,6
阅读工作表:行对应片段,列对应时间点。查找道具重复、门或人物出现、手穿过身体、面部漂移以及手势重复。指出每个问题的精确秒数,因为修复方法取决于问题位置。
在采样帧之间容易错过硬切。直接列出它们;没有输出表示连续镜头:
ffmpeg -i clips/S09_t1.mp4 -vf "select='gt(scene,0.3)',showinfo" -an -f null - 2>&1 | grep pts_time
调整片段以适应镜头
一个剪辑需要一个片段精确填充其镜头,并与剪辑的帧率匹配:
| 问题 | 修复 |
|---|---|
| 开始不好(在台词前做了手势,第一秒道具重复) | 稍后开始:--off 1.5。 |
| 修剪后太短 | 用 --speed 1.22 减速(最多约1.25倍速仍然正常);最后一帧保持。 |
| 中间不好 | 拆分镜头:在第一个台词上播放一个裁剪版本,将问题排除在画面外,然后在其后切回。 |
| 无法修复(一扇门出现,第二个人走进来) | 使用固定的提示词重新生成,2-3个片段,并在工作表上挑选。 |
lipsync_parts.py normalize clip.mp4 shot.mp4 --frames N --off S --speed K 一步完成偏移、速度、fps、缩放(覆盖和中心裁剪,绝不拉伸)和最后一帧保持,并始终返回正好N帧。
唇形同步对话
- 标准化 将片段调整为镜头:
python3 <this-skill-dir>/scripts/lipsync_parts.py normalize clip.mp4 shot.mp4 --frames 132 --off 1.5 --speed 1.22。 - 分割 在台词边界处,使每个部分只有一个说话者。
- 编写
shot.json:每个台词及其在镜头中的开始/结束时间(秒)以及说话者;frames等于你标准化时的--frames。对于从背后看到、屏幕外或群喊的说话者,添加"skip": true:{"id": "S05", "video": "shot.mp4", "fps": 24, "frames": 132, "lines": [{"id": "05-1", "audio": "lines/05-1.mp3", "start": 0.72, "end": 2.31, "speaker": "maya"}, {"id": "05-2", "audio": "lines/05-2.mp3", "start": 2.43, "end": 4.10, "speaker": "ido"}]} - 运行
lipsync_parts.py split shot.json parts/。除了部分文件外,它还写入parts/S05_lipsync_jobs.json:每个非跳过部分一个条目,包含绝对路径,out已按join期望的方式命名(synced/S05_<k>.mp4),并且face: null。
- 编写
- 指向 每个部分中的说话者,并将它写入作业文件为
"face": "x,y@<mid>"(mid在每个条目中)。- 在该部分的中间帧上选择说话者面部的一个像素。
- 确认它:
take_sheet.py point parts/S05_1.mp4 check.jpg --frame 30 --xy 410,560,然后查看图像。 - 面部检测器在绘制的人脸上不可靠,因此请通过肉眼选择和确认。仅当只有一个面部可见时保留
null。
- 同步:
lipsync_fal.py --jobs parts/S05_lipsync_jobs.json。预期成本约为每秒$0.13,每个部分约70-150秒;6个并行运行。现有输出会被跳过。要在一个部分修正面部后重做,单独运行该部分:lipsync_fal.py parts/S05_1.mp4 parts/S05_1.wav synced/S05_1.mp4 --face 410,560@30 --force(使用--force与--jobs会重做每个部分)。 - 合并:
lipsync_parts.py join parts/S05_plan.json synced/ final/S05.mp4。每个部分被强制对齐到其精确帧数,跳过的部分保留原始帧,没有同步文件的部分会报告警告(--strict使其成为错误),并检查总帧数。
详细信息、模型选择和失败案例:references/lipsync.md。
成本和时间(2026年10月测量)
| 步骤 | 计数 | 成本 | 时间 |
|---|---|---|---|
| Omni片段 | 按输出视频的秒数计费(6秒片段约$0.60;每个镜头计划约1.5次调用用于重拍) | ~$0.10 | 每次调用约30秒,4个并行 |
| Sync 3 唇形同步 | 按输出的秒数计费(一个部分通常3-6秒) | ~$0.13 | 每个部分约70-150秒,6个并行 |
常见错误
| 错误 | 结果 | 修复 |
|---|---|---|
| 在视频提示词中命名角色 | 错误的人会动 | 用衣着描述他们 |
| 保留Omni的音频 | 在你的对话下方出现编造的声音和音乐 | 静音(-an) |
| 未使用工作表就使用片段 | 重复的道具和新门出现 | 每个片段都使用工作表 |
| 为了糟糕的第一秒重新生成整个片段 | 其他地方出现新问题 | 偏移加上减速 |
| 对整个双说话者镜头进行唇形同步 | 一个嘴部动配合两个台词 | 在台词边界分割,每个部分一个说话者 |
| 让模型选择说话者 | 错误的面部说话 | --face X,Y@FRAME |
| 缩短fal密钥 | 401 | 传递与fal显示完全一样的密钥 |
| 不修正帧数就合并部分 | 镜头与剪辑不同步 | lipsync_parts.py join |
相关技能
- 图像生成:静态图像(角色卡、画面板)。
- elevenlabs-tts:与嘴部同步的对话。
- 查看视频:用于审查片段的帧提取。
- 制作动画剧集:使用这些片段的整个剧集工作流。