语音合成 API
使用项目级 API Key 将文本转换为自然语音。
使用场景
快速开始
请先设置 API 地址和 Key;没有 Key 时请阅读获取 API Key。
所有接口均使用 X-API-Key 请求头。API Key 决定账号、项目、可用能力、速率限制和计费归属。
export VUILABS_API_BASE_URL="https://api.vuilabs.ai"
export VUILABS_API_KEY="your-api-key"
运行示例前,请将 YOUR_PROJECT_VOICE_ID 替换为当前 API Key 可使用的音色 ID;它不是平台提供的共享演示音色。克隆音色时,请先通过音色克隆 API创建音色,再在这里传入同一个 ID。
选择模型
| 模型 | model_id | 生成方式 | 音色与参数 |
|---|---|---|---|
| Luna-TTS | luna-tts | 同步或流式 | 使用 Luna-TTS 系统音色或个人音色;支持 speed 和 text_normalization。 |
| Luna-TTS Character | luna-tts-character | 同步 | 仅使用 Luna-TTS Character 系统音色;支持 volume、scene、expressivity;不支持个人音色、speed 或流式。同步 HTTP 接口接受但忽略 text_normalization,建议省略该字段。 |
请按对应模型的音色范围和参数说明构造请求。字段的接受、忽略或拒绝行为以各参数说明为准。
Luna-TTS Character 示例
{
"model_id": "luna-tts-character",
"text": "Welcome to VUI Labs.",
"voice_id": "jasper",
"volume": 0,
"scene": "normal"
}
- cURL
- JavaScript
- Python
curl --request POST \
--url "$VUILABS_API_BASE_URL/v1/text-to-speech" \
--header "X-API-Key: $VUILABS_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"text": "Your order is ready.",
"voice_id": "YOUR_PROJECT_VOICE_ID",
"language": "en",
"speed": 1
}' \
--output speech.wav
import { writeFile } from 'node:fs/promises';
const response = await fetch(`${process.env.VUILABS_API_BASE_URL}/v1/text-to-speech`, {
method: 'POST',
headers: {
'X-API-Key': process.env.VUILABS_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({ text: 'Your order is ready.', voice_id: 'YOUR_PROJECT_VOICE_ID', language: 'en', speed: 1 }),
});
if (!response.ok) throw new Error(await response.text());
await writeFile('speech.wav', Buffer.from(await response.arrayBuffer()));
import os
import requests
response = requests.post(
f"{os.environ['VUILABS_API_BASE_URL']}/v1/text-to-speech",
headers={"X-API-Key": os.environ["VUILABS_API_KEY"]},
json={"text": "Your order is ready.", "voice_id": "YOUR_PROJECT_VOICE_ID", "language": "en", "speed": 1},
)
response.raise_for_status()
with open("speech.wav", "wb") as output:
output.write(response.content)
流式生成仅支持 Luna-TTS。将路径改为 /v1/text-to-speech/stream,并按顺序消费响应块。
指定音色
请传入当前项目已启用的 voice_id。建议先用一段简短的代表性文本试听,再用于更长内容。
- cURL
- JavaScript
- Python
curl --request POST \
--url "$VUILABS_API_BASE_URL/v1/text-to-speech" \
--header "X-API-Key: $VUILABS_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"text": "This request uses a specific voice.",
"voice_id": "YOUR_PROJECT_VOICE_ID",
"language": "en",
"speed": 1
}' \
--output speech.wav
import { writeFile } from 'node:fs/promises';
const response = await fetch(`${process.env.VUILABS_API_BASE_URL}/v1/text-to-speech`, {
method: 'POST',
headers: {
'X-API-Key': process.env.VUILABS_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
text: 'This request uses a specific voice.',
voice_id: 'YOUR_PROJECT_VOICE_ID',
language: 'en',
speed: 1,
}),
});
if (!response.ok) throw new Error(await response.text());
await writeFile('speech.wav', Buffer.from(await response.arrayBuffer()));
import os
import requests
response = requests.post(
f"{os.environ['VUILABS_API_BASE_URL']}/v1/text-to-speech",
headers={"X-API-Key": os.environ["VUILABS_API_KEY"]},
json={
"text": "This request uses a specific voice.",
"voice_id": "YOUR_PROJECT_VOICE_ID",
"language": "en",
"speed": 1,
},
)
response.raise_for_status()
with open("speech.wav", "wb") as output:
output.write(response.content)
控制表达效果
请先用一段简短的代表性文本生成语音;每次只调整一个参数,便于比较效果。
- 语速: 仅 Luna-TTS 支持。请使用
0.6到1.2之间的值。 - 音量: Luna-TTS 与 Character 支持,范围
-5到5。 - Character 场景: 仅 Character 支持;
normal(默认)表示日常对话,whisper表示耳边私语。 - 表达标签: 仅 Luna-TTS 支持。将以下官方标签直接写入
text,并保留中括号,例如欢迎回来。[laughs]。
| 官方标签 | 官方标签 | 官方标签 |
|---|---|---|
[laughs] | [chuckles] | [gasps] |
[sighs] | [inhales] | [breath] |
[exhale] | [coughs] | [clears throat] |
[sniffles] | [snorts] | [hisses] |
[tsks] | [groans] |
API 细节
请求方式
POST /v1/text-to-speech获得完整音频后再播放或保存。
POST /v1/text-to-speech/stream仅 Luna-TTS 支持;Character 调用此接口会被拒绝。
请求头
| 请求头 | 必填 | 说明 |
|---|---|---|
X-API-Key | 是 | 项目 API Key |
Content-Type | 是 | application/json |
JSON 请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
text | string | 是 | 待合成文本,最多 500 个加权字符:每个中文字符按 2 个字符计,其他 Unicode 字符按 1 个字符计。 |
language | string | 否 | 当前 TTS 账号已启用的语言代码。 |
voice_id | string | 是 | 当前项目已启用的音色 ID;省略会被接口拒绝。 |
model_id | string | 否 | luna-tts(默认)或 luna-tts-character。 |
speed | number | 否 | 仅 Luna-TTS 支持,范围 0.6–1.2;0(默认语速)。 |
volume | number | 否 | Luna-TTS 与 Character 支持,范围 -5–5。 |
scene | string | 否 | 仅 Character 支持:normal(默认)或 whisper。 |
expressivity | string | 否 | 仅 Character 支持:normal(默认)或 strong。 |
text_normalization | boolean | 否 | Luna-TTS:true(默认,启用文本归一化)或 false(保留输入文本)。Character 接受但忽略该字段。 |
audio_format | string | 否 | wav(默认)或 pcm。同步和流式均支持 PCM;流式仅支持 Luna-TTS。 |
请使用控制台中当前项目可用的音色和语言。
文本归一化
同步和流式接口仅在 Luna-TTS 下应用 text_normalization。请传 JSON 布尔值,不要给 true 或 false 加引号;true 是默认值,表示启用文本归一化;如需保留输入文本,请显式传 false。每一段使用同一个开关值。Character 会忽略该字段:同步 HTTP 接口接受布尔值 true 或 false,但这两个值均不控制 Character 的文本归一化,建议省略该字段。
{
"text": "今天36度,错误率是60%。",
"voice_id": "YOUR_PROJECT_VOICE_ID",
"text_normalization": true
}
使用 Luna-TTS 时,省略 text_normalization 或传 true 会先进行文本归一化;需要保留输入原文时请显式传 false。控制台语音合成中的“文本归一化”开关会随每次生成提交。
同步响应格式
POST /v1/text-to-speech 省略 audio_format 或传 wav 时返回完整 WAV 文件,Content-Type: audio/wav。如需裸 PCM,请在 JSON 请求体中传入 "audio_format": "pcm":
{
"text": "Your order is ready.",
"voice_id": "YOUR_PROJECT_VOICE_ID",
"audio_format": "pcm"
}
PCM 响应为不含 WAV 文件头的 16 位有符号小端音频数据(PCM_S16LE),Content-Type: audio/pcm。保存时可使用 .pcm 扩展名;播放时请读取以下响应头配置播放器:
| 响应头 | 含义 |
|---|---|
X-Audio-Sample-Rate | 实际采样率,单位 Hz。 |
X-Audio-Channels | 实际声道数。 |
X-Audio-Bit-Depth | 位深,PCM 为 16。 |
采样率与声道保留合成结果的实际值,接口不进行重采样,不能假定固定为 24000 Hz 或单声道。WAV 和 PCM 均支持同步接口的可用音色及模型;其他格式会被拒绝。
流式生成
POST /v1/text-to-speech/stream 仅支持 model_id: "luna-tts"。HTTP 响应体按顺序返回音频字节,不是 SSE、JSON 事件或 base64。Character 不支持此接口。
audio_format | Content-Type | 音频字节 |
|---|---|---|
省略或 wav | audio/wav | 包含容器头的 WAV 音频,需使用支持 WAV 的解码器。 |
pcm | audio/pcm | 有符号 16 位小端原始 PCM(PCM16LE),不含 WAV 文件头。 |
PCM 播放器须根据响应头配置解码参数。采样率与声道数来自实际生成的音频,不要写死采样率。
| PCM 响应头 | 含义 |
|---|---|
X-Audio-Sample-Rate | 采样率,单位 Hz。 |
X-Audio-Channels | 声道数。 |
X-Audio-Bit-Depth | 每个采样的位数;PCM16LE 为 16。 |
即使文本分为多段生成,PCM 流中也只包含音频采样数据。请按顺序处理字节。HTTP 块边界不代表音频帧边界,单次读取末尾不足一帧的数据需要保留并与下次读取拼接。
保存 PCM 流
沿用上文配置的 API 地址和密钥,将 YOUR_PROJECT_VOICE_ID 替换为已启用的 Luna-TTS 音色。以下命令分别保存原始采样数据和响应头。
curl --fail --silent --show-error --no-buffer \
--request POST \
--url "$VUILABS_API_BASE_URL/v1/text-to-speech/stream" \
--header "X-API-Key: $VUILABS_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model_id": "luna-tts",
"text": "Your order is ready.",
"voice_id": "YOUR_PROJECT_VOICE_ID",
"audio_format": "pcm"
}' \
--dump-header speech-pcm.headers \
--output speech.pcm
播放前先读取 speech-pcm.headers:.pcm 文件本身不存储采样率与声道数。此示例用于保存字节,不是播放示例。
首个音频字节发送前,失败使用标准 JSON 错误体和对应 HTTP 错误状态。流开始后发生错误会中断音频响应,不会在音频后追加 JSON。仅收到 200 不代表完整生成成功,请保留传输异常并处理播放未完成的情况。
两个接口的 HTTP 200 响应体都是音频而非 JSON;Content-Type 为实际音频 MIME 类型。