API 快速开始
创建密钥、选择声音、生成第一段语音。
创建 API 密钥
登录后打开 API 密钥,点击“新建密钥”,复制以 sk- 开头的密钥。密钥只显示一次。
在终端中保存为环境变量,后面的示例都会用到:
export VAL_API_KEY="sk-your-api-key"确认账户
curl https://voiceailabs.com/api/v1/account \
-H "Authorization: Bearer $VAL_API_KEY"返回中的 credits.balance 是可用积分,limits.max_text_length 是单次合成的最大字数。
选择声音
可以直接使用声音广场中的公共声音(不占声音名额),也可以使用你克隆的声音:
# 公共声音
curl "https://voiceailabs.com/api/v1/voices/public?limit=5" \
-H "Authorization: Bearer $VAL_API_KEY"
# 我的声音
curl "https://voiceailabs.com/api/v1/voices" \
-H "Authorization: Bearer $VAL_API_KEY"记下某个声音的 id,作为下一步的 voice_id。
创建合成任务
curl https://voiceailabs.com/api/v1/tts \
-H "Authorization: Bearer $VAL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1024-intro" \
-d '{
"voice_id": "VOICE_ID",
"text": "欢迎使用 Voice AI Labs。",
"language": "zh"
}'接口返回 202 和任务对象,status 为 pending。Idempotency-Key 可以保证网络重试时不会重复创建和扣费,详见错误码与限制。
获取音频
每隔几秒查询一次,直到 status 为 completed 或 failed:
curl https://voiceailabs.com/api/v1/syntheses/SYNTHESIS_ID \
-H "Authorization: Bearer $VAL_API_KEY"完成后从 audio_url 下载 MP3。生产环境推荐用 Webhook 代替轮询。
完整示例
const BASE_URL = "https://voiceailabs.com/api/v1";
const headers = { Authorization: `Bearer ${process.env.VAL_API_KEY}` };
async function call(path, init = {}) {
const response = await fetch(`${BASE_URL}${path}`, {
...init,
headers: { ...headers, ...init.headers },
});
const body = await response.json();
if (body.code !== 0) {
const error = new Error(body.message);
Object.assign(error, body.data); // error_code, retryable, request_id
throw error;
}
return body.data;
}
async function textToSpeech(voiceId, text) {
let task = await call("/tts", {
method: "POST",
headers: { "Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID() },
body: JSON.stringify({ voice_id: voiceId, text }),
});
while (task.status === "pending" || task.status === "processing") {
await new Promise((resolve) => setTimeout(resolve, 3000));
task = await call(`/syntheses/${task.id}`);
}
if (task.status === "failed") {
throw new Error(`Synthesis failed, refund: ${task.refund?.status}`);
}
return task.audio_url;
}
textToSpeech("VOICE_ID", "Hello from Voice AI Labs!").then(console.log);import os
import time
import uuid
import requests
BASE_URL = "https://voiceailabs.com/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['VAL_API_KEY']}"}
def call(method, path, **kwargs):
headers = {**HEADERS, **kwargs.pop("headers", {})}
body = requests.request(method, f"{BASE_URL}{path}", headers=headers, timeout=60, **kwargs).json()
if body["code"] != 0:
raise RuntimeError(f"{body['data']['error_code']}: {body['message']} ({body['data']['request_id']})")
return body["data"]
def text_to_speech(voice_id, text):
task = call(
"POST",
"/tts",
json={"voice_id": voice_id, "text": text},
headers={"Idempotency-Key": str(uuid.uuid4())},
)
while task["status"] in ("pending", "processing"):
time.sleep(3)
task = call("GET", f"/syntheses/{task['id']}")
if task["status"] == "failed":
raise RuntimeError(f"Synthesis failed, refund: {task['refund']}")
return task["audio_url"]
print(text_to_speech("VOICE_ID", "Hello from Voice AI Labs!"))