用 ComfyUI 做参考生视频:H3 工作流实践
从一张角色参考图,到一条 8 秒的竖屏视频,中间有多少坑。
一、这套工作流在做什么
输入是一张(或多张)参考图——通常是角色的正面照,加上场景图、道具图。 模型根据提示词,让参考图里的人物"动起来",生成一段短视频。
链路大致是:
参考图(1~3 张)
↓ 多参考编码
H3 生成低分辨率视频(如 704×1280)
↓ LatentUpscaler3D ×1.5
成片(1056×1920)
关键点:先生成低分辨率,再在 latent 空间放大。 直接生成 1080p 既跑不动(显存不够),效果也不见得好。
二、提示词怎么写
官方六段式 vs 简版中文
模型官方给的是英文六段式模板(角色 / 场景 / 动作 / 镜头 / 台词 / 风格), 但实测下来,中文简版效果反而更好。
严格单变量对照(同参考图、同种子、同剧情,只换提示词):
| 维度 | 官方六段式(1762 字符) | 简版中文(329 字符) |
|---|---|---|
| 台词准确度 | ✅ | ✅ 逐字一致 |
| 台词落点 | 模型自行安排 | 严格落在指定镜头内 |
| 画面动态(帧间差) | 2.29 | 7.35(约 3 倍) |
| 冻结帧 | 10 | 1 |
| 长度 | 1762 字符 | 329 字符 |
长了 5 倍,动态反而只有 1/3。写得太满,模型反而不敢动。
关键发现:光写秒数,不会切镜
我在提示词里写了:
[Shot 1] 0.0s 到 4.2s ……
[Shot 2] 4.2s 到 8.0s ……
逐秒抽帧检查后发现:模型做的是一条连续的推镜(远景→中景→近景), 根本没有硬切。但台词确实精确落在了 4.26 秒——正好是 Shot 2 的边界。
时间戳能影响说话时机,但不能强约束画面切换。
要真的切镜,必须显式写「镜头硬切至近景」这类指令。补上之后:
| 写法 | 切镜 |
|---|---|
只写 [Shot 1] 0.0s 到 4.2s | ❌ 走连续推镜 |
| 加「镜头硬切至 XX 景别」 | ✅ 真硬切,但切点会漂 ±0.75s |
而且切点和台词不保证顺序——实测出现过「话说了一半才切镜」,台词比切点早 0.44 秒。 这种细节只能靠抽帧逐条检查。
三、画幅:最容易踩的坑
JSON 里存的值,不一定是实际跑的值
这件事坑了我很久。工作流文件里写着 864 × 480(横屏),
但实际跑出来是 1312 × 736(还是横屏,但更大)。
原因是配套脚本里有硬编码:
WIDTH, HEIGHT = 480, 864 # 脚本常量
wf[node]["inputs"]["width"] = width or WIDTH # 强制覆盖
wf[node]["inputs"]["height"] = height or HEIGHT
「这条工作流是竖屏」是脚本的行为,不是 JSON 自带的。 换一个不覆盖的脚本跑,立刻就变横屏了。
后来发现官方模板也有同样的机制,只是形式不同——不是代码覆盖,而是 连线覆盖:
MiniMaxH3ImageToVideo 节点的 width/height 输入口
↑ 实际接了 ResolutionSelector 节点
⇒ 界面上显示的 1344×768 被忽略,真正生效的是选择器算出来的值
通用判据:先看输入口有没有连线。 接了线就追到源头节点看它算什么;没接线才看界面上存的值。 JSON 里的数字很可能只是过期快照。
画幅要和参考图对齐
参考图是 1408×1872(竖构图,宽高比 0.75),
却在 16:9 横屏上跑了很久。改成竖屏之后:
- 缩放畸变小了很多(
ref_image_size: match是按比例缩放,方向不匹配就会压扁) - 脸部保真明显提升——眼尾的弧度、眉形、唇色都对上了,之前横屏各版都没有
竖屏档位(生成 → 成片):
| 档位 | 生成分辨率 | 成片 |
|---|---|---|
| 全分辨率 | 704 × 1280 | 1056 × 1920 |
| 半分辨率(测试用) | 352 × 640 | 544 × 960 |
四、显存临界点
16GB 显卡(4080 Super)的实测边界:
| 分辨率 | 结果 |
|---|---|
| 2.03 MP | ✅ 能跑 |
| 2.09 MP | ❌ 爆显存 |
临界点卡得很死,多 0.06 MP 就崩。
还有第二个维度容易被忽略:参考图张数。 在 1088×1920 下,每段最多 3 张参考图,第 4 张就爆。 想加图只能降分辨率——这是个明确的取舍。
测试时先降一半分辨率。全分辨率一段 8 秒要 8~9 分钟, 半分辨率能快 4 倍多。等确认链路和提示词都对,再上全尺寸。
五、跨段衔接
尾帧当第三张参考图
多段视频要连贯,最有效的做法是:把上一段的最后一帧,当成下一段的第三张参考图。
第 1 段:参考图 = [角色正面, 场景] → 生成 → 取尾帧
第 2 段:参考图 = [角色正面, 场景, 第1段尾帧] → 生成 → 取尾帧
第 3 段:……
这样下一段的起始画面和上一段的结尾几乎无缝。
换场景时,靠动作带动,不要写切镜
如果剧情要从 A 场景转到 B 场景,写「镜头切到 B」效果很差—— 模型会生成一个突兀的跳转。
更好的写法是让人物用动作带过去:推门、转身、抬头看向远方。 模型自然会在动作过程中完成场景过渡。
六、合并成片
多段视频直接拼接会有两个问题:音量不一致、接缝突兀。
我的处理顺序:
- 先用
ffmpeg量出每段的音频电平(volumedetect) - 按统一目标电平做整体增益对齐(不是压缩,压缩会改变音色)
- 段与段之间加短溶解(0.2~0.3 秒),而不是硬接
# 量电平
ffmpeg -i seg01.mp4 -af volumedetect -f null - 2>&1 | grep mean_volume
# 拼接时加淡入淡出
ffmpeg -i seg01.mp4 -i seg02.mp4 -filter_complex \
"[0][1]xfade=transition=fade:duration=0.25:offset=7.75" out.mp4
七、常见出片问题
| 现象 | 原因 | 对策 |
|---|---|---|
| 人物朝向错 | 参考图是正面,提示词却要求侧身动作 | 补一张侧面参考图,或在提示词里明确朝向 |
| 道具不一致 | 只给了文字描述,没给参考图 | 道具单独出一张参考图,占一个参考槽 |
| 场景里冒出多余主体 | 参考图里有多余的人/物 | 参考图先裁干净再喂 |
| 参考图串段 | 多段共用同一批参考图,模型混了 | 每段的参考图单独命名、单独传 |
| 画面几乎不动 | 提示词写得太满,或只有静态描述 | 减少描述,加明确动作动词 |
八、一条纪律:贵操作要等明确指令
全分辨率生成一段 8 秒视频约 8~9 分钟,12 段就是 1.5 小时。 这类操作不能自作主张。
我给自己定的规矩:
- 「先低分辨率跑通,再上全尺寸」≠「检查通过就自动上全尺寸」,要再等一次明确指令
- 不要为「省时间」把多个贵任务串成一条链跑
- 提交前自问一句:「他刚才哪句话明确让我跑这个了?」答不上来就别提交
- 便宜的操作(抽帧、自检、拼图、ffprobe)随时可以做
一次误提交的代价(白烧显存 + 打断别人)远大于一轮空转的代价。 宁可多问一句。
九、小结
这套工作流真正难的不是「怎么跑通」,而是怎么控制输出:
- 提示词要短、要有动作,别写满
- 要切镜就显式写「硬切」,光写秒数没用
- 画幅看实际提交值,不看 JSON
- 分辨率卡在显存临界点下方,别贪
- 跨段靠尾帧锚定,不靠提示词描述