做 AI 视频最容易掉的坑不是"生成得不好看",而是"这次好看,下次不可复现"。 同一个角色,第二个镜头换了张脸;同一个场景,光线从黄昏跳到正午;台词已经写好了, 生成的画面里人物的口型对不上。单看每个镜头都能用,连起来就是灾难。
我在做一个 10 集的动漫短片系列(每集约 70 秒,双主角设定)。做到第三集的时候, 真正的问题暴露出来:靠"写一段漂亮的提示词"这条路走不通。必须把它当成一条软件流水线来做—— 有输入、有中间产物、有校验、有重试。
一、核心思路:脚本是唯一真相源
整条流水线的第一个决定是:剧本不是一段文字,而是一张表。 每个镜头是一条结构化记录,包含固定字段:
| 字段 | 说明 | 作用 |
|---|---|---|
| shot_id | 镜号,如 S01-03 | 对齐素材文件名,缺了哪个一眼看得出 |
| duration | 时长(秒) | 决定生成参数,也决定后期时间轴 |
| shot_size | 景别(特写 / 中景 / 全景) | 控制镜头语言的节奏 |
| scene | 场景描述 | 同一场景的镜头要复用同一段环境提示 |
| characters | 出场角色 ID 列表 | 生成时自动拼接角色锚定描述 |
| action | 动作 / 表情 | 这是唯一需要每镜头重写的内容 |
| dialogue | 台词 | 后期配音与字幕来源 |
| transition | 转场方式 | 决定拼接时用硬切还是叠化 |
有了这张表,一个镜头就变成了"角色锚定文本 + 场景锚定文本 + 本镜头动作"的字符串拼接, 而不是每次从零写一段长提示词。这一条把随机性砍掉了一大半。
二、角色锚定:把描述写死,不要每次都润色
角色一致性是这类项目最难的部分。我的做法是给每个角色维护一份固定描述(character sheet), 内容不是"一只可爱的马",而是明确到不能再改的程度:
CHAR_BENBEN = """
角色:奔奔,一匹少年马,棕红色短鬃毛,额前一撮白色星形斑纹,
戴深蓝色围巾,身高比例偏瘦长,圆眼,表情活泼。
风格:二维动漫赛璐璐上色,线条干净,无写实质感。
"""
CHAR_YUNDUO = """
角色:云朵,一只少女羊,乳白色卷毛,头顶一对小圆角,
穿浅绿色背带裤,体态圆润,眼神温和。
风格:同上。
"""
关键在于:这段文字一旦定稿就不再改。如果某个镜头效果不好,改的是 action 那一句, 不是角色描述。我早期犯的错就是每次觉得"这句可以写得更生动",结果角色的外形在每个镜头之间微妙漂移, 直到有一天两个主角看起来像换了演员。
如果没有参考图能力,纯文本锚定大概能保住七成一致性;如果能提供角色参考图,建议在整集里固定用同一张, 不要中途更换更"好看"的那张——换图就是换人。
三、生成:单镜头、可重试、留证据
流水线按镜头逐个生成,而不是一次性生成整段。原因有三:单个镜头失败只损失几秒素材;
可以针对某个镜头单独调参重试;产物按 S01-03.mp4 命名,后期拼接时按镜号排序即可。
for shot in script:
prompt = build_prompt(shot) # 角色 + 场景 + 动作
for attempt in range(3):
out = generate(prompt, duration=shot.duration)
if check(out, shot): # 时长、分辨率、是否黑屏
save(out, f"build/S01-{shot.id}.mp4")
break
else:
log_failure(shot, prompt) # 留下失败记录,人工兜底
校验函数 check() 很粗糙但有用:只检查客观指标(时长是否接近、分辨率是否一致、
首帧是否为纯黑),不判断"好不好看"。好不好看必须人来判断,让程序去猜只会浪费时间。
自动化的边界要划清楚:能验证客观指标的交给程序,需要审美判断的留给人。 试图让程序判断"这个镜头够不够好看",只会得到一个不可信的打分。
四、拼接:先把参数统一,再谈剪辑
AI 生成的不同片段,分辨率、帧率、编码参数经常不一致,直接 concat 会花屏或音画不同步。 我现在的做法是先统一转码,再拼接:
# 1. 统一到 1080x1920 / 30fps / H.264
ffmpeg -i raw/S01-01.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,\
pad=1080:1920:(ow-iw)/2:(oh-ih)/2,fps=30" \
-c:v libx264 -crf 20 -pix_fmt yuv420p norm/S01-01.mp4
# 2. 按镜号顺序拼接
printf "file 'norm/S01-01.mp4'\nfile 'norm/S01-02.mp4'\n" > list.txt
ffmpeg -f concat -safe 0 -i list.txt -c copy out/S01.mp4
pad 那一串是必要的:不同镜头可能生成不同宽高比,直接 scale 会拉伸变形,
加黑边再裁掉比变形好看得多。这一步看着琐碎,但它决定了成片是"专业"还是"拼凑"。
五、一致性失控时怎么救
做到现在,我总结出三级补救方案,按成本从低到高:
- 改动作,不改角色。 大部分"看起来不对"其实是动作描述太抽象(比如"开心地跑"), 换成具体动作("前蹄抬起,身体前倾,向右奔跑")就能解决。
- 降低镜头复杂度。 一个镜头里塞进两个角色 + 环境变化 + 运镜,翻车率极高。 拆成两个镜头分别生成,剪辑时接起来,反而更稳。
- 牺牲这一帧,保整段。 如果只有某个镜头的角色脸崩了,而这个镜头不到两秒, 考虑用前一镜头的尾帧做转场遮掉,或者直接剪掉。观众记不住个别帧,但会记住"这个人怎么变样了"。
六、几条踩出来的经验
- 先把剧本写完,再开始生成。 边写边生成会导致前后风格无法统一,返工成本极高。
- 单镜头时长控制在 3–5 秒。 更长的镜头里,AI 保持角色一致性的能力会明显下降。
- 素材目录结构比工具重要。
raw/ norm/ out/三层分开,任何时候都能从头重跑。 - 记录每次生成的提示词。 看到一个好镜头却想不起当时写了什么,是最难受的事。
- 别追求一次成片。 把"生成"和"剪辑"当两个独立阶段,中间产物可复用,心理压力小很多。
最后一点感想:这套流程的价值不在于它多先进,而在于它把一件"靠灵感"的事变成了"靠流程"的事。 灵感会枯竭,流程不会。第一季还有七集,流程已经稳定了,剩下的是耐心问题。