简介:这是一份面向 ComfyUI 使用者的图像生成工作流资源,核心是针对剧情分镜场景的“多角度图生图”,结合 QwenImageEdit 模型能力,帮助创作者从单一参考图出发生成多个视角的连贯画面。压缩包采用 rar 格式,体积仅 12KB,内含一个 JSON 工作流文件,无需安装额外依赖即可导入 ComfyUI 直接运行,适合 AI 绘画爱好者、短视频团队和漫画/影视分镜设计者使用。目前已有 595 人学习/下载,表明该配置在小范围 ComfyUI 社区中具备一定参考价值和实用性。借助这份工作流,可省去从零搭建节点图表的步骤,快速了解 QwenImageEdit 在分镜生成中的调用方式;也能作为模板替换提示词、微调参数,适配不同剧情脚本,辅助生成更稳定的多角度分镜素材。整体而言,这套小体积资源兼具实用性与学习价值,适合需要快速产出多视角分镜参考的创作者,也可作为后续二次开发与流程定制的简洁起点。
1. ComfyUI+QwenImageEdit:多角度剧情分镜图生图的正确打开方式
做多角度剧情分镜图生图,最折磨人的不是想不出镜头,而是同一个角色在第3页到第10页长成了两个人。换角度、换景别、换机位,每次重画都像一次仿生人换脸。ComfyUI 加 QwenImageEdit 的组合,正好把这件事变成一条可复用的图生图流水线:一张参考图喂进去,多角度剧情分镜一张接一张出来,脸型、发型、服装细节锁定在同一个基准上。这套方案适合漫画主笔、短剧分镜师、游戏过场美术,也适合所有需要批量出分镜的个人创作者。工作流怎么搭、参考图怎么备、批量生产怎么控,以及我踩过的几个坑,下面按落地顺序讲清楚。
2. ComfyUI 与 QwenImageEdit 选型:分镜生产为什么需要这套组合
2.1 节点式工作流才是批量分镜的骨架
先立一个概念:ComfyUI 是节点式工作流,不是单张抽卡工具。它的核心优势在于把加载模型、输入图像、写提示词、出图、保存拆成可连接的节点,调好一次之后,整套连接关系可以保存成工作流 JSON,后面换分支、换参数就能批量复用。多角度剧情分镜的特点是同一角色、多种机位、连续剧情,本质是同一套节点在不同提示词和不同参考图之间循环。这个需求在 ComfyUI 里是顺水推舟,在 WebUI 里却要反复进同一套界面手动改参数,几十张分镜改下来,错一个数值就得重来,效率差太多。
QwenImageEdit 是 Qwen 系的多模态图像编辑模型,跟标签驱动的图生图模型相比,中文指令理解有明显的优势。分镜表里写的「微微仰视的中景,画面带一点黄昏氛围」可以直接进提示词,不用翻译成英文标签。做剧情分镜的人会特别受用这一点,因为分镜描述本身就是叙事语言,不是标签语言:一句话里同时有动作、情绪、景别和光线,用自然语言描述比堆 tag 准确得多。
这两个东西合在一起之后,ComfyUI 提供批量生产骨架,QwenImageEdit 提供中文叙事理解,正好接住分镜生产的两块硬需求。这也是我这套工作流里始终没有换成别的工具组合的原因。
在安装上,最常见的方式是打开 ComfyUI-Manager,搜索 QwenImageEdit 对应的自定义节点一键安装。用秋叶一键整合包的话更省事,Manager 里直接搜,省去了手动配 Python 环境和 torch 版本的功夫。模型权重下载后放进 models/checkpoints,刷新节点列表就能看到。这类节点更新快,ComfyUI 插件生态的版本差异也很大,不要死记网上的某个仓库地址,以你打开 Manager 时能搜到的版本为准。
2.2 最小工作流:从一张参考图跑出第一张分镜
先搭一个能跑起来的最小工作流,后面所有批量能力都在它上面加。节点链路是 CheckpointLoaderSimple → LoadImage → QwenImageEdit → VAEDecode → SaveImage。在界面里连好线之后,导出工作流 JSON,核心段长这样:
{ "1": { "class_type": "CheckpointLoaderSimple", "inputs": { "ckpt_name": "qwen_image_edit.safetensors" } }, "2": { "class_type": "LoadImage", "inputs": { "image": "ref_character.png" } }, "3": { "class_type": "QwenImageEdit", "inputs": { "image": ["2", 0], "prompt": "把这张角色参考图改为仰视中景,机位放在角色左前方,背景是夜晚街道,角色抬头看路灯", "image_strength": 0.75, "denoise": 0.45, "seed": 42 } }, "4": { "class_type": "VAEDecode", "inputs": { "samples": ["3", 0] } }, "5": { "class_type": "SaveImage", "inputs": { "images": ["4", 0], "filename_prefix": "storyboard_001" } } }这个 JSON 对应界面上的五个节点,中间那个 QwenImageEdit 是整套工作流的核心。prompt 不用写英文,直接写中文分镜需求;image_strength 控制参考图对结果的影响强度,0.75 表示保留角色大部分外貌特征,同时允许机位变化带来的透视变形;denoise 是重绘幅度,0.45 意味着在参考图基础上一半程度的重绘,太高会丢掉脸型,太低则角度变化不明显。seed 固定随机种子,这是批量场景里必须养成的习惯:如果某张分镜出了满意的效果,把种子记到分镜表里,重跑能稳定复现同一张。
有一点要提前说明:QwenImageEdit 这个节点名在不同插件里可能有版本后缀。你不用背 JSON,直接在 ComfyUI 界面里点节点就能看到参数名,它们跟这里的结构一一对应。
第一次跑通后,检查三件事:出图的人脸还像不像参考图、机位是否真的变了、背景是否符合提示词描述。三个答案里至少有两个是肯定的,这个工作流就可以进入批量阶段。如果只有一个是肯定的,先调 image_strength 和 denoise,不要急着改提示词,多数情况是强度配比不对。
2.3 免费生图 API 在分镜工作流里的定位:做预演,不做生产
很多新人会问,既然有免费生图 API,为什么还要本地装 ComfyUI?这个问题得分两段看。日常做创意验证、垫图、找参考配色的时候,API 确实方便,一句话出图,不占本地算力。但到了多角度剧情分镜这个任务上,API 是黑匣子:你控制不了 seed、控制不了图像强度、一次只能出一张、中间状态也不好拆改。把几十行分镜表灌进 API,出图手感跟抽卡差不多,运气不好就得整批重来。
我一般的做法是让 API 和本地 ComfyUI 分工:API 负责风格预演和参考图初筛,快速判断某个机位值不值得细做;真正成批生产时回到本地工作流。举个例子,我用免费生图 API 做预演时,提示词会模仿 QwenImageEdit 的句式:「保持角色特征,机位切到右侧中景,黄昏光线」。返回的图只需要目测大致构图有没有潜力,不要求细节一致。确认这个机位值得做之后,才把它写进分镜表,交给本地工作流生产。这个习惯帮我省掉了大量无效跑图。
如果你的显卡确实带不动高分辨率模型,API 可以兜底,但要接受它很难锁定角色一致性。多数从业者最后还是会上一张能跑的显卡或者云 GPU,把 ComfyUI 装起来,因为分镜生产拼的不是单张质量,而是整批统一。一次性把 60 格分镜全部交给 API 出图,结果是每张都好看、连起来不像同一个人,这是图生图工作流里最容易忽略的问题。
3. 人物一致性基础:参考图选不对,后面全是玄学
3.1 一套能锁住角色的参考图,按三条原则准备
多角度剧情分镜的角色一致性,七成在参考图,三成在参数。我每次准备参考图都按三条原则来。
第一,四到八张,覆盖不同角度和景别。不是说越多越好,而是每个关键角度都要有一张:正脸、三分之二侧、正侧面、微仰、微俯,各来一张。模型只能从参考图里学「这个人在三维空间长什么样」,只有一张正面图,机位切到侧面时,模型的处理方式更像在猜,五官比例很容易崩。备齐角度之后,正面像和侧面像之间的脸型、眉眼间距就能被模型当作同一组特征约束起来。
第二,光线统一。不同参考图之间,冷暖光源、硬光软光不要混着来。模型判断「这是不是同一个人」的重要线索是脸型和五官结构,但光线变化会干扰它,尤其肤色和发色在同一色温区间时更容易被识别成同一个人。参考图全部用漫射光环境拍,肤色、发色、服装色保持一致,后面出图才不会一会儿偏暖一会儿偏冷。
第三,背景要干净,面部不要遮挡。手挡脸、围巾挡下巴这类参考图,生成其他角度时会带着遮挡痕迹。全身、半身各备一套,服装变化分开建档,不要混用。准备参考图时多花二十分钟,后面少踩两小时的坑,这属于分镜工作流里最该花时间的资产积累。
3.2 用 CLIP 特征给参考图打分,筛掉低质量图
参考图备好之后,先用脚本做一次快速体检,别直接肉眼凑合。这里用 CLIP 图像特征计算每张参考图和整套图均值之间的相似度,分数偏差大的那张,就是会影响整体一致性的「问题图」。脚本如下:
from PIL import Image import torch from transformers import CLIPProcessor, CLIPModel model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32") processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32") paths = [ "ref_front.png", "ref_left.png", "ref_right.png", "ref_up.png", "ref_down.png" ] features = [] for p in paths: img = Image.open(p).convert("RGB") inputs = processor(images=img, return_tensors="pt") with torch.no_grad(): feat = model.get_image_features(**inputs) features.append(feat / feat.norm(dim=-1, keepdim=True)) mean_feat = torch.stack(features).mean(dim=0) for i, feat in enumerate(features): score = (feat * mean_feat).sum().item() print(f"{paths[i]}: {score:.4f}")这段脚本里,CLIP 模型把每张参考图压缩成 512 维特征向量,归一化之后做点乘,得到的就是余弦相似度,区间在 0 到 1 之间。每张图跟整套图的均值向量比较,分数明显偏低的那张,说明它的风格或视角偏离整体,放进图生图容易带偏角色形象。我一般把 0.92 当作分界线,低于这个值的直接剔除或替换。
这块逻辑除了筛参考图,还能用在 ComfyUI 的 CLIP 询问机这类节点上做实时分析,不过那是进阶玩法,先把手头的图筛干净再说。CLIP 模型可以用 vit-base-patch32,也可以换更大版本,速度慢一点但特征更准;分数值只在这套同一模型的内部比较里有意义,不要跨模型直接对比。
3.3 参考图张数和 image_strength 的搭配
参考图张数不是越少越好,也不是越多越好,关键在于和 image_strength 配合。我常用的一组对应关系是:
| 参考图张数 | 实际效果 | image_strength 建议 |
|---|---|---|
| 1 张 | 出图快,改机位容易跑样 | 0.80 ~ 0.90 |
| 3~5 张 | 姿态和脸型比较平衡 | 0.70 ~ 0.80 |
| 8 张左右 | 特征稳定,但提示词自由度下降 | 0.60 ~ 0.75 |
为什么参考图越多,image_strength 反而要调低?因为多张参考图本身就给了模型足够的约束,它已经知道脸型、发型、服装的稳定特征;image_strength 再拉高,约束会强到把机位变化也压住,动作和角度都显得僵硬。反过来,只有一张图时,模型手里信息少,必须靠高 image_strength 死死拽住特征,代价是角度变化也受限。实际批量之前,我会用同一张分镜表抽样三组参数各跑一张,再决定这一批用哪组。这个步骤看着多花几分钟,但能帮你避免 60 张图全部跑偏之后才发现的尴尬。
3.4 批量循环里参考图怎么自动切换
真正批量跑的时候,分镜表里不同行会指向不同的参考图。默认的 LoadImage 节点只能加载一张固定图片,如果整批不管参考图切换,角色特征会在第 N 张开始乱套。常见做法是给工作流加一个可以从路径读图的 LoadImageFromPath 节点,然后由脚本在循环里依次把参考图路径写进工作流再提交。核心逻辑是这样的:
import csv import json workflow = json.load(open("base_workflow.json", encoding="utf-8")) with open("storyboard.csv", encoding="utf-8") as f: rows = list(csv.DictReader(f)) for i, row in enumerate(rows, 1): workflow["2"]["inputs"]["image"] = row["参考图"] workflow["3"]["inputs"]["prompt"] = ( f"保持{row['参考图']}中角色的长相、发型、服装完全一致," f"{row['机位']},{row['景别']},{row['动作']},{row['画面描述']}" ) workflow["5"]["inputs"]["filename_prefix"] = f"shot_{i:03d}" # submit(workflow) 在这里调用本地 ComfyUI 接口逻辑说明:每次循环把参考图路径、提示词、输出文件名按行换掉,再提交工作流。第几行对应第几张图,文件名也按 shot_001、shot_002 排下去,输出不会互相覆盖。参数说明:shot_{i:03d}里 03d 指的是用三位数字补零,保证文件按序号排列;如果只写{i},到了 shot_10 会排在 shot_2 前面,后期挑图、拼长图都会很难受。
4. 批量生产:用分镜表驱动多角度剧情分镜
4.1 分镜表的数据结构:一行一个镜头
批量生产的源头是一张分镜表,常见做法是用 CSV 承载,字段设计如下:
| 字段 | 含义 | 示例 |
|---|---|---|
| 分镜号 | 每一格画面的唯一编号 | S01 |
| 景别 | 远景、中景、近景、特写 | 中景 |
| 机位 | 平视、仰视、俯视、俯拍 | 仰视 |
| 角度 | 正面、侧面、斜侧等方位 | 左前45° |
| 动作 | 角色的肢体动作 | 抬头看路灯 |
| 画面描述 | 剧情和氛围信息 | 夜晚街道,路灯昏黄 |
| 参考图 | 该分镜使用的角色参考图文件 | ref_character.png |
| seed | 该分镜想固定的随机种子 | 42 |
对应的 CSV 文件:
分镜号,景别,机位,角度,动作,画面描述,参考图,seed S01,中景,平视,正脸微侧,低头看手机,室内白天,窗外有雨,ref_character.png,42 S02,中景,仰视,左前45°,抬头看路灯,夜晚街道,路灯昏黄,ref_character.png,42 S03,近景,平视,正脸,哭,深夜卧室,台灯亮,ref_character.png,43字段的意义在于,把「镜头语言」和「剧情语言」拆开。景别、机位、角度是镜头语言,动作和画面描述是剧情语言,两者分列,后面生成提示词时才能分块组合,模型也不会把镜头词和剧情词混在一起。seed 列是后加进去的,效果稳定的分镜直接记种子,重跑就是同一张。分镜号则是最容易被忽略的一列:没有唯一编号,批量脚本里没法定位某一张图对应哪一个镜头,出了问题只能整批重跑。
4.2 三个必调的参数:image_strength、denoise、seed
进入批量之前,先看三个影响分镜质量的核心参数。image_strength 控制参考图的影响程度,denoise 控制重绘幅度,seed 控制可复现性。三者的关系不是各自独立,而是互相拉扯。
| 场景类型 | image_strength | denoise |
|---|---|---|
| 正脸平视近景 | 0.85 | 0.35 |
| 机位大角度切换(仰视/俯视) | 0.70 | 0.50 |
| 动作或情绪变化 | 0.75 | 0.45 |
正脸平视近景时,画面结构简单,模型照抄参考图就能完成任务,image_strength 可以拉高到 0.85,防止五官漂移。机位大角度切换时,模型需要重新计算透视关系,image_strength 太高会「抄不动作」,角度切不过去,所以要降到 0.7 左右,同时 denoise 给到 0.5。动作和情绪变化属于中间状态,0.75 和 0.45 的搭配兼顾了一致性和表达力。注意这组参数是起点不是终点,每一批图都要抽样验证。
4.3 提示词模板:把剧情描述和镜头语言拼成一句话
分镜表字段拆开之后,生成提示词的逻辑就很固定了。用 Python 脚本把每一行拼成完整提示词:
import csv with open("storyboard.csv", encoding="utf-8") as f: rows = list(csv.DictReader(f)) def build_prompt(row): return ( "保持参考图中角色的长相、发型、服装完全一致," f"景别:{row['景别']},机位:{row['机位']},角度:{row['角度']}," f"动作:{row['动作']},画面:{row['画面描述']}" ) prompts = [build_prompt(row) for row in rows] print(prompts[0])这段代码没有复杂逻辑,但有两个细节值得说明。第一,「保持参考图中角色的长相、发型、服装完全一致」必须放在提示词最前面,因为在 QwenImageEdit 这类模型中,靠前的 token 对整张图的约束力强于靠后的。第二,镜头语言和剧情语言用分号分隔,模型对「景别、机位、角度、动作、画面」这个结构的解析更稳定,不会把「夜晚街道」误当成角色的一部分。
4.4 批量提交 ComfyUI API:循环、排队、自动出图
提示词生成之后,批量生产就是把工作流反复提交给本地 ComfyUI 服务。ComfyUI 默认监听 8188 端口,/prompt 接口接收工作流 JSON 并排进队列。脚本如下:
import json import time import urllib.request SERVER = "http://127.0.0.1:8188" def submit(workflow): payload = json.dumps({"prompt": workflow}).encode("utf-8") req = urllib.request.Request( f"{SERVER}/prompt", data=payload, headers={"Content-Type": "application/json"}, ) return urllib.request.urlopen(req).read() with open("base_workflow.json", encoding="utf-8") as f: workflow = json.load(f) rows = load_storyboard("storyboard.csv") for idx, row in enumerate(rows, 1): workflow["2"]["inputs"]["image"] = row["参考图"] workflow["3"]["inputs"]["prompt"] = build_prompt(row) seed = int(row["seed"]) if row["seed"] else 42 workflow["3"]["inputs"]["seed"] = seed workflow["5"]["inputs"]["filename_prefix"] = f"shot_{idx:03d}" submit(workflow) time.sleep(1)逻辑说明:脚本按分镜表逐行改写工作流里 LoadImage 的图片路径、QwenImageEdit 的提示词和种子、SaveImage 的输出前缀,然后提交到本地队列。ComfyUI 会按顺序执行,不需要等一张完成再提交下一张。参数说明:sleep(1) 是为了避免本地服务瞬间接收过多请求导致排队异常,如果你的工作流很轻可以去掉。要查看是否全部跑完,可以请求 /queue 接口看队列剩余数量,留空时再统一收图。
万一跑出来的某张图明显失败,不需要重跑全部,直接把那行分镜的 seed 换掉再单独提交一次。批量循环支持按分镜号单独调用,所以分镜表的设计才一定要有唯一编号。
5. 批量多角度分镜的五个常见问题:现象、原因、解决
5.1 一换机位,人脸就换人
现象:参考图角色是明显的方脸宽下颌,机位切到仰视后,出图变成瓜子脸,眼睛间距也不对。这是做多角度分镜时最典型的翻车现场。
原因:机位大幅切换时,模型需要重新计算透视关系,这个计算过程本身就会改变五官比例。如果 image_strength 偏低或 denoise 偏高,模型对参考图特征的约束不够,就会「自由发挥」出一张新脸。
解决:机位大切换时把 image_strength 拉回 0.75 左右,denoise 控制在 0.4~0.45。如果还不行,把参考图里对应角度的图也丢进去,让模型有「这个角度下他长这样」的直接依据。这算是分镜工作流里最常见的血泪经验。
5.2 改动作,背景也一起乱改
现象:提示词写「角色举起左手」,出图后角色动作对了,但背后窗户位置变了、墙上的画换了。剧情分镜的场景连续性被破坏。
原因:QwenImageEdit 是全图编辑模型,动作、背景都在同一轮重绘里完成。提示词里的动作和画面描述会平等地带起背景重绘,尤其背景词里有「夜晚街道」这类强环境信息时,模型会顺带重画环境。
解决:在提示词最前面加「保持参考图背景结构不变」,并把背景描述固定成同一个句式。更彻底的做法是分两步:先在原参考图上做纯动作重绘,再把动作结果跟场景图合成。后一种工作流复杂,但适合对场景连续性要求极高的分镜。
5.3 提示词写了「保持发型」,发型还是变了
现象:开头写上「保持发型、发色、服装完全一致」,出图后发型从短发改成长发,衣服的颜色也偏了。这种做法在多数图生图模型里都靠不住。
原因:模型对「保持」类指令的理解比重绘指令弱,「保持××」本质上是否定性指令,而这类模型主要响应正向描述。提示词越长,靠后的「保持」越容易被稀释。
解决:别把一致性压力放在文字上,把它放在图像上。用 image_strength 控制特征保留,把「黑长直」「蓝色衬衫」这类正向描述写在提示词里,比写「保持发型」更稳。一致性这活交给图像强约束,文字负责表达剧情和动作。
5.4 直接出 2K 分辨率,显存爆了或细节崩坏
现象:分镜表里写 1920×1080,提交后爆显存,任务直接失败;勉强跑出来的图,人脸细节也崩得没法用。
原因:QwenImageEdit 这类模型的训练分辨率大多在 1MP(约 1024×1024)这个档位,直接放大两倍,模型会失去对细节的把控,显存消耗也会成倍增长。
解决:批量生产统一用基础分辨率跑图,比如 1024×1024,出图稳定后再挂一个放大节点,或者用专门的超分模型把关键分镜放大到 2K。不要在批量循环里直接放大,那只会让整批任务变成显存灾难。
5.5 批量跑到第 15 张,风格开始飘
现象:前 14 张色调一致,第 15 张开始画面突然偏亮、偏暖,后面几张越来越跑偏。整批分镜拿给甲方看,前一段和后一段像两个项目。
原因:主要是种子变化带来的随机性累积,其次是模型在长时间运行后权重或缓存状态有轻微漂移。批量循环里每张都换 seed,出图风格很难完全统一。
解决:批量循环里固定 seed 基线,只在个别分镜里手动换 seed;参考图在脚本里统一预处理到同一尺寸和格式,减少加载差异;跑完一组后重新加载一次模型权重,把状态复位。风格飘移这种问题,比单张脸歪更隐蔽,收图时一定要横向拼起来看。
6. 出图后的验证:用 CLIP 给整套分镜打分,别等交付再后悔
6.1 用 CLIP 特征做镜头间的一致性快速校验
批量出图之后,不要急着交付,先跑一遍自动校验。把所有分镜图和参考图做一次 CLIP 特征相似度比较,分数直观地告诉你哪些镜头跑偏了。脚本:
import glob from PIL import Image import torch from transformers import CLIPProcessor, CLIPModel model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32") processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32") def get_feature(path): image = Image.open(path).convert("RGB") inputs = processor(images=image, return_tensors="pt") with torch.no_grad(): feat = model.get_image_features(**inputs) return feat / feat.norm(dim=-1, keepdim=True) ref = get_feature("ref_character.png") for shot in sorted(glob.glob("output/shot_*.png")): feat = get_feature(shot) score = (feat * ref).sum().item() print(f"{shot}: {score:.4f}")逻辑说明:参考图特征作为角色锚点,每张分镜图跟它做余弦相似度比较。分数在 0.90 以上可以认为是同一个角色,0.85~0.90 需要人工复查,低于 0.85 直接重画。参数说明:这个阈值不是绝对的,不同参考图光照差异会影响基线,所以先拿参考图自己跟自己算一遍,确定基线分数,再下调 0.03~0.05 作为合格线。跑完自动校验,再拼长图做一次肉眼扫查,重点看脸型和发型在同视角切换时不要跳变。
6.2 拼长图对着分镜表过,改完记住更新种子
拼长图是我每批必做的操作:把所有分镜按顺序拼成一张长图,眼睛扫过一遍,视角切换的顿挫感很直观。看到不顺眼的分镜,直接回分镜表改 seed 或参数重跑,改完记得把新 seed 更新进 CSV。这套流程跑顺之后,一个 60 格的多角度剧情分镜,从参考图准备到收图验证,大概半天时间。我不追求第一版全对,而是依赖这套一致性与校验体系,保证每一版都能稳定落在可接受的范围内。希望这一套思路能帮你省下反复抽卡的时间。
本文还有配套的精品资源,点击获取