GPU API工具箱 API 文档Proxy Base URL(画布内部)视频类
视频脱衣
视频脱衣组合 GPU API 的请求、阶段、轮询与错误说明
文档更新时间:2026年09月08日 12时53分18秒(UTC+8)
视频脱衣(组合 API)
最后更新:2026-09-07
| 项目 | 值 |
|---|---|
model | video-undress |
| 输入 | 1 个源视频 |
| 内部 Scheduler | POST /v1/video-undress |
| 输出 | 1 个经过媒体校验的视频 |
组合流程
首帧提取 → Krea2 图片脱衣 → 新首帧 → Wan2.1 SCAIL2
创建任务
curl -X POST "$BASE_URL/api/proxy/v1/videos" \
-H "Cookie: ic_session=$IC_SESSION" \
-H "X-IC-Operation-ID: $(uuidgen)" \
-F "model=video-undress" \
-F "prompt=保持原视频动作、镜头运动和节奏" \
-F "seed=12345" \
-F "input_reference[]=@source.mp4"源视频支持 MP4/MOV、最大 500MB,并须包含可解码音轨;人物图支持 JPG/PNG/BMP/WEBP、单张最大 30MB。Proxy 会按 MIME 分类,不把文件名后缀当作唯一判断。
状态与结果
- 创建成功保存返回的
id。 POST /api/proxy/v1/videos/{id}轮询pending/running/completed/failed。- 完成后调用
GET /api/proxy/v1/videos/{id}/content下载视频。 - 取消调用
POST /api/proxy/v1/videos/{id}/cancel;只有服务端确认取消后才视为终止。
完整 Python 调用
下面代码可直接保存为 call_video_undress.py。先执行 pip install requests,再设置 BASE_URL、IC_SESSION 并准备示例媒体。代码会提交任务、轮询、下载最终 MP4;若存在首帧预处理结果,也会下载为 intermediate.png。
import mimetypes
import os
import time
import uuid
from contextlib import ExitStack
from pathlib import Path
import requests
BASE_URL = os.environ.get("BASE_URL", "https://ic.xshow.live").rstrip("/")
IC_SESSION = os.environ["IC_SESSION"]
MODEL = "video-undress"
POLL_SECONDS = 5
TIMEOUT_SECONDS = 6 * 60 * 60
session = requests.Session()
session.cookies.set("ic_session", IC_SESSION)
def mime(path: str) -> str:
value = mimetypes.guess_type(path)[0]
if not value:
raise ValueError(f"无法识别媒体 MIME: {path}")
return value
def checked(response: requests.Response) -> requests.Response:
if not response.ok:
raise RuntimeError(f"HTTP {response.status_code}: {response.text[:1000]}")
return response
with ExitStack() as stack:
files = [
("input_reference[]", (Path("source.mp4").name, stack.enter_context(open("source.mp4", "rb")), mime("source.mp4")))
]
created = checked(session.post(
f"{BASE_URL}/api/proxy/v1/videos",
headers={"X-IC-Operation-ID": str(uuid.uuid4())},
data={
"model": MODEL,
"prompt": "保持原视频动作、镜头运动和节奏",
"seed": "12345",
},
files=files,
timeout=1800,
)).json()
task_id = created.get("id") or (created.get("data") or {}).get("id")
if not task_id:
raise RuntimeError(f"创建响应缺少任务 ID: {created}")
print("task_id:", task_id)
deadline = time.time() + TIMEOUT_SECONDS
while time.time() < deadline:
state = checked(session.post(
f"{BASE_URL}/api/proxy/v1/videos/{task_id}",
timeout=60,
)).json()
status = str(state.get("status") or (state.get("data") or {}).get("status") or "pending").lower()
print("status:", status)
if status == "completed":
video = checked(session.get(
f"{BASE_URL}/api/proxy/v1/videos/{task_id}/content",
timeout=1800,
))
Path("result.mp4").write_bytes(video.content)
print("saved: result.mp4")
payload = state.get("data") if isinstance(state.get("data"), dict) else state
if payload.get("intermediate_image_available") is True:
intermediate = checked(session.get(
f"{BASE_URL}/api/proxy/v1/videos/{task_id}/intermediate",
timeout=600,
))
Path("intermediate.png").write_bytes(intermediate.content)
print("saved: intermediate.png")
break
if status in {"failed", "cancelled", "canceled", "expired"}:
raise RuntimeError(f"任务失败: {state}")
time.sleep(POLL_SECONDS)
else:
raise TimeoutError(f"任务 {task_id} 超过 {TIMEOUT_SECONDS} 秒仍未完成")阶段失败
错误会保留首帧提取、图片预编辑、SCAIL2 提交、GPU 执行或结果校验阶段的真实原因。400 通常是媒体数量/格式错误,503 是工作流未就绪,502 是上游或结果媒体校验失败。