Files
video-gen/API_v3_接口文档.md
T
root 0c511f3451 1、增加调用 AI 视频生成能力和虚拟素材库管理的对外api
2、增加后台apikkey管理
3、增加apikey单独的模型定价
4、增加apikey调用情况
5、完善所有数据的注释增加
2026-08-06 13:13:28 +08:00

954 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 对外开放模型 API v3 接口文档
## 概述
本文档描述视频/图片生成平台的对外开放 API v3 接口。外部调用方通过 API Key 认证,调用 AI 视频和图片生成能力。
- **Base URL**: `http://your-domain.com/api/v3`
- **认证方式**: `Authorization: Bearer {api-key}`
- **数据格式**: JSON
- **字符编码**: UTF-8
---
## 认证
所有接口均需在请求头中携带 API Key:
```
Authorization: Bearer vk_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
```
### 错误响应
认证失败时返回:
```json
// 401 API Key 无效或过期
{
"error": {
"code": "invalid_api_key",
"message": "无效的 API Key"
}
}
// 429 配额不足
{
"error": {
"code": "quota_exceeded",
"message": "配额不足 (需要 1.00 元, 剩余 0.50 元)"
}
}
```
---
## 接口列表
### 1. 获取可用模型列表
获取当前 API Key 可调用的所有视频和图片模型(仅返回已配置价格的模型)。
```
GET /api/v3/models
```
**请求头:**
| 参数 | 必填 | 说明 |
|------|------|------|
| Authorization | 是 | `Bearer {api-key}` |
**响应示例:**
```json
{
"models": [
{
"model": "doubao-seedance-2-0-260128",
"engine_type": "video",
"engine_id": "eng_xxxx",
"supported_ratios": ["16:9", "9:16", "1:1", "4:3"],
"supported_resolutions": ["480p", "720p", "1080p"],
"supported_durations": [3, 4, 5, 6, 7, 8, 9, 10, 15]
},
{
"model": "doubao-seedream-5-0-260128",
"engine_type": "image",
"engine_id": "eng_yyyy",
"supported_sizes": ["2K", "4K"]
}
]
}
```
**响应字段:**
| 字段 | 类型 | 说明 |
|------|------|------|
| models | array | 可用模型列表 |
| models[].model | string | 模型名称 |
| models[].engine_type | string | 引擎类型: `video` / `image` |
| models[].engine_id | string | 引擎 ID |
| models[].supported_ratios | string[] | 视频支持的比例列表 |
| models[].supported_resolutions | string[] | 视频支持的分辨率列表 |
| models[].supported_durations | int[] | 视频支持的时长列表(秒) |
| models[].supported_sizes | string[] | 图片支持的尺寸列表 |
---
### 2. 创建视频生成任务(异步)
创建视频生成任务,接口立即返回 `task_id`,调用方通过轮询查询任务状态和结果。
**并发排队机制:**
- 每个 API Key 可配置最大并发视频任务数(`max_concurrent_video_tasks`
- 未超并发:任务立即执行,`status="queued"`
- 超过并发:任务排队等待,`status="pending_queue"`
- 当有任务完成/失败时,自动从队列中启动下一个任务
```
POST /api/v3/videos
```
**请求头:**
| 参数 | 必填 | 说明 |
|------|------|------|
| Authorization | 是 | `Bearer {api-key}` |
| Content-Type | 是 | `application/json` |
**请求体:**
```json
{
"model": "doubao-seedance-2-0-260128",
"content": [
{
"type": "text",
"text": "一只猫在草地上奔跑"
},
{
"type": "image_url",
"image_url": {"url": "https://..."},
"role": "reference_image"
},
{
"type": "video_url",
"video_url": {"url": "https://..."},
"role": "reference_video"
},
{
"type": "audio_url",
"audio_url": {"url": "https://..."},
"role": "reference_audio"
}
],
"ratio": "16:9",
"duration": 5,
"resolution": "1080p",
"generate_audio": true,
"watermark": false,
"idempotency_key": "unique-key-123"
}
```
**请求字段:**
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| model | string | 是 | - | 模型名称 |
| content | array | 是 | - | 生成内容数组(见下方) |
| ratio | string | 否 | `16:9` | 视频比例: `16:9` / `9:16` / `1:1` / `4:3` / `3:4` / `21:9` |
| duration | int | 否 | `5` | 视频时长(秒): 3-15 |
| resolution | string | 否 | `480p` | 分辨率: `480p` / `720p` / `1080p` |
| generate_audio | bool | 否 | `true` | 是否生成音频 |
| watermark | bool | 否 | `false` | 是否添加水印 |
| idempotency_key | string | 否 | - | 幂等键,防止重复创建 |
**content 数组元素 (ApiVideoContentPart)**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| type | string | 是 | 内容类型: `text` / `image_url` / `video_url` / `audio_url` |
| text | string | 否 | 文本内容(type=text 时必填) |
| image_url | object | 否 | 图片URL对象: `{"url": "..."}`type=image_url 时必填) |
| video_url | object | 否 | 视频URL对象: `{"url": "..."}`type=video_url 时必填) |
| audio_url | object | 否 | 音频URL对象: `{"url": "..."}`type=audio_url 时必填) |
| role | string | 否 | 参考角色: `first_frame` / `last_frame` / `reference_image` / `reference_video` / `reference_audio` |
**响应示例:**
```json
{
"id": "cgt-20260730183334-wdgfl"
}
```
**响应字段:**
| 字段 | 类型 | 说明 |
|------|------|------|
| id | string | 任务 ID,用于查询状态 |
---
### 3. 查询视频任务状态
根据 `task_id` 查询视频生成任务的状态和结果。
```
GET /api/v3/videos/{task_id}
```
**请求头:**
| 参数 | 必填 | 说明 |
|------|------|------|
| Authorization | 是 | `Bearer {api-key}` |
**路径参数:**
| 参数 | 类型 | 说明 |
|------|------|------|
| task_id | string | 创建任务时返回的 task_id |
**响应示例(排队中):**
```json
{
"id": "cgt-20260730183334-wdgfl",
"model": "doubao-seedance-2-0-mini-260615",
"status": "queued",
"created_at": 1785407620,
"updated_at": 1785407620,
"content": null,
"duration": null,
"ratio": null,
"resolution": null
}
```
**响应示例(运行中):**
```json
{
"id": "cgt-20260730183334-wdgfl",
"model": "doubao-seedance-2-0-mini-260615",
"status": "running",
"created_at": 1785407620,
"updated_at": 1785407650,
"content": null,
"duration": null,
"ratio": null,
"resolution": null
}
```
**响应示例(成功):**
```json
{
"id": "cgt-20260730183334-wdgfl",
"model": "doubao-seedance-2-0-mini-260615",
"status": "succeeded",
"created_at": 1785407620,
"updated_at": 1785407723,
"content": {
"video_url": "https://..."
},
"duration": 4,
"ratio": "9:16",
"resolution": "480p"
}
```
**响应示例(失败):**
```json
{
"id": "cgt-20260730183334-wdgfl",
"model": "doubao-seedance-2-0-mini-260615",
"status": "failed",
"created_at": 1785407620,
"updated_at": 1785407650,
"content": null,
"duration": null,
"ratio": null,
"resolution": null
}
```
**响应字段:**
| 字段 | 类型 | 说明 |
|------|------|------|
| id | string | 任务 ID |
| model | string | 模型名称 |
| status | string | 任务状态(见下方状态说明) |
| created_at | int | 创建时间戳(Unix) |
| updated_at | int | 更新时间戳(Unix) |
| content | object | 视频内容(成功时返回,包含 video_url) |
| duration | int | 视频时长(秒) |
| ratio | string | 视频比例 |
| resolution | string | 分辨率 |
**任务状态说明:**
| 状态 | 说明 |
|------|------|
| `queued` | 排队中 |
| `running` | 任务运行中 |
| `succeeded` | 任务成功 |
| `failed` | 任务失败 |
| `expired` | 任务超时 |
---
### 4. 生成图片(同步)
同步生成图片,接口阻塞等待完成后直接返回结果。
```
POST /api/v3/images
```
**请求头:**
| 参数 | 必填 | 说明 |
|------|------|------|
| Authorization | 是 | `Bearer {api-key}` |
| Content-Type | 是 | `application/json` |
**请求体:**
```json
{
"model": "doubao-seedream-5-0-260128",
"prompt": "一只可爱的猫咪",
"size": "2K",
"response_format": "url",
"watermark": false,
"image": ["https://example.com/ref1.jpg"],
"output_format": "png",
"sequential_image_generation": "auto",
"generation_count": 1
}
```
**请求字段:**
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| model | string | 是 | - | 模型名称 |
| prompt | string | 是 | - | 图片描述提示词 |
| size | string | 否 | `2K` | 图片尺寸: `2K` / `4K``2048x2048` |
| response_format | string | 否 | `url` | 返回格式: `url` / `b64_json` |
| watermark | bool | 否 | `false` | 是否添加水印 |
| image | string[] | 否 | - | 参考图片 URL 列表 |
| output_format | string | 否 | - | 输出格式: `jpeg` / `png` / `webp` |
| sequential_image_generation | string | 否 | - | 组图模式: `auto` 开启 |
| generation_count | int | 否 | `1` | 生成数量: 1-5 |
**响应示例 (200 OK)**
```json
{
"created": 1721000000,
"data": [
{
"url": "https://volc.example.com/image/xxx.png",
"size": "2K",
"output_format": "png"
}
],
"model": "doubao-seedream-5-0-260128"
}
```
**响应字段:**
| 字段 | 类型 | 说明 |
|------|------|------|
| created | int | 创建时间戳(Unix) |
| data | array | 图片结果列表 |
| data[].url | string | 图片 URL |
| data[].b64_json | string | Base64 编码图片(response_format=b64_json 时) |
| data[].size | string | 图片尺寸 |
| data[].output_format | string | 输出格式 |
| model | string | 使用的模型名称 |
---
## 虚拟素材库接口(中转)
虚拟素材库用于在**火山方舟私域可信素材服务**中管理专属的图片/视频素材(如客户专属虚拟人)。数据与前台用户私域素材库完全隔离,归属按 API Key 管理。
**启用前置条件:**
1. 管理员在后台「API Key 管理 → 详情 → 虚拟素材库配额」中配置项目数/素材数/存储 MB 上限(默认 0=不可用)
2. 任一上限大于 0 即表示该 API Key 启用了虚拟素材库功能
3. 所有操作占用对应配额,超出上限返回 403 `quota_exceeded`
**生命周期流程(新,一步到位):**
1. 创建虚拟项目(CreateAssetGroup 建远端组)
2. 直接调用「项目下创建素材」接口,**仅传一个公网可访问的 URL**(http/https 图片/视频直链)
- 服务端先将该 URL 的文件**下载保存到本地存储系统**(路径见下),占用存储配额
- 保存成功后,再将**本地公网 URL** 同步提交给火山平台 CreateAsset 做异步审核
3. 素材状态 Creating → 轮询 `/assets/{id}``/assets/{id}/sync` 主动刷新 → 状态 Active(可使用)
4. AI 创作时通过 `/selectable-assets` 选择器拿到已就绪素材
5. 素材/项目删除(软删本地 + 同步清理本地落盘文件 → 异步删火山远端,返回 `remote_delete_status=pending`
**素材文件本地保存路径(服务端自动处理,调用方无需关心):**
- 图片:`/uploads/images/vp_v3_virtual/{api_key_id_short}/yyyy/mm/dd/vp_v3_{uuid}.{ext}`
- 视频:`/uploads/videos/vp_v3_virtual/{api_key_id_short}/yyyy/mm/dd/vp_v3_{uuid}.{ext}`
**技术细节 & 错误处理(保证数据一致性):**
1. URL 下载阶段失败(网络/超时/4xx/5xx/大文件/非法 MIME):立即清理临时文件,不占用任何配额,返回对应错误码
2. 下载成功但**配额不足**:立即删除已下载的本地文件,释放磁盘,再抛 403 `quota_exceeded`
3. 视频时长:若请求未传 `video_duration`,服务端自动 ffprobe 探测;两者都失败则删本地文件并 400 要求显式传时长
4. 本地写库成功但**火山 CreateAsset 失败**:保留本地文件(已占配额和素材数),素材状态标记为 `Failed`,错误信息记录在 `error_message` / `moderation_json`。调用方可选择:
- 保留并排查(后续可调用 DELETE 删除 → 自动清理本地文件 + 返还配额)
- 直接 DELETE 重试
5. 删除素材:**本地 commit 时同步删除本地落盘文件**(目录穿越防御,仅允许删 `/uploads` 目录内),返还存储配额和素材数配额;火山远端异步删除
---
### 5. 获取配额配置
获取当前 API Key 的虚拟素材库配额上限和已使用量,判断是否可用。
```
GET /api/v3/virtual-portrait/config
```
**响应示例:**
```json
{
"project_limit": 5,
"asset_limit": 50,
"storage_mb_limit": 500,
"project_used": 2,
"asset_used": 18,
"storage_mb_used": 128.43,
"enabled": true
}
```
**响应字段:**
| 字段 | 类型 | 说明 |
|------|------|------|
| project_limit | int | 虚拟项目上限,0=不可创建 |
| asset_limit | int | 虚拟素材总数上限(图片+视频),0=不可上传 |
| storage_mb_limit | int | 上传存储上限 MB,0=不可上传文件 |
| project_used | int | 已创建项目数(未删除) |
| asset_used | int | 已上传素材数(未删除) |
| storage_mb_used | float | 已占用存储 MB |
| enabled | bool | 该 Key 是否可使用虚拟素材库功能(任一上限>0即可) |
---
### 6. 获取枚举元数据
返回素材/项目所有枚举值及其说明,便于前端展示筛选选项。
```
GET /api/v3/virtual-portrait/enums
```
**响应示例:**
```json
{
"asset_type": { "Image": "图片素材", "Video": "视频素材" },
"asset_status": {
"creating": "创建中/审核中",
"active": "已就绪/可用",
"failed": "失败",
"deleting": "删除中"
},
"project_status": {
"creating_remote_group": "远端组创建中",
"active": "就绪",
"create_group_failed": "远端组创建失败",
"deleting": "删除中"
},
"remote_delete_status": {
"none": "未删除",
"pending": "待异步删除",
"processing": "远端删除中",
"deleted": "远端已删除",
"failed": "远端删除失败"
}
}
```
---
### 7. 虚拟项目 CRUD
#### 7.1 创建项目
创建一个虚拟素材项目(同步调火山 CreateAssetGroup 创建远端素材组)。
```
POST /api/v3/virtual-portrait/projects
```
**请求体:**
```json
{
"name": "客户A的虚拟人素材",
"description": "用于客户A的电商视频生成(可选)"
}
```
**字段说明:**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| name | string | 是 | 项目名称,1-100 字符 |
| description | string | 否 | 项目描述,最多 500 字符 |
**响应(VpV3ProjectOut):**
```json
{
"Id": "0019xxxxxxxxxxxxxxxx"
}
```
#### 7.2 查询项目列表
```
GET /api/v3/virtual-portrait/projects
```
**Query 参数:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| page | int | 否 | 页码,默认 1 |
| page_size | int | 否 | 每页数量 1-100,默认 20 |
| keyword | string | 否 | 项目名称模糊搜索 |
| status | string | 否 | 项目状态筛选(不传查全部) |
**响应:** `{ "items": [...], "total": N, "page": X, "page_size": Y }`
#### 7.3 项目详情
```
GET /api/v3/virtual-portrait/projects/{project_id}
```
#### 7.4 更新项目
修改展示信息(名称/描述),不会重新创建火山远端 Group。
```
PUT /api/v3/virtual-portrait/projects/{project_id}
```
#### 7.5 删除项目
软删项目和其下所有素材。**本地 commit 后会投递 Celery 异步任务去删除火山远端 AssetGroup/Asset**,接口返回 `remote_delete_status=pending` 表示远端删除处理中,可通过项目详情接口轮询最终状态。
```
DELETE /api/v3/virtual-portrait/projects/{project_id}
```
**响应示例:**
```json
{ "success": true, "remote_delete_status": "pending" }
```
---
### 8. 虚拟素材 CRUD
#### 8.1 在项目下创建素材
创建素材(一步到位:**仅传 URL**:
1. 服务端先将 `source_url`(公网 http(s))下载保存到本地存储系统(自动校验 URL/网络/MIME/大小)
2. 下载成功后占用 **本地存储配额 & 素材数配额
3. 再将本地公网 URL 同步提交给火山方舟 CreateAsset 进行异步审核
```
POST /api/v3/virtual-portrait/projects/{project_id}/assets
```
**请求体:**
```json
{
"source_url": "https://cdn.example.com/avatars/portrait_01.png",
"name": "虚拟人正面照片",
"asset_type": "Image"
}
```
**请求字段(新):**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| source_url | string | 是 | **公网可访问的 http(s) 图片/视频直链**,最多 2000 字符。<br/>⚠️ 不允许指向内网/本机地址(SSRF 防御) |
| name | string | 否 | 素材展示名,1-100 字符;不传自动从 URL 文件名或响应头 Content-Disposition 推断 |
| asset_type | string | 是 | `Image` / `Video` |
| video_duration | float | Video 可选 | 视频时长秒(1-60)。Video 不传会自动 ffprobe 探测,两者都失败则返回 400 需显式传入 |
| video_cover_url | string | 否(Video | 视频封面图 URL(可选,仅 Video 用) |
> 💡 **不再需要**`upload_resource_id` / `file_size_bytes` / `mime_type` —— 服务端自动探测并写入。
**创建流程时序(服务端内部处理步骤):**
1. 校验 URL 格式(http/https + 非内网) → 400
2. 下载 URL 文件到临时目录
- HTTP 4xx/5xx → 502(含前 200B 响应片段);连接/读取超时 → 502
- Content-Type 非法 → 415application/octet-stream 除外);大小超限 → 413
- 任一步失败:立即清理临时文件,不占配额
3. 配额校验(素材数 + 存储 MB,按真实大小)→ 不足则删除刚下载的本地文件,403
4. Video 时长合并校验(payload 优先,否则 ffprobe 探测) → 非法删本地文件并 400
5. 写 VpV3Assetstatus=Creating+ 刷新 next_poll_at
6. 调火山 CreateAsset(url=本地公网 URL) → 成功返回 Creating + remote_asset_id;失败则 status=Failed, error_message=错误
**响应:VpV3AssetOut**(字段见素材详情)
创建成功后 `status=Creating`,火山审核 3-30 秒,建议:
- 轮询 GET /assets/{id} 或 POST /assets/{id}/sync 主动刷新
- 直到 status=Active 才能在 AI 创作中使用
- 如果 status=Failed,读取 `error_message` / `moderation_json` 查看原因;可选择 DELETE 后重试
#### 8.2 查询项目下素材列表
```
GET /api/v3/virtual-portrait/projects/{project_id}/assets
```
**Query 参数:**
| 参数 | 类型 | 说明 |
|------|------|------|
| page / page_size | int | 分页,默认 1/20 |
| status | string | 素材状态筛选:Creating/Active/Failed/Deleting |
| keyword | string | 素材名称模糊搜索 |
| asset_type | string | Image / Video |
#### 8.3 素材详情
```
GET /api/v3/virtual-portrait/assets/{asset_id}
```
#### 8.4 主动同步素材状态
主动调火山 GetAsset 刷新素材状态、URL、审核结果(轮询中断或前端主动刷新时使用)。
```
POST /api/v3/virtual-portrait/assets/{asset_id}/sync
```
#### 8.5 删除素材
软删素材。本地 commit 时**同步删除本地落盘文件**(自动清理 `/uploads/...` 目录下的文件,带目录穿越防御),再投递 Celery 异步任务删除火山远端 Asset,返回 `remote_delete_status=pending` 表示处理中。
```
DELETE /api/v3/virtual-portrait/assets/{asset_id}
```
**响应示例:** `{ "success": true, "remote_delete_status": "pending" }`
> 说明:
> - 本地文件删除失败只打日志,不会影响素材状态置为 deleting + soft-delete(避免远端删除也回滚)
> - 删除成功后存储/素材数配额会自动返还(`/config` 接口再次查询可见 used 降低)
---
### 9. AI 创作选择器素材
只返回当前 API Key 虚拟素材库中 **status=Active** 的图片/视频素材,提供给 AI 创作参考素材选择器使用。
```
GET /api/v3/virtual-portrait/selectable-assets
```
**Query 参数:**
| 参数 | 类型 | 说明 |
|------|------|------|
| page / page_size | int | 分页,默认 1/201-100 |
| project_id | string | 可选,按项目筛选 |
| keyword | string | 可选,素材名称模糊搜索 |
| asset_type | string | 可选,Image / Video |
**响应字段(VpV3SelectableAssetOut):**
| 字段 | 类型 | 说明 |
|------|------|------|
| asset_id | string | 素材 ID,供后续带入生成(预留使用:`source=vp_v3_asset, asset_id` |
| project_id | string | 所属项目 ID |
| name | string | 素材名称 |
| asset_type | string | Image/Video |
| status | string | Active |
| source_url | string | 原始上传 URL |
| preview_url | string | 显示用预览 URL(直接绑定 img/video src |
| video_duration | float | 视频时长秒(Video 时有值) |
| video_cover_url | string | 视频封面 |
| file_size_bytes | int | 文件大小字节 |
| created_at | datetime | 创建时间 |
---
### 虚拟素材库配额限制错误
当 API Key 的虚拟素材库配额不足时,会返回 403:
```json
{
"error": {
"code": "quota_exceeded",
"message": "虚拟素材库配额不足:素材总数 上限 50,已使用 50,本次需要 1,超出上限"
}
}
```
如果管理员完全没有配置配额(全 0),任何虚拟素材库操作都返回:
```json
{
"error": {
"code": "forbidden",
"message": "当前 API Key 未开启虚拟素材库功能,请联系管理员配置配额"
}
}
```
---
## 价格计算规则
API 采用**先扣后退回**策略:任务创建/生成前预扣配额,失败时自动退回。
### 视频价格公式
```
基础费用 = (base_price + per_second_price × duration) × price_ratio
传入视频附加 = (input_video_base_price + input_video_per_second_price × 视频时长) × input_video_ratio
传入图片附加 = (input_image_base_price + input_image_per_image_price × 图片数量) × input_image_ratio
总价格 = 基础费用 + 传入视频附加 + 传入图片附加
```
### 图片价格公式
```
基础费用 = base_price × price_ratio
传入图片附加 = (input_image_base_price + input_image_per_image_price × 图片数量) × input_image_ratio
总价格 = 基础费用 + 传入图片附加
```
### 价格查找优先级
1. 引擎专属规则: `gen_type + engine_id + resolution`
2. 降级: `gen_type + resolution`(取 base_price 最高的)
3. 未配置价格的模型不会出现在可用列表中
---
## 状态码说明
| 状态码 | 说明 |
|--------|------|
| 200 | 请求成功 |
| 202 | 任务已创建(视频接口) |
| 401 | API Key 无效或缺失 |
| 403 | API Key 过期或无权限 |
| 404 | 资源不存在 |
| 422 | 请求参数校验失败 |
| 429 | 配额不足或并发超限 |
| 500 | 服务器内部错误 |
| 504 | 生成超时(图片接口) |
---
## 使用示例
### cURL 示例
```bash
# 1. 获取可用模型
curl -X GET http://localhost:8000/api/v3/models \
-H "Authorization: Bearer vk_xxxxxxxxxxxx"
# 2. 创建视频任务
curl -X POST http://localhost:8000/api/v3/videos \
-H "Authorization: Bearer vk_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seedance-2-0-260128",
"content": [{"type": "text", "text": "一只猫在草地上奔跑"}],
"ratio": "16:9",
"duration": 5,
"resolution": "1080p"
}'
# 3. 查询视频状态
curl -X GET http://localhost:8000/api/v3/videos/{task_id} \
-H "Authorization: Bearer vk_xxxxxxxxxxxx"
# 4. 生成图片
curl -X POST http://localhost:8000/api/v3/images \
-H "Authorization: Bearer vk_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seedream-5-0-260128",
"prompt": "一只可爱的猫咪",
"size": "2K"
}'
```
### Python 示例
```python
import requests
BASE_URL = "http://localhost:8000/api/v3"
API_KEY = "vk_xxxxxxxxxxxx"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
# 获取模型列表
resp = requests.get(f"{BASE_URL}/models", headers=HEADERS)
models = resp.json()["models"]
# 创建视频任务
resp = requests.post(f"{BASE_URL}/videos", headers=HEADERS, json={
"model": "doubao-seedance-2-0-260128",
"content": [{"type": "text", "text": "一只猫在草地上奔跑"}],
"ratio": "16:9",
"duration": 5,
"resolution": "1080p",
})
task_id = resp.json()["task_id"]
# 轮询视频状态
import time
while True:
resp = requests.get(f"{BASE_URL}/videos/{task_id}", headers=HEADERS)
data = resp.json()
if data["status"] == "completed":
print(f"视频URL: {data['video_url']}")
break
elif data["status"] == "failed":
print(f"失败: {data['error']}")
break
time.sleep(30)
# 生成图片
resp = requests.post(f"{BASE_URL}/images", headers=HEADERS, json={
"model": "doubao-seedream-5-0-260128",
"prompt": "一只可爱的猫咪",
"size": "2K",
})
images = resp.json()["data"]
for img in images:
print(f"图片URL: {img['url']}")
```
---
## HTTP 状态码
所有接口 HTTP 状态码固定返回 **200**,业务结果通过响应体中的 `code` 字段判断:
| code | 说明 |
|------|------|
| 0 | 成功 |
| 40000 | 请求参数错误 |
| 40001 | 模型+分辨率未配置价格 |
| 40100 | API Key 无效或缺失 |
| 40300 | API Key 过期或无权限 |
| 40400 | 资源不存在 |
| 42200 | 参数校验失败 |
| 42900 | 配额不足或并发超限 |
| 50000 | 服务器内部错误 |
| 50400 | 生成超时(图片接口) |
---
## 统一响应格式
**成功响应:**
```json
{
"code": 0,
"data": { ... },
"message": "ok"
}
```
**错误响应:**
```json
{
"code": 40001,
"data": null,
"message": "模型 'eng_xxxx' 在分辨率 '1080p' 下未配置,无法生成"
}
```
---
## 注意事项
1. **配额预扣**: 视频任务创建时预扣配额,失败时自动退回
2. **并发限制**: 每个 API Key 有最大并发视频任务数限制
3. **轮询间隔**: 视频任务建议轮询间隔 30 秒(前 10 分钟可缩短至 30 秒,之后逐步增加)
4. **超时时间**: 视频任务最长 24 小时,超时自动失败并退回配额
5. **幂等键**: 视频接口支持 `idempotency_key`,相同键重复请求返回同一任务
6. **图片同步**: 图片接口为同步阻塞调用,建议设置 300 秒超时
7. **统一格式**: 所有接口 HTTP 状态码固定 200,通过 `code` 字段判断业务结果
---
## 部署与运维
### Celery Worker 启动命令
API v3 视频异步生成依赖以下 3 个 Celery 队列:
| 队列 | 用途 | 推荐并发 |
|------|------|---------|
| `gen_api_create` | 视频任务创建(调用 Volcano Ark SDK | 2-4 |
| `gen_api_poll` | 视频状态轮询 | 2-4 |
| `gen_api_download` | 视频下载与超分 | 2-4 |
```bash
# 启动 API v3 专用 Worker
celery -A app.tasks.celery_app worker -l info \
-Q gen_api_create,gen_api_poll,gen_api_download \
--concurrency=4 -n worker_api@%h
# 启动 Beat 调度器(定时恢复任务)
celery -A app.tasks.celery_app beat -l info
```
### 容灾恢复
服务重启后,Worker 会自动触发恢复扫描:
- 扫描 48 小时内未完成的 `ApiGenerationTask`
- 重新入队中断的 Celery 任务
- 每分钟定时扫描(Beat 调度)
### 日志目录
```
storage/logs/external/
├── requests/ # 外部 API 请求/响应日志
├── models/ # 模型调用日志
├── upscale/ # 超分轮询日志
└── errors/ # 错误日志
```