AionRouter Text-to-Speech (TTS) API Guide
Text-to-speech converts text into playable audio for app narration, voiceovers and spoken notifications. Prepare a model that supports synthesis, a voice ID and an output format accepted by that model.
macOS/Linux, Windows PowerShell/CMD and Python examples cover synthesis, saving, playback and review. Synthesis, transcription and real-time voice use different interactions; do not mix endpoints simply because a model is described as an audio model.
Distinguish TTS, transcription and real-time audio
Speech synthesis and other audio endpoints
| Capability | Endpoint | Input and output |
|---|---|---|
| Text-to-speech (TTS) | POST /v1/audio/speech |
Text input, audio output |
| Speech-to-text | POST /v1/audio/transcriptions |
Audio file input, transcription output |
| Audio translation | POST /v1/audio/translations |
Audio input and translation output supported by the model |
These endpoints use different parameters and request types. Transcription and translation typically upload multipart files; speech synthesis sends JSON text. TTS support does not imply support for the other two endpoints.
Synchronized audio generated by video models belongs to video generation. It is not an independent voiceover endpoint replacing /audio/speech.
| Input and goal | Capability to check | Why the flows differ |
|---|---|---|
| Text for narration | TTS model, voice and audio output | The request contains text and usually returns audio |
| A recording to transcribe | Transcription model, format and duration | Uploading and parsing differ from speech JSON requests |
| Live recognition while recording | The relevant recognition endpoint and event protocol | Enabling stream on ordinary TTS does not provide this |
| Speech while an assistant answers | Text generation plus TTS, or a specialized real-time model | Requires two stages or a dedicated session protocol |
Test a short sample containing your actual language, numbers and punctuation before an entire article. An audio-recognition model is not necessarily a TTS model, and the web microphone feature is not the external TTS API.
Prepare and run your first synthesis
Before you start
Choose a model that supports speech synthesis in the Model Marketplace, confirm its voice ID and output format, and prepare an API Key. Speech recognition models are not speech synthesis models.
These examples assume the model supports MP3 output:
Terminal compatibility
Use the examples for your shell: macOS/Linux use Bash or Zsh; Windows uses PowerShell or CMD. Git Bash/WSL can use the Bash examples, but run all setup and requests in the same environment. The current API root is https://test.aionrouter.io.
Windows examples explicitly use curl.exe to avoid the curl alias in Windows PowerShell 5.1. Check curl --version or curl.exe --version; --fail-with-body requires cURL 7.76.0 or later. Microsoft: curl on Windows · cURL options
Run one shell variant only. Environment variables apply to that terminal and programs started from it. In CMD, run each line separately; at the AIONROUTER_BASE_URL prompt, paste the API root shown above, without a trailing slash. Then enter the actual key, model or voice when prompted. Do not paste Bash export, backslash continuations or heredocs into CMD or PowerShell.
macOS / Linux — Bash / Zsh
export AIONROUTER_BASE_URL='https://test.aionrouter.io'
export AIONROUTER_API_KEY='替换为控制台复制的完整密钥'
export AIONROUTER_TTS_MODEL='替换为支持语音合成的实际模型 ID'
export AIONROUTER_TTS_VOICE='替换为该模型支持的实际音色 ID'
Windows — PowerShell
$env:AIONROUTER_BASE_URL = 'https://test.aionrouter.io'
$env:AIONROUTER_API_KEY = Read-Host 'AIONROUTER_API_KEY'
$env:AIONROUTER_TTS_MODEL = Read-Host 'AIONROUTER_TTS_MODEL'
$env:AIONROUTER_TTS_VOICE = Read-Host 'AIONROUTER_TTS_VOICE'
Windows — CMD
set "AIONROUTER_BASE_URL="
set /p "AIONROUTER_BASE_URL=AIONROUTER_BASE_URL: "
set "AIONROUTER_API_KEY="
set /p "AIONROUTER_API_KEY=AIONROUTER_API_KEY: "
set "AIONROUTER_TTS_MODEL="
set /p "AIONROUTER_TTS_MODEL=AIONROUTER_TTS_MODEL: "
set "AIONROUTER_TTS_VOICE="
set /p "AIONROUTER_TTS_VOICE=AIONROUTER_TTS_VOICE: "
Use the API service root supplied in the console, without a trailing slash. Voice IDs are not interchangeable between providers. If the model does not support MP3, change both the request and the saved file format.
cURL: convert text to speech
macOS / Linux — Bash / Zsh
curl --fail-with-body --silent --show-error \
"$AIONROUTER_BASE_URL/v1/audio/speech" \
-H "Authorization: Bearer $AIONROUTER_API_KEY" \
-H 'Content-Type: application/json' \
--dump-header speech.headers \
--output speech.response \
--data-binary @- <<JSON
{
"model": "$AIONROUTER_TTS_MODEL",
"input": "欢迎使用 AionRouter。现在可以把这段文字转换成语音,用于应用中的朗读和配音。",
"voice": "$AIONROUTER_TTS_VOICE",
"response_format": "mp3"
}
JSON
Windows request body: text-to-speech-2.json
Save this JSON in the current directory as UTF-8 without BOM, replacing YOUR_... values with actual model IDs or other required values. JSON files do not expand environment variables: changing a terminal model variable does not change this file. Do not use Windows PowerShell 5.1 > to create it, because that defaults to UTF-16LE. Both Windows commands below read the same file. Microsoft: character encoding
{
"model": "YOUR_AIONROUTER_TTS_MODEL",
"input": "欢迎使用 AionRouter。现在可以把这段文字转换成语音,用于应用中的朗读和配音。",
"voice": "YOUR_AIONROUTER_TTS_VOICE",
"response_format": "mp3"
}
Windows — PowerShell
curl.exe --fail-with-body --silent --show-error "${env:AIONROUTER_BASE_URL}/v1/audio/speech" -H "Authorization: Bearer ${env:AIONROUTER_API_KEY}" -H 'Content-Type: application/json' --dump-header 'speech.headers' --output 'speech.response' --data-binary '@text-to-speech-2.json'
Windows — CMD
curl.exe --fail-with-body --silent --show-error "%AIONROUTER_BASE_URL%/v1/audio/speech" -H "Authorization: Bearer %AIONROUTER_API_KEY%" -H "Content-Type: application/json" --dump-header "speech.headers" --output "speech.response" --data-binary "@text-to-speech-2.json"
First check the HTTP status and Content-Type in speech.headers:
- With a successful response and an expected audio type such as
audio/mpeg,speech.responsecontains audio. Name it for the actual format. - With a JSON error, the file contains an error body and cannot be played as audio.
- With
302andLocation, fetch the audio separately from the download URL.
Download the Location URL in a separate request without AionRouter authentication headers. Do not configure redirects to forward your gateway key to another domain.
Validate audio before adding a player. Check HTTP status, headers and file content before opening the download. A file's existence does not prove success: error JSON, redirect bodies and empty responses can also be saved as files.
Choose model and voice IDs separately from supported configuration. A display name is not the request ID, and another model's voice names may not apply. Free-text input fields in a client still require verification with a real request.
Save audio and handle formats and redirects
Python: save audio and handle redirects
This standard-library example requests MP3. It sends the key to the gateway, then follows a download redirect with a new request that has no gateway key. Set the environment variables above first.
import json
import os
from pathlib import Path
import urllib.error
import urllib.parse
import urllib.request
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
base_url = os.environ["AIONROUTER_BASE_URL"].rstrip("/")
request = urllib.request.Request(
f"{base_url}/v1/audio/speech",
data=json.dumps({
"model": os.environ["AIONROUTER_TTS_MODEL"],
"input": "你好,这是一段通过 API 生成的语音。",
"voice": os.environ["AIONROUTER_TTS_VOICE"],
"response_format": "mp3",
}, ensure_ascii=False).encode("utf-8"),
headers={
"Authorization": f"Bearer {os.environ['AIONROUTER_API_KEY']}",
"Content-Type": "application/json",
},
method="POST",
)
opener = urllib.request.build_opener(NoRedirect())
try:
response = opener.open(request, timeout=180)
except urllib.error.HTTPError as error:
location = error.headers.get("Location")
if error.code != 302 or not location:
detail = error.read().decode("utf-8", errors="replace")
raise RuntimeError(f"HTTP {error.code}: {detail}") from error
download_url = urllib.parse.urljoin(base_url + "/", location)
if urllib.parse.urlsplit(download_url).scheme != "https":
raise RuntimeError("下载地址不是 HTTPS,请检查响应。")
# 使用独立请求,下载域名不会收到 AionRouter API Key。
response = urllib.request.urlopen(download_url, timeout=180)
with response:
content_type = response.headers.get_content_type()
if content_type not in {"audio/mpeg", "audio/mp3"}:
raise RuntimeError(f"预期 MP3,实际返回 {content_type},请检查模型格式。")
audio = response.read()
if not audio:
raise RuntimeError("没有收到音频内容。")
Path("speech.mp3").write_bytes(audio)
print("已保存 speech.mp3")
Run the Python example on macOS or Windows
Save the code as example.py in UTF-8. In the terminal where you set the variables above, use python3 example.py on macOS/Linux or py -3 example.py on Windows. If the Windows launcher is unavailable but Python 3 is installed, use python example.py. The standard-library code is shared; variables set in PowerShell, CMD and WSL are not automatically shared.
The 180-second timeout is an example client setting, not a delivery-time guarantee for every model. This example handles non-streaming MP3 and should not be reused unchanged for SSE or raw PCM.
Save the actual encoding, not just an extension. MP3, WAV and PCM have different containers and playback requirements. Raw PCM also needs matching sample rate, channels and bit depth. Renaming it to MP3 does not convert it.
Separate synthesis from redirected downloads. An endpoint may return audio directly or, for a particular channel, redirect to a download. Confirm the status and destination, then fetch appropriately. Do not reuse an authenticated platform request against unrelated storage domains.
Track synthesis completion, download completion, playability and human approval separately. If audio exists and only downloading failed, recover the download before considering another synthesis request.
Configure voices, language, speed and long text
Request parameters
| Field | Type | Purpose and limitations |
|---|---|---|
model |
string | An available TTS model ID |
input |
string | Text to convert to speech |
voice |
string | A voice ID supported by the selected model |
response_format |
string | Requested output format, such as mp3 when supported; allowed values depend on the integration |
speed |
number | Controls speaking speed when supported; there is no universal valid range |
instructions |
string | Reading-style instructions when supported; not every model accepts them |
stream_format |
string | Supported integrations may accept sse; event processing differs from downloading an audio file |
metadata |
object | Provider-specific extensions whose meaning depends on the model and channel |
Validate the model, text, voice and output format first. Then add speed, emotion, language or provider extensions. A field being valid JSON does not mean the model implements it.
Check the actual model documentation for character limits, languages and voices. This endpoint has no single voice list covering every provider.
Choosing voices, languages and long-text handling
Use the actual voice ID
A voice display name may differ from its API ID. Copy the actual ID and test a short sample in the target language. Do not reuse one provider's voice name with another model.
Test with readable text
Start with one or two complete sentences, then test numbers, abbreviations, proper nouns and mixed languages. Your application can expand dates, units and special symbols into more readable text before generation.
Punctuation, sentence boundaries and the model's speech capabilities affect the result. Confirm support before adding emotion or pause tags, or the model may read the control text aloud.
Split long text by meaning
Split articles at paragraph or semantic boundaries, generate each segment and combine audio in your application. Segment lengths must respect the selected model's limits; one character limit does not suit every model.
Segments may be billed separately. Keep the voice, speed and format consistent. Validate seamless joins, fixed sample rates and subtitle timing in your application when required.
Choose a voice with your own sample. Compare a short introduction, numeric notice, technical terms and multilingual text for clarity, pauses and listening quality. Similar voice names do not imply identical pronunciation, language coverage or parameters across models.
Prepare text to be spoken. Decide how abbreviations, units, dates, URLs and code should sound. Remove unwanted Markdown, table separators and interface labels. SSML and pronunciation controls are model-specific; markup is not a universal instruction format.
Split long articles at natural paragraphs. Keep sentences intact and record each segment's ID, text version, model, voice and output file. Regenerate only revised segments. Match actual encoding before joining, and check pauses and volume transitions. Files from different models cannot be assumed safe to concatenate byte by byte.
Stabilize the voice style before adjusting speed. Support, style instructions and speed bounds vary. Remove unsupported fields instead of repeatedly changing their values to bypass validation.
Understand streaming speech and segmented playback
Streaming speech versus ordinary downloads
For models and channels that explicitly support SSE speech, set stream_format: "sse" as required. The client receives events and must read audio chunks and other data using that model's event structure.
This differs from returning an MP3 file directly. Do not save SSE text as .mp3 or assume the text-generation setting stream: true is a universal TTS switch.
Some audio responses transfer binary content incrementally. That does not guarantee playback can begin at any byte position. Playback during generation depends on the response, encoding and player buffering.
A streaming response needs client adaptation before a browser can play it immediately. Identify the event protocol or audio chunks and pass them to a decoder and playback path supporting that encoding. Do not write SSE text events into an MP3 file.
When generating text first and applying TTS incrementally, queue complete sentences or suitable spoken segments. Preserve order and handle text revisions, audio queues, user stops and retries. Synthesizing character by character harms continuity and creates more requests.
For low-latency interactions, measure text generation, first-segment synthesis, downloading and playback preparation separately. A slowdown does not guarantee that changing voices will help or that a file endpoint provides real-time sessions.
Check costs and troubleshoot audio
Costs and troubleshooting
Audio billing may use input text, audio or other model-specific usage. Check model details and prices and consumption records; do not convert every minute of audio into a fixed character count or price.
| Problem | Check first |
|---|---|
| Model unavailable | Whether it supports TTS and your key and group allow access |
| Voice error | Whether voice is an exact ID belonging to that model |
| Output format rejected | Whether the integration supports the selected response_format |
| Saved file will not play | HTTP status, Content-Type, and whether the body is JSON, a redirect or SSE |
| Speed or instructions ignored | Model support and the structure of provider extensions |
| Long-text failure | Input limits, timeout and content requirements; test a short sample first |
After a network interruption, check request and usage records before retrying. A new generation is a new request; retries are not guaranteed to be free.
Identify the model's billing unit first. Text input, audio output, per-request and duration pricing depend on current model details. Some transcription paths in this project bill by audio minutes; this does not mean every TTS model does. Do not infer a universal audio price from text length.
For a downloaded file that will not play, check status, media type, empty content, error bodies, player codec support and sample parameters first. If it plays but reads incorrectly, investigate text preprocessing, language, voice and model capabilities.
Track retries by segment for long text. A network timeout only says the client did not receive a result in time, not that synthesis never ran. Retain segment IDs, request details and available request IDs to avoid endless regeneration.
FAQ and related guides
Frequently asked questions
Does every model support MP3, WAV and PCM?
No. Use only formats explicitly supported by the model and check the actual Content-Type. Raw PCM also requires the sample rate, bit depth and channel count; the file extension is insufficient.
Why is the speech response not JSON?
A successful response may contain audio bytes directly, or a download redirect. Do not JSON-decode every successful response.
Can I clone my own voice?
This guide does not describe voice cloning as a universal public feature. Availability, authorization and obtaining a voice ID depend on the models and service workflow actually offered.
Can generated speech be used commercially?
Follow the applicable terms for the model, voice and platform. Confirm the necessary rights when using another person's voice, protected characters or commercial material.