2026 实战:用 ComfyUI 加 n8n 在 VPS 搭批量 AI 图片与 PDF 处理流水线(电商出图自动化)

2026 年用 ComfyUI 加 n8n 在 VPS 搭建无人值守的批量 AI 出图与 PDF 处理流水线,覆盖队列限速、超时重试与自动质检,附电商实战。

延伸阅读

更多相关攻略推荐:Ollama AI系列(2):VPS上的AI推理与API应用Ollama AI系列(2):VPS上的AI推理与API应用ARM / Ampere 席卷 VPS:性价比真香还是兼容陷阱?【VPS 硬件选型指南 (内存 篇) 02】大内存 VPS 能干嘛?2026 独立站 PCI-DSS 自查清单:SAQ A 还是 A-E

为什么要在 VPS 上自建 AI 出图流水线

按张付费的生图 SaaS 看似省事,一旦你要为电商铺几百个 SKU 做主图、详情页套图,或者给自媒体每天产出几十张封面,单价就扛不住了。2026 年 GPU VPS 的成本已经明显下探,自部署 ComfyUI 之后,边际成本几乎只剩电费。更关键的是,自建意味着你能完全控制工作流、模型权重和出图参数,而不是被某个平台的额度与审核卡脖子。

但单跑 ComfyUI 的图形界面只能手动一张张点,真正的价值在于“流水线化”。本文要落地的方案是:用 n8n 当总指挥,向 ComfyUI 的 API 批量派单,自动限速防 GPU 过载,失败自动重试,出图后做自动质检,再和 PDF 解析、文件落库串成一条无人值守的生产线。电商运营、自媒体团队和需要批量素材的站长,照着做就能搭出自己的出图工厂。

整体架构:编排层、出图层、落库层

整套系统分成三层,职责清晰才好排错:

  • 编排层(n8n):负责读取任务来源(表格、Webhook、定时触发器)、构造请求、派单、轮询状态、做重试与质检,以及把成品写库。
  • 出图层(ComfyUI API):以无头模式运行,监听本地端口,接收 /prompt 提交的工作流 JSON,在 GPU 上执行并返回 prompt_id,结果通过 /history 查询。
  • 落库层(PDF 与对象存储):把生成的图片合并成 PDF、解析上游传入的 PDF 订单、做 OCR,再归档到本地磁盘或 S3,回写链接到业务表。

三者都跑在同一台 VPS 上最省事;如果出图压力很大,也可以把 ComfyUI 单独放到带 GPU 的机器,n8n 通过内网地址调用。无论哪种,ComfyUI 的端口千万不要直接暴露到公网。

第一步:选 VPS 并部署 ComfyUI

出图是显存密集型任务,选型先看显存再看内存。给你三个常见档位参考:

  • Vultr:提供按小时计费的 GPU 实例,适合峰值弹性扩容,跑一阵子就销毁,成本可控,适合需要 Flux 这类大模型但对长期占用不敏感的场景。
  • Contabo:大内存、大硬盘、价格厚道,部分机型能上到 24G 显存,适合 7×24 常驻的生产线,模型权重常驻内存,冷启动慢的痛点被抹平。
  • RackNerd:低价入门机型,显存一般不大,更适合放 n8n 编排机、PDF 处理和落库服务,把重活留给带 GPU 的节点。

部署时先装好 CUDA 驱动和 PyTorch,再拉取 ComfyUI 源码,用无头模式启动并开启 API:

git clone https://github.com/comfyanonymous/ComfyUI
cd ComfyUI
python -m pip install -r requirements.txt
python main.py --listen 127.0.0.1 --port 8188 --enable-api --gpu-only --force-fp16

参数要点:--listen 127.0.0.1 只绑本地,配合反代再加鉴权,别直接对公网开 8188;--enable-api 是程序化调用的前提;--gpu-only--force-fp16 能压低显存占用,批量跑更稳。

第二步:在 ComfyUI 里导出 API 格式工作流

n8n 调 ComfyUI 不是截图操作,而是提交一段 JSON。先在 ComfyUI 画布上把出图流程连好(加载模型、CLIP 编码、采样、保存图像),然后点菜单里的“Save (API Format)”,得到一份精简 JSON。这份 JSON 就是后续 POST 的 body 骨架。

它的结构是 prompt 字典,键是节点 ID,值是该节点的类与输入。你要动态替换的通常只有两处:CLIP Text Encode 节点的 text(正向提示词),以及 KSampler 节点的 stepscfgwidthheightseed。把固定部分存成模板,变量部分交给 n8n 注入,这就是流水线化的核心。

第三步:用 n8n 编排批量派单

在 n8n 里新建一个工作流,典型节点顺序是:

  • Schedule Trigger 或 Webhook:定时触发,或接收外部系统的任务(比如电商后台推来的 SKU 列表)。
  • Set / Code:把每条任务构造成完整的 ComfyUI 工作流 JSON,把提示词、尺寸、种子写进去。
  • Split In Batches:关键限速节点,把成百上千条任务按批次切开,比如每批 1 到 3 条,避免一窝蜂压垮 GPU。
  • HTTP Request(POST /prompt):把 JSON 发给 ComfyUI,拿到 prompt_id。注意 HTTP 超时只覆盖“提交”这一步,设 10 秒足够。
  • Wait + HTTP Request(GET /history):轮询任务状态,仍未完成就 Wait 几秒再查,直到 success。
  • If:判断状态,成功走落库分支,失败走重试或告警分支。

ComfyUI 本身没有完成回调,必须靠轮询。每 8 到 15 秒查一次即可,不要高频打接口,那是典型的“用请求量制造故障”。

第四步:队列防 GPU 过载

批量出图最怕显存爆掉。即便单张能跑通,几百张连发也会 OOM。三道闸门要一起上:

  • 批次大小:Split In Batches 的 batch size 设 1 最稳,宁愿慢点也不要贪心。
  • 队列上限:自己的包装层里设一个待处理上限(例如 5),超过就延后或拒绝,避免任务在 ComfyUI 里堆积。
  • VRAM 监控:提交前先查显存水位,压力高就等队列排空。可以用这个接口:
curl http://127.0.0.1:8188/system_stats

返回的 JSON 里有 vram_usedvram_total,占用超过 80% 就先别派新单。如果模型之间要切换,记得在两段工作流之间加 Unload Model 节点,或在代码里调用 /free 清掉旧模型,腾出显存再加载下一个。

第五步:超时重试与自动质检

重试要讲策略,不能无脑重发,否则同样的错会反复烧 GPU。分类处理:

  • 参数非法 / 节点缺失(node_errors):修工作流和环境,不要重试。
  • OOM:先降 batch size、开 --lowvram,再谨慎重试,不要原样重发。
  • WebSocket 断连 / 网络抖动:重连后查 /history/{prompt_id},拿结果就好。
  • 执行超时:设一个执行上限(比如 300 秒),超时就 POST /interrupt 打断当前任务,让队列继续。

自动质检(QC)放在出图成功之后。最小可用的 QC 是:检查 /history 的 outputs 里确实有图像节点输出;对下载到的图片做 HEAD 请求,确认文件大小大于阈值;用一段 Code 节点读 PNG 头拿到真实分辨率,低于目标尺寸就判不合格、进重试队列。更进一步可以接一个视觉分类或 NSFW 过滤接口,把明显翻车的图自动剔除。质检不过的任务,回写状态为“待重跑”,而不是默默入库。

下面这段 Python 包装函数把队列上限、超时打断和轮询串了起来,逻辑和 n8n 里做的完全一致:

import requests, time, uuid

COMFY = "http://127.0.0.1:8188"
QUEUE_CEILING = 5
TIMEOUT = 300

def submit(workflow_json):
    client_id = "n8n-worker-" + uuid.uuid4().hex[:8]
    payload = {"prompt": workflow_json, "client_id": client_id}
    resp = requests.post(COMFY + "/prompt", json=payload, timeout=10)
    return resp.json().get("prompt_id")

def wait_done(prompt_id):
    start = time.time()
    while time.time() - start < TIMEOUT:
        hist = requests.get(COMFY + "/history/" + prompt_id, timeout=10).json()
        if prompt_id in hist:
            status = hist[prompt_id]["status"]["status_str"]
            if status == "success":
                return hist[prompt_id]["outputs"]
            if status == "error":
                raise RuntimeError("ComfyUI node error")
        time.sleep(8)
    requests.post(COMFY + "/interrupt")
    raise TimeoutError("generation timeout")

def vram_pressure():
    stats = requests.get(COMFY + "/system_stats", timeout=10).json()
    dev = stats["system_stats"]["devices"][0]
    return dev["vram_used"] / dev["vram_total"]

第六步:PDF 解析与文件落库

电商场景里,任务源常常是 PDF 报价单、订单表或商品手册,产出也常要合并成带图的 PDF 详情册。n8n 社区节点能补齐这块能力,常用的有 PDF.co、@custom-js/n8n-nodes-pdf-toolkit 等。典型链路是:

  • 解析上游 PDF:用 PDF Parse 节点抽取文本和表格,拿到 SKU、标题、卖点,作为出图提示词的原料。
  • 生成图片:把解析出的每条商品喂给 ComfyUI 出图。
  • 图片转 PDF:用 Images to PDF 节点把套图拼成商品详情 PDF,可加水印、页眉页脚。
  • 落库与回写:Write Binary File 落本地,或 HTTP Request 上传到 S3 / 图床,再把链接回写到 Airtable、Google Sheets 或业务数据库。

文件命名要有规律,推荐 output/{日期}/{sku}_{seed}.png,同时把 prompt、seed、尺寸、业务 ID 写进日志或数据库,后期检索和复盘都靠它。ComfyUI 的 output 目录是工作流共享的,别直接对外提供,下载后传到对象存储再返回签名 URL。

实战示例:电商批量出图生产线

把上面六步拼起来,一条可用的电商出图线长这样:每天凌晨 Schedule Trigger 启动,从商品表读当日待出图 SKU;Split In Batches 每批 1 条,逐条提交 ComfyUI;Wait 轮询直到出图成功;QC 节点校验分辨率与文件大小;通过后把图合并进商品 PDF,上传对象存储;最后把成品链接回写商品表,企业微信或 Telegram 推送一条“今日出图完成”的汇总。整条线无人值守,运营只需要在表里维护商品和提示词。

如果某张图超时或质检不过,If 节点把它丢进重试分支,最多重试两次仍失败就转人工并告警,不会让一条坏数据卡住整批。这就是流水线相比手工点图的真正优势:可观测、可恢复、可规模化。

成本与避坑清单

  • 别把 ComfyUI 端口裸奔公网:默认 API 无鉴权,几千台暴露实例已被扫描到,务必绑 127.0.0.1 加反代鉴权。
  • 模型常驻比反复加载便宜:常驻机型选 Contabo 这类大内存方案,避免每次任务都重新加载十几 GB 权重。
  • 幂等设计:给每条业务任务生成 request_id,映射到 prompt_id;重复到达时直接返回已有结果,别重复烧卡。
  • 工作流要版本化:API Format 的 JSON 是产物,按哈希固定版本,先在测试环境验证再上生产,避免周五晚上被一张改坏的画布坑。
  • 显存不够先降负载:降 batch size、开 --lowvram、拆分工作流,再做重试,而不是原样重发。

整体算下来,常驻一台带 24G 显存的 GPU VPS,月度成本往往低于同等产量的按张付费 SaaS,且出图风格、模型、参数完全自主。对于日均几十到几百张素材的团队,自建流水线的回收周期很短。