# Vidu TTS API 开发文档

> 来源：https://platform.vidu.cn/docs/text-to-speech  
> 更新时间：2026-04-21

## 一、概述

Vidu（生数科技）提供语音合成（TTS）和声音复刻能力，所有接口均为**同步接口**，直接返回结果，无需轮询。

- **Base URL**: `https://api.vidu.cn`
- **认证方式**: `Authorization: Token {your_api_key}`
- **Content-Type**: `application/json`

---

## 二、语音合成 TTS

### 端点

```
POST /ent/v2/audio-tts
```

### 请求头

| 字段 | 值 | 描述 |
|------|-----|------|
| Content-Type | application/json | 数据交换格式 |
| Authorization | Token {your_api_key} | API Key 认证 |

### 请求体

| 参数名称 | 类型 | 必填 | 描述 |
|----------|------|------|------|
| text | String | 是 | 待合成文本，**< 10000 字符**。支持 `<#x#>` 停顿标记，x 为停顿时长（秒），范围 [0.01, 99.99] |
| voice_setting_voice_id | String | 是 | 音色 ID |
| voice_setting_speed | Float | 否 | 语速，默认 1.0，范围 [0.5, 2] |
| voice_setting_volume | Int | 否 | 音量，默认 0（正常音量），范围 [0, 10]，值越大音量越高 |
| voice_setting_pitch | Int | 否 | 语调，默认 0（原音色），范围 [-12, 12] |
| voice_setting_emotion | String | 否 | 情绪控制：`happy`/`sad`/`angry`/`fearful`/`disgusted`/`surprised`/`calm`。一般无需手动指定，模型自动匹配 |
| pronunciation_dict_tone | list | 否 | 多音字发音定义，如 `["燕少飞/(yan4)(shao3)(fei1)"]` |
| payload | String | 否 | 透传参数，最多 1048576 字符 |

### 响应体

```json
{
  "task_id": "your_task_id_here",
  "state": "success",
  "file_url": "https://...",
  "credits": 10,
  "payload": "",
  "created_at": "2025-01-01T15:41:31.968916Z"
}
```

| 字段 | 类型 | 描述 |
|------|------|------|
| task_id | String | Vidu 生成的任务 ID |
| state | String | `queueing` / `success` / `failed` |
| file_url | String | 音频文件 URL |
| credits | Int | 本次调用消耗的积分数 |
| payload | String | 透传参数 |
| created_at | String | 任务创建时间 |

### Curl 示例

```bash
curl -X POST https://api.vidu.cn/ent/v2/audio-tts \
  -H "Authorization: Token {your_api_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "你好，欢迎使用vidu开放平台",
    "voice_setting_voice_id": "female-tianmei"
  }'
```

---

## 三、声音复刻

### 端点

```
POST /ent/v2/audio-clone
```

### 请求体

| 参数名称 | 类型 | 必填 | 描述 |
|----------|------|------|------|
| audio_url | String | 是 | 原音频 URL（需可访问）。格式：mp3/m4a/wav；时长：10秒~5分钟；大小：≤20MB |
| voice_id | String | 是 | 自定义声音 ID。长度 [8, 256]；首字符必须为英文字母；允许数字、字母、横线、下划线；末位不可为 `-`、`_`；不可与已有 ID 重复 |
| prompt_audio_url | String | 否 | 音色复刻示例音频（< 8秒），可增强音色相似度和稳定性 |
| prompt_text | String | 否 | 示例音频对应文本，需与音频内容一致，句末需有标点 |
| text | String | 是 | 复刻试听文本，≤1000 字符。使用复刻后的音色朗读，返回试听音频 |
| payload | String | 否 | 透传参数 |

### 响应体

```json
{
  "task_id": "your_task_id_here",
  "state": "success",
  "voice_id": "vidu01",
  "demo_audio": "https://...",
  "payload": "",
  "created_at": "2025-01-01T15:41:31.968916Z"
}
```

| 字段 | 类型 | 描述 |
|------|------|------|
| task_id | String | 任务 ID |
| state | String | `queueing` / `success` / `failed` |
| voice_id | String | 用户自定义的 voice_id（任务失败时不返回）|
| demo_audio | String | 试听音频链接（仅当请求传入 text 时返回）|
| payload | String | 透传参数 |
| created_at | String | 创建时间 |

### Curl 示例

```bash
curl -X POST https://api.vidu.cn/ent/v2/audio-clone \
  -H "Authorization: Token {your_api_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "audio_url": "your_audio_url",
    "voice_id": "vidu01",
    "text": "你好，欢迎使用vidu开放平台"
  }'
```

---

## 四、预设音色列表

共 **16 个中文（普通话）**音色，分标准版和 Beta（精品）版。

### 标准版

| voice_id | 音色名称 |
|----------|----------|
| male-qn-qingse | 青涩青年音色 |
| male-qn-jingying | 精英青年音色 |
| male-qn-badao | 霸道青年音色 |
| male-qn-daxuesheng | 青年大学生音色 |
| female-shaonv | 少女音色 |
| female-yujie | 御姐音色 |
| female-chengshu | 成熟女性音色 |
| female-tianmei | 甜美女性音色 |

### Beta（精品）版

| voice_id | 音色名称 |
|----------|----------|
| male-qn-qingse-jingpin | 青涩青年音色-beta |
| male-qn-jingying-jingpin | 精英青年音色-beta |
| male-qn-badao-jingpin | 霸道青年音色-beta |
| male-qn-daxuesheng-jingpin | 青年大学生音色-beta |
| female-shaonv-jingpin | 少女音色-beta |
| female-yujie-jingpin | 御姐音色-beta |
| female-chengshu-jingpin | 成熟女性音色-beta |
| female-tianmei-jingpin | 甜美女性音色-beta |

> 音色试听示例 URL 格式：`https://scene.vidu.zone/media-asset/{id}.mp3`（见飞书表格原始链接）

---

## 五、与 MiniMax 对比（接入参考）

| 维度 | Vidu | MiniMax |
|------|------|---------|
| Base URL | `https://api.vidu.cn` | `https://api.minimaxi.com` |
| 认证 | `Token {key}` | `Bearer {key}` |
| TTS 端点 | `POST /ent/v2/audio-tts` | `POST /v1/t2a_v2` |
| 同步/异步 | 同步 | 同步 + 异步 |
| 文本上限 | 10000 字符 | 10000 字符（同步）|
| 语速范围 | 0.5 ~ 2.0 (Float) | 需传 Int |
| 音量范围 | 0 ~ 10 (Int，0=正常) | 需传 Int |
| 语调范围 | -12 ~ 12 (Int) | 需传 Int |
| 情绪控制 | 7 种情绪可选 | 不支持 |
| 多音字 | 支持 `pronunciation_dict_tone` | 不支持 |
| 声音复刻 | 同步，自定义 voice_id | 异步，系统分配 voice_id |
| 复刻音频要求 | 10秒~5分钟，≤20MB | 约 10秒~5分钟 |
| 预设音色 | 16 个中文 | 6 个中文 |
| 响应音频字段 | `file_url` | `audio` |

---

## 六、视频生成（Lip Sync）

### 端点

```
POST /ent/v2/lip-sync
```

**⚠️ 异步接口**，创建后返回 task_id，需要通过查询接口轮询或使用 callback_url 接收回调。

### 请求体

| 参数名称 | 类型 | 必填 | 描述 |
|----------|------|------|------|
| video_url | String | 是 | 原视频 URL（需可访问）。格式：mp4/mov/avi；时长：1~600秒（建议 10~120秒）；大小：≤5G；分辨率：360p~4096p；编码：H.264 |
| audio_url | String | 否 | 音频文件 URL。格式：wav/mp3/wma/m4a/aac/ogg；时长：>1s 且 <600s；大小：≤100MB |
| text | String | 否 | 文本内容，4~2000 字符。与 audio_url 同时有值时，以 audio_url 为准 |
| speed | Float | 否 | 语速，默认 1.0，范围 [0.5, 2]。仅文字生成时生效 |
| voice_id | String | 否 | 音色 ID。仅文字生成时生效 |
| volume | Int | 否 | 音量，默认 0（正常音量），范围 [0, 10]。仅文字生成时生效 |
| ref_photo_url | String | 否 | 人脸参考图 URL（jpg/jpeg/png/bmp/webp，192~4096px，≤10MB）。视频中有多张人脸时，用于指定视频生成目标人物 |
| callback_url | String | 否 | 回调地址，任务状态变化时 POST 回调 |

### 视频素材规范

- 真人出镜（卡通人物需五官比例接近真人）
- 人脸正对镜头，水平转动不超过 45°，俯仰不超过 15°
- 人脸尽量不遮挡，面部光线稳定

### 创建响应

```json
{
  "task_id": "your_task_id_here",
  "state": "created",
  "payload": "",
  "created_at": "2025-01-01T15:41:31.968916Z"
}
```

### 查询任务状态

```
GET /ent/v2/tasks/{task_id}/creations
```

**响应体**：

| 字段 | 类型 | 描述 |
|------|------|------|
| id | String | 任务 ID |
| state | String | `created`/`queueing`/`processing`/`success`/`failed` |
| err_code | String | 错误码 |
| credits | Int | 消耗的积分数 |
| payload | String | 透传参数 |
| bgm | Bool | 是否使用 BGM |
| off_peak | Bool | 是否使用错峰模式 |
| creations | Array | 生成物结果列表 |
| creations[].id | String | 生成物 ID |
| creations[].url | String | 生成物 URL（24小时有效期） |
| creations[].cover_url | String | 生成物封面 URL（24小时有效期） |
| creations[].watermarked_url | String | 带水印的生成物 URL |

### Curl 示例（音频驱动）

```bash
curl -X POST https://api.vidu.cn/ent/v2/lip-sync \
  -H "Authorization: Token {your_api_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "video_url": "your_video_url",
    "audio_url": "your_audio_url"
  }'
```

### Curl 示例（文字驱动）

```bash
curl -X POST https://api.vidu.cn/ent/v2/lip-sync \
  -H "Authorization: Token {your_api_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "video_url": "your_video_url",
    "text": "你好，欢迎使用vidu开放平台",
    "voice_id": "female-tianmei",
    "speed": 1.0
  }'
```

---

## 七、回调签名验证

Vidu 在回调通知时会携带 **HMAC-SHA256** 签名，后端必须验证签名后才能信任回调内容，防止第三方伪造回调请求。

### 7.1 签名生成公式

```
signature = base64(HMAC-SHA256(secret_key, signingString))
```

其中：
- `secret_key`：创建任务时使用的 Token，即 `VIDU_API_KEY`
- `signingString`：签名字符串，按以下格式构建

### 7.2 签名字符串（signingString）

```
signingString = http_method + "\n"
              + http_uri + "\n"
              + canonical_query_string + "\n"
              + access_key + "\n"
              + Date + "\n"
              + signed_headers_string
```

各参数说明：

| 参数 | 说明 |
|------|------|
| `http_method` | HTTP 方法，必须全大写（如 `POST`） |
| `http_uri` | 从 `callback_url` 解析出的 **path** 部分，必须以 `"/"` 开头 |
| `canonical_query_string` | 从 `callback_url` 解析出的原始 **query** 部分（不含 `?`），无参数时为空字符串 |
| `access_key` | 固定为 `"vidu"` |
| `Date` | 请求头中的 `Date` 值，GMT 格式，如 `"Tue, 06 May 2025 12:09:42 GMT"` |
| `signed_headers_string` | 按 `X-HMAC-SIGNED-HEADERS` 指定的顺序，拼接 `HeaderKey:HeaderValue\n` |

> ⚠️ **注意**：字符串末尾有一个换行符；查询参数必须使用原始格式，不要包含 `"?"`。

### 7.3 签名相关请求头

Vidu 回调时会携带以下请求头：

| Header | 说明 |
|--------|------|
| `Date` | GMT 格式时间，例如：`Tue, 06 May 2025 12:09:42 GMT` |
| `x-request-nonce` | UUID 格式随机字符串，用于防止重放攻击 |
| `X-HMAC-SIGNED-HEADERS` | 签名使用的头部字段列表，用分号分隔，如 `Date;x-request-nonce` |
| `X-HMAC-SIGNATURE` | 最终计算出的 Base64 签名 |
| `X-HMAC-ALGORITHM` | 签名算法，固定为 `hmac-sha256` |
| `X-HMAC-ACCESS-KEY` | 访问密钥标识符，固定为 `vidu` |

### 7.4 后端验证逻辑

后端 `/vidu/callback` 接口在读取请求体之前，必须执行以下验证：

1. **基础校验**：确认所有签名相关 Header 存在，且 `X-HMAC-ALGORITHM` 为 `hmac-sha256`、`X-HMAC-ACCESS-KEY` 为 `vidu`
2. **防重放检查**：将 `x-request-nonce` 存入 Redis（TTL 5 分钟），若已存在则拒绝请求
3. **构建 signingString**：从当前请求 URL 提取 `path` 和 `query`，按公式拼接签名字符串
4. **计算期望签名**：使用 `VIDU_API_KEY` 作为 `secret_key`，计算 `HMAC-SHA256` 后进行 Base64 编码
5. **安全比对**：使用 `hmac.compare_digest()` 进行常量时间比对，防止时序攻击

验证失败时返回 **HTTP 401**，不处理请求体。

### 7.5 示例：签名字符串生成

假设 Vidu 发起回调：

```http
POST /api/v1/vidu/callback HTTP/1.1
Host: 127.0.0.1:8081
Date: Tue, 06 May 2025 12:09:42 GMT
x-request-nonce: 123e4567-e89b-12d3-a456-426614174000
X-HMAC-SIGNED-HEADERS: Date;x-request-nonce
X-HMAC-SIGNATURE: xxxxxx
X-HMAC-ALGORITHM: hmac-sha256
X-HMAC-ACCESS-KEY: vidu
```

生成的 `signingString` 为：

```
POST
/api/v1/vidu/callback

vidu
Tue, 06 May 2025 12:09:42 GMT
Date:Tue, 06 May 2025 12:09:42 GMT
x-request-nonce:123e4567-e89b-12d3-a456-426614174000
```

> 注意：
> - `canonical_query_string` 为空（URL 无 query 参数），所以第四行是空行后的 `vidu`
> - 每行以 `\n` 结尾，包括最后一行 `HeaderValue` 后面也有 `\n`

### 7.6 代码实现位置

签名验证逻辑封装在 `python-api/app/api/v1/vidu.py`：

- `_build_vidu_signing_string()` — 构建签名字符串
- `_verify_vidu_callback()` — 完整验证流程（签名 + 防重放）
- `vidu_callback()` — 在读取请求体前调用 `_verify_vidu_callback()`，验证失败返回 401

---

## 八、接入建议

1. **Vidu 优势**：情绪控制、多音字标注、16 个音色（含精品版）、同步复刻、视频生成
2. **Vidu 劣势**：没有独立的"查询音色列表"API，音色通过飞书表格维护
3. **接口类型差异**：
   - TTS / 声音复刻：**同步接口**，直接返回结果
   - 视频生成：**异步接口**，需轮询 `GET /tasks/{id}/creations` 或使用 callback
4. **速度/音量/音调类型**：Vidu 的速度是 **Float**，音量和音调是 **Int**（和 MiniMax 不同，MiniMax 三者都要求 Int）
5. **前端适配**：语速 slider 范围改为 0.5~2.0；音量改为 0~10；音调改为 -12~12
