# 视频生成网关 API 文档

版本：2.0  
基础地址：`https://api.tiaotiao.shop`

本文档只描述网关对外接口。所有生成结果均返回本网关地址。

---

## 1. 鉴权

所有 `/v1/*` 接口建议使用 Bearer Token：

```http
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

兼容模式也支持查询参数：

```text
?api_key=YOUR_API_KEY
```

---

## 2. 视频模型列表

### 请求

```http
GET /api/models?modality=video
```

### 响应示例

```json
{
  "models": [
    {
      "id": "tiaotiao:video:t2v",
      "name": "视频生成",
      "modality": "video",
      "task_type": "text_to_video",
      "supported_aspect_ratios": ["9:16", "16:9", "1:1", "4:3", "3:4", "21:9"],
      "supported_durations": [5, 10, 15],
      "audio": true
    },
    {
      "id": "tiaotiao:video:i2v",
      "name": "图生视频",
      "modality": "video",
      "task_type": "image_to_video",
      "supported_aspect_ratios": ["9:16", "16:9", "1:1", "4:3", "3:4", "21:9"],
      "supported_durations": [5, 10, 15],
      "audio": true
    }
  ]
}
```

说明：视频固定带音频，客户端不需要传递音频开关字段。

---

## 3. 提交文生视频任务

### 请求

```http
POST /v1/videos/generations
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

### Body

```json
{
  "model": "tiaotiao:video:t2v",
  "prompt": "一只橘猫在雨夜霓虹街道上奔跑，电影感镜头",
  "duration": 10,
  "ratio": "9:16"
}
```

### 字段

| 字段 | 类型 | 必填 | 说明 |
|---|---:|---:|---|
| `model` | string | 否 | 视频模型 ID；默认文生视频 |
| `prompt` | string | 是 | 视频提示词 |
| `duration` | integer | 否 | 秒数，支持 `5`、`10`、`15`；默认 `15` |
| `ratio` | string | 否 | 比例，支持 `9:16`、`16:9`、`1:1`、`4:3`、`3:4`、`21:9`；默认 `9:16` |

### 响应示例

```json
{
  "task_id": "24368c66b7b1447a9644f52265853742",
  "status": "queued"
}
```

---

## 4. 提交图生视频任务

### 请求

```http
POST /v1/videos/generations
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

### Body：base64 图片

```json
{
  "model": "tiaotiao:video:i2v",
  "prompt": "让画面中的人物向镜头微笑并挥手，镜头缓慢推进",
  "duration": 10,
  "ratio": "9:16",
  "images": [
    {
      "name": "first-frame.jpg",
      "mime": "image/jpeg",
      "data_b64": "BASE64_IMAGE_DATA"
    }
  ]
}
```

### Body：已上传文件路径

```json
{
  "model": "tiaotiao:video:i2v",
  "prompt": "让图片中的场景动起来，电影感光影",
  "duration": 10,
  "ratio": "16:9",
  "input_files": ["uploads/OBJECT_KEY"]
}
```

说明：

- `images` 与 `input_files` 二选一。
- 首帧/参考图由网关处理。
- 视频固定带音频，客户端不需要传递音频字段。

---

## 5. 上传图片文件

网页端可使用预签名上传流程。

### 5.1 获取上传地址

```http
POST /api/upload/presign-object
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

Body：

```json
{
  "filename": "first-frame.jpg",
  "content_type": "image/jpeg"
}
```

响应：

```json
{
  "upload_url": "/api/nexus-upload/UPLOAD_TOKEN",
  "object_key": "uploads/UPLOAD_TOKEN",
  "headers": {
    "Content-Type": "image/jpeg",
    "Authorization": "Bearer YOUR_API_KEY"
  },
  "filename": "first-frame.jpg"
}
```

### 5.2 上传文件

```http
PUT /api/nexus-upload/UPLOAD_TOKEN
Authorization: Bearer YOUR_API_KEY
Content-Type: image/jpeg
```

Body 为图片二进制。

### 5.3 确认上传

```http
POST /api/upload/confirm-object
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

Body：

```json
{
  "object_key": "uploads/UPLOAD_TOKEN"
}
```

响应：

```json
{
  "object_key": "uploads/UPLOAD_TOKEN",
  "path": "uploads/UPLOAD_TOKEN",
  "url": "/uploads/UPLOAD_TOKEN",
  "public_url": "/uploads/UPLOAD_TOKEN"
}
```

---

## 6. 查询任务状态

### 请求

```http
GET /v1/tasks/{task_id}
Authorization: Bearer YOUR_API_KEY
```

### 响应：排队中

```json
{
  "task_id": "24368c66b7b1447a9644f52265853742",
  "type": "video",
  "status": "queued",
  "model": "tiaotiao:video:t2v",
  "ratio": "9:16",
  "duration": 10,
  "progress": "正在生成",
  "result_urls": [],
  "video_url": null,
  "download_url": null,
  "error": null
}
```

### 响应：生成中

```json
{
  "task_id": "24368c66b7b1447a9644f52265853742",
  "type": "video",
  "status": "running",
  "model": "tiaotiao:video:t2v",
  "ratio": "9:16",
  "duration": 10,
  "progress": "正在生成",
  "result_urls": [],
  "video_url": null,
  "download_url": null,
  "error": null
}
```

### 响应：成功

```json
{
  "task_id": "24368c66b7b1447a9644f52265853742",
  "type": "video",
  "status": "success",
  "model": "tiaotiao:video:t2v",
  "ratio": "9:16",
  "duration": 10,
  "progress": "生成完成",
  "result_urls": [
    "/v1/tasks/24368c66b7b1447a9644f52265853742/video"
  ],
  "video_url": "/v1/tasks/24368c66b7b1447a9644f52265853742/video",
  "download_url": "/v1/tasks/24368c66b7b1447a9644f52265853742/video",
  "error": null
}
```

### 响应：失败

```json
{
  "task_id": "24368c66b7b1447a9644f52265853742",
  "type": "video",
  "status": "failed",
  "model": "tiaotiao:video:t2v",
  "ratio": "9:16",
  "duration": 10,
  "progress": "生成失败",
  "result_urls": [],
  "video_url": null,
  "download_url": null,
  "error": "生成失败，请稍后重试"
}
```

状态枚举：

| 状态 | 说明 |
|---|---|
| `queued` | 已提交，等待处理 |
| `running` | 正在生成 |
| `success` | 已完成 |
| `failed` | 失败 |

---

## 7. 下载/播放视频

### 请求

```http
GET /v1/tasks/{task_id}/video
Authorization: Bearer YOUR_API_KEY
```

成功时返回 `video/mp4` 文件流。

也可直接访问查询任务返回的 `video_url`：

```text
https://api.tiaotiao.shop/v1/tasks/{task_id}/video
```

注意：该地址是网关本机视频地址。

---

## 8. 兼容网页任务接口

### 登录

```http
POST /api/auth/login
Content-Type: application/x-www-form-urlencoded
```

Body：

```text
username=USERNAME&password=API_KEY
```

响应：

```json
{
  "access_token": "API_KEY",
  "token_type": "bearer",
  "user": {
    "id": "USER_ID",
    "username": "USERNAME",
    "display_name": "USERNAME",
    "credits": 1000,
    "balance_points": 1000,
    "is_admin": false
  }
}
```

### 创建网页任务

```http
POST /api/tasks/
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

文生视频：

```json
{
  "task_type": "text_to_video",
  "global_prompt": "城市夜景延时摄影，霓虹灯闪烁",
  "config_json": {
    "model": "tiaotiao:video:t2v",
    "aspect_ratio": "9:16",
    "seconds": 10
  },
  "tasks": [
    {"prompt": "城市夜景延时摄影，霓虹灯闪烁"}
  ]
}
```

图生视频：

```json
{
  "task_type": "image_to_video",
  "global_prompt": "图片中的人物自然转头，背景微风摆动",
  "config_json": {
    "model": "tiaotiao:video:i2v",
    "aspect_ratio": "9:16",
    "seconds": 10
  },
  "tasks": [
    {"input_files": ["uploads/OBJECT_KEY"]}
  ]
}
```

响应：

```json
{
  "id": "TASK_ID",
  "title": "文生视频 城市夜景延时摄影",
  "task_type": "text_to_video",
  "status": "queued",
  "total_count": 1,
  "completed_count": 0,
  "failed_count": 0,
  "progress_message": "正在生成",
  "tasks": [
    {
      "id": "TASK_ID",
      "status": "queued",
      "output_file": null,
      "source_url": null
    }
  ]
}
```

### 任务列表

```http
GET /api/tasks/?limit=100
Authorization: Bearer YOUR_API_KEY
```

### 网页视频文件

```http
GET /v1/tasks/{task_id}/video
Authorization: Bearer YOUR_API_KEY
```

成功时返回 `video/mp4` 文件流。

---

## 9. 常见错误

| HTTP 状态 | 说明 |
|---:|---|
| `400` | 请求参数错误 |
| `401` | API Key 无效或缺失 |
| `402` | 当前用户余额不足 |
| `404` | 任务或文件不存在 |
| `409` | 任务生成中，暂不可删除 |
| `429` | 当前队列繁忙，请稍后重试 |
| `500` | 服务端处理异常 |

错误响应示例：

```json
{
  "detail": "生成队列已满，请稍后重试"
}
```

---

## 10. 调用示例

### cURL 提交文生视频

```bash
curl -X POST "https://api.tiaotiao.shop/v1/videos/generations" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model":"tiaotiao:video:t2v",
    "prompt":"一只橘猫在雨夜霓虹街道上奔跑，电影感镜头",
    "duration":10,
    "ratio":"9:16"
  }'
```

### cURL 查询任务

```bash
curl "https://api.tiaotiao.shop/v1/tasks/TASK_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### cURL 下载视频

```bash
curl -L "https://api.tiaotiao.shop/v1/tasks/TASK_ID/video" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -o result.mp4
```
