1. 为什么我要折腾本机 ComfyUI 加 WorkBuddy 这套组合
做 AI 短剧这半年,我最大的感受不是"生成质量不够",而是"流程太碎"。一条 60 秒的成片,拆下来大概是 12 到 18 个镜头,每个镜头要跑图、挑图、再图生视频、再挑视频、再拼接、再配音配字幕。如果全靠手动点,一天下来能出 2 条成片就算效率高的了,而且人会被这种重复劳动磨到完全没有创作欲望。
真正让我下决心做流水线的,是算了一笔账。假设一条短剧 15 个镜头,每个镜头平均要生成 4 次才有一版能用,那就是 60 次图生成加 60 次视频生成。手动操作每次从打开工作流、改提示词、点队列、等结果、下载文件,平均 3 分钟,光机械操作就是 6 个小时。这还没算挑片和返工。而如果把这套流程交给一个调度层去跑,我只需要在前期把提示词和分镜表准备好,剩下的时间可以去做下一集的剧本。
这里就要说到WorkBuddy的定位了。很多人第一次听到这个名字会以为是某种聊天助手,其实它更像是一个"本机任务调度中枢"——你可以把它理解成一个能听懂自然语言、又能真正调用本机程序去干活的执行层。它和ComfyUI的关系,有点像"导演"和"摄影棚":ComfyUI 负责实际的图像与视频生成,WorkBuddy 负责按分镜顺序把任务一个个丢进去、等结果、收文件、记录状态。
我选择本机部署而不是云端,核心原因有三个。第一是成本,本机跑一次图生视频的电费摊下来几乎可以忽略,云端按次计费跑批量会非常肉疼。第二是隐私与素材安全,短剧的剧本、角色设定、参考图这些都属于核心资产,放在自己机器上最踏实。第三是可控性,本机可以随时改工作流、换模型、调参数,不用等平台更新。
提示:本机方案的前提是你有一张显存够用的显卡。图生视频这一环对显存的要求比纯出图高不少,后面我会给出具体的显存对照参考。
这套流水线适合谁?如果你已经在用 ComfyUI 出图、对节点工作流不陌生,那这套东西能直接把你从"手动点队列"里解放出来。如果你是完全的新手,也不用慌,我会把安装、配置、调度脚本、踩坑都写清楚,照着抄作业也能跑起来。整篇文章我会围绕"零成本批量流水线"这个目标,把设计思路、核心细节、实操过程、问题排查四块讲透,中间穿插我实测的耗时数据和踩过的坑。
2. 整体架构设计与方案选型思路
2.1 三层架构:调度层、生成层、资产层
我把整套流水线拆成三层,这样出问题的时候能快速定位是哪一层挂了。
调度层就是 WorkBuddy。它负责读取分镜表、按顺序触发任务、监控 ComfyUI 的队列状态、把生成结果按规则重命名并归档。它的核心价值是"编排"——把一堆离散的操作串成一条自动流动的线。
生成层是 ComfyUI 本体加上具体的工作流。图生成用一个工作流,图生视频用另一个工作流,两者通过 API 暴露出来。ComfyUI 本身提供了 HTTP 接口,只要把工作流导出成 API 格式的 JSON,就能通过接口提交任务。
资产层是文件系统。分镜表、提示词、参考图、生成的中间帧、最终视频,全部按固定目录结构存放。这一层看起来最不起眼,但恰恰是批量流水线最容易翻车的地方——文件命名混乱、覆盖、找不到对应关系,是批量任务的头号杀手。
三层之间的数据流是这样的:WorkBuddy 读分镜表 → 组装参数 → 调用 ComfyUI API 提交任务 → 轮询任务状态 → 任务完成后从输出目录取文件 → 按规则重命名归档 → 记录日志 → 进入下一个镜头。
2.2 为什么用 API 而不是模拟点击
一开始我图省事,想过用模拟鼠标点击的方式去驱动 ComfyUI 界面。实测下来这条路走不通,原因很直接:ComfyUI 的界面元素位置会随窗口大小、节点折叠状态变化,模拟点击极其脆弱,跑几十个任务必崩。而且模拟点击没法准确判断"任务是否真的完成",只能靠固定等待时间,效率极低。
改用 API 之后,整个逻辑就干净了。ComfyUI 的接口设计其实很朴素,核心就两个动作:提交任务(POST 到/prompt)和查询状态(GET/history/{prompt_id})。提交任务时把工作流的 API JSON 和参数一起发过去,它会返回一个 prompt_id,之后拿这个 id 去查历史记录,就能知道任务是否完成、输出文件在哪。
注意:工作流必须导出成API 格式,而不是普通的界面格式 JSON。在 ComfyUI 里通过"导出(API)"选项保存,两者的结构完全不同,用错了接口会直接报错。
2.3 参数注入的设计:让一个工作流服务所有镜头
批量流水线的关键,是让同一个工作流能服务所有镜头,而不是每个镜头改一次工作流。做法是把工作流里所有需要变化的地方"参数化"——提示词、随机种子、参考图路径、帧数、分辨率,全部通过接口传入。
具体实现上,ComfyUI 的 API JSON 里每个节点都有唯一的 id,节点的输入字段就是我们要替换的目标。比如正向提示词节点的text字段、随机种子的seed字段、加载图片节点的image字段。WorkBuddy 在提交前,把这些字段按分镜表里的值替换掉,再发出去。
这里有个细节值得说:随机种子。批量生成时如果种子固定,同一提示词永远出同一张图,没有挑选空间;如果完全随机,又没法复现某一版满意的结果。我的做法是每个镜头生成 N 版,种子用"基础种子 + 序号"的方式递增,这样既有多样性,又能通过基础种子复现整批结果。
2.4 目录结构设计:批量任务的隐形地基
我踩过最惨的一次坑,就是文件命名混乱导致成片拼接时镜头顺序全乱。后来我定了一套强制规范,所有文件路径都由分镜表驱动,程序不允许自由发挥。
project_root/ ├── storyboard/ │ └── ep01.csv # 分镜表,每行一个镜头 ├── refs/ │ └── ep01/ # 参考图,按镜头编号命名 ├── workflows/ │ ├── t2i_api.json # 图生成工作流 │ └── i2v_api.json # 图生视频工作流 ├── output/ │ ├── ep01/ │ │ ├── img/ # 生成的图 │ │ └── vid/ # 生成的视频 └── logs/ └── ep01_run.log分镜表用 CSV 而不是 Excel,是因为 CSV 纯文本、易 diff、程序读取零依赖。字段我固定成这几列:shot_id、prompt、negative、ref_image、frames、seed_base、status。status这一列是断点续跑的关键,后面会细讲。
3. 核心细节解析与实操要点
3.1 ComfyUI 的安装与工作流准备
安装这块,新手最容易卡在环境和模型上。我的建议是直接用整合包起步,省去配 Python 环境和依赖的麻烦。整合包的好处是开箱即用,坏处是版本可能偏旧,等你熟悉了再考虑手动装。
装好之后,第一件事是确认能正常出图。随便跑一个默认工作流,出一张图,确认显卡、模型、路径都没问题。这一步别跳过,很多后面的报错其实都是基础环境没通。
接下来是准备两个工作流。图生成工作流相对简单,文生图或者图生图都行。图生视频工作流是重点,它决定了成片的质量和稳定性。我用的结构是:加载参考图 → 编码 → 视频生成节点 → 保存视频。不同视频模型的工作流差异很大,这里不绑定具体模型,你按自己机器能跑动的来。
导出 API 格式后,用文本编辑器打开,你会看到类似这样的结构:
{ "3": { "class_type": "KSampler", "inputs": { "seed": 12345, "steps": 20, "cfg": 7.5, "sampler_name": "euler", "scheduler": "normal", "denoise": 1.0, "model": ["4", 0], "positive": ["6", 0], "negative": ["7", 0], "latent_image": ["5", 0] } } }每个数字 key 就是节点 id,inputs里就是可以替换的参数。你要做的就是找到提示词、种子、图片路径对应的节点 id,记下来,写进调度脚本的映射表里。
提示:节点 id 不是固定的,你重新拖一个工作流,id 可能就变了。所以映射表要跟着工作流一起维护,改工作流就更新映射表,别偷懒。
3.2 WorkBuddy 的调度逻辑设计
WorkBuddy 在这里扮演的是"总控"。它的调度逻辑我设计成四个阶段:准备、提交、轮询、归档。
准备阶段读分镜表,过滤掉status已经是done的行,实现断点续跑。然后检查每个镜头的参考图是否存在,不存在就标记为missing_ref跳过,避免任务跑到一半才报错。
提交阶段把分镜参数注入工作流 JSON,POST 到 ComfyUI 的/prompt接口,拿到 prompt_id 后写进内存的任务表。
轮询阶段是核心。ComfyUI 的任务是排队执行的,不能提交完就以为完成了。我的做法是每隔几秒查一次/history/{prompt_id},如果返回里有输出文件信息,就认为完成。这里要注意超时设置,视频生成慢的时候一个任务可能跑十几分钟,超时设太短会误判失败。
归档阶段把输出文件从 ComfyUI 的默认输出目录复制到项目目录,按shot_id重命名,更新分镜表的status。
整个调度逻辑用伪代码表达大概是这样:
for shot in storyboard: if shot.status == "done": continue workflow = load_workflow("i2v_api.json") workflow = inject_params(workflow, shot) prompt_id = submit(workflow) result = poll_until_done(prompt_id, timeout=1800) if result.success: archive(result.files, shot.shot_id) shot.status = "done" else: shot.status = "failed" save_storyboard(storyboard)关键点是每处理完一个镜头就保存一次分镜表。这样即使中途断电或者程序崩了,重启后也能从断点继续,不会白跑。
3.3 参数注入的细节与常见陷阱
参数注入看着简单,实际有几个坑。
第一个坑是数据类型。ComfyUI 的接口对类型敏感,种子必须是整数,帧数必须是整数,提示词必须是字符串。如果你从 CSV 读出来全是字符串,直接塞进去会报类型错误。所以注入前要做类型转换,int()、str()该加就加。
第二个坑是路径格式。加载图片节点需要的是 ComfyUI 能识别的路径,通常是相对于它 input 目录的路径,而不是绝对路径。我一开始传绝对路径,任务一直失败,排查半天才发现是路径问题。解决办法是把参考图统一放到 ComfyUI 的 input 目录下,传相对路径。
第三个坑是节点依赖。有些参数改了之后,下游节点需要重新计算。比如你改了参考图,编码节点必须重新跑。ComfyUI 的 API 会自动处理依赖,但前提是你改的是正确的节点。如果改错了节点,可能表面上任务成功,实际输出还是旧参数的结果。
第四个坑是批量提交的并发。ComfyUI 默认是串行执行队列的,你一次性提交 100 个任务,它会一个个跑。这本身没问题,但如果你提交太快,接口可能来不及响应。我的做法是提交时加一个小延迟,或者分批提交,每批 10 个,等这批跑完再提交下一批。
3.4 耗时实测:心里有数才敢批量
这部分是我实测的数据,机器配置是单张中端显卡,具体型号不重要,重要的是量级参考。
| 环节 | 单次耗时 | 说明 |
|---|---|---|
| 图生成(1024x1024,20步) | 8-15 秒 | 取决于模型和步数 |
| 图生视频(2秒,16帧) | 60-120 秒 | 视频模型差异极大 |
| 图生视频(4秒,32帧) | 150-300 秒 | 帧数翻倍,耗时不止翻倍 |
| 单镜头全流程(含挑选) | 3-8 分钟 | 生成4版图+2版视频 |
| 15镜头短剧全流程 | 60-120 分钟 | 纯机器时间 |
看到这个数据你就明白了,为什么手动操作不可行。15 个镜头手动跑,加上人的反应时间和操作时间,轻松超过 6 小时。而流水线跑起来,人可以去做别的事,机器自己跑 1 到 2 小时就出全部素材。
注意:视频生成的耗时和帧数不是线性关系。16 帧到 32 帧,耗时可能翻 2 到 3 倍,因为显存压力和计算量都上去了。所以分镜设计时,能用 2 秒镜头表达的就别硬拉 4 秒。
4. 实操过程与核心环节实现
4.1 环境搭建的完整步骤
第一步,装 ComfyUI。整合包解压后直接运行启动脚本,浏览器打开本地地址,能看到界面就成功了。第一次启动会下载一些基础依赖,耐心等。
第二步,放模型。把图生成模型放到models/checkpoints,视频模型放到对应目录。不同视频模型的目录要求不一样,看模型说明。放错目录是新手最常见的错误,模型列表里找不到就是路径不对。
第三步,验证工作流。手动跑一次图生成,再手动跑一次图生视频,确认两个工作流都能出结果。这一步是后面自动化的前提,手动都跑不通,自动化更别想。
第四步,导出 API 格式工作流。在图生成工作流界面点导出,选 API 格式,保存为t2i_api.json。图生视频同理,保存为i2v_api.json。
第五步,准备 WorkBuddy。安装好之后,确认它能执行本机命令、能发 HTTP 请求。这两个能力是调度 ComfyUI 的基础。
第六步,建目录结构。按前面说的结构建好文件夹,把分镜表 CSV 放进去。
4.2 分镜表的编写规范
分镜表是整条流水线的"剧本",写得好不好直接决定跑起来顺不顺。我总结了几条规范。
shot_id用ep01_s001这种格式,集数加镜头号,排序时不会乱。prompt写正向提示词,尽量具体,包含主体、动作、场景、光线、镜头语言。negative写负向提示词,把不想要的东西列清楚。ref_image写参考图文件名,对应refs/ep01/目录下的文件。frames写视频帧数,2 秒按 16 帧算,4 秒按 32 帧算。seed_base写基础种子,每个镜头不同,方便复现。
写分镜表有个技巧:提示词要"可批量"。什么意思?就是同一批镜头的提示词结构要一致,只是主体和动作不同。这样生成出来的画面风格才统一,拼接起来才像一部剧,而不是一堆不相干的片段。
4.3 调度脚本的核心实现
调度脚本我用 Python 写,因为处理 JSON 和 HTTP 请求最顺手。核心逻辑分几个函数。
读分镜表用csv模块,逐行读成字典。过滤已完成的行,收集待处理任务。
注入参数用一个映射表,把分镜字段映射到工作流节点。映射表长这样:
PARAM_MAP = { "prompt": ("6", "text"), "negative": ("7", "text"), "seed": ("3", "seed"), "ref_image": ("10", "image"), "frames": ("15", "frame_count"), }提交任务用requests库:
import requests, json def submit(workflow): resp = requests.post( "http://127.0.0.1:8188/prompt", json={"prompt": workflow} ) return resp.json()["prompt_id"]轮询状态:
import time def poll(prompt_id, timeout=1800): start = time.time() while time.time() - start < timeout: resp = requests.get( f"http://127.0.0.1:8188/history/{prompt_id}" ) data = resp.json() if prompt_id in data: return data[prompt_id] time.sleep(5) return None归档就是把输出文件复制到项目目录,重命名,更新分镜表状态。
4.4 断点续跑与失败重试
批量任务最怕的就是跑到一半崩了,前面全白跑。所以断点续跑是必须的。
实现方式很简单:每处理完一个镜头,立刻把分镜表的status更新为done并写回文件。程序启动时先读分镜表,跳过done的行。这样无论什么时候中断,重启后都从断点继续。
失败重试我设了三次。第一次失败可能是偶发的显存不足或者接口超时,重试往往能过。三次都失败就标记为failed,跳过继续跑后面的,最后统一处理失败列表。这样不会因为一个镜头卡住整个批次。
提示:失败重试之间要加延迟,比如等 30 秒再重试。立刻重试往往还是同样的错误,因为显存还没释放。
4.5 成片拼接与后期
所有镜头生成完,就到了拼接环节。这一步我暂时没做全自动,因为拼接涉及节奏、转场、配乐,需要人的判断。但素材准备可以自动化:把所有视频按shot_id排序,生成一个拼接清单,导入剪辑软件后按清单顺序拖入即可。
配音和字幕我用的是"先生成音频,再对齐画面"的方式。音频生成可以单独跑,字幕用语音识别生成时间轴,再和视频对齐。这部分工具选择很多,按自己习惯来。
5. 常见问题与排查技巧实录
5.1 任务提交后一直没反应
这是最常见的问题。排查顺序是这样的:先看 ComfyUI 界面里队列有没有任务,如果没有,说明提交失败,检查接口地址和 JSON 格式。如果有任务但一直排队,说明前面有任务卡住了,去界面里看是哪个节点卡住。如果任务在跑但很慢,那就是正常的,视频生成本来就慢。
我遇到过一次提交成功但队列不动的,最后发现是工作流里有个节点引用了不存在的模型文件。ComfyUI 不会立刻报错,而是卡在那里。所以工作流一定要先手动跑通再自动化。
5.2 生成的视频和参考图对不上
这个问题通常是参数注入错了节点。检查映射表里的节点 id 是不是加载图片那个节点。另一个可能是参考图路径不对,ComfyUI 读不到图,用了默认图或者空图。把参考图放到 input 目录,用相对路径,基本能解决。
还有一种情况是缓存。ComfyUI 会缓存节点结果,如果你改了参数但节点没重新执行,输出还是旧的。解决办法是在提交前清一下缓存,或者改一个会触发重算的参数。
5.3 显存不足导致任务失败
视频生成对显存要求高,尤其是帧数多的时候。如果频繁报显存不足,有几个办法:降低分辨率、减少帧数、换更省显存的模型、开启显存优化选项。实在不行就分批跑,跑完一批清一次显存。
我实测下来,2 秒 16 帧的镜头在中端显卡上比较稳,4 秒 32 帧就容易爆。所以分镜设计时优先用短镜头,需要长镜头就拆成几个短镜头拼接。
5.4 文件命名混乱导致拼接错位
这个坑我踩过,教训深刻。根本原因是程序归档时用了 ComfyUI 的默认文件名,没有重命名。解决办法是归档时强制按shot_id重命名,并且校验文件数量,数量不对就报警。
下面是我整理的常见问题速查表:
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 提交无反应 | 接口地址错/JSON格式错 | 检查地址,验证JSON |
| 队列不动 | 节点引用缺失文件 | 手动跑通工作流 |
| 视频与参考图不符 | 注入节点错/路径错 | 核对映射表和路径 |
| 输出是旧结果 | 节点缓存 | 清缓存或触发重算 |
| 显存不足 | 分辨率/帧数过高 | 降参数或分批跑 |
| 拼接错位 | 文件命名混乱 | 强制按shot_id重命名 |
| 中途崩溃白跑 | 无断点续跑 | 每镜头保存状态 |
5.5 独家避坑心得
说几个文档里不会写、但实际很要命的点。
第一,ComfyUI 的输出目录会越积越大。批量跑几百个任务后,输出目录可能几十个 G。定期清理,或者归档后自动删除源文件,不然硬盘很快满。
第二,轮询间隔别设太短。我一开始设 1 秒查一次,结果 ComfyUI 的接口被查爆了,反而拖慢任务。改成 5 到 10 秒查一次,稳定很多。
第三,分镜表要备份。调度脚本会频繁写分镜表,万一写坏了,整个项目状态就丢了。我现在的做法是每次写之前先备份一份,出问题能回滚。
第四,别一次性提交所有任务。虽然 ComfyUI 会排队,但一次性提交几百个任务,内存占用会很高,而且中途想调整都没法调。分批提交,每批 10 到 20 个,灵活得多。
第五,测试用小批量。新工作流或者新脚本,先用 2 到 3 个镜头测试,确认没问题再上全量。我吃过一次亏,脚本有个小 bug,跑了 50 个镜头才发现全错了,白跑两小时。
6. 关于成本与效率的一些真实体会
这套流水线跑顺之后,我最大的变化是心态。以前做短剧,一想到要手动点几百次就犯怵,现在把分镜表写好,剩下的交给机器,我可以专心打磨剧本和分镜设计。效率上,一条 15 镜头的短剧,从素材生成到成片,纯机器时间 1 到 2 小时,人的介入时间大概 30 分钟,主要是写分镜和最后拼接。
成本这块,本机方案的电费摊到每条短剧上几乎可以忽略。真正的时间成本在前期搭建,第一次配环境、调工作流、写脚本,我花了大概两个周末。但这是一次性投入,后面每一条短剧都在摊薄这个成本。
如果你也想搭这套东西,我的建议是先从最小的闭环开始:一个镜头,从分镜表到自动生成到归档,跑通。然后再扩展到多个镜头,再加断点续跑,再加失败重试。别一上来就追求全自动,那样容易在细节里迷路。
最后分享一个我最近在试的扩展方向:把配音和字幕也纳入调度。思路是视频生成完后,自动触发语音合成,再用识别工具生成字幕时间轴,最后用命令行工具合成。这样整条线就真的从分镜表一路走到成片了。不过这块我还在调,等跑稳了再单独写一篇。