视频系列Vidu 视频
Vidu Python 轮询与下载
创建 Vidu Q3 任务,保存公共 ID,使用有界轮询处理终态,并下载生成视频;支持原生和统一格式。
下面的完整示例通过原生接口创建一条 Q3 Turbo 文生视频任务。每次创建都会产生独立的计费任务;程序不会自动重试创建。先安装依赖并设置 ModelSell 凭据:
pip install requests
export MODELSELL_BASE_URL="https://api.modelsell.com"
export MODELSELL_API_KEY="<your-modelsell-api-key>"import os
import time
from pathlib import Path
from urllib.parse import quote, urlparse
import requests
BASE = os.environ.get("MODELSELL_BASE_URL", "https://api.modelsell.com").rstrip("/")
KEY = os.environ["MODELSELL_API_KEY"]
HEADERS = {"Authorization": f"Bearer {KEY}"}
PROMPT = "A red ceramic teapot on a wooden table in warm morning light."
def create_task(path, body, family="native"):
response = requests.post(BASE + path, headers=HEADERS, json=body, timeout=300)
response.raise_for_status()
payload = response.json()
task_id = payload.get("task_id") if family == "native" else payload.get("id")
if not isinstance(task_id, str) or not task_id.startswith("task_"):
raise RuntimeError("Creation returned no ModelSell public task ID")
print(f"Save this task ID: {task_id}", flush=True)
return task_id
def wait_for_task(task_id, family="native", max_wait=1800, interval=12):
escaped_id = quote(task_id, safe="")
path = (f"/ent/v2/tasks/{escaped_id}/creations"
if family == "native" else f"/v1/videos/{escaped_id}")
waiting = ({"created", "queueing", "processing"} if family == "native"
else {"queued", "in_progress"})
success = "success" if family == "native" else "completed"
deadline = time.monotonic() + max_wait
while time.monotonic() < deadline:
remaining = deadline - time.monotonic()
response = requests.get(
BASE + path, headers=HEADERS,
timeout=min(120, max(0.1, remaining)),
)
response.raise_for_status()
task = response.json()
state = task.get("state" if family == "native" else "status")
if state == success:
return task
if state == "failed":
detail = task.get("err_code") if family == "native" else task.get("error")
raise RuntimeError(f"Task {task_id} failed: {detail}")
if state not in waiting:
raise RuntimeError(f"Unexpected state {state!r}; retain ID {task_id}")
print(f"{task_id}: {state}", flush=True)
time.sleep(min(interval, max(0, deadline - time.monotonic())))
raise TimeoutError(f"Local wait expired; query this task later: {task_id}")
def result_url(task, family="native"):
if family == "native":
creations = task.get("creations") or []
url = creations[0].get("url") if creations else None
else:
url = task.get("video_url") or (task.get("metadata") or {}).get("url")
if not isinstance(url, str) or urlparse(url).scheme not in {"http", "https"}:
raise RuntimeError("Successful task has no downloadable video URL")
return url
def download_video(url, destination):
target = Path(destination)
temporary = target.with_suffix(target.suffix + ".part")
try:
# Result URLs may use a CDN: do not send the ModelSell API Key.
with requests.get(url, stream=True, timeout=300) as response:
response.raise_for_status()
with temporary.open("wb") as output:
for chunk in response.iter_content(65536):
if chunk:
output.write(chunk)
temporary.replace(target)
except Exception:
temporary.unlink(missing_ok=True)
raise
if __name__ == "__main__":
# Set MODELSELL_TASK_ID to resume polling without creating another task.
task_id = os.environ.get("MODELSELL_TASK_ID")
if not task_id:
task_id = create_task("/ent/v2/text2video", {
"model": "viduq3-turbo", "prompt": PROMPT,
"duration": 5, "resolution": "720p", "aspect_ratio": "16:9",
"audio": False, "is_rec": False, "watermark": False,
})
task = wait_for_task(task_id)
download_video(result_url(task), "vidu-output.mp4")轮询每 12 秒执行一次,最多等待 30 分钟。网络错误、HTTP 错误、失败终态或未知状态都会结束示例。保存程序打印的 task_… 公共 ID;超时不代表取消或退款,稍后可用同一 API Key 继续查询。
要继续查询已有任务而不创建新任务:
export MODELSELL_TASK_ID="<previously-returned-task-id>"
python vidu_example.py将完整示例保存为 vidu_example.py 后运行。确认需要创建新任务时再取消该环境变量。原生查询的响应 ID 字段为 id,创建响应则为 task_id,不要混淆。
改用统一视频格式
复用上述函数,将主程序的创建、查询和下载部分替换为以下代码。统一格式的三个步骤均使用 family="generic":
task_id = create_task("/v1/videos", {
"model": "viduq3-turbo", "prompt": PROMPT, "seconds": "5", "size": "720p",
"metadata": {
"vidu_operation": "text2video", "aspect_ratio": "16:9",
"audio": False, "is_rec": False, "watermark": False,
},
}, "generic")
task = wait_for_task(task_id, "generic")
download_video(result_url(task, "generic"), "vidu-generic-output.mp4")该片段会创建新任务;恢复已有统一任务时只设置真实 task_id,直接调用 wait_for_task(task_id, "generic"),不要再次执行 create_task。使用统一视频格式中的 metadata.vidu_operation 指定图生、首尾帧或参考生操作。
视频 URL 可能属于独立 CDN,下载时不要附带 ModelSell API Key。官方结果地址有效期为 24 小时;成功后应及时保存,失败时保留任务 ID 和错误信息。