Appearance
任务管理 — 查询状态、下载结果、上传图片、查询队列
所有 ComfyUI 图像/视频生成任务共用以下接口,与具体生成模型无关。
ComfyUI 任务为异步执行:提交工作流 → 轮询 tasks/{prompt_id} 直到 completed=true → 下载结果。
bash
export GW="https://ai.ospreyai.cn"
export API_KEY="sk-your-api-key"接口清单
| 用途 | 方法 | 路径 |
|---|---|---|
| 查询任务状态 | GET | /api/v1/ai/tasks/{prompt_id} |
| 下载结果文件 | GET | /api/v1/ai/image/view/ |
| 上传图片 | POST | /api/v1/upload |
| 查询队列 | GET | /api/v1/ai/queue |
查询任务状态
GET /api/v1/ai/tasks/{prompt_id}
Authorization: Bearer sk-xxxbash
curl -H "Authorization: Bearer $API_KEY" "$GW/api/v1/ai/tasks/0871f625-65f6-4d2f-abd8-0b248dafa58f"响应(进行中):
json
{
"0871f625-...": {
"prompt": [...],
"outputs": {},
"status": { "status_str": "success", "completed": false }
}
}响应(已完成):
json
{
"0871f625-...": {
"status": { "status_str": "success", "completed": true },
"outputs": {
"9": {
"images": [
{ "filename": "output_00001_.png", "subfolder": "", "type": "output" }
]
}
}
}
}图片 vs 视频的输出字段:
- 图片:
outputs[].images[],文件名.png- 视频:
outputs[].images[](同一字段),文件名.mp4,同节点有animated: [true]标记- 下载视频时
subfolder=video必须带上
缓存坑:若提交的工作流与历史完全相同(尤其 seed 相同),ComfyUI 会命中
execution_cached直接返回,outputs可能为空。提交时换个随机 seed 可避免。
下载结果文件
GET /api/v1/ai/image/view/?filename={filename}&type={type}&subfolder={subfolder}
Authorization: Bearer sk-xxx参数值来自任务状态响应中的 outputs 字段。
bash
# 下载图片(subfolder 可为空)
curl -H "Authorization: Bearer $API_KEY" \
"$GW/api/v1/ai/image/view/?filename=output_00001_.png&type=output&subfolder=" \
-o output.png
# 下载视频(subfolder=video 必须带上)
curl -H "Authorization: Bearer $API_KEY" \
"$GW/api/v1/ai/image/view/?filename=my_video_00001_.mp4&type=output&subfolder=video" \
-o result.mp4上传图片
用于图片编辑 / 图生视频任务的输入图片上传。
POST /api/v1/upload
Content-Type: multipart/form-data
Authorization: Bearer sk-xxxbash
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/upload" \
-F "image=@/path/to/image.png" \
-F "overwrite=true"响应:
json
{"name": "image.png", "subfolder": "", "type": "input"}最大文件大小: 50MB。返回的 name 填入工作流的 LoadImage 节点 image 字段。
Python 上传示例
python
import requests
GW = "https://ai.ospreyai.cn"
API_KEY = "sk-your-api-key"
with open("/path/to/image.png", "rb") as f:
resp = requests.post(
f"{GW}/api/v1/upload",
headers={"Authorization": f"Bearer {API_KEY}"},
files={"image": ("image.png", f, "image/png")},
data={"overwrite": "true"},
)
print(resp.json()) # {"name": "image.png", "subfolder": "", "type": "input"}查询队列状态
GET /api/v1/ai/queue
Authorization: Bearer sk-xxxbash
curl -H "Authorization: Bearer $API_KEY" "$GW/api/v1/ai/queue"响应:
json
{
"queue_running": [],
"queue_pending": []
}完整调用流程示例
python
import json, time, urllib.request
GW = "https://ai.ospreyai.cn"
API_KEY = "sk-your-api-key"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
# 1. 提交任务(以文生图为例)
nodes = { /* 工作流节点 */ }
req = urllib.request.Request(
f"{GW}/api/v1/ai/image/generate",
data=json.dumps({"prompt": nodes}).encode(),
headers=HEADERS, method="POST",
)
prompt_id = json.loads(urllib.request.urlopen(req, timeout=30).read())["prompt_id"]
# 2. 轮询直到完成
while True:
r = urllib.request.Request(f"{GW}/api/v1/ai/tasks/{prompt_id}", headers=HEADERS)
task = json.loads(urllib.request.urlopen(r, timeout=15).read())[prompt_id]
if task["status"].get("completed"):
break
time.sleep(5)
# 3. 下载结果
for out in task["outputs"].values():
for img in out.get("images", []):
url = f"{GW}/api/v1/ai/image/view/?filename={img['filename']}&type={img['type']}&subfolder={img.get('subfolder','')}"
req = urllib.request.Request(url, headers=HEADERS)
open(img["filename"], "wb").write(urllib.request.urlopen(req, timeout=120).read())常见问题
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
任务一直 completed: false | 排队中或首帧加载慢 | 首次约 30s 加载;查 /api/v1/ai/queue 看队列 |
任务 success 但 outputs 为空 | 命中 ComfyUI 缓存(execution_cached) | 提交时换随机 seed |
| 下载 404 | 参数缺失 | filename / type / subfolder 必须与状态响应完全一致;视频必带 subfolder=video |
| outputs 里找不到视频 | 找错字段 | 视频在 outputs[].images(文件名 .mp4 + animated 标记),不是 gifs |