Appearance
图生视频 — Wan2.2 I2V
网关地址:
https://ai.ospreyai.cn(公网) 模型:wan2.2_i2v_high_noise_14B+wan2.2_i2v_low_noise_14B(4步加速 LightX2V LoRA) 无需后端 Bearer Token
概述
使用 Wan2.2 I2V + LightX2V 4步加速 工作流,仅需 4 步采样即可生成约 5 秒视频。任务异步执行:提交工作流 → 轮询状态 → 下载结果。任务状态查询、结果下载等通用接口见 任务管理。
前置条件: 需先通过 /api/v1/upload 上传输入图片。
bash
export GW="https://ai.ospreyai.cn"
export API_KEY="sk-your-api-key"接口清单
| 用途 | 方法 | 路径 |
|---|---|---|
| 上传输入图片 | POST | /api/v1/upload |
| 提交视频任务 | POST | /api/v1/ai/video/generate |
| 查询任务状态 | GET | /api/v1/ai/tasks/{prompt_id} |
| 下载结果文件 | GET | /api/v1/ai/image/view/ |
| 查询队列 | GET | /api/v1/ai/queue |
提交任务后异步生成,需轮询
tasks/{prompt_id}直到status.completed=true,再下载。视频输出在任务状态outputs的images字段(文件名 .mp4,同节点animated标记为视频),下载时需带subfolder=video。
提交视频生成任务
POST /api/v1/ai/video/generate
Content-Type: application/json
Authorization: Bearer sk-xxx1. 上传图片
bash
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/upload" \
-F "image=@/path/to/input.png" \
-F "overwrite=true"
# 返回: {"name": "input.png", "subfolder": "", "type": "input"}2. 提交视频工作流
bash
curl -H "Authorization: Bearer $API_KEY" -X POST "$GW/api/v1/ai/video/generate" \
-H "Content-Type: application/json" \
-d '{
"prompt": {
"84": {"inputs": {"clip_name": "umt5_xxl_fp8_e4m3fn_scaled.safetensors", "type": "wan", "device": "default"}, "class_type": "CLIPLoader"},
"85": {"inputs": {"add_noise": "disable", "noise_seed": 0, "steps": 4, "cfg": 1, "sampler_name": "euler", "scheduler": "simple", "start_at_step": 2, "end_at_step": 4, "return_with_leftover_noise": "disable", "model": ["103", 0], "positive": ["98", 0], "negative": ["98", 1], "latent_image": ["86", 0]}, "class_type": "KSamplerAdvanced"},
"86": {"inputs": {"add_noise": "enable", "noise_seed": 42, "steps": 4, "cfg": 1, "sampler_name": "euler", "scheduler": "simple", "start_at_step": 0, "end_at_step": 2, "return_with_leftover_noise": "enable", "model": ["104", 0], "positive": ["98", 0], "negative": ["98", 1], "latent_image": ["98", 2]}, "class_type": "KSamplerAdvanced"},
"87": {"inputs": {"samples": ["85", 0], "vae": ["90", 0]}, "class_type": "VAEDecode"},
"89": {"inputs": {"text": "色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸变的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走", "clip": ["84", 0]}, "class_type": "CLIPTextEncode"},
"90": {"inputs": {"vae_name": "wan_2.1_vae.safetensors"}, "class_type": "VAELoader"},
"93": {"inputs": {"text": "A bird spreading its wings and flying away", "clip": ["84", 0]}, "class_type": "CLIPTextEncode"},
"94": {"inputs": {"fps": 16, "images": ["87", 0]}, "class_type": "CreateVideo"},
"95": {"inputs": {"unet_name": "wan2.2_i2v_high_noise_14B_fp8_scaled.safetensors", "weight_dtype": "default"}, "class_type": "UNETLoader"},
"96": {"inputs": {"unet_name": "wan2.2_i2v_low_noise_14B_fp8_scaled.safetensors", "weight_dtype": "default"}, "class_type": "UNETLoader"},
"97": {"inputs": {"image": "input.png"}, "class_type": "LoadImage"},
"98": {"inputs": {"width": 640, "height": 640, "length": 81, "batch_size": 1, "positive": ["93", 0], "negative": ["89", 0], "vae": ["90", 0], "start_image": ["97", 0]}, "class_type": "WanImageToVideo"},
"101": {"inputs": {"lora_name": "wan2.2_i2v_lightx2v_4steps_lora_v1_high_noise.safetensors", "strength_model": 1.0, "model": ["95", 0]}, "class_type": "LoraLoaderModelOnly"},
"102": {"inputs": {"lora_name": "wan2.2_i2v_lightx2v_4steps_lora_v1_low_noise.safetensors", "strength_model": 1.0, "model": ["96", 0]}, "class_type": "LoraLoaderModelOnly"},
"103": {"inputs": {"shift": 5.0, "model": ["102", 0]}, "class_type": "ModelSamplingSD3"},
"104": {"inputs": {"shift": 5.0, "model": ["101", 0]}, "class_type": "ModelSamplingSD3"},
"108": {"inputs": {"filename_prefix": "video/my_video", "format": "auto", "codec": "auto", "video-preview": "", "video": ["94", 0]}, "class_type": "SaveVideo"}
}
}'响应:
json
{"prompt_id": "03464627-3b48-43fe-91b9-ca7c779ba618", "number": 130, "node_errors": {}}关键节点参数
| 节点 | 字段 | 说明 | 推荐值 |
|---|---|---|---|
| 97 | image | 输入图片文件名(需先上传) | 上传返回的 name |
| 93 | text | 正向提示词(英文动作描述) | — |
| 98 | width / height | 视频尺寸 | 640 × 640 |
| 98 | length | 视频帧数(81帧≈5秒@16fps) | 81 |
| 86 | noise_seed | 随机种子 | 任意整数 |
| 108 | filename_prefix | 输出文件名前缀 | "video/xxx" |
提示词技巧
- 英文动作描述优先:
A bird spreading its wings and flying away - 动作 + 主体 + 场景:
A girl walking through a rainy street, holding an umbrella - 描述要体现动态,避免静态描述(如
a beautiful girl不如a beautiful girl dancing)
下载结果
视频输出在任务状态 outputs 的 images 字段(文件名是 .mp4),同节点有 animated 布尔列表标记是视频。
bash
# 注意 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输出: MP4 视频,640×640, 81帧, 16fps, 约5秒。
Python 调用示例
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. 上传图片(参考「任务管理」页上传示例)
# 2. 提交工作流
nodes = {
"84": {"inputs": {"clip_name": "umt5_xxl_fp8_e4m3fn_scaled.safetensors", "type": "wan", "device": "default"}, "class_type": "CLIPLoader"},
# ...其余节点同上 curl 示例...
}
nodes["93"]["inputs"]["text"] = "A bird spreading its wings and flying away"
nodes["97"]["inputs"]["image"] = "input.png"
nodes["86"]["inputs"]["noise_seed"] = 42 # 避免缓存
req = urllib.request.Request(
f"{GW}/api/v1/ai/video/generate",
data=json.dumps({"prompt": nodes}).encode(),
headers=HEADERS, method="POST",
)
prompt_id = json.loads(urllib.request.urlopen(req, timeout=30).read())["prompt_id"]
# 3. 轮询
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)
# 4. 下载(视频在 outputs 的 images 字段,文件名 .mp4,subfolder=video)
for out in task["outputs"].values():
for g in out.get("images", []):
if not g["filename"].endswith(".mp4"):
continue
url = f"{GW}/api/v1/ai/image/view/?filename={g['filename']}&type=output&subfolder={g.get('subfolder','')}"
req = urllib.request.Request(url, headers=HEADERS)
open(g["filename"], "wb").write(urllib.request.urlopen(req, timeout=120).read())常见问题
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 401 Unauthorized | API Key 错误/未传 | 检查 Authorization: Bearer sk-xxx |
| 500 on generate | 工作流 JSON 格式错 | 用 {"prompt": {...}},节点连接用 ["id", slot] |
任务 success 但 outputs 为空 | 命中 ComfyUI 缓存(execution_cached) | 提交时换个随机 noise_seed |
| 下载 404 | 没带 subfolder=video | 视频在 output 的 video/ 子目录,URL 必须带 subfolder=video |
| outputs 里找不到视频 | 找错字段 | 视频在 outputs[].images(文件名 .mp4 + animated 标记),不是 gifs |
详细文档见 ComfyUI 视频生成 Skill。