MiniMax 语音合成
同步语音合成(HTTP)
使用本接口将文本转换为语音,支持流式和非流式两种模式。
http
POST /v1/t2a_v2请求头
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
Content-Type | string | 是 | application/json | 数据交换格式 |
Authorization | string | 是 | - | 鉴权信息,格式为 Bearer <API_KEY> |
请求体
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | 是 | 模型版本。可选:speech-2.8-hd、speech-2.8-turbo |
text | string | 是 | 待合成文本,最长 10000 字符。超过 3000 字符建议使用流式模式。支持 <#x#> 停顿(秒)、行内发音替换 (拼音或IPA)、语气词标签 |
stream | boolean | 否 | 是否流式输出,默认 false |
voice_setting | object | 是 | 音色设置,见下表 |
audio_setting | object | 否 | 音频输出参数,见下表 |
pronunciation_dict | object | 否 | 自定义发音字典 |
language_boost | string | 否 | 小语种/方言增强,可选 auto 或指定语种 |
voice_modify | object | 否 | 声音效果器设置 |
subtitle_enable | boolean | 否 | 是否开启字幕,默认 false |
subtitle_type | string | 否 | 字幕粒度:sentence、word、word_streaming |
output_format | string | 否 | 非流式结果格式:hex(默认)或 url。url 返回下载链接,有效期 24h |
aigc_watermark | boolean | 否 | 是否在音频末尾添加水印节奏标识,默认 false |
voice_setting 详细参数
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
voice_id | string | 是 | - | 音色 ID,支持系统音色、复刻音色、文生音色 |
speed | number | 否 | 1.0 | 语速,范围 [0.5, 2] |
vol | number | 否 | 1.0 | 音量,范围 (0, 10] |
pitch | integer | 否 | 0 | 语调,范围 [-12, 12],0 为原语调 |
emotion | string | 否 | - | 情绪控制。可选:happy、sad、angry、fearful、disgusted、surprised、calm、fluent、whisper |
text_normalization | boolean | 否 | false | 中文/英语文本规范化,开启可提升数字阅读性能 |
latex_read | boolean | 否 | false | 是否朗读 LaTeX 公式(需将 language_boost 设为 Chinese,公式用 $$ 包裹) |
audio_setting 详细参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
sample_rate | integer | 32000 | 采样率。可选:8000、16000、22050、24000、32000、44100 |
bitrate | integer | 128000 | 比特率。可选:32000、64000、128000、256000(仅 mp3 生效) |
format | string | mp3 | 音频格式。可选:mp3、pcm、flac、wav、pcmu_raw、pcmu_wav、opus |
channel | integer | 1 | 声道数,1 为单声道,2 为双声道 |
force_cbr | boolean | false | 恒定比特率控制,仅流式 mp3 有效 |
pronunciation_dict 详细参数
| 参数名 | 类型 | 说明 |
|---|---|---|
tone | array<string> | 自定义发音规则。格式:"原文/替换内容"。替换内容可为文本、拼音带声调数字、IPA 或假名。示例:"处理/(chu3)(li3)"、"危险/dangerous" |
voice_modify 详细参数
| 参数名 | 类型 | 范围 | 说明 |
|---|---|---|---|
pitch | integer | [-100, 100] | 音高调整:-100 低沉,100 明亮 |
intensity | integer | [-100, 100] | 强度调整:-100 刚劲,100 轻柔 |
timbre | integer | [-100, 100] | 音色调整:-100 浑厚,100 清脆 |
sound_effects | string | - | 音效。可选:spacious_echo(空旷回音)、auditorium_echo(礼堂广播)、lofi_telephone(电话失真)、robotic(电音) |
请求示例
bash
curl -X POST "https://neolink.com/api/minimax/v1/t2a_v2" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <API_KEY>" \
-d '{
"model": "speech-2.8-hd",
"text": "今天是不是很开心呀(laughs),当然了!",
"stream": false,
"voice_setting": {
"voice_id": "male-qn-qingse",
"speed": 1,
"vol": 1,
"pitch": 0,
"emotion": "happy"
},
"audio_setting": {
"sample_rate": 32000,
"bitrate": 128000,
"format": "mp3",
"channel": 1
},
"pronunciation_dict": {
"tone": [
"处理/(chu3)(li3)",
"危险/dangerous"
]
},
"subtitle_enable": false
}'非流式响应(HTTP 200)
json
{
"data": {
"audio": "hex编码的完整音频数据",
"status": 2,
"extra_info": {
"audio_length": 9900,
"audio_sample_rate": 32000,
"audio_size": 160323,
"bitrate": 128000,
"word_count": 52,
"usage_characters": 26,
"audio_format": "mp3",
"audio_channel": 1
},
"trace_id": "01b8bf9bb7433cc75c18eee6cfa8fe21"
},
"base_resp": {
"status_code": 0,
"status_msg": "success"
}
}| 字段 | 类型 | 说明 |
|---|---|---|
data.audio | string | 音频数据。output_format=hex 时为 hex 编码,url 时为下载链接(有效期 24h) |
data.status | int | 合成状态:2 表示合成结束 |
data.extra_info | object | 音频元数据及计费信息 |
data.extra_info.audio_length | int64 | 音频时长(毫秒) |
data.extra_info.audio_sample_rate | int64 | 音频采样率 |
data.extra_info.audio_size | int64 | 音频大小(字节) |
data.extra_info.bitrate | int64 | 比特率 |
data.extra_info.word_count | int64 | 合成字符数(不含标点) |
data.extra_info.usage_characters | int64 | 计费字符数 |
data.extra_info.audio_format | string | 音频格式 |
data.extra_info.audio_channel | int64 | 音频声道数 |
data.trace_id | string | 请求追踪 ID |
base_resp.status_code | int | 状态码;具体定义见错误码 |
base_resp.status_msg | string | 状态详情 |
Python 示例(非流式)
python
import requests
url = "https://neolink.com/api/minimax/v1/t2a_v2"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer <API_KEY>"
}
payload = {
"model": "speech-2.8-hd",
"text": "今天是不是很开心呀(laughs),当然了!",
"stream": False,
"voice_setting": {
"voice_id": "male-qn-qingse",
"speed": 1,
"vol": 1,
"pitch": 0,
"emotion": "happy"
},
"audio_setting": {
"sample_rate": 32000,
"bitrate": 128000,
"format": "mp3",
"channel": 1
}
}
resp = requests.post(url, headers=headers, json=payload)
resp_data = resp.json()
if resp_data["base_resp"]["status_code"] == 0:
audio_hex = resp_data["data"]["audio"]
audio_bytes = bytes.fromhex(audio_hex)
with open("output.mp3", "wb") as f:
f.write(audio_bytes)
print("音频已保存为 output.mp3")
else:
print("错误:", resp_data["base_resp"]["status_msg"])异步长文本语音合成
适用于大批量长文本的离线合成场景。创建任务后返回 task_id 和 file_id,需通过任务查询接口轮询状态,完成后通过文件检索接口下载音频文件。
http
POST /v1/t2a_async_v2请求头
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
Content-Type | string | 是 | application/json | 数据交换格式 |
Authorization | string | 是 | - | 鉴权信息,格式为 Bearer <API_KEY> |
请求体
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | 是 | 模型版本。可选:speech-2.8-hd、speech-2.8-turbo |
voice_setting | object | 是 | 音色设置,参见同步语音合成的 voice_setting 参数(text_normalization 改为 english_normalization) |
text | string | 二选一 | 待合成文本,最长 5 万字符。2.8 系列模型支持语气词标签 |
text_file_id | int64 | 二选一 | 待合成文本文件 ID。单个文件 < 100 万字符,支持 txt、zip 格式。zip 文件支持 title、content、extra 结构化字段 |
language_boost | string | 否 | 增强指定小语种或方言,可选 auto 或具体语种 |
audio_setting | object | 否 | 音频输出参数。字段:audio_sample_rate(默认 32000)、bitrate(默认 128000)、format(默认 mp3)、channel(默认 2) |
pronunciation_dict | object | 否 | 自定义发音字典,同同步语音合成 |
voice_modify | object | 否 | 声音效果器设置,仅 mp3/wav/flac 格式支持 |
aigc_watermark | boolean | 否 | 是否在音频末尾添加水印,默认 false |
注:语气词标签仅 speech-2.8 系列支持,包括:
(laughs)、(chuckle)、(coughs)、(groans)、(breath)、(sighs)、(crying)、(applause)等 23 种。
请求示例(传入文本)
bash
curl -X POST "https://neolink.com/api/minimax/v1/t2a_async_v2" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <API_KEY>" \
-d '{
"model": "speech-2.8-hd",
"text": "真正的危险不是计算机开始像人一样思考(sighs),而是人开始像计算机一样思考。",
"language_boost": "auto",
"voice_setting": {
"voice_id": "audiobook_male_1",
"speed": 1,
"vol": 1,
"pitch": 1
},
"audio_setting": {
"audio_sample_rate": 32000,
"bitrate": 128000,
"format": "mp3",
"channel": 2
}
}'请求示例(传入文件 ID)
bash
curl -X POST "https://neolink.com/api/minimax/v1/t2a_async_v2" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <API_KEY>" \
-d '{
"model": "speech-2.8-hd",
"text_file_id": 1234567890,
"language_boost": "auto",
"voice_setting": {
"voice_id": "audiobook_male_1",
"speed": 1,
"vol": 10,
"pitch": 1
},
"audio_setting": {
"audio_sample_rate": 32000,
"bitrate": 128000,
"format": "mp3",
"channel": 2
}
}'成功响应(HTTP 200)
json
{
"task_id": "95157322514444",
"file_id": 95157322514496,
"task_token": "xxxxxxxxxxxx",
"usage_characters": 30,
"base_resp": {
"status_code": 0,
"status_msg": "success"
}
}| 字段 | 类型 | 说明 |
|---|---|---|
task_id | string | 异步任务唯一 ID |
file_id | int64 | 音频文件 ID。任务完成后通过 检索文件 下载,下载链接自生成起 9 小时内有效 |
task_token | string | 任务令牌 |
usage_characters | int64 | 计费字符数 |
base_resp.status_code | int | 状态码;0=成功,1002=限流,1004=鉴权失败,1039=TPM 限流,1042=非法字符超 10%,2013=参数错误 |
base_resp.status_msg | string | 状态详情 |
查询异步合成任务状态
轮询查询异步语音合成任务的处理状态。
http
GET /v1/query/t2a_async_query_v2请求头
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
Authorization | string | 是 | 鉴权信息,格式为 Bearer <API_KEY> |
查询参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
task_id | int64 | 是 | 异步任务 ID(创建任务时返回) |
限流:最高 10 QPS。
请求示例
bash
curl -X GET "https://neolink.com/api/minimax/v1/query/t2a_async_query_v2?task_id=95157322514444" \
-H "Authorization: Bearer <API_KEY>"成功响应(HTTP 200)
json
{
"task_id": 95157322514444,
"status": "success",
"file_id": 95157322514496,
"base_resp": {
"status_code": 0,
"status_msg": "success"
}
}| 字段 | 类型 | 说明 |
|---|---|---|
task_id | int64 | 任务 ID |
status | string | 任务状态:processing(处理中)、success(成功)、failed(失败)、expired(已过期) |
file_id | int64 | 音频文件 ID(仅 status=success 时返回)。通过 检索文件 获取下载链接,链接有效期 9 小时 |
base_resp.status_code | int | 状态码;具体定义见错误码 |
base_resp.status_msg | string | 状态详情 |
轮询示例(Python)
python
import requests
import time
url = "https://neolink.com/api/minimax/v1/query/t2a_async_query_v2"
headers = {"Authorization": "Bearer <API_KEY>"}
task_id = 95157322514444
while True:
resp = requests.get(url, headers=headers, params={"task_id": task_id})
data = resp.json()
status = data.get("status")
if status == "success":
print("合成完成,file_id:", data.get("file_id"))
break
elif status == "failed":
print("合成失败:", data)
break
else:
print(f"状态: {status},30秒后重试...")
time.sleep(30)同步语音合成(WebSocket)
通过 WebSocket 长连接实现低延迟流式语音合成,适用于实时对话等场景。
http
WSS /ws/v1/t2a_v2通信流程
客户端 服务端
| ----------- 建立 WebSocket -----------→ |
| ←-------- connected_success ---------- |
| ----------- task_start --------------→ |
| ←-------- task_started --------------- |
| ----------- task_continue -----------→ |
| ←-------- task_continued (audio) ----- |
| ----------- task_continue -----------→ |
| ←-------- task_continued (audio) ----- |
| ...(可多次)... |
| ----------- task_finish -------------→ |
| ←-------- task_finished -------------- |若最后一次收到服务端结果后 120 秒内无新事件,连接将自动断开。
客户端 → 服务端事件
task_start - 启动合成任务
必须先收到服务端的 task_started 后才能继续发送 task_continue。
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
event | string | 是 | 固定值 task_start |
model | string | 是 | 模型版本。可选:speech-2.8-hd、speech-2.8-turbo 等 |
voice_setting | object | 是 | 音色设置,参见 同步语音合成(HTTP) |
audio_setting | object | 否 | 音频输出参数,参见 同步语音合成(HTTP) |
language_boost | string | 否 | 小语种/方言增强,可选 auto 或具体语种 |
pronunciation_dict | object | 否 | 自定义发音字典 |
请求示例:
json
{
"event": "task_start",
"model": "speech-2.8-hd",
"language_boost": "Chinese",
"voice_setting": {
"voice_id": "male-qn-qingse",
"speed": 1,
"vol": 1,
"pitch": 0
},
"pronunciation_dict": {
"tone": [
"处理/(chu3)(li3)",
"危险/dangerous"
]
},
"audio_setting": {
"sample_rate": 32000,
"bitrate": 128000,
"format": "mp3",
"channel": 1
}
}task_continue - 发送合成文本
可多次发送。仅在收到 task_started 后可用。
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
event | string | 是 | 固定值 task_continue |
text | string | 是 | 待合成文本,支持语气词标签如 (sighs)、(laughs) |
请求示例:
json
{
"event": "task_continue",
"text": "真正的危险不是计算机开始像人一样思考(sighs),而是人开始像计算机一样思考。"
}task_finish - 结束任务
通知服务端不再发送新文本,等待队列中的合成任务完成后关闭连接。
json
{
"event": "task_finish"
}服务端 → 客户端事件
connected_success - 连接成功
json
{
"session_id": "301871346491491",
"event": "connected_success",
"trace_id": "0303a2882bf18235ae7a809ae0f3cca7",
"base_resp": {
"status_code": 0,
"status_msg": "success"
}
}task_started - 任务已开始
收到此事件后即可开始发送 task_continue。
json
{
"session_id": "301871346491491",
"event": "task_started",
"trace_id": "0303a2882bf18235ae7a809ae0f3cca7",
"base_resp": {
"status_code": 0,
"status_msg": "success"
}
}task_continued - 音频数据返回
每次 task_continue 发送后,服务端返回对应的音频数据。
json
{
"data": {
"audio": "base64编码的音频数据"
},
"extra_info": {
"audio_channel": 1,
"audio_format": "mp3",
"audio_length": 9914,
"audio_sample_rate": 32000,
"audio_size": 157869,
"bitrate": 128000,
"invisible_character_ratio": 0,
"usage_characters": 158,
"word_count": 158
},
"is_final": true,
"session_id": "301871346491491",
"trace_id": "04ee3794e2c9e4a",
"base_resp": {
"status_code": 0,
"status_msg": "success"
}
}| 字段 | 类型 | 说明 |
|---|---|---|
data.audio | string | base64 编码的音频数据 |
is_final | boolean | 是否最后一段音频 |
extra_info | object | 音频元数据(声道、格式、时长、大小等) |
session_id | string | 会话标识 |
trace_id | string | 请求追踪 ID |
base_resp.status_code | int | 状态码;0=成功 |
task_finished - 任务已结束
正常流程下,所有 task_continue 对应的音频都已返回后,服务端发送此事件关闭任务。
json
{
"session_id": "301871346491491",
"event": "task_finished",
"trace_id": "0303a2882bf18235ae7a809ae0f3cca7",
"base_resp": {
"status_code": 0,
"status_msg": "success"
}
}task_failed - 任务失败
json
{
"session_id": "301871346491491",
"event": "task_failed",
"trace_id": "0303a2882bf18235ae7a809ae0f3cca7",
"base_resp": {
"status_code": 1004,
"status_msg": "authentication failed"
}
}Python WebSocket 示例
python
import asyncio
import websockets
import json
import base64
url = "wss://neolink.com/minimax/ws/v1/t2a_v2"
headers = {"Authorization": "Bearer <API_KEY>"}
async def tts_websocket():
async with websockets.connect(url, extra_headers=headers) as ws:
# 1. 等待连接成功
msg = json.loads(await ws.recv())
print(f"连接成功: {msg['event']}")
# 2. 启动合成任务
task_start = {
"event": "task_start",
"model": "speech-2.8-hd",
"language_boost": "Chinese",
"voice_setting": {
"voice_id": "male-qn-qingse",
"speed": 1,
"vol": 1,
"pitch": 0
},
"audio_setting": {
"sample_rate": 32000,
"bitrate": 128000,
"format": "mp3",
"channel": 1
}
}
await ws.send(json.dumps(task_start))
# 3. 等待 task_started
msg = json.loads(await ws.recv())
print(f"任务状态: {msg['event']}")
# 4. 发送合成文本
task_continue = {
"event": "task_continue",
"text": "真正的危险不是计算机开始像人一样思考,而是人开始像计算机一样思考。"
}
await ws.send(json.dumps(task_continue))
# 5. 接收音频数据
audio_data = b""
while True:
msg = json.loads(await ws.recv())
if msg["event"] == "task_continued":
chunk = base64.b64decode(msg["data"]["audio"])
audio_data += chunk
if msg.get("is_final"):
break
elif msg["event"] == "task_failed":
print(f"任务失败: {msg['base_resp']}")
break
# 6. 结束任务
await ws.send(json.dumps({"event": "task_finish"}))
msg = json.loads(await ws.recv())
print(f"任务结束: {msg['event']}")
# 保存音频
with open("output_ws.mp3", "wb") as f:
f.write(audio_data)
print("音频已保存为 output_ws.mp3")
asyncio.run(tts_websocket())