# Qwen Audio 3.1 TTS Flash speech synthesis

> Audio Generation

Synthesizes speech from text. By default the response is JSON containing an audio URL or Base64 audio. When `metadata.stream` is `true` the response is `text/event-stream`, pushing audio chunks sentence by sentence, with usage in the final event.

`input` and `voice` are required; `instructions`, `speed`, `response_format` and `audio_config` are optional. When no format is given, the upstream defaults to `mp3` with a `22050` Hz sample rate.

## Endpoint

`POST https://api.modelverse.cn/v1/audio/speech`

## Request Body

## Responses

- **200** — Synthesis succeeded. Non-streaming returns JSON (the audio URL is valid for 24 hours); with `metadata.stream=true` the response is `text/event-stream`.

- **400** — Invalid request parameters, or the voice does not match the model. When the very first upstream event is an error, the API returns that error directly instead of a partial event stream.

- **401** — Authentication failed; the API key is missing or invalid.
- **default** — Other error responses.

## OpenAPI Definition

```json
{
  "openapi": "3.1.0",
  "x-language": "en-US",
  "info": {
    "title": "Qwen Audio 3.1 TTS Flash Speech Synthesis",
    "version": "1.0.0",
    "description": "This document describes the ModelVerse speech synthesis API for `qwen-audio-3.1-tts-flash`: how to submit text, read the audio result, enable SSE streaming, and handle errors.\n\nThe endpoint is `POST /v1/audio/speech`.\n\n## Model capabilities\n\n- Non-realtime speech synthesis: submit the full text in one request, with either a non-streaming response (complete audio returned at once) or an SSE stream (audio chunks pushed sentence by sentence).\n- Supports Mandarin Chinese, multiple languages and dialects. Use `voice` to select a timbre and `instructions` to control emotion, speaking rate and dialect.\n- Supports SSML and LaTeX. See the official Non-realtime Speech Synthesis and Instruction Control guides for syntax.\n\n## Billing\n\n`qwen-audio-3.1-tts-flash` is billed by **input tokens plus output tokens**, reported in `usage.input_tokens`, `usage.output_tokens` and `usage.total_tokens`.\n\n## Notes\n\n- `voice` must belong to the voice list of `qwen-audio-3.1-tts-flash`; voices cannot be shared across models. A mismatched voice makes the upstream return `InvalidParameter`, for example `[cosyvoice:]Engine error [411]: TTS speak operation failed`.\n- Some voices (for example the \"other system voices\" group) are only available in the Beijing region. Make sure the channel endpoint and the API key belong to the same region.\n- `instructions` must not exceed 100 equivalent characters, where one Chinese character counts as two.\n- Streaming is enabled with `metadata.stream=true`; the gateway then adds the `X-DashScope-SSE: enable` header to the upstream request.\n"
  },
  "servers": [
    {
      "url": "https://api.modelverse.cn",
      "description": "ModelVerse production API endpoint."
    }
  ],
  "tags": [
    {
      "name": "Qwen TTS",
      "description": "Speech synthesis operations for `qwen-audio-3.1-tts-flash`."
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/v1/audio/speech": {
      "post": {
        "tags": [
          "Qwen TTS"
        ],
        "operationId": "createQwenAudio31TTSFlashSpeech",
        "summary": "Qwen Audio 3.1 TTS Flash speech synthesis",
        "description": "Synthesizes speech from text. By default the response is JSON containing an audio URL or Base64 audio. When `metadata.stream` is `true` the response is `text/event-stream`, pushing audio chunks sentence by sentence, with usage in the final event.\n\n`input` and `voice` are required; `instructions`, `speed`, `response_format` and `audio_config` are optional. When no format is given, the upstream defaults to `mp3` with a `22050` Hz sample rate.\n",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QwenAudioTTSFlashSpeechRequest"
              },
              "examples": {
                "basic": {
                  "summary": "Basic synthesis (WAV / 24 kHz)",
                  "value": {
                    "model": "qwen-audio-3.1-tts-flash",
                    "input": "Hello, the weather is really nice today.",
                    "voice": "longanhuan_v3.1",
                    "response_format": "wav",
                    "audio_config": {
                      "format": "wav",
                      "sample_rate": 24000
                    }
                  }
                },
                "withInstructions": {
                  "summary": "Control emotion and speaking rate with instructions",
                  "value": {
                    "model": "qwen-audio-3.1-tts-flash",
                    "input": "Shanghai will be sunny to partly cloudy today with a high of 22 degrees.",
                    "voice": "anxiaolan_v3.1",
                    "instructions": "Read it in a gentle, slightly slower broadcast tone.",
                    "speed": 0.9,
                    "response_format": "mp3"
                  }
                },
                "stream": {
                  "summary": "SSE streaming synthesis",
                  "value": {
                    "model": "qwen-audio-3.1-tts-flash",
                    "input": "This is a sample sentence for streaming synthesis.",
                    "voice": "longanhuan_v3.1",
                    "response_format": "pcm",
                    "audio_config": {
                      "format": "pcm",
                      "sample_rate": 24000
                    },
                    "metadata": {
                      "stream": true
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Synthesis succeeded. Non-streaming returns JSON (the audio URL is valid for 24 hours); with `metadata.stream=true` the response is `text/event-stream`.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QwenAudioTTSResponse"
                },
                "examples": {
                  "synthesizedSpeech": {
                    "summary": "Non-streaming synthesis result",
                    "value": {
                      "request_id": "5c63c65c-cad8-4bf4-959d-xxxxxxxxxxxx",
                      "output": {
                        "finish_reason": "stop",
                        "audio": {
                          "data": "",
                          "url": "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/xx/xxxxxxxx.wav?Expires=1766113409&OSSAccessKeyId=LTAI5xxxxxx&Signature=xxxxxx",
                          "id": "audio_5c63c65c-cad8-4bf4-959d-xxxxxxxxxxxx",
                          "expires_at": 1766113409
                        }
                      },
                      "usage": {
                        "input_tokens": 12,
                        "output_tokens": 30,
                        "total_tokens": 42,
                        "characters": 22
                      }
                    }
                  }
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "Server-sent events. Each event consists of `id:`, `event:result`, `:HTTP_STATUS/200`, `data:<JSON>` and a blank line; payloads follow the native Alibaba Cloud format.\n\n`output.audio.data` holds a Base64 audio chunk; concatenating chunks in event order reproduces the complete audio. `output.type` is one of `sentence-begin`, `sentence-synthesis`, `sentence-end`. The terminal event has `output.finish_reason=stop` and carries `usage`.\n"
                },
                "examples": {
                  "streamEvents": {
                    "summary": "Sample stream events (excerpt)",
                    "value": "id:1\nevent:result\n:HTTP_STATUS/200\ndata:{\"output\":{\"finish_reason\":null,\"type\":\"sentence-begin\",\"original_text\":\"This is a sample sentence for streaming synthesis.\",\"sentence\":{\"index\":0,\"words\":[]},\"audio\":{\"data\":\"\",\"id\":\"audio_xxxx\",\"expires_at\":1766113409}},\"request_id\":\"5c63c65c-cad8-4bf4-959d-xxxxxxxxxxxx\"}\n\nid:2\nevent:result\n:HTTP_STATUS/200\ndata:{\"output\":{\"finish_reason\":null,\"type\":\"sentence-synthesis\",\"sentence\":{\"index\":0},\"audio\":{\"data\":\"UklGRiQAAABXQVZF...\",\"id\":\"audio_xxxx\",\"expires_at\":1766113409}},\"request_id\":\"5c63c65c-cad8-4bf4-959d-xxxxxxxxxxxx\"}\n\nid:3\nevent:result\n:HTTP_STATUS/200\ndata:{\"output\":{\"finish_reason\":\"stop\",\"type\":\"sentence-end\",\"audio\":{\"data\":\"\",\"id\":\"audio_xxxx\",\"expires_at\":1766113409}},\"usage\":{\"input_tokens\":12,\"output_tokens\":30,\"total_tokens\":42,\"characters\":22},\"request_id\":\"5c63c65c-cad8-4bf4-959d-xxxxxxxxxxxx\"}\n"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request parameters, or the voice does not match the model. When the very first upstream event is an error, the API returns that error directly instead of a partial event stream.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QwenAudioTTSErrorResponse"
                },
                "examples": {
                  "invalidVoice": {
                    "summary": "Voice does not match the model",
                    "value": {
                      "error": {
                        "message": "[trace_id: 73bb3306-cb43-464f-9d62-0ae10601dfa9] Request llm server Error: upstream error: sse status=400, body=id:1\nevent:error\n:HTTP_STATUS/400\ndata:{\"code\":\"InvalidParameter\",\"message\":\"[cosyvoice:]Engine error [411]: TTS speak operation failed\",\"request_id\":\"7d610784-8df4-9244-9544-26b338145fd6\"}",
                        "type": "internal_error",
                        "code": "model_server_error",
                        "param": null,
                        "trace_id": "73bb3306-cb43-464f-9d62-0ae10601dfa9"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication failed; the API key is missing or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QwenAudioTTSErrorResponse"
                }
              }
            }
          },
          "default": {
            "description": "Other error responses.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QwenAudioTTSErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API key",
        "description": "Bearer token authentication, using `Authorization: Bearer <API Key>`."
      }
    },
    "schemas": {
      "QwenAudioTTSFlashSpeechRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "model",
          "input",
          "voice"
        ],
        "properties": {
          "model": {
            "type": "string",
            "const": "qwen-audio-3.1-tts-flash",
            "description": "Model name, pinned to `qwen-audio-3.1-tts-flash`."
          },
          "input": {
            "type": "string",
            "description": "Text to synthesize. Plain text, SSML (with `metadata.enable_ssml=true`) and LaTeX are supported.\nLonger text increases synthesis latency; splitting by sentence or paragraph is recommended.\n"
          },
          "voice": {
            "type": "string",
            "description": "Voice ID, required. It must belong to the voice list supported by `qwen-audio-3.1-tts-flash` and cannot be shared with other models.\nA mismatched voice makes the upstream return `InvalidParameter` (`[cosyvoice:]Engine error [411]`).\n\nCommon voices: `longanhuan_v3.1` (female, multilingual), `anxiaolan_v3.1` (female, Mandarin only, Beijing region only).\n",
            "examples": [
              "longanhuan_v3.1",
              "anxiaolan_v3.1"
            ]
          },
          "instructions": {
            "type": "string",
            "description": "Synthesis instruction mapped to upstream `input.instruction`, used to control emotion, tone, dialect or role.\nIt must not exceed 100 equivalent characters, where one Chinese character counts as two.\n",
            "examples": [
              "Read it in a gentle, slightly slower broadcast tone.",
              "Please speak in Shanghai dialect."
            ]
          },
          "speed": {
            "type": "number",
            "format": "float",
            "minimum": 0.5,
            "maximum": 2,
            "default": 1,
            "description": "Speaking rate mapped to upstream `input.rate`, in the range `[0.5, 2.0]`."
          },
          "response_format": {
            "type": "string",
            "enum": [
              "mp3",
              "pcm",
              "wav",
              "opus"
            ],
            "default": "mp3",
            "description": "Audio encoding mapped to upstream `input.format`. If `audio_config.format` is also set, it takes precedence."
          },
          "audio_config": {
            "$ref": "#/components/schemas/QwenAudioTTSAudioConfig"
          },
          "metadata": {
            "$ref": "#/components/schemas/QwenAudioTTSMetadata"
          }
        }
      },
      "QwenAudioTTSAudioConfig": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "format": {
            "type": "string",
            "enum": [
              "mp3",
              "pcm",
              "wav",
              "opus"
            ],
            "description": "Audio encoding; takes precedence over `response_format`."
          },
          "sample_rate": {
            "type": "integer",
            "enum": [
              8000,
              12000,
              16000,
              22050,
              24000,
              44100,
              48000
            ],
            "description": "Audio sample rate in Hz, mapped to upstream `input.sample_rate`; default is `22050`.\nWith `format=opus`, only `8000`, `12000`, `16000`, `24000` and `48000` are supported.\n"
          }
        }
      },
      "QwenAudioTTSMetadata": {
        "type": "object",
        "additionalProperties": true,
        "description": "Extension object. Keys other than those documented here are forwarded to the upstream `input` as native Alibaba Cloud fields (for example `bit_rate`, `hot_fix`). Fields already mapped by the gateway (`text`, `voice`, `format`, `sample_rate`, `rate`, `instruction`) cannot be overridden.\n",
        "properties": {
          "stream": {
            "type": "boolean",
            "default": false,
            "description": "Whether to return audio as an SSE stream. When `true`, the response type is `text/event-stream`.\nThis field only switches the output mode and is not forwarded upstream.\n"
          },
          "volume": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "default": 50,
            "description": "Volume mapped to upstream `input.volume`."
          },
          "pitch": {
            "type": "number",
            "format": "float",
            "minimum": 0.5,
            "maximum": 2,
            "default": 1,
            "description": "Pitch mapped to upstream `input.pitch`."
          },
          "language_hints": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Target language hints mapped to upstream `input.language_hints`; only the first element is processed.\nCommon values include `zh`, `en`, `ja`, `ko`, `fr`, `de`, `ru`, `pt`, `es`, `it`, `th`, `id`, `vi`, `ms`, `fil`, `ar`; `other` covers additional languages (flash only).\n"
          },
          "enable_ssml": {
            "type": "boolean",
            "default": false,
            "description": "Whether to parse `input` as SSML, mapped to upstream `input.enable_ssml`."
          },
          "seed": {
            "type": "integer",
            "minimum": 0,
            "maximum": 65535,
            "default": 0,
            "description": "Random seed mapped to upstream `input.seed`. The same parameters and seed reproduce the same audio."
          },
          "enable_aigc_tag": {
            "type": "boolean",
            "default": false,
            "description": "Whether to embed an invisible AIGC label in the audio, mapped to upstream `input.enable_aigc_tag`."
          }
        }
      },
      "QwenAudioTTSResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "request_id",
          "output"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "description": "Unique request identifier for troubleshooting."
          },
          "output": {
            "$ref": "#/components/schemas/QwenAudioTTSOutput"
          },
          "usage": {
            "$ref": "#/components/schemas/QwenAudioTTSUsage"
          }
        }
      },
      "QwenAudioTTSOutput": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "finish_reason",
          "audio"
        ],
        "properties": {
          "finish_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "stop",
              null
            ],
            "description": "Synthesis status. `null` while synthesizing, `stop` when finished."
          },
          "type": {
            "type": "string",
            "enum": [
              "sentence-begin",
              "sentence-synthesis",
              "sentence-end"
            ],
            "description": "Streaming only. `sentence-begin` starts a sentence, `sentence-synthesis` is an audio chunk (a sentence may span several chunks), `sentence-end` finishes a sentence and returns usage."
          },
          "original_text": {
            "type": "string",
            "description": "A sentence split from the input text; the last sentence may omit this field."
          },
          "sentence": {
            "type": "object",
            "additionalProperties": true,
            "description": "Sentence information, including `index` and word-level timestamps in `words`."
          },
          "audio": {
            "$ref": "#/components/schemas/QwenAudioTTSAudio"
          }
        }
      },
      "QwenAudioTTSAudio": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "data",
          "url",
          "id",
          "expires_at"
        ],
        "properties": {
          "data": {
            "type": "string",
            "description": "Base64 audio chunk for streaming output; an empty string for non-streaming responses."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Download URL of the complete audio file, valid for 24 hours; intermediate streaming events may omit it."
          },
          "id": {
            "type": "string",
            "description": "Identifier of the synthesized audio."
          },
          "expires_at": {
            "type": "integer",
            "format": "int64",
            "description": "Unix timestamp (seconds) when the audio URL expires."
          }
        }
      },
      "QwenAudioTTSUsage": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "input_tokens": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of input tokens, one of the billing meters for this model."
          },
          "output_tokens": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of output tokens, one of the billing meters for this model."
          },
          "total_tokens": {
            "type": "integer",
            "minimum": 0,
            "description": "Sum of input and output tokens."
          },
          "characters": {
            "type": "integer",
            "minimum": 0,
            "description": "Accumulated character count returned by the upstream; not used for billing for this model."
          }
        }
      },
      "QwenAudioTTSErrorResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "$ref": "#/components/schemas/QwenAudioTTSError"
          }
        }
      },
      "QwenAudioTTSError": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "message",
          "type",
          "code"
        ],
        "properties": {
          "message": {
            "type": "string",
            "description": "Error description; upstream errors include the raw upstream body."
          },
          "type": {
            "type": "string",
            "description": "Error type.",
            "examples": [
              "invalid_request_error",
              "internal_error"
            ]
          },
          "code": {
            "type": "string",
            "description": "Machine-readable error code.",
            "examples": [
              "model_server_error"
            ]
          },
          "param": {
            "type": [
              "string",
              "null"
            ],
            "description": "Field that caused the error, or `null` when not applicable."
          },
          "trace_id": {
            "type": "string",
            "description": "Trace ID of this request, used for feedback and troubleshooting."
          }
        }
      }
    }
  }
}
```
