# Wan 3.0 — /videos/generations

通义万相 Wan 3.0 视频生成接口，按秒计费。一个接口按参数切换玩法：文生视频、首帧、首尾帧、多图参考、参考视频改写。支持 2–30 秒、480P / 720P / 1080P、5 种画面比例，带首帧时可以跟随原图比例。异步任务，失败不收费。

**端点:** `POST https://nezhagate.com/v1/videos/generations`

## 快速开始

三步跑通：提交任务 → 查询结果 → 拿到视频链接。把 YOUR_API_KEY 换成你的 Key，下面的命令可以直接运行。

**第 1 步 · 提交任务（立刻返回任务号，HTTP 202）**

```
curl https://nezhagate.com/v1/videos/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "wan3.0-video", "prompt": "一只柴犬在樱花树下追逐飘落的花瓣，阳光明媚，慢动作", "duration": 5, "resolution": "720P", "size": "16:9"}'
```

返回（HTTP 202）

```
{
  "id": "img_5c2e8f1a9b3d7e6f0a4c8b2d",
  "object": "video.generation.job",
  "status": "queued",
  "created": 1791281400,
  "model": "wan3.0-video"
}
```

**第 2 步 · 每 5–10 秒查询一次，直到 `status` 变成 `succeeded` 或 `failed`**

```
curl https://nezhagate.com/v1/videos/jobs/img_5c2e8f1a9b3d7e6f0a4c8b2d \
  -H "Authorization: Bearer YOUR_API_KEY"
```

成功时的返回

```
{
  "id": "img_5c2e8f1a9b3d7e6f0a4c8b2d",
  "object": "video.generation.job",
  "status": "succeeded",
  "created": 1791281400,
  "model": "wan3.0-video",
  "data": [
    {"url": "https://img.nezhagate.com/i/8c1f0e5d2b7a49e3a6d0c4f1b9e2a7d5.mp4"}
  ],
  "usage": {"clips": 1, "model": "wan3.0-video"}
}
```

**第 3 步 · `data[0].url` 就是成片（MP4），保留 15 天；需要长期使用，请下载到你自己的存储。**

**完整示例（Python：提交 → 等待 → 保存到本地）**

```
import time
import requests

BASE = "https://nezhagate.com/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

# 1. 提交任务
job = requests.post(f"{BASE}/videos/generations", headers=HEADERS, json={
    "model": "wan3.0-video",
    "prompt": "一只柴犬在樱花树下追逐飘落的花瓣，阳光明媚，慢动作",
    "duration": 5,
    "resolution": "720P",
    "size": "16:9",
}).json()
if "error" in job:
    raise SystemExit(job["error"]["message"])

# 2. 每 10 秒查询一次，最多等一小时
deadline = time.time() + 3600
while job["status"] not in ("succeeded", "failed") and time.time() < deadline:
    time.sleep(10)
    job = requests.get(f"{BASE}/videos/jobs/{job['id']}", headers=HEADERS).json()

# 3. 下载视频
if job["status"] == "succeeded":
    url = job["data"][0]["url"]
    with open("wan3.0-video.mp4", "wb") as f:
        f.write(requests.get(url).content)
    print("saved", url)
elif job["status"] == "failed":
    print("failed:", job["error"]["code"], job["error"]["message"])
else:
    print("still", job["status"], job["id"])
```

排队时，查询结果里还有 `queue_position`（前面还有几个任务）和 `eta_seconds`（预计还要等几秒）。超过你设的等待时间也不要重新提交：任务还在，稍后用同一个任务号接着查。

## 认证
```
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

## 规格速览

| 时长 | 2–30 秒 |
| --- | --- |
| 分辨率 | 480P / 720P / 1080P |
| 画面比例 | 16:9 / 9:16 / 1:1 / 4:3 / 3:4 / adaptive |
| 参考图 | 最多 10 张 · 1 张作首帧，2 张可作首尾帧，多张作参考 |
| 参考视频 | 最多 5 段，合计不超过 15 秒 |
| 参考音频 | 最多 5 段 |
| 声音 | 由模型决定，没有开关（传 `audio: false` 会被拒绝） |
| 提示词长度 | 最多 5,000 字节（UTF-8，约 1,666 个汉字） |
| 计费方式 | 按秒：每秒单价 ×（成片秒数 + 参考视频秒数） |

## 请求参数

`POST /v1/videos/generations` 的请求体（JSON）：

| 参数 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| model | string | 是 | 模型 id：`wan3.0-video`。 |
| prompt | string | 是 | 画面、镜头和动作的描述，最多 5,000 字节（UTF-8，一个汉字算 3 字节，约 1,666 个汉字）。 |
| duration | integer | 否 | 成片时长（秒），2–30 之间的整数，不传为 2。也可以写作 `seconds`。带参考视频时，成片秒数加参考视频秒数合计不能超过 30。 |
| resolution | string | 否 | 分辨率：480P / 720P / 1080P，不传为 720P。请带上 P（`720` 这样不带 P 的写法会被拒绝）。 |
| size | string | 否 | 画面比例：16:9 / 9:16 / 1:1 / 4:3 / 3:4，不传为 16:9。带首帧时可以传 `adaptive`，让成片跟随首帧图片的比例。也可以写作 `aspect_ratio`。 |
| images | array | 否 | 参考图，最多 10 张：1 张作首帧；2 张默认作多图参考，加 `image_role: first_frame` 则作首尾帧；3 张及以上作参考。在提示词里用 `@Image1` 点名。只有一张时也可以放在 `image`。 真人面部审核限制：请避免使用含真人面部的参考素材，写实面部也可能触发检测。`FaceDetectionSuspect` 表示素材疑似包含真人面部；`DataInspectionFailed` 表示输入素材未通过内容审核，不代表服务不可用。请更换参考素材后再提交，不建议原样反复重试；怀疑误判时请联系支持。失败任务未计费。 |
| image_role | string | 否 | 参考图怎么用：`first_frame`（首帧或首尾帧，最多 2 张）或 `reference`（参考）。不传时 1 张按首帧、2 张及以上按参考；带参考视频时只能按参考。 |
| video_references | array | 否 | 参考视频，最多 5 段，每段写成 `{"url": "...", "duration": 5}`：`duration` 是这段视频的秒数（1–15），必须写。合计不超过 15 秒，参考秒数加成片秒数不超过 30。参考视频的秒数也计费。链接要能直接下载到文件本身；YouTube、B 站、抖音、网盘分享页这类网页链接不行，提交时会直接返回 400。 |
| audio_reference | array | 否 | 参考音频，最多 5 段，只收公网 http(s) 链接，要和参考图或参考视频一起传，不计费。链接要能直接下载到文件本身；YouTube、B 站、抖音、网盘分享页这类网页链接不行，提交时会直接返回 400。 |
| audio | boolean | 否 | 音轨由模型决定，没有开关；传 `false` 会被拒绝（400），可以不传。 |
| prompt_extend | boolean | 否 | 是否让模型自动扩写提示词；不传时由模型决定。 |
| callback_url | string | 否 | 任务结束时把结果推送到这个地址，见下文的 Webhook。 |
| n | integer | 否 | 每个任务出 1 条视频，不用传。传了大于 1 的值也只出 1 条，但提交时会按 n 条预扣，任务结束后退回多扣的部分。 |

其他字段（如 `seed`、`negative_prompt`、`fps`、`watermark`）不会转发，也不影响价格；成片一律是 MP4，通过 `url` 返回。

## 价格

按秒计费：费用 = 所选分辨率的每秒单价 ×（成片秒数 + 各段参考视频的秒数）。参考图和参考音频不计费。提交时预扣，失败全额退回。1 积分 = $0.005。

| 分辨率 | 积分 / 秒 | 美元 / 秒 | 5 秒一条 |
| --- | --- | --- | --- |
| 480P | 8 | $0.04 | $0.20 |
| 720P | 13 | $0.065 | $0.325 |
| 1080P | 26 | $0.13 | $0.65 |

## 参考素材

- 一个接口按参数切换玩法：不带图是文生视频；1 张图作首帧；2 张图加 `image_role: first_frame` 作首尾帧（第 1 张首帧、第 2 张尾帧）；不加时 2 张及以上都是多图参考，最多 10 张。

- 参考视频最多 5 段（合计 15 秒，每段都要写 `duration`），用来改写或延续那段画面；带参考视频时，图片只能作参考，不能作首尾帧。参考音频最多 5 段，只收公网链接。

- 带首帧时传 `size: adaptive`，成片会跟随首帧图片的比例。 真人面部审核限制：请避免使用含真人面部的参考素材，写实面部也可能触发检测。`FaceDetectionSuspect` 表示素材疑似包含真人面部；`DataInspectionFailed` 表示输入素材未通过内容审核，不代表服务不可用。请更换参考素材后再提交，不建议原样反复重试；怀疑误判时请联系支持。失败任务未计费。

- 每张图可以是公网图片链接、`data:` URI 或 base64，单张不超过 16MB，多张用数组放在 `images` 里。提交时我们先把图片转存好再排队；读不到的图片会直接返回 400，`message` 写明是第几张，这一单不计费。

- 我们转存的参考素材保留 7 天，成片保留 15 天。

**首尾帧：在两张图之间生成过渡**

```
curl https://nezhagate.com/v1/videos/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "wan3.0-video", "prompt": "从清晨过渡到黄昏，云层流动，光线逐渐变暖", "images": ["https://example.com/first.png", "https://example.com/last.png"], "image_role": "first_frame", "duration": 5, "resolution": "720P", "size": "adaptive"}'
```

`image_role: first_frame` 让 2 张图作首尾帧，`size: adaptive` 让成片跟随首帧图片的比例。不加 `image_role` 时，2 张图会作为多图参考。

## 任务状态与返回字段

`GET /v1/videos/jobs/{id}` 返回这些状态，各字段的说明见 [异步任务](https://nezhagate.com/docs/guide/async-jobs#fields)。每 5–10 秒查一次，或者用下面的 Webhook 等推送。查询不收费，同一个账号的任何 Key 都能查。

| 状态 | 含义 |
| --- | --- |
| queued | 排队中。返回里带 `queue_position`（前面还有几个任务）和 `eta_seconds`（预计等待秒数）。 |
| processing | 生成中。 |
| succeeded | 已完成。结果在 `data[0].url`，计费明细在 `usage`。 |
| failed | 失败。原因在 `error`，预扣的积分已全额退回。 |

- `processing` 有时会回到 `queued`：例如线路都在忙、成片正在重新取回，或者服务重启。某条线路没能完成任务时，网关可能把它交给下一条线重新生成；无论经过几条线，一个任务只扣一次费用。

- 同一个账号最多 50 个任务同时生成，更多的任务按提交顺序排队；排队超过 15 分钟还没开始的任务会自动失败并全额退款。任务记录保留 3 天，视频链接保留 15 天。

## 出片时间

一般 2–4 分钟；参考素材多时会更久。

近 7 天真实调用：中位 3.5 分钟，90% 在 6.9 分钟 内完成。

## 错误与退款

提交时出错会直接返回 HTTP 4xx / 5xx，不建任务、不扣费；提交成功后的失败写在查询结果里，预扣的积分全额退回。全部错误码见 [错误码](https://nezhagate.com/docs/guide/errors)。

### 提交时返回的错误

| HTTP | code | 原因 | 怎么办 |
| --- | --- | --- | --- |
| 400 | invalid_request | 参数不合法：时长、分辨率、比例或素材数量超出这个模型的范围，提示词太长，参考图或参考视频读不到，或者给固定带声音的模型传了 `audio: false` 等。`message` 写明原因。 | 按 `message` 修改后重新提交。 |
| 400 | invalid_callback_url | `callback_url` 不是公网的 http(s) 地址，或超过 2000 个字符。 | 换成能从公网访问的地址。 |
| 400 | model_not_found | 型号写错、没有传 `model`，或这个型号不能用在这个接口上（例如拿对话模型调生图接口）。 | 以 `GET /v1/models` 或 [API 手册](https://nezhagate.com/docs/api) 里的模型 id 为准。 |
| 401 | invalid_api_key | Key 不存在、已删除或已停用，或者账号已停用。 | 到控制台「API Keys」页面检查这把 Key。 |
| 402 | insufficient_quota | 余额不够预扣这一单。网关先按这一单可能的最高费用预扣，同时发很多请求时也可能出现。 | 如果是并发突发，稍等几秒重试；否则充值。 |
| 429 | rate_limit_exceeded | 超过了这把 Key 设置的每分钟请求数（按最近 60 秒计）。不带 `Retry-After`。 | 等几秒再试，或在控制台调高这把 Key 的上限。 |
| 503 | model_maintenance | 型号维护中，暂停接单，期间不会改由其他模型作答。 | 维护结束后重试，进度见 [服务状态](https://nezhagate.com/status)。 |
| 503 | service_unavailable | 我们这边临时出错，例如保存参考素材失败。这一单没有创建任务，也没有扣费。 | 稍后重试。 |

### 任务失败（`status` 为 `failed`）

| code | 什么时候出现 | 怎么办 |
| --- | --- | --- |
| content_policy | Wan 标准版和 Prime：输入素材未通过审核。`error.reason` 为 `FaceDetectionSuspect`（疑似真人面部）或 `DataInspectionFailed`（输入内容审核未通过）。`error.message` 说明原因和调整建议；失败任务未计费。 | 改写提示词或更换素材后再提交；原样重交还会被拒。 |
| invalid_request | 模型方拒绝了这个请求：参数或参考素材不可用，或者内容没有通过审核。`message` 写明原因。 | 按 `message` 调整参数后再提交。 |
| upstream_error | 其他失败：所有线路都试过仍然失败、排队 15 分钟还没开始、上游拒绝但没有说明原因等，`message` 写明具体情况。 | 通常重新提交就能成功。 |

请按 `code` 判断，不要匹配 `message` 的文字。遇到不认识的 `code`（或者没有 `code`），按 `upstream_error` 处理：重新提交通常就能成功。失败的任务一律全额退款。

## 用 Webhook 代替轮询

提交时加上 `callback_url`，任务一结束（成功或失败），网关就把和查询接口完全一样的结果推送到这个地址，带签名，失败会自动重试。也可以在控制台「设置 → Webhook」里配一个账户级地址。 [Webhook 文档 →](https://nezhagate.com/docs/webhooks)

```
curl https://nezhagate.com/v1/videos/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "wan3.0-video", "prompt": "一只柴犬在樱花树下追逐飘落的花瓣，阳光明媚，慢动作", "duration": 5, "resolution": "720P", "size": "16:9", "callback_url": "https://your-domain.com/webhook"}'
```
