Use the ListenHub OpenAPI to convert text to speech. Supports three synthesis modes, covering the full range of scenarios from short text to long text.
API Information
- Base URL:
https://api.marswave.ai/openapi - Authentication:
Authorization: Bearer $LISTENHUB_API_KEY(read from environment variable) - Pre-check: Before calling any API, first confirm that
LISTENHUB_API_KEYenvironment variable is set; if not set, prompt the user to configure it
Voice Selection Process
User has explicitly specified a voice
Directly use the speakerId specified by the user, skipping the selection process.
User has not specified a voice
- Call
GET /v1/speakers/list?language=zhto get the list of available voices - Display the voice list for the user to select according to AskUserQuestion, in the following format:
- Default selected
chat-girl-105-cn(Xiaoman dxqqq) - List display:
{name}({gender},{speakerId}) - Include each voice's demoAudioUrl for reference
- Default selected
- After the user confirms, use the selected speakerId
Default voice
| Field | Value |
|---|---|
| speakerId | chat-girl-105-cn |
| Name | Xiaoman dxqqq |
Three Synthesis Modes
Mode 1: Quick Synthesis (short text, single voice)
Applicable scenarios: Short text (< 1000 characters), single voice, requires low latency
Endpoint: POST /v1/tts
Request body:
{
"text": "要合成的文本",
"speakerId": "chat-girl-105-cn",
"format": "mp3",
"sampleRate": 24000,
"speed": 1.0
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| text | string | Yes | The text to synthesize |
| speakerId | string | Yes | Voice ID |
| format | string | No | Output format, default mp3 |
| sampleRate | int | No | Sample rate, default 24000 |
| speed | float | No | Speech rate, default 1.0, range 0.5 ~ 2.0 |
Response: directly returns an MP3 binary stream (Content-Type: audio/mpeg)
Example call:
curl -X POST "https://api.marswave.ai/openapi/v1/tts" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text": "你好世界", "speakerId": "chat-girl-105-cn"}' \
-o output.mp3
Mode 2: Multi-role Script Synthesis
Applicable scenarios: Multi-role dialogue, podcasts, audiobook segments, requiring alternating narration with different voices
Endpoint: POST /v1/speech
Request body:
{
"script": [
{
"text": "你好,欢迎收听本期节目。",
"speakerId": "chat-girl-105-cn"
},
{
"text": "谢谢,今天我们来聊聊 AI。",
"speakerId": "chat-boy-101-cn"
}
],
"format": "mp3",
"sampleRate": 24000
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| script | array | Yes | Script array, each item contains text and speakerId |
| script[].text | string | Yes | This segment's text |
| script[].speakerId | string | Yes | This segment's voice ID |
| format | string | No | Output format, default mp3 |
| sampleRate | int | No | Sample rate, default 24000 |
Response: JSON
{
"audioUrl": "https://cdn.example.com/output.mp3",
"duration": 12.5
}
Example call:
curl -X POST "https://api.marswave.ai/openapi/v1/speech" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"script": [
{"text": "你好,欢迎收听。", "speakerId": "chat-girl-105-cn"},
{"text": "谢谢,我们开始吧。", "speakerId": "chat-boy-101-cn"}
]
}'
Mode 3: Long-text Streaming Synthesis
Applicable scenarios: Long text (> 1000 characters), article reading, requiring AI polishing or segmentation
Endpoint: POST /v1/flow-speech/episodes
Request body:
{
"title": "文章标题",
"content": "长文本内容...",
"speakerId": "chat-girl-105-cn",
"mode": "direct",
"format": "mp3"
}
| Parameter | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | Audio title |
| content | string | No | Text content (choose one of contentUrl) |
| contentUrl | string | No | Content URL (choose one of content) |
| speakerId | string | Yes | Voice ID |
| mode | string | No | direct(direct synthesis) or aiPolish(AI polishing), default direct |
| format | string | No | Output format, default mp3 |
Response: JSON
{
"episodeId": "ep_abc123",
"status": "processing"
}
Poll for results:
GET /v1/flow-speech/episodes/{episodeId}
Polling strategy:
- After submission, wait 30 seconds
- then poll every 10 seconds
- until status becomes
completedorfailed
Polling response:
{
"episodeId": "ep_abc123",
"status": "completed",
"audioUrl": "https://cdn.example.com/output.mp3",
"duration": 180.5
}
| status value | Description |
|---|---|
| processing | Synthesizing, continue polling |
| completed | Synthesis complete, audioUrl is available |
| failed | Synthesis failed, check errorMessage |
Example call:
# 提交任务
curl -X POST "https://api.marswave.ai/openapi/v1/flow-speech/episodes" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "AI 技术趋势",
"content": "长文本内容...",
"speakerId": "chat-girl-105-cn",
"mode": "direct"
}'
# 轮询结果
curl "https://api.marswave.ai/openapi/v1/flow-speech/episodes/ep_abc123" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"
Voice list query
Endpoint: GET /v1/speakers/list
Query parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| language | string | No | Filter language, e.g. zh(Chinese),en(English) |
Response:
{
"speakers": [
{
"name": "晓曼 dxqqq",
"speakerId": "chat-girl-105-cn",
"demoAudioUrl": "https://cdn.example.com/demo.mp3",
"gender": "female",
"language": "zh"
}
]
}
Mode selection logic
Automatically select the most appropriate mode based on user input:
| Condition | Mode |
|---|---|
| Text ≤ 1000 characters, single voice | Mode 1:/v1/tts |
| Multi-character script, requires different voices | Mode 2:/v1/speech |
| Text > 1000 characters, or AI polishing required | Mode 3:/v1/flow-speech/episodes |
| User provides a URL as the content source | Mode 3:/v1/flow-speech/episodes |
If the user explicitly specifies a mode, use the user-specified mode first.
User interaction
Voice selection
When the user does not specify a voice, use AskUserQuestion to display the voice list:
请选择音色(默认:晓曼 dxqqq):
A. 晓曼 dxqqq(女,chat-girl-105-cn)[默认]
B. [其他音色名称]([性别],[speakerId])
C. ...
Synthesis parameters
Optional prompts:
- Speech rate speed (default 1.0)
- Output format format (default mp3)
- Long text mode: direct or aiPolish (default direct)
- Output file path (default
./output.mp3)
Output
- Save the audio to the specified path (default
./output.mp3) - Output synthesis summary:
- Mode used
- Voice name and ID
- Audio duration
- File size
- File path
Error handling
- 401 Unauthorized: Prompt the user to check the
LISTENHUB_API_KEYenvironment variable - 400 Bad Request: Check the request parameters and report the specific error to the user
- flow-speech failed: Report errorMessage, suggest the user retry or switch modes
- Network error: Prompt to check the network connection and suggest retrying
Complete example
User input: "Convert this text to speech: The weather is really nice today, suitable for going out for a walk."
Execution flow:
- Check
LISTENHUB_API_KEY✓ - Text length < 1000 characters, single voice → select Mode 1
/v1/tts - User did not specify a voice → use default
chat-girl-105-cn(Xiaoman) - Call API to synthesize
- Save to
./output.mp3 - Output summary
User input: "Read this article aloud in Xiaoman's voice: article.md"
Execution flow:
- Read
article.mdcontent - Check text length > 1000 characters → select Mode 3
/v1/flow-speech/episodes - Voice specified:
chat-girl-105-cn(Xiaoman) - Submit synthesis task
- Poll until complete
- Download audio and save to
./article.mp3 - Output summary