视频生成最贵的一课是:任务在提交那一刻就已经计费了,不是在你拿到结果的时候。

这句话听起来像常识,但它决定了一整块流程设计。因为提交之后的一切——
轮询几分钟、下载、重试——都可能被进程被杀、断网、机器休眠打断。
而这些打断不退还那笔钱。

踩过一次之后,我给生产环节加了一道四步闸门。下面说说为什么是四步,以及那个
“不要重投”的坑。

一、四步闸门,顺序不能合并

1
2
3
4
1. 建立有边界的 job
2. prepare —— 只预览,不生产
3. 等创作者在看到预览之后明确确认
4. run —— 才启动真实生成

每一步的职责是分开的,合并就会出问题。

第 1 步:job 必须有边界

一个 job 只做一种模态。要写清:

数量 · 完整 prompt · 参考文件 · 参数 · 输出路径 · adapter profile

一个 job 不混合模态。 大批量工作拆成创作者能看清数量和成本边界的小 job——
不要把整季隐式塞进一次确认。

第 2 步:prepare 只预览

prepare 会返回一份完整预览:数量、prompt、来源条目、参考绑定、输出路径、
是否覆盖、走哪个 adapter。

这一步还会做一次机械核对:所选标题里的可复制提示词、参考图槽位、顺序、路径、
中文名和控制边界。任一漂移都 fail closed。

第 3 步:确认不能复用

这一步是整套设计的核心。以下这些都不算本次生产确认:

  • “继续”
  • “都做完”
  • “预算没问题”
  • 上游内容已被接受
  • 之前确认过另一版

只有在看到这份预览之后明确同意这一项任务,才算。

还有一条更要命的规则:

job、prompt、参数、输出路径或直接输入任一变化,旧确认立即失效。

改了一个字,确认作废,重新走。

第 4 步:run 消费确认

run 在启动前消费一次确认。成功或失败之后再次执行,都必须重新确认。

这一条防的是”失败重试意外产生第二笔费用”——失败了然后脚本自动重跑,
是很自然的反应,但每一次重跑都是一次计费。

二、最贵的坑:中断不等于要重跑

前面说”提交即计费”,但它有个正面的推论:

既然提交时已经付过钱了,中断之后就不该再付一次。

内置 adapter 因此在拿到供应商任务 ID 的第一时间就把它写进一个固定路径
(handle_path),早于第一次轮询。这个路径不随本次尝试一起删除。

于是中断之后有三条确定的动作,不必再花钱:

  1. audit 会把带着任务 ID 的未完成尝试报成 orphaned_provider_job,
    action 是 collect_before_retry
  2. collect 用那个 ID 把结果取回来,并把这尝试标成成功
  3. 只有在 collect 也确认那边确实失败之后,才走重新确认与重投

关键的一句:

不要在 audit 报出 orphaned_provider_job 时直接重投——那是在为同一个镜头付第二次钱。

这里还有个反直觉的设计:**collect 不走确认闸门**。

为什么?因为闸门防的是意外花钱,而 collect 不花钱。
如果 collect 也要求重新确认,那么中断之后”最省事”的路径就变成再付一次——
正好是闸门想防的事。

三、失败要对症,不要原样重投

失败分三路走:

1. 技术失败——超时、限流、服务端错误。可以做有上限的重试。

2. 输入被拒——失败信息会点名被拒的是哪一项:

被拒的怎么改
提示词文本改写那一句
参考图换一张构图与角色一致、画面本身合规的图
音频重录那句台词

改完写进新 job 重新 prepare,让创作者在预览里看到改的是哪一项再确认。

3. 重复内容缺陷——回到对应的提示词/spec owner。

关于第 2 类,有个具体的改写例子很能说明问题。原文是:

1
一拳砸在对方脸上,血顺着下巴滴

被拒之后改成:

1
一拳挥空,对方侧身避开,桌上的杯子被带倒

同样是冲突,同样有动作和后果,但画面本身合规了。

原样重投的那次确认不产生修复,只产生一笔费用。

四、参考绑定:生产时读的是它,不是分镜

分镜里的”输入参考图”路径,只是创作阶段的可读依据与使用意图,
不是生产输入快照。

进入生产时,job 必须从《图片提示词》或《视频提示词》的对应条目建立绑定。
prepare 展示的 reference_bindings 和已确认的 job,才是本次实际读取哪些文件字节、
各自允许影响什么的权威
。

绑定字段要逐张填:槽位、顺序、路径、中文名、用途、允许控制范围、禁止控制范围。

而这里有个细节:用途 字段会被 adapter 读成供应商自己的 role,
而且只接受供应商公布的取值——带参考图却没有绑定的 job 会直接失败,
不替它猜一个 role。

顺带说,本地图片由内置 adapter 按 base64 data URI 直接送出,不需要自建上传服务。
这个细节比想象中省事得多。

五、凭据边界

一条硬规矩:adapter 配置必须在项目外,且只包含命令和超时。

凭据由 adapter 自己从进程环境或系统凭据存储读取。

项目里的 job、确认记录、运行记录、Dashboard——都不得保存密钥。

这条的意义是:项目目录可能会被备份、打包、交给别人看,而密钥不该出现在那里。

六、结果不等于质量

功能跑完了,也有一句很清醒的定位:

不要把”adapter 返回成功”写成质量结论。

成功后回报的应该是:实际输出路径、媒体类型、运行状态。质量结论由审查环节给。

同理:

  • repeated_content 只是成本与诊断信号,不能自动判定同文重试合理或不合理
  • running_attempt 是未决运营状态,必须返回 attention
  • 输出缺失、或文件的哈希/大小不再等于运行记录时,先复核当前字节或重新生产

还有一条:生产结束后不自动进入剪辑。
素材要装配成成片时由用户点名,剪辑环节只取舍已有帧,不回头改 job,也不生成新素材。

七、小结

这道闸门看起来繁琐——四步、确认不能用”继续”、改了参数确认作废。
但它解决的是一个很具体的问题:生成任务按次计费,而模型和脚本都倾向于重试。

把”确认”做成一次性的、和具体 job 指纹绑定的东西之后,重试变得”贵”了,
人就不得不先想清楚再动手。这是设计出来的摩擦力。

完整链路的其他环节:视频提示词、
流水线实战、分镜与审查。