语音生成
用文本、参考音色或图片端到端异步生成语音与音效,提交后轮询任务获取成品音频。
ListenHub Voice API 端到端生成音频——纯文本旁白、音效、单音色语音、多音色对白、参考音频克隆音色,或图片转音频。生成为异步:提交请求后轮询任务直到完成。所有端点位于 https://api.marswave.ai/openapi/v1/listenhub-voice 下,使用 Authorization: Bearer $LISTENHUB_API_KEY 鉴权。
每个响应都包裹在 { "code": 0, "message": "", "data": { ... } } 中。code 非 0 表示错误——见错误处理。下文示例均从 data 读取字段。
模型与限制
| 项目 | 取值 |
|---|---|
model | listenhub-voice-1.0(默认,且为唯一支持值) |
| 限速 | 每用户每分钟 5 次,作用于 /generate |
text | 最多 1400 字符 |
voices | 1–3 项(纯文本/音效时省略) |
durationHint | 1–110 秒(积分预估 + 目标时长提示) |
音色(voices)
voices 决定由谁来说。每项二选一:
type | 必填字段 | 说明 |
|---|---|---|
speaker | id | 内置音色——ListenHub 音色代号或官方 voice_type。此类型不要传 url。 |
reference | url | 自定义参考音频 URL(http/https),用于克隆音色。≤30 秒、≤10MB,wav/mp3/pcm/ogg_opus。此类型不要传 id。 |
多音色对白时,列出 2–3 个音色,并在 text 每句前用 @音频1、@音频2…… 按顺序把台词指派给对应音色。完全省略 voices 则生成纯旁白或纯音效。
voices 与 image 互斥——至多传一个。同时传入会被拒绝。speaker 项只能带
id,reference 项只能带 url,混传会返回 33004(参数无效)。
异步任务生命周期
- 向
POST /v1/listenhub-voice/generate提交生成请求,响应携带taskId,初始status为pending。 - 轮询
GET /v1/listenhub-voice/tasks/{taskId},status依次经过pending→generating→uploading→success。 - 成功后读取
audioUrl;失败则读取errorMessage。
| 状态 | 含义 |
|---|---|
pending | 已创建,待提交生成。 |
generating | 生成中,audioUrl 尚未就绪。 |
uploading | 生成完成,正在转存至存储。 |
success | 完成,audioUrl 可用。 |
failed | 某阶段失败,errorMessage 说明原因;已预占的积分自动退回。 |
创建 ListenHub Voice 任务
POST /v1/listenhub-voice/generate
提交文本(可附带音色或参考图片)进行端到端音频生成。发送 JSON。返回 202 与 taskId。
# 纯文本 / 音效(不传 voices)
curl -X POST "https://api.marswave.ai/openapi/v1/listenhub-voice/generate" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "A gentle rain falls on a quiet street at midnight.",
"durationHint": 20
}'
# 单音色(speaker)
curl -X POST "https://api.marswave.ai/openapi/v1/listenhub-voice/generate" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Welcome to ListenHub. Here is your daily briefing.",
"voices": [{ "type": "speaker", "id": "zh_female_warm" }]
}'
# 参考音频克隆音色
curl -X POST "https://api.marswave.ai/openapi/v1/listenhub-voice/generate" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "@音频1 Hi there! @音频2 Hello, how can I help?",
"voices": [
{ "type": "reference", "url": "https://example.com/host.mp3" },
{ "type": "speaker", "id": "zh_male_calm" }
]
}'const response = await fetch(
'https://api.marswave.ai/openapi/v1/listenhub-voice/generate',
{
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.LISTENHUB_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
text: 'Welcome to ListenHub. Here is your daily briefing.',
voices: [{ type: 'speaker', id: 'zh_female_warm' }],
durationHint: 20,
}),
},
)
const { data } = await response.json()
console.log('Task ID:', data.taskId)import os
import requests
response = requests.post(
'https://api.marswave.ai/openapi/v1/listenhub-voice/generate',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
json={
'text': 'Welcome to ListenHub. Here is your daily briefing.',
'voices': [{'type': 'speaker', 'id': 'zh_female_warm'}],
'durationHint': 20,
},
)
data = response.json()['data']
print('Task ID:', data['taskId'])图片转音频时,传 image 对象代替 voices(两者互斥):
{
"text": "Describe this scene as a short narrated clip.",
"image": { "url": "https://example.com/scene.jpg" }
}请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | 否 | listenhub-voice-1.0。默认 listenhub-voice-1.0 |
text | string | 是 | 要朗读的脚本,最多 1400 字符。用 @音频N 前缀把对白台词指派给对应音色 |
voices | array | 否 | 1–3 个音色项(见音色)。纯文本/音效时省略。与 image 互斥 |
image | object | 否 | 图片转音频的参考图。url(http/https)与 data(Base64,可带 data:image/...;base64, 前缀)二选一。仅 1 张、≤10MB、jpeg/png/webp。与 voices 互斥 |
audioConfig | object | 否 | 输出调节(见下) |
durationHint | number | 否 | 目标时长,1–110 秒。驱动积分预估并提示模型 |
watermark | boolean | 否 | 添加音频水印 |
audioConfig 字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
speechRate | number | 否 | 语速,-50–100 |
loudnessRate | number | 否 | 响度,-50–100 |
pitchRate | number | 否 | 音高,-12–12 |
format | string | 否 | mp3(默认)、wav、pcm 或 ogg_opus |
返回 202:
{
"code": 0,
"message": "",
"data": {
"taskId": "68e780390fc5c9a54f695a7e",
"status": "pending"
}
}查询单个任务
GET /v1/listenhub-voice/tasks/{taskId}
获取单个任务。这是提交生成请求后用于轮询的端点。
curl -X GET "https://api.marswave.ai/openapi/v1/listenhub-voice/tasks/{taskId}" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"const response = await fetch(
`https://api.marswave.ai/openapi/v1/listenhub-voice/tasks/${taskId}`,
{ headers: { Authorization: `Bearer ${process.env.LISTENHUB_API_KEY}` } },
)
const { data } = await response.json()
console.log('Status:', data.status)
if (data.status === 'success') console.log('Audio:', data.audioUrl)import os
import requests
response = requests.get(
f'https://api.marswave.ai/openapi/v1/listenhub-voice/tasks/{task_id}',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
)
data = response.json()['data']
print('Status:', data['status'])
if data['status'] == 'success':
print('Audio:', data['audioUrl'])成功的任务:
{
"code": 0,
"message": "",
"data": {
"id": "68e780390fc5c9a54f695a7e",
"status": "success",
"model": "listenhub-voice-1.0",
"params": {
"text": "Welcome to ListenHub. Here is your daily briefing.",
"voices": [{ "type": "speaker", "id": "zh_female_warm" }]
},
"audioUrl": "https://assets.listenhub.ai/seed-audio/68e780390fc5c9a54f695a7e.mp3",
"audioDuration": 18.4,
"creditCharged": 12,
"creditRefunded": 0,
"createdAt": 1730000000000,
"updatedAt": 1730000040000
}
}任务响应字段:
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 任务 ID |
status | string | pending、generating、uploading、success 或 failed |
model | string | listenhub-voice-1.0 |
params | object | 提交请求的回显(敏感的图片/音频负载已剥离;内联图片显示为 { "hasData": true },可附 thumbnailUrl) |
audioUrl | string | 成品音频 URL。仅 status 为 success 时返回 |
audioDuration | number | 音频时长(秒,即计费时长) |
creditCharged | number | 实际扣费积分(未扣为 0) |
creditRefunded | number | 失败退回积分(用于对账) |
errorMessage | string | 失败原因。仅 status 为 failed 时返回 |
createdAt | number | 创建时间(毫秒时间戳) |
updatedAt | number | 更新时间(毫秒时间戳) |
查询任务列表
GET /v1/listenhub-voice/tasks
列出你的 ListenHub Voice 任务,按创建时间倒序。
curl -X GET "https://api.marswave.ai/openapi/v1/listenhub-voice/tasks?page=1&pageSize=20&status=success" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"const response = await fetch(
'https://api.marswave.ai/openapi/v1/listenhub-voice/tasks?page=1&pageSize=20',
{ headers: { Authorization: `Bearer ${process.env.LISTENHUB_API_KEY}` } },
)
const { data } = await response.json()
console.log(`${data.total} tasks, showing ${data.items.length}`)import os
import requests
response = requests.get(
'https://api.marswave.ai/openapi/v1/listenhub-voice/tasks',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
params={'page': 1, 'pageSize': 20},
)
data = response.json()['data']
print(data['total'], 'tasks, showing', len(data['items']))查询参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
page | integer | 否 | 页码,最小 1。默认 1 |
pageSize | integer | 否 | 每页数量,1–100。默认 20 |
status | string | 否 | 按 pending、generating、uploading、success 或 failed 过滤 |
keyword | string | 否 | 按任务 text 模糊匹配,最多 64 字符 |
响应:
{
"code": 0,
"message": "",
"data": {
"items": [
{
"id": "68e780390fc5c9a54f695a7e",
"status": "success",
"model": "listenhub-voice-1.0",
"audioUrl": "https://assets.listenhub.ai/seed-audio/68e780390fc5c9a54f695a7e.mp3",
"audioDuration": 18.4,
"creditCharged": 12,
"creditRefunded": 0,
"createdAt": 1730000000000,
"updatedAt": 1730000040000
}
],
"page": 1,
"pageSize": 20,
"total": 1
}
}每个 item 与查询单个任务字段相同。
错误
业务错误返回 HTTP 400,具体错误码在顶层 code 字段中。
| 错误码 | 含义 |
|---|---|
33001 | 任务未找到(或不属于当前 API 用户) |
33002 | speaker 音色项对应的音色未找到 |
33003 | 生成服务不可用 |
33004 | 参数无效(如 voices 与 image 同传,或音色项混传 id 与 url) |
33005 | 音色过多(最多 3 个) |
33006 | 积分不足 |
33007 | 触发限流 |
33008 | 生成超时 |
33009 | 达到单用户并发上限 |
| HTTP 状态 | 含义 |
|---|---|
400 | 参数无效或业务错误——见上方 33xxx 错误码 |
429 | 超出限速(/generate 每用户 5 RPM) |
积分
积分在提交时预占,成功时确认扣除,失败自动退回。每个任务返回 creditCharged(实际扣费)与 creditRefunded(失败退回)用于对账。计费时长为 audioDuration。用 GET /v1/user/subscription 查询实时余额,并参见定价了解积分与功能的对应关系。