通义万象2.2开源了,5B模型具有文生视频和图生视频的能力。这里介绍通过ComfyUI部署wan2.2并开放API,通过url返回生成的视频。环境配置,api的worlflow配置文件获取,ComfyUI启动,配置url路径参考这里。
文生视频
这里直接给出API启动脚本:
python
from fastapi import FastAPI, HTTPException, Header
from fastapi import FastAPI, HTTPException, Header
from pydantic import BaseModel
import requests
import copy
import json
import os
import urllib.parse
import time
import base64
API_KEY = "12345"
# ---------------- 配置 ----------------
COMFYUI_API_URL = "http://127.0.0.1:8188" # ComfyUI API 地址
WORKFLOW_FILE = "text_to_video_wan22_5B_API.json" # 固定 workflow 文件
OUTPUT_DIR = "output_videos"
POLL_INTERVAL = 2 # 秒
STATIC_DIR = "/var/www/static" # 存储视频的目录
SERVER_BASE_URL = "http://server_ip:9001" # 对外访问的服务器地址
os.makedirs(OUTPUT_DIR, exist_ok=True)
os.makedirs(STATIC_DIR, exist_ok=True)
# ---------------- 读取 workflow ----------------
with open(WORKFLOW_FILE, "r", encoding="utf-8") as f:
base_workflow = json.load(f)
# ---------------- 请求体定义 ----------------
class GenerateVideoRequest(BaseModel):
positive: str
negative: str = ""
height: int = 704
width: int = 1280
length: int = 121 # 视频帧数
fps: int = 24
# ---------------- FastAPI 实例 ----------------
app = FastAPI(title="ComfyUI Video API Server")
# ---------------- 生成接口 ----------------
@app.post("/generate_video")
def generate_video(req: GenerateVideoRequest, x_api_key: str = Header(None)):
if x_api_key != API_KEY:
raise HTTPException(status_code=401, detail="Invalid API Key")
workflow = copy.deepcopy(base_workflow)
# 修改 workflow 中的输入参数
workflow["6"]["inputs"]["text"] = req.positive
workflow["7"]["inputs"]["text"] = req.negative
workflow["55"]["inputs"]["width"] = req.width
workflow["55"]["inputs"]["height"] = req.height
workflow["55"]["inputs"]["length"] = req.length
workflow["47"]["inputs"]["fps"] = req.fps # 保存 WEBM
workflow["28"]["inputs"]["fps"] = float(req.fps) # 保存 WEBP 动图
# 提交任务
resp = requests.post(f"{COMFYUI_API_URL}/prompt", json={"prompt": workflow})
resp.raise_for_status()
prompt_id = resp.json()["prompt_id"]
public_urls = []
while True:
history = requests.get(f"{COMFYUI_API_URL}/history/{prompt_id}").json()
if prompt_id in history:
outputs = history[prompt_id].get("outputs", {})
for node_id, output_data in outputs.items():
if "images" in output_data: # 视频也会走这里
for file in output_data["images"]:
filename = file["filename"]
subfolder = file.get("subfolder", "")
filetype = file.get("type", "output") # webm / webp / png
file_url = (
f"{COMFYUI_API_URL}/view"
f"?filename={urllib.parse.quote(filename)}"
f"&subfolder={urllib.parse.quote(subfolder)}"
f"&type={urllib.parse.quote(filetype)}"
)
file_data = requests.get(file_url).content
save_path = os.path.join(STATIC_DIR, filename)
with open(save_path, "wb") as f:
f.write(file_data)
public_url = f"{SERVER_BASE_URL}/static/{filename}"
public_urls.append(public_url)
if public_urls:
break
time.sleep(POLL_INTERVAL)
return {"prompt_id": prompt_id, "video_urls": public_urls}
将上面的脚本保存为serve_fastapi.py,其中COMFYUI_API_URL
是启动的ComfyUI服务,WORKFLOW_FILE
是保存的workflow配置文件。使用下面的命令启动API:
bash
uvicorn serve_fastapi:app --host 0.0.0.0 --port 9002
这里给出python访问api的脚本:
python
import requests
import base64
from PIL import Image
from io import BytesIO
headers = {"x-api-key": "12345"}
resp = requests.post(
"http://server_ip:9002/generate_video",
headers=headers,
json={
"positive": "Two anthropomorphic cats in comfy boxing gear and bright gloves fight intensely on a spotlighted stage.",
"negative": "色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走",
"height": 512,
"width": 768,
"length": 73, # 帧数,帧率固定为24 fps
}
)
print(resp.json())
api会返回可访问的生成视频的url。
图生视频
直接给出api启动脚本,与上面不同的就是图生视频需要多传如一个图像,这里以url的形式传入:
python
from fastapi import FastAPI, HTTPException, Header
from pydantic import BaseModel
import requests
import copy
import json
import os
import urllib.parse
import time
import base64
import tempfile
API_KEY = "12345"
# ---------------- 配置 ----------------
COMFYUI_API_URL = "http://127.0.0.1:8188" # ComfyUI API 地址
WORKFLOW_FILE = "image_to_video_wan22_5B_api.json" # 你准备好的图生视频 workflow
OUTPUT_DIR = "output_videos"
POLL_INTERVAL = 2 # 秒
STATIC_DIR = "/var/www/static" # 存储视频的目录
SERVER_BASE_URL = "http://server_ip:9001" # 对外访问的服务器地址
os.makedirs(OUTPUT_DIR, exist_ok=True)
os.makedirs(STATIC_DIR, exist_ok=True)
# ---------------- 读取 workflow ----------------
with open(WORKFLOW_FILE, "r", encoding="utf-8") as f:
base_workflow = json.load(f)
# ---------------- 请求体定义 ----------------
class GenerateVideoRequest(BaseModel):
image_url: str # 输入图像 URL
positive: str = "" # 可选的正向 prompt
negative: str = "" # 可选的负向 prompt
height: int = 704
width: int = 1280
length: int = 121 # 视频帧数
fps: int = 24
# ---------------- FastAPI 实例 ----------------
app = FastAPI(title="ComfyUI Image-to-Video API Server")
# ---------------- 生成接口 ----------------
@app.post("/generate_video_i2v")
def generate_video(req: GenerateVideoRequest, x_api_key: str = Header(None)):
if x_api_key != API_KEY:
raise HTTPException(status_code=401, detail="Invalid API Key")
workflow = copy.deepcopy(base_workflow)
# ----------- 下载输入图像到临时目录,并传给 ComfyUI -----------
resp = requests.get(req.image_url)
if resp.status_code != 200:
raise HTTPException(status_code=400, detail="Failed to download input image")
tmp_path = os.path.join(STATIC_DIR, "input_image.png")
with open(tmp_path, "wb") as f:
f.write(resp.content)
# 替换 workflow 的图像节点 (假设节点 id 是 "57")
workflow["57"]["inputs"]["image"] = tmp_path
# 修改其他输入
if "6" in workflow: # 正向 prompt 节点
workflow["6"]["inputs"]["text"] = req.positive
if "7" in workflow: # 负向 prompt 节点
workflow["7"]["inputs"]["text"] = req.negative
if "55" in workflow:
workflow["55"]["inputs"]["width"] = req.width
workflow["55"]["inputs"]["height"] = req.height
workflow["55"]["inputs"]["length"] = req.length
if "47" in workflow:
workflow["47"]["inputs"]["fps"] = req.fps # 保存 WEBM
if "28" in workflow:
workflow["28"]["inputs"]["fps"] = float(req.fps) # 保存 WEBP 动图
# 提交任务
resp = requests.post(f"{COMFYUI_API_URL}/prompt", json={"prompt": workflow})
resp.raise_for_status()
prompt_id = resp.json()["prompt_id"]
public_urls = []
while True:
history = requests.get(f"{COMFYUI_API_URL}/history/{prompt_id}").json()
if prompt_id in history:
outputs = history[prompt_id].get("outputs", {})
for node_id, output_data in outputs.items():
if "images" in output_data: # 视频也会走这里
for file in output_data["images"]:
filename = file["filename"]
subfolder = file.get("subfolder", "")
filetype = file.get("type", "output")
file_url = (
f"{COMFYUI_API_URL}/view"
f"?filename={urllib.parse.quote(filename)}"
f"&subfolder={urllib.parse.quote(subfolder)}"
f"&type={urllib.parse.quote(filetype)}"
)
file_data = requests.get(file_url).content
save_path = os.path.join(STATIC_DIR, filename)
with open(save_path, "wb") as f:
f.write(file_data)
public_url = f"{SERVER_BASE_URL}/static/{filename}"
public_urls.append(public_url)
if public_urls:
break
time.sleep(POLL_INTERVAL)
return {"prompt_id": prompt_id, "video_urls": public_urls}
将上面的脚本保存为serve_fastapi_i2v.py,其中COMFYUI_API_URL
是启动的ComfyUI服务,WORKFLOW_FILE
是保存的workflow配置文件。使用下面的命令启动API:
bash
uvicorn serve_fastapi:app --host 0.0.0.0 --port 9003
这里给出python调用api的示例:
python
import requests
headers = {"x-api-key": "12345"}
resp = requests.post(
"http://127.0.0.1:9003/generate_video_i2v",
headers=headers,
json={
"image_url": "https://comfyanonymous.github.io/ComfyUI_examples/chroma/fennec_girl_hug.png",
"positive": "a cute anime girl with fennec ears and a fluffy tail walking in a beautiful field",
"negative": "色调艳丽,过曝,静态,细节模糊不清,字幕,风格,作品,画作,画面,静止,整体发灰,最差质量,低质量,JPEG压缩残留,丑陋的,残缺的,多余的手指,画得不好的手部,画得不好的脸部,畸形的,毁容的,形态畸形的肢体,手指融合,静止不动的画面,杂乱的背景,三条腿,背景人很多,倒着走",
"height": 704,
"width": 1280,
"length": 141, # 帧数,帧率固定为24 fps
}
)
print(resp.json())
图生视频的图像用url进行传入,如果是图像就在服务器上,可以直接使用路径,如果图像在本地主机,可以传到某个可访问的云服务上,开放url。api会返回生成视频的url。