Streaming TTS
Stream synthesized speech with word-level timestamp alignment snapshots for captions, karaoke, and timeline editing.
Stream text-to-speech with word/phrase-level timestamp alignment for karaoke highlighting, synced captions, and timeline editing.
The response is text/event-stream. Each SSE message contains a Base64 audio chunk and, when available, the latest cumulative alignment snapshot for that chunk_seq. Concatenate audio_base64 in arrival order. A newer snapshot for the same chunk_seq should replace the old snapshot — do not append segments.
Base URL
https://api.autorouter.top— Production
Authentication
BearerAuth: http (bearer)
Authenticate using a Bearer Token.
Format: Authorization: Bearer sk-xxxxxx
Endpoints
POST /fishaudio/v1/tts/stream/with-timestamp
Create Streaming TTS with Timestamps
The request header may set model: s1, s2-pro, s2.1-pro (default), s2.1-pro-free, drama-3-preview. Multi-speaker dialogue is supported only by the S2 series and drama-3-preview, not s1.
Request Body
Content-Type: application/json
Example:
{
"text": "Hello! Welcome to Fish Audio.",
"reference_id": "model-id",
"format": "opus",
"latency": "balanced"
}Properties:
| Name | Type | Required | Description |
|---|---|---|---|
text | string | Yes | Text to synthesize. For multi-speaker, switch with <|speaker:0|>, <|speaker:1|> |
reference_id | string | string[] | null | No | Voice ID. A string for a single speaker; an array of IDs for multiple speakers |
references | object[] | No | Inline reference audio for zero-shot cloning. Requires MessagePack; JSON cannot carry binary |
format | string | No | Output format: wav, pcm, mp3 (default), opus. Recommended: opus @ 48 kHz |
latency | string | No | Latency vs quality trade-off: normal (default, best quality), balanced, low. With balanced, long text may be split into multiple text chunks |
prosody | object | No | Speed and volume |
chunk_length | integer | No | Text chunk length, [100, 300]. Default 300 |
normalize | boolean | No | Whether to normalize Chinese/English text (improves number reading stability). Default true |
sample_rate | integer | null | No | Sample rate (Hz). When null, format defaults apply: 44100 for most formats, 48000 for opus |
mp3_bitrate | integer | No | MP3 bitrate (kbps): 64, 128 (default), 192 |
opus_bitrate | integer | No | Opus bitrate (bps). -1000 (default, auto), 24000, 32000, 48000, 64000 |
temperature | number | No | Expressiveness, [0, 1]. Default 0.. Higher is more diverse |
top_p | number | No | Nucleus sampling, [0, 1]. Default 0. |
max_new_tokens | integer | No | Maximum audio tokens generated per text chunk. Default 1024 |
repetition_penalty | number | No | Repetition penalty. Values greater than 1. reduce repetition. Default 1. |
min_chunk_length | integer | No | Minimum characters before splitting a new chunk, [0, 100]. Default 50 |
condition_on_previous_chunks | boolean | No | Whether to use previous audio as context to keep the voice consistent. Default true |
pronunciation_dictionary | object[] | No | Up to 3 pronunciation dictionaries (platform reference or inline; mutually exclusive) |
prosodyobject(Optional)
Speed and volume adjustments.
Speed multiplier, [0.5, 2.0]. 1.0 is normal speed.
Volume adjustment (dB). 0 is unchanged; positive is louder; negative is quieter.
Whether to normalize loudness. Supported only by s2-pro and the S2.1-Pro series.
Responses
200: SSE stream
Content-Type: text/event-stream
401: Unauthorized
Content-Type: application/json
402: Insufficient balance
Content-Type: application/json
503: Service overloaded
Content-Type: application/json
Request Example
curl --no-buffer -X POST "https://api.autorouter.top/fishaudio/v1/tts/stream/with-timestamp" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-xxxxxx" \
-H "model: s2-pro" \
-d '{
"text": "Hello! Welcome to Fish Audio.",
"reference_id": "model-id",
"format": "opus",
"latency": "balanced"
}'Response Example
{
"audio_base64": "SUQzBAAAAAAA...",
"content": "Hello world",
"chunk_seq": 0,
"chunk_audio_offset_sec": 0.0,
"alignment": {
"audio_duration": 0.86,
"segments": [
{
"text": "Hello",
"start": 0,
"end": 0.42
},
{
"text": "world",
"start": 0.42,
"end": 0.86
}
]
}
}Response fields:
| Name | Type | Description |
|---|---|---|
audio_base64 | string | One Base64 audio chunk. Concatenate in arrival order to reconstruct the full audio. This is a transport chunk, not a sentence/word boundary |
content | string | Text described by the latest alignment snapshot in this event. Long input may be split into multiple content chunks |
alignment | object | null | Latest cumulative timestamp snapshot for this chunk_seq. When present, replace the old snapshot; do not append. null before the first snapshot or when unavailable |
alignment. | number | Duration of the audio generated for this text chunk, in seconds |
alignment. | object[] | Ordered text time segments |
alignment. | string | Segment text |
alignment. | number | Start time in seconds relative to this text chunk's audio start |
alignment. | number | End time in seconds relative to this text chunk's audio start |
chunk_seq | integer | Text chunk index that the alignment belongs to. Bucket snapshots by this value |
chunk_audio_offset_sec | number | Absolute start of this text chunk in the full audio, in seconds. Add segment start/end to get the global timeline |
Processing guidance:
- Concatenate every
audio_base64in order even whenalignmentisnull. - Store alignments in a map keyed by
chunk_seq; each non-nullalignmentreplaces that key. - Add
chunk_audio_offset_secto each segment's local time to get global time.
Error Handling
HTTP 401 / 403 Auth Errors
401 Unauthorized: API Key invalid or expired403 Forbidden: API Key has no access to this model (check token's model allowlist)
HTTP 402 Insufficient Balance
Returns insufficient user quota. Top up at the AutoRouter console.
HTTP 503 Service Overloaded
The server is under too much load to process the request. Retry later.