把 ComfyUI 做成局域网出图服务:API 调用与队列管理
内容标识:本文为 AI 辅助生成内容。依据 《人工智能生成合成内容标识办法》2025-09-01,已添加显式标识(本声明)与隐式标识(文件元数据 / 图片 ComfyUI 元信息)。文中技术细节与结论均由作者复核确认。
我在上一篇里把 ComfyUI 在本机跑通了(见 ComfyUI 本地部署指南),但真正的价值在于:显卡只有一块,要用图的人和脚本却有很多。与其每人装一套环境,不如把 ComfyUI 当成一个「局域网出图服务」——任何机器发一个 HTTP 请求就能排队出图。这篇记录改造过程和脚本侧的队列、超时、重试处理。
第一步:让 ComfyUI 监听局域网
ComfyUI 默认只监听本机回环地址 127.0.0.1,局域网其它机器访问不到。启动时加 --listen 参数即可:
python main.py --listen 0.0.0.0 --port 8188
启动后日志里会提示监听地址变为 0.0.0.0:8188,局域网内用 http://<服务器IP>:8188 就能打开界面。
注意开放监听等于把出图接口暴露给整个网段,没有任何鉴权。建议在路由器或主机防火墙层面做白名单,只允许可信网段访问。
第二步:拿到 API 格式的工作流 JSON
ComfyUI 界面上拖拽出来的工作流,默认保存的 JSON 是给前端画布用的,不能直接提交给 API。需要在设置里开启「开发者模式选项」(Dev Mode),保存按钮旁才会出现「Save (API Format)」,导出的才是后端可执行的节点图。
导出的 API JSON 是一个以节点 ID 为键的字典,每个节点包含 class_type 和 inputs。提交前通常要在脚本里动态改几个参数,比如提示词、种子和出图尺寸:
wf["6"]["inputs"]["text"] = prompt # CLIP Text Encode 的提示词
wf["3"]["inputs"]["seed"] = random.randint(0, 2**32 - 1) # KSampler 随机种子
第三步:提交任务并轮询结果
核心 API 只有三个:POST /prompt 提交、GET /history/{prompt_id} 查结果、GET /view 下载图片。ComfyUI 服务端自带队列,提交后立即返回 prompt_id,不必自己抢锁:
import requests, time
BASE = "http://10.11.200.172:8188" # 换成你的服务器地址
def queue_prompt(workflow):
r = requests.post(f"{BASE}/prompt",
json={"prompt": workflow}, timeout=10)
r.raise_for_status()
return r.json()["prompt_id"]
def wait_result(pid, timeout=180):
deadline = time.time() + timeout
while time.time() < deadline:
h = requests.get(f"{BASE}/history/{pid}", timeout=10).json()
if pid in h:
return h[pid]["outputs"]
time.sleep(2)
raise TimeoutError(f"出图超时: {pid}")
拿到 outputs 后,遍历节点输出里的 images 字段,用 GET /view?filename=...&type=output 把图片拉回来保存即可。
第四步:客户端侧的排队与重试
服务端队列只管「排队执行」,不管「失败补偿」。脚本侧要自己兜底三件事:
- 提交重试:网络抖动导致
POST /prompt失败时,指数退避重试 3 次(间隔 2s/4s/8s),仍失败则放弃并记录。 - 超时判定:
wait_result超时后不要直接重提交——任务可能还在队列里。先GET /queue确认任务是否仍在排队或执行中,避免同一任务提交两遍白白翻倍占卡。 - 失败识别:
history里若出现status.status_str == "error",取出messages里的报错(常见是显存不足、模型路径错),按错误类型决定是否值得重试。
def queue_status(pid):
q = requests.get(f"{BASE}/queue", timeout=10).json()
running = [x[1] for x in q.get("queue_running", [])]
pending = [x[1] for x in q.get("queue_pending", [])]
return pid in running, pid in pending
如果有多台客户端并发提交,建议给每个客户端分配独立的 client_id,配合 WebSocket(/ws)可以拿到逐节点的执行进度,做进度条或看板时很有用;纯轮询方案不接 WebSocket 也完全够用。
总结
把 ComfyUI 服务化只需要三步:加 --listen 开放监听、导出 API 格式工作流、用 POST /prompt + GET /history 提交轮询。真正的工程量在客户端——超时判定要先查 /queue 防止重复提交,失败要区分「可重试的网络错」和「无意义的参数错」。这套接口稳定之后,任何脚本、定时任务甚至其他服务都能共享这块显卡,这才是本地出图环境的正确打开方式。