音色克隆接口
通过上传参考音频,克隆出专属音色,后续 TTS 生成直接使用自定义 voice_id 调用即可。
使用限制
- 每个账户最多保存 5 个自定义音色
响应说明
- 本页三个接口均返回 JSON;成功返回 HTTP
200。查询和删除音色的业务失败也返回 HTTP200;保存音色失败时返回对应的 HTTP 错误状态码(见本页错误码表) - 请通过
succeed判断操作是否成功,通过error_code和error_message查看失败原因 - 成功响应的结果位于
data字段内
{
"error_code": 0,
"error_message": "成功",
"succeed": true,
"data": {}
}
完整使用流程
Step 1:上传本地参考音频,取得 object_key
Step 2:使用 object_key 和自定义名称保存音色,参考文本由服务端自动解析
Step 3:(可选)查看已保存的音色列表
Step 4:在 TTS 生成接口中使用自定义 voice_id
Step 5:(可选)删除不再使用的音色
如果参考音频已经有可公开访问的 HTTP/HTTPS URL,可以跳过 Step 1,直接把 URL 作为 ref_audio。
一、保存音色
创建新音色或更新已有音色(同名则覆盖)。
接口信息
- 接口路径:
/v1/voice/save - 请求方式:
POST - 认证方式: Header 中的
X-API-Key
请求头
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| X-API-Key | string | 是 | 应用密钥 |
请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| voice_id | string | 是 | 自定义音色名称,只允许小写字母、数字、-、_,最长 64 字符 |
| ref_audio | string | 是 | 参考音频,支持公开 HTTP/HTTPS URL 或 OSS object_key;HTTP/HTTPS URL 必须解析到公网地址 |
ref_audio始终必填,参考文本由服务端自动解析参考音频获得,无需手动填写。原始参考音频支持常见格式(MP3、WAV、M4A 等),大小不超过 50MB,时长为 3~60 秒。音频应包含清晰语音;无法获得有效文本时,保存会失败。
服务端从原始参考音频中选取 3~15 秒语音片段,保存该片段及其配对文本。原始音频可长于选取片段,最长为 60 秒。
响应说明
请求成功时,data 为空对象:
{
"error_code": 0,
"error_message": "成功",
"succeed": true,
"data": {}
}
请求示例
推荐方式:先上传参考音频
调用通用文件上传接口上传本地文件。上传和保存音色必须使用同一个 X-API-Key:
上传文件要求
上传前请确保参考音频符合以下要求:
- 文件大小不超过 50MB。
- 原始参考音频时长为 3~60 秒。
不符合要求的文件将无法用于音色克隆。
curl -X POST "https://api.vuilabs.cn/v1/files/upload" \
-H "X-API-Key: your-secret-key-here" \
-F "scene=audio" \
-F "file=@/path/to/sample.wav"
从成功响应中读取 data.object_key:
{
"error_code": 0,
"error_message": "成功",
"succeed": true,
"data": {
"object_key": "uploads/audio/1001/20260630/1782820801123_abcd1234_sample.wav",
"file_name": "sample.wav",
"size": 123456,
"scene": "audio"
}
}
将 data.object_key 原样填入保存音色请求的 ref_audio:
curl -X POST "https://api.vuilabs.cn/v1/voice/save" \
-H "X-API-Key: your-secret-key-here" \
-H "Content-Type: application/json" \
-d '{
"voice_id": "my-voice",
"ref_audio": "uploads/audio/1001/20260630/1782820801123_abcd1234_sample.wav"
}'
上传接口默认不返回
url;这里直接使用object_key,不需要自行拼接 OSS URL。服务端会自动解析参考音频并获得文本。
使用已有公开 URL
curl -X POST "https://api.vuilabs.cn/v1/voice/save" \
-H "X-API-Key: your-secret-key-here" \
-H "Content-Type: application/json" \
-d '{
"voice_id": "my-voice",
"ref_audio": "https://example.com/sample.wav"
}'
各语言示例
Python
import requests
response = requests.post(
"https://api.vuilabs.cn/v1/voice/save",
headers={"X-API-Key": "your-secret-key-here"},
json={
"voice_id": "my-voice",
"ref_audio": "https://example.com/sample.wav"
}
)
payload = response.json()
if payload["succeed"]:
print("音色保存成功")
else:
print(payload["error_code"], payload["error_message"])
Node.js
const https = require("https");
const body = JSON.stringify({
voice_id: "my-voice",
ref_audio: "https://example.com/sample.wav",
});
const req = https.request(
{
hostname: "api.vuilabs.cn",
path: "/v1/voice/save",
method: "POST",
headers: {
"X-API-Key": "your-secret-key-here",
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(body),
},
},
(res) => {
let data = "";
res.on("data", (chunk) => (data += chunk));
res.on("end", () => {
const payload = JSON.parse(data);
if (payload.succeed) {
console.log("音色保存成功");
} else {
console.error("Error:", payload.error_code, payload.error_message);
}
});
}
);
req.write(body);
req.end();
二、查看音色列表
分页列出当前账户下已保存的自定义音色。每页最多返回 20 条,下一页使用上次响应中的 next_voice_id 作为请求参数。
接口信息
- 接口路径:
/v1/voice/list - 请求方式:
GET - 认证方式: Header 中的
X-API-Key
请求头
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| X-API-Key | string | 是 | 应用密钥 |
查询参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| voice_id | string | 否 | 上一页响应中的 next_voice_id;首次查询不传 |
| page_size | int | 否 | 每页数量,默认 20,最大 20 |
响应参数
| 字段 | 类型 | 说明 |
|---|---|---|
| error_code | int | 错误码;成功为 0 |
| error_message | string | 错误信息;成功为 成功 |
| succeed | boolean | 查询是否成功 |
| data | object | 音色列表分页数据 |
| data.list | array | 音色列表 |
| data.list[].voice_id | string | 音色名称 |
| data.list[].voice_url | string | 参考音频地址 |
| data.list[].created_at | int64 | 创建时间(Unix 秒) |
| data.total | int64 | 当前页返回数量 |
| data.next_voice_id | string | 下一页起始音色 ID;has_more 为 false 时为空或不返回 |
| data.has_more | boolean | 是否还有下一页 |
响应示例
{
"error_code": 0,
"error_message": "成功",
"succeed": true,
"data": {
"list": [
{
"voice_id": "my-voice",
"voice_url": "https://lunalab-res.oss-cn-hangzhou.aliyuncs.com/ttsVoiceV1/20260326/xxx.wav",
"created_at": 1743000000
}
],
"total": 1,
"next_voice_id": "",
"has_more": false
}
}
请求示例
首次查询:
curl -X GET "https://api.vuilabs.cn/v1/voice/list" \
-H "X-API-Key: your-secret-key-here"
查询下一页:
curl -X GET "https://api.vuilabs.cn/v1/voice/list?voice_id=my-voice&page_size=20" \
-H "X-API-Key: your-secret-key-here"
Python
import requests
response = requests.get(
"https://api.vuilabs.cn/v1/voice/list",
headers={"X-API-Key": "your-secret-key-here"}
)
payload = response.json()
print(payload)
if payload["succeed"] and payload["data"]["has_more"]:
next_response = requests.get(
"https://api.vuilabs.cn/v1/voice/list",
headers={"X-API-Key": "your-secret-key-here"},
params={"voice_id": payload["data"]["next_voice_id"], "page_size": 20},
)
print(next_response.json())
elif not payload["succeed"]:
print(payload["error_code"], payload["error_message"])
三、删除音色
删除当前账户下指定的自定义音色。该操作为幂等删除:如果 voice_id 未对应当前账户的自定义音色,也可能返回成功;成功不表示系统预置音色被删除。
接口信息
- 接口路径:
/v1/voice/{voice_id} - 请求方式:
DELETE - 认证方式: Header 中的
X-API-Key
请求头
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| X-API-Key | string | 是 | 应用密钥 |
路径参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| voice_id | string | 是 | 要删除的音色名称 |
响应说明
请求成功时,data 为空对象:
{
"error_code": 0,
"error_message": "成功",
"succeed": true,
"data": {}
}
请求示例
curl -X DELETE "https://api.vuilabs.cn/v1/voice/my-voice" \
-H "X-API-Key: your-secret-key-here"
Python
import requests
response = requests.delete(
"https://api.vuilabs.cn/v1/voice/my-voice",
headers={"X-API-Key": "your-secret-key-here"}
)
payload = response.json()
if payload["succeed"]:
print("音色删除成功")
else:
print(payload["error_code"], payload["error_message"])
四、在 TTS 中使用自定义音色
音色保存成功后,在 音频生成接口 中直接使用自定义的 voice_id 即可,接口调用方式完全相同。
# 同步生成
curl -X POST "https://api.vuilabs.cn/v1/text-to-speech" \
-H "X-API-Key: your-secret-key-here" \
-H "Content-Type: application/json" \
-d '{
"voice_id": "my-voice",
"generate_text": "你好,这是用我的克隆音色生成的语音。",
"model_id": "lunatts-0813"
}' \
--output audio.wav
# 流式生成
curl -X POST "https://api.vuilabs.cn/v1/text-to-speech/stream" \
-H "X-API-Key: your-secret-key-here" \
-H "Content-Type: application/json" \
-d '{
"voice_id": "my-voice",
"generate_text": "你好,这是用我的克隆音色生成的语音。",
"model_id": "lunatts-0813"
}' \
--output audio.wav
五、错误响应
保存音色失败时会返回对应的 HTTP 错误状态码;查询和删除的业务失败仍返回 HTTP 200。三个接口均保留统一 JSON 错误体:
{
"error_code": 10018,
"error_message": "该名称已被占用,请换一个名称",
"succeed": false,
"data": null
}
错误码说明
以下错误信息用于说明错误类别,同一 error_code 可能对应不同提示;请以实际响应中的 error_message 为准。
下表 HTTP 状态码适用于保存音色接口 /v1/voice/save;查询和删除接口请通过 JSON 中的 succeed 和 error_code 判断业务结果。
| HTTP 状态码 | error_code | error_message | 说明 |
|---|---|---|---|
| 400 | 10001 | 参数错误 | voice_id 格式不合法、缺少 ref_audio、解析出的参考文本超过 500 字符、ref_audio URL 非公网地址等 |
| 400 | 20012 | 音频文件格式错误 | 音频格式不支持、文件损坏、下载或解析失败 |
| 400 | 20015 | 克隆音色参考音频时长不能超过 60 秒 | 原始参考音频超过 60 秒 |
| 400 | 20016 | 有效语音不足或未检测到可用语音 | 请重新上传包含连续清晰语音的参考音频 |
| 400 | 20017 | 音频停顿过长 | 音频内容不符合克隆要求,请重新录制连续说话的参考音频 |
| 401 | 10003 | 未授权 | X-API-Key 缺失或无效 |
| 403 | 10004 | 禁止访问 | API Key 未开通音色克隆权限 |
| 402 | 20003 | 余额不足 | 免费次数已用完且账户余额不足 |
| 409 | 10017 | 个人音色数量已达上限 | 删除未使用音色后重试 |
| 409 | 10018 | 该名称已被占用 | voice_id 与系统预置音色重名 |
| 409 | 10019 | 音色 ID 冲突 | voice_id 与已有自定义音色冲突 |
| 409 | 10020 | 音色已被 Agent 绑定 | 先解除绑定后再删除 |
| 409 | 10021 | 音色正在处理中 | 稍后重试 |
| 429 | 10014 | 连接数限制 | 请求频率超限 |
| 503 | 20002 | 服务暂时不可用 | 音频解析或其他服务依赖暂时不可用,稍后重试 |
| 500 | 10000 | 服务器内部错误 | 操作失败,请查看 error_message;持续失败请联系支持 |
六、计费说明
具体计费规则、价格和免费额度请参见 产品计费。