模型能力
Custom Voices
从简短的参考音频 clip 克隆 voice,并在任何支持内置 voice 的位置使用。上传音频 sample 后,即可立即在 TTS 和 Speech to Speech API 中使用。
如何使用 Custom Voices
在 Console中创建 voice 后,点击 voice card 上的三点菜单,然后选择 Copy Voice ID。如果通过 API 创建 custom voice(仅限 Enterprise),response 会返回 voice_id。
在所有 Voice API 中,custom voice 与内置 voice 可以互换使用。将 voice_id 传给以下任一 API:
POST /v1/ttswss://api.x.ai/v1/ttswss://api.x.ai/v1/realtime
内置 voice 仍可通过 GET /v1/tts/voices 获取。Custom voice 仅由 GET /v1/custom-voices 返回,不会出现在内置 voice 列表中。Custom voice 仅限你的 team 使用,其他用户无法访问。
录制参考音频
通过克隆最长 120 秒的参考音频 clip 创建 custom voice。为获得最佳效果:
在安静环境中录制,最好使用高质量麦克风。
自然朗读。 如果听起来像照着脚本念,生成的 voice 也会保留这种特点。
音频越长越好。 少于 30 秒的 clip 可能缺乏细节。建议录制 90–120 秒以获得最佳效果。
表达要富有变化。 生成的 voice 会匹配录音中的表现力。
录制什么内容
Model 不仅会学习音色,还会学习参考 clip 的表达方式。为获得最佳效果,请让录音内容与计划生成的内容相匹配:
客户支持 — 录制真实的支持对话,包括问候、等待、故障排查步骤和结束语。
有声书旁白 — 使用最终输出所需的节奏与语调朗读几段散文。
对话式 assistant — 录制自然、无脚本的讲话,例如向朋友解释某个主题。
新闻或纪录片 — 使用自然的播报 voice 朗读一篇短文。
与预期用例相符的录音,比精心制作但无关的 sample 效果更好。
录音设置
麦克风。 建议使用录音室电容麦克风或高质量 USB 麦克风。手机耳机也能使用,但会引入明显噪声。
防喷罩。 建议使用。没有防喷罩时,爆破音(
p、b)会被还原成明显的冲击声。房间声学处理。 请在较小且配有柔软家具的房间中录制。硬墙房间会产生回声和混响,这些也会被生成的 voice 还原。
单一说话者。 录音应只包含一个 voice,不要有背景音乐或音效。
背景噪声。 保持房间安静。关闭 HVAC、风扇和通知声音。背景噪声会与 voice 一起被克隆。
创建 Custom Voice
在 Console 中开始使用,可以免费创建最多 30 个 custom voice,并立即在所有 Voice API 中使用。
API 快速开始
根据参考音频文件创建 custom voice,然后使用它合成语音:
# 1. Create the voice from a reference clip (max 120s).
CREATE_RESPONSE=$(curl -s -X POST https://api.x.ai/v1/custom-voices \
-H "Authorization: Bearer $XAI_API_KEY" \
-F "name=Friendly Narrator" \
-F "language=en" \
-F "gender=female" \
-F "tone=warm" \
-F "use_case=narration" \
-F "file=@reference.wav;type=audio/wav")
echo "$CREATE_RESPONSE"
# {"voice_id":"abc123xy","name":"Friendly Narrator",...}
# Extract the voice_id from the response (requires jq).
VOICE_ID=$(echo "$CREATE_RESPONSE" | jq -r '.voice_id')
# 2. Use the new voice for TTS.
curl -X POST https://api.x.ai/v1/tts \
-H "Authorization: Bearer $XAI_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"text\": \"Hello! This audio was synthesized using my custom voice.\",
\"voice_id\": \"$VOICE_ID\",
\"language\": \"en\"
}" \
--output hello.mp3Endpoints
所有 endpoint 都位于 https://api.x.ai/v1/custom-voices 下,并使用 Bearer API key 进行身份验证。
创建 custom voice
POST /v1/custom-voices 使用 multipart/form-data。只有 file 是必填项。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
file | binary | 是 | 参考音频。最长 120 秒。 |
name | string | 显示名称。 | |
description | string | 自由文本说明。 | |
gender | string | male、female 或 neutral。 | |
accent | string | 自由文本(例如 British、American)。 | |
age | string | young、middle-aged 或 old。 | |
language | string | ISO 639(en)或 BCP-47 格式(en-US、zh-CN)。Region 必须大写。 | |
use_case | string | conversational、narration、characters、educational、advertisement、social_media、entertainment。 | |
tone | string | warm、casual、professional、friendly、authoritative、expressive、calm。 |
建议上传的参考文件使用以下格式和设置:
| 设置 | 建议 |
|---|---|
| Codec | .wav(uncompressed PCM)。也接受 MP3、FLAC、OGG、Opus、M4A、AAC、MKV 和 MP4,但 lossy 格式可能引入压缩 artifact,并被生成的 voice 还原。 |
| Sample rate | 24 kHz。更高的 rate(44.1 kHz、48 kHz)会在服务端 downsample。较低的 rate 会降低 fidelity。 |
| Bit depth | 16-bit PCM 已足够。也支持 24-bit。 |
| Channels | Mono。Stereo 文件会自动 downmix,但使用 mono 录制可以避免潜在的 phase artifact。 |
长度
无最短限制,最长 120 秒。 接受任意长度且不超过 120 秒的 clip;更长的 clip 会以
400。建议 90 秒以上。 更长的 clip 能捕捉更多 prosody 和语调变化,生成更自然、更富表现力的 voice。
创建成功会返回 201 以及新的 voice object:
{
"voice_id": "nlbqfwie",
"name": "Friendly Narrator",
"description": "Warm, conversational tone for narration.",
"gender": "female",
"accent": "American",
"age": "young",
"language": "en",
"use_case": "narration",
"tone": "warm",
"created_at": "2026-04-26T18:56:34.872993+00:00"
}voice_id 是由 8 个小写字母或数字组成的标识符。
列出 custom voices
GET /v1/custom-voices 会分页返回你的 team 拥有的所有 voice。
| Query parameter | 默认值 | 说明 |
|---|---|---|
limit | 100 | Page size,1-1000。 |
pagination_token | 上一页 response 中的 token。第一页省略。 |
curl -s "https://api.x.ai/v1/custom-voices?limit=50" \
-H "Authorization: Bearer $XAI_API_KEY"Response:
{
"voices": [
{
"voice_id": "nlbqfwie",
"name": "Friendly Narrator",
"description": "Warm, conversational tone for narration.",
"gender": "female",
"accent": "American",
"age": "young",
"language": "en",
"use_case": "narration",
"tone": "warm",
"created_at": "2026-04-26T18:56:34.872993+00:00"
}
],
"pagination_token": null
}获取 custom voice
GET /v1/custom-voices/{voice_id} 返回单个 voice 的 metadata。未知 ID 或属于其他 team 的 voice 会返回 404。
Response body 与 Create。
更新 metadata
PATCH /v1/custom-voices/{voice_id},使用 JSON body。所有字段均为可选,并遵循以下规则:
省略字段 — 不做更改。
字段设为
null— 清除该值。字段设为非空 string — 更新该值。
字段设为
""— 会以400。
该 endpoint 永远不会更改底层音频。如需重新录制,请删除 voice 并创建新的 voice。
curl -X PATCH "https://api.x.ai/v1/custom-voices/nlbqfwie" \
-H "Authorization: Bearer $XAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"description": "Updated after a tuning pass.", "tone": "calm"}'返回完整的已更新 voice object:
{
"voice_id": "nlbqfwie",
"name": "Friendly Narrator",
"description": "Updated after a tuning pass.",
"gender": "female",
"accent": "American",
"age": "young",
"language": "en",
"use_case": "narration",
"tone": "calm",
"created_at": "2026-04-26T18:56:34.872993+00:00"
}下载参考音频
GET /v1/custom-voices/{voice_id}/audio 会以正确的 Content-Type header streaming 原始参考文件(例如 audio/wav、audio/mpeg)。
删除 custom voice
DELETE /v1/custom-voices/{voice_id} 会删除 voice 及其底层音频。
curl -X DELETE "https://api.x.ai/v1/custom-voices/nlbqfwie" \
-H "Authorization: Bearer $XAI_API_KEY"Response 为 {"deleted": true}。删除后,对同一 voice_id 的后续请求会返回 404,任何引用该 voice 的 TTS / Speech to Speech 调用都会以 unknown-voice error 失败。
使用 Custom Voice
创建后,custom voice_id 可以用于任何支持内置 voice_id 的位置。
REST TTS
curl -X POST https://api.x.ai/v1/tts \
-H "Authorization: Bearer $XAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Welcome back. How can I help today?",
"voice_id": "nlbqfwie",
"language": "en"
}' \
--output welcome.mp3Streaming TTS WebSocket
打开连接时,将 custom voice 作为 voice query parameter 传入。完整 event protocol 请参阅 Text to Speech - Streaming。
前置条件:安装 WebSocket client library:Python 使用 pip install websockets,Node.js 使用 npm install ws。
import asyncio
import base64
import json
import os
import websockets
async def stream_with_custom_voice(voice_id: str):
uri = f"wss://api.x.ai/v1/tts?language=en&voice={voice_id}&codec=mp3"
async with websockets.connect(
uri,
additional_headers={"Authorization": f"Bearer {os.environ['XAI_API_KEY']}"},
) as ws:
await ws.send(json.dumps({"type": "text.delta", "delta": "Streaming with my custom voice."}))
await ws.send(json.dumps({"type": "text.done"}))
audio = bytearray()
async for msg in ws:
event = json.loads(msg)
if event["type"] == "audio.delta":
audio.extend(base64.b64decode(event["delta"]))
elif event["type"] == "audio.done":
break
with open("stream.mp3", "wb") as f:
f.write(audio)
asyncio.run(stream_with_custom_voice("nlbqfwie"))Speech to Speech API
在 voice message 中设置 session.update。完整 session 生命周期请参阅 Speech to Speech API 文档。
import asyncio
import json
import os
import websockets
async def realtime_with_custom_voice(voice_id: str):
async with websockets.connect(
"wss://api.x.ai/v1/realtime",
additional_headers={"Authorization": f"Bearer {os.environ['XAI_API_KEY']}"},
) as ws:
await ws.send(json.dumps({
"type": "session.update",
"session": {
"voice": voice_id,
"instructions": "You are a helpful assistant.",
"turn_detection": {"type": "server_vad"},
},
}))
# ... continue with the standard realtime event loop ...
asyncio.run(realtime_with_custom_voice("nlbqfwie"))限制
| 值 | |
|---|---|
| 参考音频最长时长 | 120 秒 |
| 每个 team 的 custom voice 数量 | 30 |
| Voice ID 长度 | 8 个字符,小写字母或数字 |
需要超过 30 个 voice?
默认每个 team 最多 30 个 custom voice。如果需要更多,请联系我们讨论提高限制。
错误处理
| Status | 含义 | 操作 |
|---|---|---|
201 | Voice 已创建 | 保存 voice_id 并开始使用。 |
200 | 读取 / 更新 / 删除成功 | - |
400 | 错误请求 | 检查:音频不超过 120 秒;label 值在允许的 enum 范围内;PATCH 不包含空 string。达到 team 的 30 个 voice 限制时也会返回该错误,请删除现有 voice 或 申请更多。 |
401 | 未授权 | API key 缺失或无效。 |
403 | 该 team 未启用 custom voice,或 POST /v1/custom-voices 在没有 Enterprise contract 的情况下被调用 | 请在 Console Playground 或 联系销售团队以启用 create API。 |
404 | Voice 不存在 | 该 ID 不存在或属于其他 team。 |
500 | Server 错误 | 使用 exponential backoff 重试。 |