# 对外开放模型 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 字符。
⚠️ 不允许指向内网/本机地址(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 非法 → 415(application/octet-stream 除外);大小超限 → 413 - 任一步失败:立即清理临时文件,不占配额 3. 配额校验(素材数 + 存储 MB,按真实大小)→ 不足则删除刚下载的本地文件,403 4. Video 时长合并校验(payload 优先,否则 ffprobe 探测) → 非法删本地文件并 400 5. 写 VpV3Asset(status=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/20(1-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/ # 错误日志 ```