# ComfyUI 后端 API 接口文档 ## 目录 - [1. WebSocket 连接](#1-websocket-连接) - [2. 基础接口](#2-基础接口) - [2.1 获取根页面](#21-获取根页面) - [2.2 获取 Embeddings](#22-获取-embeddings) - [2.3 列出模型类型](#23-列出模型类型) - [2.4 获取指定文件夹的模型](#24-获取指定文件夹的模型) - [2.5 获取扩展](#25-获取扩展) - [2.6 查看图片](#26-查看图片) - [2.7 查看元数据](#27-查看元数据) - [2.8 系统状态](#28-系统状态) - [2.9 获取特性](#29-获取特性) - [2.10 获取提示信息](#210-获取提示信息) - [2.11 获取对象信息](#211-获取对象信息) - [2.12 获取特定节点信息](#212-获取特定节点信息) - [3. 文件上传接口](#3-文件上传接口) - [3.1 上传图片](#31-上传图片) - [3.2 上传 Mask](#32-上传-mask) - [4. 任务管理接口](#4-任务管理接口) - [4.1 获取所有任务](#41-获取所有任务) - [4.2 获取特定任务](#42-获取特定任务) - [4.3 获取历史记录](#43-获取历史记录) - [4.4 获取特定历史记录](#44-获取特定历史记录) - [4.5 获取队列](#45-获取队列) - [4.6 提交提示](#46-提交提示) - [4.7 队列操作](#47-队列操作) - [4.8 中断任务](#48-中断任务) - [4.9 释放资源](#49-释放资源) - [4.10 历史记录操作](#410-历史记录操作) - [5. 内部接口](#5-内部接口) - [5.1 获取日志](#51-获取日志) - [5.2 获取原始日志](#52-获取原始日志) - [5.3 订阅日志](#53-订阅日志) - [5.4 获取文件夹路径](#54-获取文件夹路径) - [5.5 获取文件列表](#55-获取文件列表) - [6. 任务提交与结果获取流程](#6-任务提交与结果获取流程) - [6.1 流程接口概述](#61-流程接口概述) - [6.2 任务状态说明](#62-任务状态说明) - [6.3 完整任务生命周期调用示例](#63-完整任务生命周期调用示例) --- ## 1. WebSocket 连接 ### 1.1 WebSocket 连接 **接口路径:** `GET /ws` **HTTP 方法:** GET **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | clientId | string | 否 | 客户端ID,用于重连现有会话 | **请求头要求:** 无特殊要求 **响应数据结构:** - WebSocket 连接建立后,服务器会发送初始状态消息 - 支持接收和发送 JSON 格式的消息 - 支持二进制消息传输(预览图片等) **错误码及错误信息:** - 连接失败:WebSocket 连接异常 **说明:** - 建立 WebSocket 连接用于实时通信 - 如果提供 clientId,会重用现有会话 - 首次连接时会发送服务器特性标志 - 支持实时接收任务状态更新和执行进度 --- ## 2. 基础接口 ### 2.1 获取根页面 **接口路径:** `GET /` **HTTP 方法:** GET **请求参数:** 无 **请求头要求:** 无特殊要求 **响应数据结构:** - 返回 HTML 页面(index.html) **错误码及错误信息:** - 404:页面不存在 **说明:** - 返回 ComfyUI 的前端主页 - 设置了不缓存的响应头 --- ### 2.2 获取 Embeddings **接口路径:** `GET /embeddings` **HTTP 方法:** GET **请求参数:** 无 **请求头要求:** 无特殊要求 **响应数据结构:** ```json [ "embedding1", "embedding2", ... ] ``` **字段说明:** - 返回 embeddings 文件夹中所有文件的名称(不含扩展名) **错误码及错误信息:** - 无 **说明:** - 获取所有可用的 embedding 文件列表 --- ### 2.3 列出模型类型 **接口路径:** `GET /models` **HTTP 方法:** GET **请求参数:** 无 **请求头要求:** 无特殊要求 **响应数据结构:** ```json [ "checkpoints", "loras", "embeddings", "vae", ... ] ``` **字段说明:** - 返回所有模型文件夹类型的名称 **错误码及错误信息:** - 无 **说明:** - 获取所有可用的模型类型列表 --- ### 2.4 获取指定文件夹的模型 **接口路径:** `GET /models/{folder}` **HTTP 方法:** GET **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | folder | string | 是 | 模型文件夹名称(路径参数) | **请求头要求:** 无特殊要求 **响应数据结构:** ```json [ "model1.safetensors", "model2.safetensors", ... ] ``` **字段说明:** - 返回指定文件夹中的所有模型文件 **错误码及错误信息:** - 404:指定的文件夹不存在 **说明:** - 获取指定类型文件夹中的所有模型文件 --- ### 2.5 获取扩展 **接口路径:** `GET /extensions` **HTTP 方法:** GET **请求参数:** 无 **请求头要求:** 无特殊要求 **响应数据结构:** ```json [ "/extensions/core/extension1.js", "/extensions/custom/extension2.js", ... ] ``` **字段说明:** - 返回所有 JavaScript 扩展文件的路径 **错误码及错误信息:** - 无 **说明:** - 获取前端扩展文件列表,包括核心扩展和自定义节点扩展 --- ### 2.6 查看图片 **接口路径:** `GET /view` **HTTP 方法:** GET **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | filename | string | 是 | 文件名 | | type | string | 否 | 文件类型(output/input/temp),默认 output | | subfolder | string | 否 | 子文件夹路径 | | preview | string | 否 | 预览参数(格式:image_format;quality) | | channel | string | 否 | 通道类型(rgba/rgb/a),默认 rgba | **请求头要求:** 无特殊要求 **响应数据结构:** - 返回图片文件或预览图片 - Content-Type 根据图片格式自动设置 **错误码及错误信息:** - 400:文件名无效或路径不合法 - 403:访问权限不足 - 404:文件不存在 **说明:** - 查看或下载生成的图片 - 支持预览格式转换和质量调整 - 支持通道分离(RGB、Alpha) --- ### 2.7 查看元数据 **接口路径:** `GET /view_metadata/{folder_name}` **HTTP 方法:** GET **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | folder_name | string | 是 | 文件夹名称(路径参数) | | filename | string | 是 | 文件名(查询参数) | **请求头要求:** 无特殊要求 **响应数据结构:** ```json { "__metadata__": { "key1": "value1", "key2": "value2" } } ``` **字段说明:** - 返回 safetensors 文件的元数据 **错误码及错误信息:** - 404:文件不存在或不是 safetensors 格式 **说明:** - 获取 safetensors 模型文件的元数据信息 --- ### 2.8 系统状态 **接口路径:** `GET /system_stats` **HTTP 方法:** GET **请求参数:** 无 **请求头要求:** 无特殊要求 **响应数据结构:** ```json { "system": { "os": "windows", "ram_total": 17179869184, "ram_free": 8589934592, "comfyui_version": "0.2.0", "required_frontend_version": "1.2.0", "installed_templates_version": "1.0.0", "required_templates_version": "1.0.0", "python_version": "3.10.0", "pytorch_version": "2.0.0", "embedded_python": false, "argv": [] }, "devices": [ { "name": "cuda:0", "type": "cuda", "index": 0, "vram_total": 8589934592, "vram_free": 4294967296, "torch_vram_total": 8589934592, "torch_vram_free": 4294967296 } ] } ``` **字段说明:** - system:系统信息 - os:操作系统类型 - ram_total:总内存(字节) - ram_free:可用内存(字节) - comfyui_version:ComfyUI 版本 - required_frontend_version:所需前端版本 - installed_templates_version:已安装模板版本 - required_templates_version:所需模板版本 - python_version:Python 版本 - pytorch_version:PyTorch 版本 - embedded_python:是否使用嵌入式 Python - argv:启动参数 - devices:设备信息数组 - name:设备名称 - type:设备类型 - index:设备索引 - vram_total:总显存(字节) - vram_free:可用显存(字节) - torch_vram_total:PyTorch 总显存(字节) - torch_vram_free:PyTorch 可用显存(字节) **错误码及错误信息:** - 无 **说明:** - 获取系统资源使用情况和版本信息 --- ### 2.9 获取特性 **接口路径:** `GET /features` **HTTP 方法:** GET **请求参数:** 无 **请求头要求:** 无特殊要求 **响应数据结构:** ```json { "custom_nodes_from_web": true, ... } ``` **字段说明:** - 返回服务器支持的特性列表 **错误码及错误信息:** - 无 **说明:** - 获取服务器支持的特性标志 --- ### 2.10 获取提示信息 **接口路径:** `GET /prompt` **HTTP 方法:** GET **请求参数:** 无 **请求头要求:** 无特殊要求 **响应数据结构:** ```json { "exec_info": { "queue_remaining": 5 } } ``` **字段说明:** - exec_info:执行信息 - queue_remaining:队列中剩余的任务数 **错误码及错误信息:** - 无 **说明:** - 获取当前队列状态信息 --- ### 2.11 获取对象信息 **接口路径:** `GET /object_info` **HTTP 方法:** GET **请求参数:** 无 **请求头要求:** 无特殊要求 **响应数据结构:** ```json { "KSampler": { "input": { "required": { "seed": ["INT", {"default": 0, "min": 0, "max": 18446744073709551615}], "steps": ["INT", {"default": 20, "min": 1, "max": 1000}], ... }, "optional": {...} }, "input_order": {...}, "output": ["LATENT"], "output_is_list": [false], "output_name": ["LATENT"], "name": "KSampler", "display_name": "KSampler", "description": "KSampler description", "python_module": "nodes", "category": "sampling", "output_node": false }, ... } ``` **字段说明:** - 返回所有节点的信息字典 - 每个节点包含: - input:输入参数定义(required/optional) - input_order:输入参数顺序 - output:输出类型列表 - output_is_list:输出是否为列表 - output_name:输出名称 - name:节点类名 - display_name:显示名称 - description:节点描述 - python_module:Python 模块 - category:节点分类 - output_node:是否为输出节点 **错误码及错误信息:** - 无 **说明:** - 获取所有可用节点的详细信息 --- ### 2.12 获取特定节点信息 **接口路径:** `GET /object_info/{node_class}` **HTTP 方法:** GET **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | node_class | string | 是 | 节点类名(路径参数) | **请求头要求:** 无特殊要求 **响应数据结构:** ```json { "KSampler": { "input": {...}, "output": ["LATENT"], ... } } ``` **字段说明:** - 返回指定节点的详细信息(同 2.11) **错误码及错误信息:** - 无(如果节点不存在,返回空对象) **说明:** - 获取指定节点的详细信息 --- ## 3. 文件上传接口 ### 3.1 上传图片 **接口路径:** `POST /upload/image` **HTTP 方法:** POST **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | image | file | 是 | 图片文件 | | overwrite | string | 否 | 是否覆盖(true/false/1) | | type | string | 否 | 上传类型(input/temp/output),默认 input | | subfolder | string | 否 | 子文件夹路径 | **请求头要求:** - Content-Type: multipart/form-data **响应数据结构:** ```json { "name": "image.png", "subfolder": "", "type": "input" } ``` **字段说明:** - name:保存的文件名 - subfolder:子文件夹路径 - type:文件类型 **错误码及错误信息:** - 400:文件无效或路径不合法 **说明:** - 上传图片到指定文件夹 - 自动处理文件名冲突(添加序号) - 支持覆盖模式 --- ### 3.2 上传 Mask **接口路径:** `POST /upload/mask` **HTTP 方法:** POST **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | image | file | 是 | Mask 图片文件 | | original_ref | string | 是 | 原始图片引用(JSON 字符串) | | overwrite | string | 否 | 是否覆盖 | | type | string | 否 | 上传类型 | | subfolder | string | 否 | 子文件夹路径 | **请求头要求:** - Content-Type: multipart/form-data **响应数据结构:** ```json { "name": "mask.png", "subfolder": "", "type": "input" } ``` **字段说明:** - 同 3.1 **错误码及错误信息:** - 400:参数无效或原始图片不存在 - 403:访问权限不足 **说明:** - 上传 mask 图片并将其应用到原始图片 - original_ref 格式:`{"filename": "image.png", "type": "output", "subfolder": ""}` --- ## 4. 任务管理接口 ### 4.1 获取所有任务 **接口路径:** `GET /api/jobs` **HTTP 方法:** GET **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | status | string | 否 | 状态过滤(逗号分隔):pending, in_progress, completed, failed | | workflow_id | string | 否 | 工作流 ID 过滤 | | sort_by | string | 否 | 排序字段(created_at/execution_duration),默认 created_at | | sort_order | string | 否 | 排序方向(asc/desc),默认 desc | | limit | integer | 否 | 返回数量限制(正整数) | | offset | integer | 否 | 跳过数量(非负整数),默认 0 | **请求头要求:** 无特殊要求 **响应数据结构:** ```json { "jobs": [ { "id": "prompt_id_1", "status": "completed", "priority": 1, "create_time": 1234567890000, "execution_start_time": 1234567891000, "execution_end_time": 1234567895000, "outputs_count": 4, "preview_output": { "filename": "image.png", "subfolder": "", "type": "output", "nodeId": "3", "mediaType": "images" }, "workflow_id": "workflow_1" } ], "pagination": { "offset": 0, "limit": 10, "total": 100, "has_more": true } } ``` **字段说明:** - jobs:任务列表 - id:任务 ID(prompt_id) - status:任务状态(pending/in_progress/completed/failed) - priority:优先级 - create_time:创建时间(毫秒时间戳) - execution_start_time:执行开始时间 - execution_end_time:执行结束时间 - execution_error:执行错误信息(失败时) - outputs_count:输出数量 - preview_output:预览输出 - workflow_id:工作流 ID - pagination:分页信息 - offset:偏移量 - limit:限制数量 - total:总数 - has_more:是否有更多 **错误码及错误信息:** - 400:参数无效(状态值、排序字段等) **说明:** - 获取所有任务列表,支持过滤、排序和分页 - 包括运行中、排队、已完成和失败的任务 --- ### 4.2 获取特定任务 **接口路径:** `GET /api/jobs/{job_id}` **HTTP 方法:** GET **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | job_id | string | 是 | 任务 ID(路径参数) | **请求头要求:** 无特殊要求 **响应数据结构:** ```json { "id": "prompt_id_1", "status": "completed", "priority": 1, "create_time": 1234567890000, "execution_start_time": 1234567891000, "execution_end_time": 1234567895000, "outputs": { "3": { "images": [ { "filename": "image.png", "subfolder": "", "type": "output" } ] } }, "execution_status": { "status_str": "success", "messages": [...] }, "workflow": { "prompt": {...}, "extra_data": {...} }, "outputs_count": 4, "preview_output": {...}, "workflow_id": "workflow_1" } ``` **字段说明:** - 同 4.1,额外包含: - outputs:完整输出数据 - execution_status:执行状态详情 - workflow:工作流详情 **错误码及错误信息:** - 400:job_id 参数缺失 - 404:任务不存在 **说明:** - 获取指定任务的详细信息,包括完整输出和工作流数据 --- ### 4.3 获取历史记录 **接口路径:** `GET /history` **HTTP 方法:** GET **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | max_items | integer | 否 | 最大返回数量 | | offset | integer | 否 | 偏移量,默认 -1(返回所有) | **请求头要求:** 无特殊要求 **响应数据结构:** ```json { "prompt_id_1": { "prompt": [...], "outputs": {...}, "status": {...} }, ... } ``` **字段说明:** - 返回历史记录字典,key 为 prompt_id - 每个记录包含: - prompt:提示数据 - outputs:输出数据 - status:状态信息 **错误码及错误信息:** - 无 **说明:** - 获取已执行任务的历史记录 --- ### 4.4 获取特定历史记录 **接口路径:** `GET /history/{prompt_id}` **HTTP 方法:** GET **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | prompt_id | string | 是 | 提示 ID(路径参数) | **请求头要求:** 无特殊要求 **响应数据结构:** ```json { "prompt": [...], "outputs": {...}, "status": {...} } ``` **字段说明:** - 同 4.3 **错误码及错误信息:** - 无(如果不存在返回空对象) **说明:** - 获取指定提示 ID 的历史记录 --- ### 4.5 获取队列 **接口路径:** `GET /queue` **HTTP 方法:** GET **请求参数:** 无 **请求头要求:** 无特殊要求 **响应数据结构:** ```json { "queue_running": [ [1, "prompt_id_1", {...}, {...}, [...]] ], "queue_pending": [ [2, "prompt_id_2", {...}, {...}, [...]], [3, "prompt_id_3", {...}, {...}, [...]] ] } ``` **字段说明:** - queue_running:正在运行的任务列表 - queue_pending:等待中的任务列表 - 每个任务是一个 5 元组: - [0]:优先级(数字) - [1]:prompt_id - [2]:prompt 数据 - [3]:extra_data - [4]:outputs_to_execute **错误码及错误信息:** - 无 **说明:** - 获取当前队列状态,包括运行中和等待中的任务 --- ### 4.6 提交提示 **接口路径:** `POST /prompt` **HTTP 方法:** POST **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | prompt | object | 是 | 工作流提示对象 | | prompt_id | string | 否 | 提示 ID,默认自动生成 UUID | | client_id | string | 否 | 客户端 ID | | number | number | 否 | 任务编号 | | front | boolean | 否 | 是否插入队列前面 | | partial_execution_targets | array | 否 | 部分执行目标 | | extra_data | object | 否 | 额外数据 | **请求头要求:** - Content-Type: application/json **响应数据结构:** ```json { "prompt_id": "550a8d1c-1234-4567-89ab-123456789abc", "number": 1, "node_errors": {} } ``` **字段说明:** - prompt_id:生成的提示 ID - number:任务编号 - node_errors:节点错误信息 **错误码及错误信息:** - 400:提示无效或验证失败 - error:错误信息 - node_errors:节点错误详情 **说明:** - 提交工作流任务到队列 - 自动验证提示的有效性 - 返回 prompt_id 用于后续查询 --- ### 4.7 队列操作 **接口路径:** `POST /queue` **HTTP 方法:** POST **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | clear | boolean | 否 | 是否清空队列 | | delete | array | 否 | 要删除的任务 ID 列表 | **请求头要求:** - Content-Type: application/json **响应数据结构:** - HTTP 200 OK **错误码及错误信息:** - 无 **说明:** - 清空队列或删除指定任务 - 可以同时执行清空和删除操作 --- ### 4.8 中断任务 **接口路径:** `POST /interrupt` **HTTP 方法:** POST **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | prompt_id | string | 否 | 要中断的任务 ID(可选) | **请求头要求:** - Content-Type: application/json **响应数据结构:** - HTTP 200 OK **错误码及错误信息:** - 无 **说明:** - 中断正在运行的任务 - 如果提供 prompt_id,只中断指定任务 - 如果不提供,中断所有正在运行的任务 --- ### 4.9 释放资源 **接口路径:** `POST /free` **HTTP 方法:** POST **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | unload_models | boolean | 否 | 是否卸载模型 | | free_memory | boolean | 否 | 是否释放内存 | **请求头要求:** - Content-Type: application/json **响应数据结构:** - HTTP 200 OK **错误码及错误信息:** - 无 **说明:** - 释放系统资源 - 可以卸载模型和/或释放内存 --- ### 4.10 历史记录操作 **接口路径:** `POST /history` **HTTP 方法:** POST **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | clear | boolean | 否 | 是否清空历史记录 | | delete | array | 否 | 要删除的历史记录 ID 列表 | **请求头要求:** - Content-Type: application/json **响应数据结构:** - HTTP 200 OK **错误码及错误信息:** - 无 **说明:** - 清空历史记录或删除指定历史记录 - 可以同时执行清空和删除操作 --- ## 5. 内部接口 ### 5.1 获取日志 **接口路径:** `GET /internal/logs` **HTTP 方法:** GET **请求参数:** 无 **请求头要求:** 无特殊要求 **响应数据结构:** ```json "2024-01-01 12:00:00 - Log message 1\n2024-01-01 12:01:00 - Log message 2\n..." ``` **字段说明:** - 返回格式化的日志字符串 **错误码及错误信息:** - 无 **说明:** - 获取系统日志(内部接口,仅供前端使用) --- ### 5.2 获取原始日志 **接口路径:** `GET /internal/logs/raw` **HTTP 方法:** GET **请求参数:** 无 **请求头要求:** 无特殊要求 **响应数据结构:** ```json { "entries": [ {"t": "2024-01-01 12:00:00", "m": "Log message 1"}, {"t": "2024-01-01 12:01:00", "m": "Log message 2"} ], "size": { "cols": 80, "rows": 24 } } ``` **字段说明:** - entries:日志条目数组 - t:时间戳 - m:消息内容 - size:终端大小 - cols:列数 - rows:行数 **错误码及错误信息:** - 无 **说明:** - 获取原始日志数据(内部接口) --- ### 5.3 订阅日志 **接口路径:** `PATCH /internal/logs/subscribe` **HTTP 方法:** PATCH **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | clientId | string | 是 | 客户端 ID | | enabled | boolean | 是 | 是否启用订阅 | **请求头要求:** - Content-Type: application/json **响应数据结构:** - HTTP 200 OK **错误码及错误信息:** - 无 **说明:** - 订阅或取消订阅日志推送(内部接口) --- ### 5.4 获取文件夹路径 **接口路径:** `GET /internal/folder_paths` **HTTP 方法:** GET **请求参数:** 无 **请求头要求:** 无特殊要求 **响应数据结构:** ```json { "checkpoints": "path/to/checkpoints", "loras": "path/to/loras", "embeddings": "path/to/embeddings", ... } ``` **字段说明:** - 返回所有文件夹类型的路径 **错误码及错误信息:** - 无 **说明:** - 获取所有文件夹路径(内部接口) --- ### 5.5 获取文件列表 **接口路径:** `GET /internal/files/{directory_type}` **HTTP 方法:** GET **请求参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | directory_type | string | 是 | 目录类型(output/input/temp) | **请求头要求:** 无特殊要求 **响应数据结构:** ```json [ "file1.png", "file2.png", ... ] ``` **字段说明:** - 返回指定目录中的文件列表(按修改时间倒序) **错误码及错误信息:** - 400:无效的目录类型 **说明:** - 获取指定目录中的文件列表(内部接口) --- ## 6. 任务提交与结果获取流程 ### 6.1 流程接口概述 ComfyUI 的任务提交与结果获取流程涉及以下核心接口: 1. **提交任务接口**:`POST /prompt` - 提交工作流任务 2. **查询任务接口**:`GET /api/jobs/{job_id}` - 查询任务状态和结果 3. **队列查询接口**:`GET /queue` - 查询队列状态 4. **历史记录接口**:`GET /history/{prompt_id}` - 获取已完成任务的详细信息 5. **文件查看接口**:`GET /view` - 查看生成的图片文件 **接口关联方式:** - 提交任务后,`POST /prompt` 返回 `prompt_id` - 使用 `prompt_id` 通过 `GET /api/jobs/{job_id}` 查询任务状态 - 任务完成后,通过 `GET /history/{prompt_id}` 获取完整结果 - 使用返回的文件信息通过 `GET /view` 下载或查看生成的图片 --- ### 6.2 任务状态说明 任务状态(status)有以下四种: | 状态值 | 英文 | 说明 | |--------|------|------| | pending | 待执行 | 任务在队列中等待执行 | | in_progress | 执行中 | 任务正在执行 | | completed | 已完成 | 任务执行成功 | | failed | 失败 | 任务执行失败 | **状态转换流程:** ``` pending → in_progress → completed ↓ failed ``` **状态判断逻辑:** - **pending**:任务在 `queue_pending` 列表中 - **in_progress**:任务在 `queue_running` 列表中 - **completed**:任务在历史记录中,且 `status.status_str == "success"` - **failed**:任务在历史记录中,且 `status.status_str == "error"` --- ### 6.3 完整任务生命周期调用示例 #### 步骤 1:提交任务 **请求:** ```bash POST /prompt Content-Type: application/json { "prompt": { "1": { "class_type": "CheckpointLoaderSimple", "inputs": { "ckpt_name": "v1-5-pruned-emaonly.safetensors" } }, "2": { "class_type": "CLIPTextEncode", "inputs": { "text": "a beautiful landscape", "clip": ["1", 1] } }, "3": { "class_type": "KSampler", "inputs": { "seed": 123456789, "steps": 20, "cfg": 7.0, "sampler_name": "euler", "scheduler": "normal", "denoise": 1.0, "model": ["1", 0], "positive": ["2", 0], "negative": ["2", 0], "latent_image": ["4", 0] } }, "4": { "class_type": "EmptyLatentImage", "inputs": { "width": 512, "height": 512, "batch_size": 1 } }, "5": { "class_type": "VAEDecode", "inputs": { "samples": ["3", 0], "vae": ["1", 2] } }, "6": { "class_type": "SaveImage", "inputs": { "filename_prefix": "ComfyUI", "images": ["5", 0] } } }, "client_id": "client_123" } ``` **响应:** ```json { "prompt_id": "550a8d1c-1234-4567-89ab-123456789abc", "number": 1, "node_errors": {} } ``` --- #### 步骤 2:查询任务状态 **请求:** ```bash GET /api/jobs/550a8d1c-1234-4567-89ab-123456789abc ``` **响应(执行中):** ```json { "id": "550a8d1c-1234-4567-89ab-123456789abc", "status": "in_progress", "priority": 1, "create_time": 1234567890000, "outputs_count": 0, "workflow_id": null } ``` **响应(已完成):** ```json { "id": "550a8d1c-1234-4567-89ab-123456789abc", "status": "completed", "priority": 1, "create_time": 1234567890000, "execution_start_time": 1234567891000, "execution_end_time": 1234567895000, "outputs": { "6": { "images": [ { "filename": "ComfyUI_00001.png", "subfolder": "", "type": "output" } ] } }, "execution_status": { "status_str": "success", "messages": [ ["execution_start", {"timestamp": 1234567891000}], ["execution_success", {"timestamp": 1234567895000}] ] }, "workflow": { "prompt": {...}, "extra_data": {...} }, "outputs_count": 1, "preview_output": { "filename": "ComfyUI_00001.png", "subfolder": "", "type": "output", "nodeId": "6", "mediaType": "images" }, "workflow_id": null } ``` **响应(失败):** ```json { "id": "550a8d1c-1234-4567-89ab-123456789abc", "status": "failed", "priority": 1, "create_time": 1234567890000, "execution_start_time": 1234567891000, "execution_end_time": 1234567892000, "execution_error": { "node_id": "3", "exception_type": "RuntimeError", "exception_message": "CUDA out of memory", "traceback": "..." }, "outputs_count": 0, "workflow_id": null } ``` --- #### 步骤 3:查看生成的图片 **请求:** ```bash GET /view?filename=ComfyUI_00001.png&type=output&subfolder= ``` **响应:** - 返回图片文件(PNG 格式) **请求(带预览参数):** ```bash GET /view?filename=ComfyUI_00001.png&type=output&preview=webp;90 ``` **响应:** - 返回 WebP 格式的预览图片(质量 90) --- #### 步骤 4:查询历史记录 **请求:** ```bash GET /history/550a8d1c-1234-4567-89ab-123456789abc ``` **响应:** ```json { "prompt": [ 1, "550a8d1c-1234-4567-89ab-123456789abc", { "1": { "class_type": "CheckpointLoaderSimple", "inputs": {...} }, ... }, { "client_id": "client_123", "create_time": 1234567890000 }, [...] ], "outputs": { "6": { "images": [ { "filename": "ComfyUI_00001.png", "subfolder": "", "type": "output" } ] } }, "status": { "status_str": "success", "messages": [...] } } ``` --- #### 步骤 5:查询队列状态(可选) **请求:** ```bash GET /queue ``` **响应:** ```json { "queue_running": [ [1, "550a8d1c-1234-4567-89ab-123456789abc", {...}, {...}, [...]] ], "queue_pending": [ [2, "another_prompt_id", {...}, {...}, [...]] ] } ``` --- ### 完整流程伪代码示例 ```python import requests import time # 1. 提交任务 def submit_task(workflow): response = requests.post( "http://localhost:8188/prompt", json={"prompt": workflow, "client_id": "my_client"} ) return response.json()["prompt_id"] # 2. 轮询任务状态 def wait_for_completion(prompt_id, poll_interval=1, timeout=300): start_time = time.time() while time.time() - start_time < timeout: response = requests.get(f"http://localhost:8188/api/jobs/{prompt_id}") job = response.json() if job["status"] == "completed": return job elif job["status"] == "failed": raise Exception(f"Task failed: {job.get('execution_error')}") time.sleep(poll_interval) raise TimeoutError("Task timed out") # 3. 获取生成的图片 def get_image(filename, subfolder=""): response = requests.get( "http://localhost:8188/view", params={ "filename": filename, "type": "output", "subfolder": subfolder } ) return response.content # 完整流程 workflow = { "1": { "class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": "v1-5-pruned-emaonly.safetensors"} }, # ... 其他节点 } # 提交任务 prompt_id = submit_task(workflow) print(f"Task submitted: {prompt_id}") # 等待完成 job = wait_for_completion(prompt_id) print(f"Task completed: {job}") # 获取图片 for node_id, outputs in job["outputs"].items(): for image in outputs.get("images", []): image_data = get_image(image["filename"], image["subfolder"]) with open(image["filename"], "wb") as f: f.write(image_data) print(f"Saved: {image['filename']}") ``` --- ### WebSocket 实时监听(可选) 除了轮询,还可以使用 WebSocket 实时接收任务状态更新: ```javascript const ws = new WebSocket('ws://localhost:8188/ws?clientId=my_client'); ws.onopen = () => { console.log('WebSocket connected'); }; ws.onmessage = (event) => { const data = JSON.parse(event.data); if (data.type === 'status') { console.log('Queue status:', data.data); } else if (data.type === 'executing') { console.log('Executing node:', data.data.node); } else if (data.type === 'progress') { console.log('Progress:', data.data); } else if (data.type === 'execution_success') { console.log('Execution successful:', data.data); } else if (data.type === 'execution_error') { console.error('Execution error:', data.data); } }; ``` --- ## 附录 ### API 前缀说明 ComfyUI 支持两种 API 路径格式: 1. **无前缀**:`/prompt`, `/queue`, `/history` 等 2. **带前缀**:`/api/prompt`, `/api/queue`, `/api/history` 等 两种格式都可以使用,建议使用带 `/api` 前缀的格式以便于代理和转发。 ### 错误处理 所有接口在发生错误时都会返回相应的 HTTP 状态码和错误信息: - **400**:请求参数错误 - **403**:访问权限不足 - **404**:资源不存在 - **500**:服务器内部错误 错误响应格式: ```json { "error": "Error message", "node_errors": {} } ``` ### 认证 ComfyUI 默认不启用认证。如果需要启用认证,请参考相关配置文档。 ### 速率限制 ComfyUI 默认不实施速率限制。在生产环境中,建议通过反向代理(如 Nginx)实施速率限制。 --- **文档版本:** 1.0 **最后更新:** 2026-03-12 **ComfyUI 版本:** 0.2.0+