背景:为什么非得折腾 ComfyUI?
做动漫短视频的朋友都懂,传统“抽卡”式出图再拼视频,三步一卡、五步一崩:
- 延迟高:一张 512×512 图动辄 3-4 s,60 帧就要 3 min,等花儿都谢了
- 效果跳:帧与帧种子对不上,人物脸忽大忽小,背景像幻灯片
- 资源炸:Stable Diffusion WebUI 开高清 + 高步数,24 GB 显存直接飙红,显卡风扇起飞
一句话:生产环境根本扛不住。于是我把目光投向了“节点式”的 ComfyUI——它把 Latent Diffusion 拆成可插拔模块,既能跑低秩微调,又能帧间复用潜变量,理论上“更快、更稳、更省”。是噱头还是真香?我踩了俩星期坑,把全过程拆给你看。
技术选型:ComfyUI vs WebUI 视频化方案
先放结论:
“WebUI 是单反,ComfyUI 是乐高。” 做视频需要批量、可编程、可复现,WebUI 的“一键出图”反而成了枷锁。
| 维度 | ComfyUI | Stable Diffusion WebUI |
|---|---|---|
| 批处理能力 | 原生支持 Batch/Loop 节点,一次跑 N 帧 | 靠脚本插件,易掉驱动 |
| 潜变量复用 | 可跨帧共享 latent,节省 30%+ 显存 | 不支持 |
| 节点热插拔 | 能同时加载 LoRA、ControlNet、IP-Adapter 并动态开关 | 需重启或切模型 |
| 代码化 | 工作流可导出为 JSON/API,CI 自动生产 | 基本靠人手点 |
| 学习曲线 | 陡峭,要理解 VAE/CLIP/K-Sampler | 开箱即用 |
如果你只做静态海报,WebUI 足够;但要生成“能播的”动漫视频,ComfyUI 是痛苦但唯一的选择。
核心实现:一条最小可运行工作流
1. 整体思路
ComfyUI 把“文生图”拆成 5 大阶段:
- Text Encode → 条件向量
- Latent Noise → 初始噪声
- K-Sampler → 去噪迭代
- VAE Decode → 像素空间
- Batch 组装 → 视频
做视频只需把“单帧”封装成 For-Loop,让 latent 在帧间平滑过渡即可。
2. 关键节点拆解
VAE Encode/Decode
动漫模型多数用kl-f8-anime2,潜空间压缩比 1:8,显存直接砍到 1/64。记得把tile_mode=1打开,4K 图也不会 OOM。CLIP 设置
用Clip Text Encode (Prompt)节点,正向提示词里加masterpiece, 1girl, <lora:animeLine_v10:0.7>,负向固定lowres, bad anatomy。CFG Scale 6-8 即可,动漫风格太高反而过饱和。K-Sampler
- 采样器:dpmpp_2m_sde_gpu
- 步数:20(测试)/ 30(成品)
- Scheduler:karras
- Denoise 1.0 首帧,后续帧用 0.6-0.7 做“部分去噪”,可保持连贯。
帧间连贯性
把前一帧的latent通过LatentBlend节点与当前帧噪声按 0.25:0.75 混合,再送入采样器,可显著抑制闪烁;同时固定 seed 增量 +1,保证随机性可控。
代码示例:Python 端批量驱动
ComfyUI 自带/promptAPI,把工作流 JSON 发过去即可。下面给出“模型加载-帧生成-视频合成”最小闭环,显存 <12 GB 可跑 512×768×48 帧。
# comfy_video.py import requests, json, torch, cv2, os, math from pathlib import Path API_URL = "http://127.0.0.1:8188/prompt" WORKFLOW_JSON = "workflow_anime48f.json" # 事先导出的节点图 def optimize_load(): """仅加载一次基础模型,后续 LoRA 动态注入""" from comfy.model_management import cleanup_models cleanup_models() # 先清掉残留 torch.cuda.empty_cache() torch.backends.cudnn.benchmark = True os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:128" def generate_frame(prompt, seed, frame_idx, prior_latent=None): """请求 ComfyUI API 生成单帧""" with open(WORKFLOW_JSON, "r", encoding="utf-8") as f: wf = json.load(f) # 找到对应节点并填充动态参数 wf["6"]["inputs"]["text"] = prompt wf["25"]["inputs"]["noise_seed"] = seed if prior_latent is not None: # 把前一帧 latent 传进去做混合 wf["37"]["inputs"]["latent0"] = prior_latent payload = {"prompt": wf} resp = requests.post(API_URL, json=payload).json() # ComfyUI 返回图片文件名列表 filename = resp["prompt_id"] + "_" + str(frame_idx).zfill(4) + ".png" return filename def images_to_video(fp_out, img_dir, fps=24, size=(512,768)): fourcc = cv2.VideoWriter_fourcc(*"mp4v") out = cv2.VideoWriter(fp_out, fourcc, fps, size) for png in sorted(Path(img_dir).glob("*.png")): frame = cv2.imread(str(png)) out.write(frame) out.release() if __name__ == "__main__": optimize_load() prompt_pos = "masterpiece, 1girl, aqua hair, detailed eyes, walking, <lora:animeLine_v10:0.7>" prompt_neg = "lowres, bad anatomy, blurry" prior = None for i in range(48): seed = 1234 + i fname = generate_frame(prompt_pos, seed, i, prior) prior = fname # 简写:实际应把 latent tensor 回传,这里用文件名代替逻辑 images_to_video("anime48f.mp4", "./output", 24)说明:
- 工作流 JSON 需预置“保存图像”节点,并勾选
output_node=true,API 才会回写文件名 - 真正生产要把
prior_latent换成 tensor 的 base64 编码,或写临时.latent文件,再让节点加载 - 如果爆显存,把
batch_size设 1,并在每次请求后cleanup_models()
性能优化三板斧
内存池管理
在extra_model_config.yaml里加vae_tiling: true vae_tile_size: 960VAE 按块解码,8G 显存也能跑 2K 输出
并发并发还是并发
ComfyUI 的/prompt非阻塞,可一次性塞 4-8 个 prompt_id,前端轮询拿结果;对 24 GB 卡,可把--gpu-only和--lowvram混用,跑两条流水线,吞吐翻倍缓存 & 预编译
- 把常用 LoRA 用
lora_comfy_cache提前转.safetensors - CUDA Graph capture 在 30 步以内可提速 15%,但 ControlNet 动态 shape 会失效,需要权衡
- 把常用 LoRA 用
避坑指南:Top5 血泪史
显存溢出(CUDA OOM)
解决:开vae_tiling+--lowvram;生成 2K 图时,把latent高宽各除以 2 跑一半,再超分画面闪烁 / 角色突变
解决:- 固定 seed 递增
- 用
LatentBlend把前一帧潜变量混进来,权重 0.2-0.3 - 打开
dpmpp_2m_sde的eta变量 0.3,让采样路径更平滑
色块水纹(VAE artifact)
解决:解码前把latent归一化到 [-4,4],并在后处理加 1 像素高斯模糊,再叠加原图的 unsharp maskLoRA 不生效
解决:节点图里Load LoRA必须连到Model和Clip双输入;只接 Model 会导致文本编码器没学到关键词音频不同步(后期配音)
解决:生成前先用ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -t 00:02:00 silence.wav垫空白音轨,锁定 24 fps,再进 PR 配音,避免抽帧
扩展:ControlNet 让镜头更听话
想让角色始终居中?给首帧画一张 OpenPose,后面每帧用ControlNet节点继承骨架图即可。要点:
- 预处理器用
dw_pose(对动漫鲁棒性最好) - 权重 0.8-1.0,引导步数 20% 即可,太高会抹掉细节
- 结合
IP-Adapter上传一张风格参考,保证色彩统一
这样既能锁定动作,又能让大模型自由发挥背景,做 MV、OP 都够用。
一键体验
我把上面完整流程(含工作流 JSON + Python 驱动)打包进了 Colab,免费 T4 也能跑 24 帧 512×512,链接如下:
https://colab.research.google.com/github/你的github/ComfyUI-AnimeVideo/blob/main/notebook.ipynb
(如无法访问,请自备 GitHub 镜像加速)
写在最后
ComfyUI 像一把瑞士军刀:节点一摆,谁都能拼出花来;但链条越长,调试越酸爽。本文的脚本和参数都是我从十几次崩溃里磨出来的“保底值”,先让视频能顺利跑通,再谈艺术风格。祝你早日脱离“抽卡地狱”,用 12G 显存也能做出 60 帧丝滑番剧短片。如果还有新坑,欢迎来评论区一起填。