StabilityMatrix + ComfyUI → Web API:从本地跑图到对外提供服务

用 StabilityMatrix 管理 ComfyUI 环境,开启 --listen 模式,封装成 REST API,再套一层 FastAPI/Express,让任何人都能通过 HTTP 调用你的 AI 画图服务。

你在本地装了 StabilityMatrix,跑 ComfyUI,出图效果不错。但每次都要开浏览器拖节点,没有办法给别人用,也没有办法接进自己的产品。

这篇文章解决这件事:把本地的 ComfyUI 变成一个真正可以调用的 API 服务,别人发一个 HTTP 请求,你这边返回图片。


一、环境:用 StabilityMatrix 管理

StabilityMatrix 是 Windows/macOS/Linux 上最好用的 AI 模型包管理器。它帮你解决:

  • Python 虚拟环境隔离(不污染系统)
  • ComfyUI / A1111 / Forge 一键安装升级
  • 模型下载到统一目录
  • 启动参数 GUI 配置

安装流程:

  1. github.com/LykosAI/StabilityMatrix/releases 下载最新版
  2. 首次启动选存储目录(建议独立盘,模型很大)
  3. Add Package → ComfyUI,安装
  4. 安装完成后先点一次「Launch」确认能正常出图

二、开启 API 模式

ComfyUI 内置 HTTP API,但默认只监听 127.0.0.1。要对外(或容器内)暴露,需要加启动参数。

在 StabilityMatrix 里加参数:

点 ComfyUI 右边的 ⚙️ → Extra Launch Arguments,加入:

--listen 0.0.0.0 --port 8188

⚠️ 0.0.0.0 代表监听所有网卡。局域网内可用,公网暴露要套一层鉴权。

启动后,局域网内任何机器都能访问 http://你的IP:8188

验证 API 可用:

curl http://localhost:8188/system_stats

返回 JSON 说明 API 已就绪。


三、理解 ComfyUI 的 API 结构

ComfyUI 的 API 很简洁,核心就三个端点:

端点方法作用
/promptPOST提交 workflow,返回 prompt_id
/history/{prompt_id}GET查询任务状态 + 结果
/viewGET下载输出图片

提交 Workflow 的 payload 格式:

先在 ComfyUI 网页界面设计好 workflow,然后点右上角 Save (API format),保存为 workflow_api.json

这个 JSON 就是你的请求 body:

{
  "prompt": { ...你的 workflow_api.json 内容... },
  "client_id": "my-app-001"
}

轮询等结果:

import requests, time

def generate(workflow: dict, host="http://localhost:8188"):
    r = requests.post(f"{host}/prompt", json={"prompt": workflow, "client_id": "demo"})
    pid = r.json()["prompt_id"]
    
    while True:
        h = requests.get(f"{host}/history/{pid}").json()
        if pid in h:
            output = h[pid]["outputs"]
            # output 里有 images 列表
            img = output[list(output.keys())[0]]["images"][0]
            return requests.get(f"{host}/view", params=img).content
        time.sleep(1)

四、封装成自己的 API(FastAPI)

直接暴露 ComfyUI 的原始 API 太难用了:调用方需要懂 workflow 格式,参数分散。

套一层 FastAPI,把参数抽象成业务接口:

# app.py
from fastapi import FastAPI
from fastapi.responses import Response
import json, requests, time, copy

app = FastAPI()
COMFY = "http://localhost:8188"

# 加载 workflow 模板
with open("workflow_api.json") as f:
    WORKFLOW_TPL = json.load(f)

@app.post("/generate")
def generate(prompt: str, width: int = 512, height: int = 512, steps: int = 20):
    wf = copy.deepcopy(WORKFLOW_TPL)
    
    # 找到 KSampler 节点,修改参数
    for node in wf.values():
        if node["class_type"] == "KSampler":
            node["inputs"]["steps"] = steps
        if node["class_type"] == "EmptyLatentImage":
            node["inputs"]["width"] = width
            node["inputs"]["height"] = height
        if node["class_type"] == "CLIPTextEncode" and "positive" in str(node):
            node["inputs"]["text"] = prompt
    
    # 提交并等待
    r = requests.post(f"{COMFY}/prompt", json={"prompt": wf, "client_id": "api"})
    pid = r.json()["prompt_id"]
    
    while True:
        h = requests.get(f"{COMFY}/history/{pid}").json()
        if pid in h:
            imgs = list(h[pid]["outputs"].values())[0]["images"]
            img_data = requests.get(f"{COMFY}/view", params=imgs[0]).content
            return Response(content=img_data, media_type="image/png")
        time.sleep(1)

启动:

pip install fastapi uvicorn requests
uvicorn app:app --host 0.0.0.0 --port 8000

现在你的 API:

curl "http://localhost:8000/generate?prompt=a+cat+in+space&width=768&height=768" \
  --output cat.png

五、加鉴权(API Key)

对外服务不能裸跑,加一个简单的 Bearer token 校验:

from fastapi import Header, HTTPException

API_KEYS = {"sk-your-key-here", "sk-another-key"}

def verify(authorization: str = Header(...)):
    token = authorization.removeprefix("Bearer ").strip()
    if token not in API_KEYS:
        raise HTTPException(status_code=401, detail="Unauthorized")

@app.post("/generate")
def generate(prompt: str, _=Depends(verify)):
    ...

调用时带上 header:

curl -H "Authorization: Bearer sk-your-key-here" \
  "http://localhost:8000/generate?prompt=a+cat+in+space" \
  --output result.png

六、让外网能用(内网穿透 / 反向代理)

本机跑,想让外网朋友用,有几种方案:

方案 A:Cloudflare Tunnel(推荐,免费)

# 安装 cloudflared
winget install Cloudflare.cloudflared

# 登录
cloudflared tunnel login

# 创建隧道
cloudflared tunnel create comfyui-api

# 运行
cloudflared tunnel --url http://localhost:8000

会给你一个 *.trycloudflare.com 域名,绑自己的域名也行。

方案 B:nginx 反向代理(有公网 IP)

server {
    listen 443 ssl;
    server_name api.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_read_timeout 120s;  # 出图可能要等一会儿
    }
}

方案 C:ngrok(最快,测试用)

ngrok http 8000

七、WebSocket 实时进度(可选)

等图的时候前端干等体验差。ComfyUI 支持 WebSocket 推送进度:

const ws = new WebSocket(`ws://localhost:8188/ws?clientId=my-app`);

ws.onmessage = (e) => {
  const msg = JSON.parse(e.data);
  if (msg.type === "progress") {
    console.log(`进度:${msg.data.value}/${msg.data.max}`);
  }
  if (msg.type === "executing" && msg.data.node === null) {
    console.log("完成!");
  }
};

前端可以实时显示进度条,体验直接拉满。


总结

步骤工具作用
环境管理StabilityMatrixPython 隔离 + ComfyUI 安装
API 暴露--listen 0.0.0.0ComfyUI 内置 HTTP API
业务封装FastAPI抽象参数,隐藏 workflow 细节
鉴权Bearer token防止滥用
对外暴露Cloudflare Tunnel免费、安全、不需要公网 IP
实时进度WebSocket更好的用户体验

整套下来,你就有了一个:自己的 AI 出图 API,可以接进任何产品,可以分享给朋友,可以包一层前端做成 Web App。


Posted by Seraph @ u14.co · May 2026