Streaming Speech
Use TTS 1.5 Flash for low-latency streaming speech generation. This capability uses the same endpoint as single-speaker speech and is enabled with version=flash-20260626 and stream=true.
Authentication
Add Authorization: Bearer <API_KEY> to the request headers to authenticate. You can generate a key on the console "API Keys" page.
curl https://api.mosi.cn/v1/audio/speech \
-H "Authorization: Bearer $MOSS_API_KEY"
Supported models
| Field | Allowed values |
|---|---|
| model |
|
| version |
|
Activation requirements and constraints
- Pass the exact lowercase value
model=moss-tts; letter case is not normalized. versionis required and must beflash-20260626.streamis required and must betrue.response_formatis required; currently onlypcmis supported.stream_format=ssereturns SSE, with each frame formatted asdata: JSON Event.- Omitting
stream_formator passingaudioreturns raw PCM bytes. sample_rateis not a public request field; passing a non-zero value returns a parameter error before task creation.stream=truecannot be combined withasync=true, and streaming calls do not accept a non-emptywebhook_url.voice_url,voice_data, andfile_idare not supported for streaming calls; usevoice_idto specify a voice ID.delivery_methodandaigc_metadatacurrently have no effect on the streaming path; do not pass them.
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
| model | string | Yes | Must be the exact lowercase value |
| version | string | Yes | Must be |
| input | string | Yes | The text to synthesize. |
| voice_id | string | No | Voice ID; get one via List Voices, or go to the Mossland voice library and copy it from a voice card's copy icon. TTS accepts only a voice ID and does not support |
| language | string | No | Language hint, trimmed before it is passed to the model. |
| speed | number | No | Speech speed. The default is |
| expected_duration_sec | number | No | Expected audio duration in seconds. When provided, it must be greater than |
| stream | boolean | Yes | Set to |
| response_format | string | Yes | Streaming requests currently support only |
| stream_format | string | No |
|
Request examples
curl --no-buffer -X POST "https://api.mosi.cn/v1/audio/speech" \
-H "Authorization: Bearer $MOSS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "moss-tts",
"version": "flash-20260626",
"input": "Welcome to the Mossland API.",
"voice_id": "<voice_id>",
"language": "en",
"speed": 1,
"expected_duration_sec": 3,
"stream": true,
"response_format": "pcm",
"stream_format": "sse"
}'
Streaming response
stream_format=sse returns SSE, with each data: line followed by a JSON Event. type is the event discriminator; clients should use it to select the corresponding field structure. Omitting stream_format or passing audio returns raw PCM bytes.
Some access paths return task.created first, while others start directly with speech.created. Clients must use each frame's type and must not depend on a fixed first event.
SSE Event Types
| Event Type | Description | Terminal |
|---|---|---|
task.created | May be returned after the streaming task is created; not all access paths send it | No |
speech.created | Declares the format parameters for subsequent PCM audio chunks | No |
speech.audio.delta | A Base64-encoded PCM audio chunk; zero or more may be returned | No |
speech.audio.done | Terminal event for a successful TTS stream; clients may stop reading after receiving it | Yes |
error | Returned when a failure occurs after the stream starts; stop reading after receiving it | Yes |
task.created
| Field | Type | Always returned | Description |
|---|---|---|---|
| type | string | Yes | Always |
| task_id | string | Yes | The streaming task ID created by AGW. |
| object | string | Yes | Always |
| status | string | Yes | Usually |
| model | string | Yes | The public model name used by the client request. |
speech.created
| Field | Type | Always returned | Description |
|---|---|---|---|
| type | string | Yes | Always |
| format | string | Yes | Currently must be |
| sample_rate | integer | Yes | Sample rate in Hz. It must be positive and within the WAV parameter range; follow the downstream event value. |
| channels | integer | Yes | Channel count. It must be positive and within the WAV parameter range; follow the downstream event value. |
| bit_depth | integer | Yes | Bit depth. It must be positive, divisible by 8, and within the WAV parameter range; follow the downstream event value. |
speech.audio.delta
| Field | Type | Always returned | Description |
|---|---|---|---|
| type | string | Yes | Always |
| audio | string | Normally | When non-empty, a Base64-encoded PCM byte chunk. The current implementation allows an empty string; clients should ignore empty chunks. |
speech.audio.done
| Field | Type | Always returned | Description |
|---|---|---|---|
| type | string | Yes | Always |
error
| Field | Type | Always returned | Description |
|---|---|---|---|
| type | string | Yes | Always |
| error | object | Normally | Error details. |
| error.code | string | No | Machine-readable error code. |
| error.message | string | No | Error description. |
Raw PCM response headers
| Field | Type | Presence | Description |
|---|---|---|---|
Content-Type | HTTP header | Always | Always audio/pcm. |
X-Sample-Rate | HTTP header | Always | Raw PCM sample rate; clients must use this value to interpret the audio. |
X-Channels | HTTP header | Always | Raw PCM channel count. |
X-Bit-Depth | HTTP header | Always | Raw PCM bit depth. |
Response example
# SSE response example: pass stream_format=sse in the request
Content-Type: text/event-stream; charset=utf-8
# Some access paths omit task.created and start directly with speech.created
data: {"type":"task.created","task_id":"task-123","object":"audio.speech","status":"PROCESSING","model":"moss-tts"}
data: {"type":"speech.created","format":"pcm","sample_rate":48000,"channels":1,"bit_depth":16}
data: {"type":"speech.audio.delta","audio":"BASE64_PCM_CHUNK"}
data: {"type":"speech.audio.done"}
# Raw PCM response example: omit stream_format or pass stream_format=audio
Content-Type: audio/pcm
X-Sample-Rate: 48000
X-Channels: 1
X-Bit-Depth: 16
<raw pcm bytes>
Errors and disconnect semantics
missing_required_field:inputis missing or empty after trimming.unsupported_response_format/response_format: the streaming request does not explicitly usepcm, or passes another audio format.unsupported_stream/stream:stream_formatis notaudio/sse, or the resolved model does not support streaming.unsupported_for_stream/sample_rate: the streaming request passes a non-zerosample_rate.invalid_range/speed:speedis outside the0.25-4range.unsupported_with_async/stream:stream=trueandasync=trueare passed together.unsupported_with_webhook/stream: the streaming request passes a non-emptywebhook_url.- Request validation, model resolution, streaming-capability checks, and task-creation errors occur before the response starts and return a standard JSON error.
- If SSE fails before
speech.audio.done, the server sends anerrordata frame and closes the connection. - If raw PCM fails after response headers or audio bytes have been written, the server can only close the connection; returned PCM may be incomplete.
- A client disconnect ends the current HTTP stream. Depending on the access path, it may cancel the upstream request or only the current subscription; clients must not assume that generation either always continues or is always canceled.
- In the raw PCM mode, EOF alone does not prove that the audio is complete.