# Seedance 视频生成 API — 客户接入说明

本文档面向**持有平台 API Key（`sk-` 令牌）**的调用方，说明如何通过 **自有 Seedance 开放平台** 提交 Seedance 文生/图生/多模态视频任务并获取成片。

> 若你使用的是中转站 **[996k.cn](https://996k.cn)** 发放的 Key，请改看 [996k-api.md](./996k-api.md)（创建 / 查询视频）。

---

## 1. 基本信息

| 项目 | 说明 |
|------|------|
| 平台名称 | **自有 Seedance 开放平台** |
| 协议 | HTTP（公网接入）；若已配置 HTTPS 可改用 `https://` |
| **Base URL** | **`http://85.137.240.157:3099`**（以服务方实际公网地址为准） |
| 认证（API 调用） | 请求头 `Authorization: Bearer sk-xxxxxxxx` |
| 默认模型 | `doubao-seedance-2.0`（由平台渠道配置，一般无需修改） |
| 计费单位 | **credits**（按时长 × 分辨率倍率；库内为整数） |

> **Base URL 说明**
>
> - 默认端口：**`3099`**
> - 完整地址示例：**`http://85.137.240.157:3099`**
> - 若服务方另行提供域名，请以通知为准。

**建议先设置环境变量（后续 curl 可复用）：**

```bash
export BASE="http://85.137.240.157:3099"
export TOKEN="sk-你的令牌"
```

---

## 2. 支持的模型

| 模型名 | 说明 |
|--------|------|
| `doubao-seedance-2.0` | 默认推荐 |
| `doubao-seedance-2.0-fast` | **暂时不开放** |

具体可用模型以服务方开通为准。

---

## 3. 接口一览

| 方法 | 路径 | 认证 | 说明 |
|------|------|------|------|
| `POST` | `/v1/video/generations` | `sk-` 令牌 | 创建视频任务 |
| `GET` | `/v1/video/generations/{task_id}` | `sk-` 令牌 | 查询任务状态 |
| `GET` | `/v1/videos/{task_id}/content` | `sk-` 令牌 | 可选：经平台代理下载 MP4 |
| `POST` | `/api/seedance/upload` | `sk-` 令牌 | 本地文件上传并资产认证（拿到 assetId 即返回） |
| `POST` | `/api/seedance/assets` | `sk-` 令牌 | **远程公网 URL 资产认证**（推荐已有图床/OSS 时使用） |
| `GET` | `/api/seedance/assets/{id}` | `sk-` 令牌 | 查询资产状态（本地 id 或 `aicc_asset_id`） |
| `POST` | `/api/seedance/real-person-auth/sessions` | `sk-` 令牌 | **创建真人认证 H5 会话**（活体检测） |
| `POST` | `/api/seedance/real-person-auth/asset-group` | `sk-` 令牌 | **通过 bytedToken 换取真人素材组 groupId** |

> API 客户日常使用 **`/v1/video/generations`** 即可。  
> - 本地文件：`/api/seedance/upload`  
> - 已有公网直链：`/api/seedance/assets`（上游直接拉取该 URL 做资产认证，返回 `asset://`）  
> - **真人参考图**：先走 `/api/seedance/real-person-auth/*` 完成活体认证，再用返回的 `group_id` 上传素材

---

## 4. 调用流程概览

```text
POST /v1/video/generations          →  获得 task_id（任务已排队，已扣费）
        ↓
GET  /v1/video/generations/{task_id} →  轮询状态（建议每 10～15 秒）
        ↓
data.status == SUCCESS               →  使用 data.result_url（上游原始视频地址）直接下载
        ↓
（可选）GET /v1/videos/{task_id}/content → 经平台中转下载 MP4（加密成片解密后提供）
```

**超时与计费说明**

- `POST /v1/video/generations` 是“创建上游任务”的同步接口；视频生成本身仍是异步任务。
- 若请求 `content` 含尚未 ACTIVE 的 `asset://`，Gateway 会先等待素材就绪再提交上游；建议 HTTP 超时设为 **120 秒以上**。
- 费用：`cost = ceil(max(1, duration) × CREDIT_PER_SECOND × 分辨率倍率)`，结果为整数 credits。  
  - 默认倍率：`480p=1`，`720p=2`，`1080p=5`（可用环境变量 `CREDIT_RESOLUTION_MULTIPLIERS` 调整）  
  - 未传 `resolution` 时按 `720p` 计费  
  - 例：5 秒 720p、`CREDIT_PER_SECOND=1` → `ceil(5×1×2)=10` credits；5 秒 1080p → `25` credits  
  - 记账约定（方案 A）：约 **1 credit ≈ ¥0.30**（对应卖价约 30 元/百万 token） 
- **创建成功后立即扣费**；若任务最终 `FAILURE`，平台会自动退回本次扣费。
- 余额不足时返回 HTTP **402**；素材未就绪/失败返回 **409**，均不会创建上游任务。

---

## 5. 创建视频任务

### 5.1 文生视频（`prompt` + `metadata`）

```http
POST /v1/video/generations
Authorization: Bearer sk-你的令牌
Content-Type: application/json
```

```bash
curl -s -X POST "$BASE/v1/video/generations" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2.0",
    "prompt": "一只橘猫在窗边打哈欠",
    "metadata": {
      "ratio": "16:9",
      "resolution": "720p",
      "duration": 5,
      "watermark": false
    }
  }'
```

**请求体字段**

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `model` | string | 否 | 默认平台模型 |
| `prompt` | string | 文生时必填 | 文本描述 |
| `metadata.ratio` | string | 否 | 画幅，如 `16:9`、`9:16`、`1:1` |
| `metadata.resolution` | string | 否 | 清晰度：`480p` / `720p` / `1080p`（推荐默认 `720p`；不传则由上游默认） |
| `metadata.duration` | number | 否 | 时长（秒），如 `5` |
| `metadata.watermark` | boolean | 否 | 是否带水印 |

**成功响应示例（HTTP 200）**

```json
{
  "id": "task_3YhzK9Yf5XuFxVi8kUKQknAL4g0kHqah",
  "task_id": "task_3YhzK9Yf5XuFxVi8kUKQknAL4g0kHqah",
  "object": "video",
  "model": "doubao-seedance-2.0",
  "status": "queued",
  "progress": 0,
  "created_at": 1780587562,
  "cost_credits": 5
}
```

请保存返回的 **`task_id`**：

```bash
export TASK_ID="task_3YhzK9Yf5XuFxVi8kUKQknAL4g0kHqah"
```

### 5.2 多模态参考（`content` 原生格式）

```json
{
  "model": "doubao-seedance-2.0",
  "content": [
    {
      "type": "text",
      "text": "根据参考图生成一段清新果茶广告，首帧贴近图片1。"
    },
    {
      "type": "image_url",
      "image_url": {
        "url": "asset://asset-xxxxxxxx"
      },
      "role": "reference_image"
    }
  ],
  "generate_audio": true,
  "ratio": "16:9",
  "resolution": "720p",
  "duration": 8,
  "watermark": false
}
```

也可直接使用公网 `https://` 图片/视频/音频 URL。推荐优先使用上传接口返回的 `asset_uri`（`asset://...`），对真人参考图更稳妥。

#### `content` 数组元素说明

| `type` | 必填子字段 | `role`（可选） | 说明 |
|--------|------------|----------------|------|
| `text` | `text` | — | 镜头脚本、旁白、分镜描述 |
| `image_url` | `image_url.url` | `reference_image` | 参考图 URL 或 `asset://` |
| `video_url` | `video_url.url` | `reference_video` | 参考视频 |
| `audio_url` | `audio_url.url` | `reference_audio` | 参考音频 |

#### 顶层参数

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `model` | string | 否 | 如 `doubao-seedance-2.0` |
| `content` | array | 多模态时必填 | 见上表 |
| `prompt` | string | 文生视频必填 | 纯文本时可只用 `prompt` |
| `generate_audio` | boolean | 否 | 是否生成/融合音频 |
| `ratio` | string | 否 | `16:9`、`9:16`、`1:1` 等 |
| `resolution` | string | 否 | `480p` / `720p` / `1080p`（推荐默认 `720p`） |
| `duration` | number | 否 | 时长（秒） |
| `watermark` | boolean | 否 | 是否带水印 |

> **清晰度说明**：`ratio` 是画幅比例，`resolution` 才是像素档位（480p/720p/1080p）。两者可同时传。也可写在 `metadata.resolution`。取值请用小写（如 `720p`，不要写 `720P`）。

**失败响应示例**

```json
{
  "code": "INSUFFICIENT_BALANCE",
  "message": "余额不足：当前 0，需要 5",
  "data": null
}
```

---

## 6. 上传参考素材

```http
POST /api/seedance/upload
Authorization: Bearer sk-你的令牌
Content-Type: multipart/form-data
```

**表单字段**

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `type` | string | 是 | `image` / `video` / `audio` |
| `file` | file | 是 | 素材文件 |
| `group_id` | string | 否 | 真人认证后的素材组 ID；不传则使用虚拟人默认 AIGC 组 |

**大小限制**：单文件 **20 MB**。

```bash
curl -s -X POST "$BASE/api/seedance/upload" \
  -H "Authorization: Bearer $TOKEN" \
  -F "type=image" \
  -F "file=@./ref.jpg"
```

**成功响应**

```json
{
  "success": true,
  "message": "",
  "data": {
    "asset_id": 123,
    "aicc_asset_id": "asset-20260628184537-xxxxx",
    "status": "processing",
    "filename": "1_uuid.jpg",
    "type": "image",
    "size": 102400,
    "url": "http://85.137.240.157:3099/uploads/1/1_uuid.jpg",
    "asset_uri": "asset://asset-20260628184537-xxxxx"
  }
}
```

将返回的 `data.aicc_asset_id` 按 `asset://{aicc_asset_id}` 使用（响应里也有现成的 `data.asset_uri`）。

> **重要**：上传接口会把文件先存到平台，再提交给上游素材库创建资产。  
> 因此平台对外地址 **必须是上游能访问的公网地址**（不能是本机或局域网地址）。  
> 拿到上游 `assetId` 后立即返回，`status` 通常为 `processing`；平台会在后台轮询并落库 `active` / `failed`。  
> 创建视频任务时若素材尚未 ACTIVE，Gateway 会自动等待就绪后再提交上游。  
> 仅当上游 `createAsset` 本身失败时返回 HTTP 502。

---

## 6.1 远程 URL 资产认证（推荐）

当你已有**公网可直链访问**的图片/视频/音频地址时，不必再上传文件，直接让平台提交上游做资产认证：

```http
POST /api/seedance/assets
Authorization: Bearer sk-你的令牌
Content-Type: application/json
```

**请求体**

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `url` | string | 是 | 公网直链（也可用 `assetUrl`） |
| `type` | string | 否 | `image`（默认）/ `video` / `audio` |
| `name` | string | 否 | 素材名称；不传则自动生成 |
| `group_id` | string | 否 | 真人认证后的素材组 ID；不传则使用虚拟人默认 AIGC 组 |

```bash
curl -s -X POST "$BASE/api/seedance/assets" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/path/ref.jpg",
    "type": "image",
    "name": "ref-1"
  }'
```

**成功响应**

```json
{
  "success": true,
  "message": "",
  "data": {
    "asset_id": 123,
    "aicc_asset_id": "asset-20260628184537-xxxxx",
    "aicc_group_id": "group-xxxxx",
    "status": "processing",
    "filename": "ref-1",
    "backend": "remote_url",
    "type": "image",
    "url": "https://example.com/path/ref.jpg",
    "asset_uri": "asset://asset-20260628184537-xxxxx"
  }
}
```

将 `data.asset_uri` 填入创建视频任务的 `content[].image_url.url`。

> **要求**：`url` 必须是上游 MaaS 能访问的公网直链（`https://` 优先），不能是本机路径、内网地址或需登录的私有链接。  
> 拿到 `assetId` 即返回；ACTIVE 由后台轮询落库。创建视频时 Gateway 会自动兜底等待。

### 6.2 查询资产状态

```http
GET /api/seedance/assets/{id}
Authorization: Bearer sk-你的令牌
```

`{id}` 可为本地数字 `asset_id`，或上游 `aicc_asset_id`。

```bash
curl -s "$BASE/api/seedance/assets/$ASSET_ID" \
  -H "Authorization: Bearer $TOKEN"
```

`data.status`：`uploaded` / `processing` / `active` / `failed`。

---

## 6.3 真人认证（LivenessFace）

真人参考图必须先完成**活体认证**，不能通过白名单等方式绕过。平台已封装上游真人认证接口，**不会对外暴露**移动云原始地址。

### 调用流程

```text
POST /api/seedance/real-person-auth/sessions
        →  获得 byted_token、h5_link
        ↓
引导用户在手机端打开 h5_link，完成活体检测
        ↓
POST /api/seedance/real-person-auth/asset-group  （body: byted_token）
        →  获得 group_id（LivenessFace 素材组）
        ↓
POST /api/seedance/upload 或 /api/seedance/assets  （body 加 group_id）
        →  获得 asset_uri（asset://...）
        ↓
POST /v1/video/generations  （content 中使用 asset_uri）
```

> **说明**
>
> - 上游 H5 认证**无平台侧 CallbackURL**；用户完成活体后，由调用方保存 `byted_token`，再主动轮询「换取素材组」接口。
> - `byted_token` 有时效（响应中的 `expires_in`），过期后需重新创建会话。
> - 真人素材必须上传到认证后的 `group_id`；上传/远程认证接口支持可选字段 `group_id`（不传则走虚拟人默认 AIGC 组）。

### 6.3.1 创建真人认证 H5 会话

```http
POST /api/seedance/real-person-auth/sessions
Authorization: Bearer sk-你的令牌
Content-Type: application/json
```

```bash
curl -s -X POST "$BASE/api/seedance/real-person-auth/sessions" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
```

**成功响应**

```json
{
  "success": true,
  "message": "",
  "data": {
    "byted_token": "byted-token-xxx",
    "h5_link": "https://...",
    "expires_in": "3600"
  }
}
```

将 `data.h5_link` 展示给用户（建议手机端打开），并**本地保存** `data.byted_token` 供下一步使用。

### 6.3.2 换取真人素材组 groupId

用户完成 H5 活体后调用（可轮询，直到返回 `group_id`）：

```http
POST /api/seedance/real-person-auth/asset-group
Authorization: Bearer sk-你的令牌
Content-Type: application/json
```

**请求体**

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `byted_token` | string | 是 | 创建会话时返回的 token（也可用 `bytedToken`） |

```bash
curl -s -X POST "$BASE/api/seedance/real-person-auth/asset-group" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"byted_token":"byted-token-xxx"}'
```

**成功响应**

```json
{
  "success": true,
  "message": "",
  "data": {
    "group_id": "group-xxxxx",
    "group_type": "LivenessFace"
  }
}
```

若用户尚未完成活体或 token 无效，返回 HTTP **404**，`code` 为 `group_not_found`。

### 6.3.3 上传真人素材到已认证素材组

在 **6.1 远程 URL 认证** 或 **6 本地上传** 时，增加 `group_id` 字段即可：

```bash
curl -s -X POST "$BASE/api/seedance/assets" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/face.jpg",
    "type": "image",
    "group_id": "group-xxxxx"
  }'
```

返回的 `data.asset_uri` 用法与虚拟人一致，填入创建视频任务的 `content[].image_url.url`。

### 6.3.4 人脸一致性校验与失败原因

素材上传后，上游会做**人脸一致性校验**（与活体认证人脸比对）。可通过 **6.2 查询资产状态** 查看：

- `data.status == active`：校验通过，可用于视频生成
- `data.status == failed`：`data.error_message` 为失败原因（如人脸不一致）

创建视频时若素材尚未 `active`，Gateway 会自动等待；校验失败则返回 HTTP **409**。

### 6.3.5 授权有效期、撤销与删除

| 项目 | 说明 |
|------|------|
| 会话有效期 | `expires_in`（秒），过期需重新创建 H5 会话 |
| 素材组 | 由上游绑定到活体认证结果，通过 `group_id` 使用 |
| 撤销/删除 | 真人授权与素材组生命周期由上游管理；如需删除已上传素材，请联系平台运营 |

### 6.3.6 视频生成时传入 asset://

与虚拟人相同，在 `POST /v1/video/generations` 的 `content` 中引用已认证素材：

```json
{
  "content": [
    {
      "type": "text",
      "text": "人物对着镜头微笑"
    },
    {
      "type": "image_url",
      "image_url": { "url": "asset://asset-20260628184537-xxxxx" }
    }
  ],
  "metadata": { "ratio": "16:9", "duration": 5 }
}
```

---

## 7. 查询任务状态（轮询）

```bash
curl -s "$BASE/v1/video/generations/$TASK_ID" \
  -H "Authorization: Bearer $TOKEN"
```

**成功示例**

```json
{
  "code": "success",
  "message": "",
  "data": {
    "task_id": "task_xxx",
    "status": "SUCCESS",
    "progress": "100%",
    "result_url": "https://ark-....volces.com/..../video.mp4?...",
    "fail_reason": ""
  }
}
```

`data.result_url` 为**上游原始视频直链**（通常为火山/TOS 临时签名 URL），客户端可直接下载，无需再经本平台中转。

> 可选中转：`GET /v1/videos/{task_id}/content` 仍可用（需 Bearer），适合需要平台代下/解密归档的场景。

### 状态说明

| `data.status` | 含义 | 建议 |
|---------------|------|------|
| `QUEUED` | 排队中 | 继续轮询 |
| `IN_PROGRESS` | 生成中 | 继续轮询 |
| `SUCCESS` | 已完成 | 下载成片 |
| `FAILURE` | 失败 | 查看 `fail_reason`（费用已自动退回） |

**轮询建议**：间隔 **10～15 秒**，总等待 **5～10 分钟**。

---

## 8. 获取视频

**推荐**：轮询到 `SUCCESS` 后，直接用 `data.result_url`（上游直链）下载。

**可选中转**（需鉴权）：

```bash
curl -L "$BASE/v1/videos/$TASK_ID/content" \
  -H "Authorization: Bearer $TOKEN" \
  -o output.mp4
```

**前提**：先轮询到 `status == SUCCESS`。

---

## 9. cURL 一键串联

```bash
export BASE="http://85.137.240.157:3099"
export TOKEN="sk-你的令牌"

CREATE_RESP=$(curl -s -X POST "$BASE/v1/video/generations" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"doubao-seedance-2.0","prompt":"一只橘猫在窗边打哈欠","metadata":{"ratio":"16:9","resolution":"720p","duration":5,"watermark":false}}')
echo "$CREATE_RESP"
export TASK_ID=$(echo "$CREATE_RESP" | python -c "import sys,json; d=json.load(sys.stdin); print(d.get('task_id') or d.get('id'))")

while true; do
  RESP=$(curl -s "$BASE/v1/video/generations/$TASK_ID" -H "Authorization: Bearer $TOKEN")
  STATUS=$(echo "$RESP" | python -c "import sys,json; print(json.load(sys.stdin)['data'].get('status',''))")
  echo "status=$STATUS"
  [ "$STATUS" = "SUCCESS" ] || [ "$STATUS" = "FAILURE" ] && break
  sleep 12
done

curl -L "$BASE/v1/videos/$TASK_ID/content" -H "Authorization: Bearer $TOKEN" -o video.mp4
```

---

## 10. 常见问题

**Q：返回 401？**  
A：检查 `Authorization: Bearer sk-xxx` 是否正确、密钥是否被禁用。

**Q：返回 402 / 余额不足？**  
A：联系服务方为账户充值 credits。

**Q：任务 FAILURE 费用怎么算？**  
A：失败会自动退款；可联系服务方核对流水中的 `refund` 记录。

**Q：上传后没有 `asset_uri`？**  
A：平台可能未配置素材组，或上传返回的 `url` 对上游不可达；请确认使用公网可达地址，或改用远程 URL 资产认证接口。

**Q：上传成功但 `status` 是 `processing`？**  
A：正常。拿到 `assetId` 后立即返回，平台后台轮询至 `active`；创建视频时若尚未就绪，Gateway 会自动等待。

**Q：`result_url` 是什么地址？**  
A：任务成功后为上游原始视频直链（通常为火山/TOS 临时签名 URL），可直接下载；可选中转见 `/v1/videos/{task_id}/content`。

**Q：创建超时是否一定失败？**  
A：不一定。创建阶段较慢时，服务端可能已成功建任务；请保留请求上下文并联系平台排查。

---

## 11. 联系与支持

- **平台名称**：自有 Seedance 开放平台  
- **API Base URL**：以服务方通知为准  
- **API Key**：由服务方发放（`sk-` 开头）  
- 技术问题请提供 `task_id` 与大致请求时间  

---

*文档版本：2026-07-09 · 自有 Seedance 开放平台*
