Use the Qwen-Audio-TTS/CosyVoice iOS SDK to turn text into high-quality, expressive speech in your iOS apps.
User guide: For model overviews and how to choose a model, see Speech synthesis.
NeoNui
Architecture highlights:
Singleton pattern: get the global instance through
NeoNui.sharedInstance().Callback-driven: receive events and audio data through the StreamInputTtsDelegate protocol.
JSON configuration: pass parameters as JSON strings.
Call flows
Qwen-Audio-TTS/CosyVoice supports two invocation modes: one-shot input and streaming input.
One-shot input: best for short-text synthesis or when you need SSML markup.
startStreamInputTts() — Initialize the SDK and set the callback delegate and connection parameters.
playStreamInputTts() or asyncPlayStreamInputTts() — Send the text and start synthesis.
onStreamInputTtsDataCallback() — Receive audio data.
TTS_EVENT_SYNTHESIS_COMPLETE — Synthesis complete.
Streaming input: best for real-time conversations or long-form "speak-while-synthesizing" scenarios. This mode does not support SSML markup.
startStreamInputTts() — Initialize the SDK and set the callback delegate and connection parameters.
sendStreamInputTts() — Continuously send text fragments to be synthesized.
onStreamInputTtsDataCallback() — Receive audio data.
stopStreamInputTts() or asyncStopStreamInputTts() — Stop sending text and wait for synthesis to complete.
TTS_EVENT_SYNTHESIS_COMPLETE — Synthesis complete.
startStreamInputTts
Starts a streaming speech synthesis task and opens a connection to the server.
Method signature
- (int) startStreamInputTts:(const char *)ticket parameters:(const char *)parameters sessionId:(const char *)sessionId logLevel:(NuiSdkLogLevel)logLevel saveLog:(BOOL)saveLog;Parameters
Parameter
Type
Description
ticketchar*JSON string that holds authentication, connection, and debugging settings.
parameterschar*JSON string that holds the speech synthesis effect settings.
sessionIdchar*Client-specified session ID. If omitted, the server generates one.
logLevelPrint level for the SDK's internal logs.
saveLogBOOLWhether to save logs locally. When set to
YES, you must specify a path with debug_path and can cap the file size with max_log_file_size.Return value
Returns an error code.
ticket JSON example: The following example does not list every field. Add the others as your code requires:
{ "url": "wss://dashscope.aliyuncs.com/api-ws/v1/inference", "apikey": "st-****", "device_id": "my_device_id" }ticket fields
Field
Type
Required
Description
urlstringYes
Service URL. Set to
wss://dashscope.aliyuncs.com/api-ws/v1/inference.apikeystringYes
API key. To limit exposure if a long-lived key leaks, use a short-lived API key instead.
device_idstringYes
Unique identifier for the end user. Set this to the in-app user ID or a client-generated device identifier. The ID is used for log tracing and troubleshooting.
complete_waiting_msintNo
Timeout, in milliseconds, for waiting on the synthesis-complete event (TTS_EVENT_SYNTHESIS_COMPLETE) after you call stopStreamInputTts.
Default: 10000.
debug_pathstringNo
Local path where log files are stored.
This field takes effect only when
saveLogis set toYESin startStreamInputTts, playStreamInputTts, or asyncPlayStreamInputTts. In that case, you must set this path; otherwise, an error is returned.At most two log files are kept locally.
max_log_file_sizeintNo
Maximum size of a log file, in bytes.
This field takes effect only when
saveLogis set toYESin startStreamInputTts, playStreamInputTts, or asyncPlayStreamInputTts.Default: 104857600 (100 × 1024 × 1024 bytes, that is, 100 MiB).
log_track_levelintNo
Filter level for logs delivered through the log callback (
onStreamInputTtsLogTrackCallback).Default: 2.
Valid values:
0: LOG_LEVEL_VERBOSE
1: LOG_LEVEL_DEBUG
2: LOG_LEVEL_INFO
3: LOG_LEVEL_WARNING
4: LOG_LEVEL_ERROR
5: LOG_LEVEL_NONE (disables the callback)
Note:
log_track_levelandlogLevel(set through startStreamInputTts, playStreamInputTts, or asyncPlayStreamInputTts) together determine which logs reach the callback. A log fires the callback only when its level is at or above both thresholds. For example, iflog_track_levelis 2 (INFO) andlogLevelis 3 (WARNING), only logs at WARNING or higher (level >= 3) are delivered.parameters JSON example: The following example does not list every field. Add the others as your code requires:
{ "model": "qwen-audio-3.0-tts-flash", "voice": "longanlingxi", "format": "mp3", "sample_rate": 24000, "volume": 50, "rate": 1, "pitch": 1, "language_hints": ["zh"], "enable_ssml": false }parameters fields
Field
Type
Required
Description
modelstringYes
The model name.
voicestringYes
The voice used for speech synthesis.
-
System voices: See CosyVoice Voice list
-
Cloned voices: Custom voices created through voice cloning
-
Custom voices: Custom voices created through voice design
formatstringNo
The audio encoding format.
Valid values:
-
pcm
-
wav
-
mp3 (default)
-
opus
Importantcosyvoice-v1doesn't support the opus format.volumeintNo
The volume level.
Default value: 50.
Valid values: [0, 100].
sample_rateintNo
The audio sample rate in Hz.
Valid values: 8000, 16000, 22050 (default), 24000, 44100, 48000.
ratefloatNo
The speech rate.
Default value: 1.0.
Valid values: [0.5, 2.0].
pitchfloatNo
The pitch.
Default value: 1.0.
Valid values: [0.5, 2.0].
bit_rateintNo
The audio bit rate in kbps. When the audio format is opus, use
bit_rateto adjust the bit rate.Default value: 32.
Valid values: [6, 510].
cosyvoice-v1doesn't support this parameter.enable_ssmlbooleanNo
Whether to enable SSML.
Default: false.
true: enabled.
false: disabled.
For the SSML usage restrictions (supported models, voices, and APIs), see Limitations.
word_timestamp_enabledbooleanNo
Specifies whether to enable word-level timestamps.
Default value: false.
Available only in streaming output mode. Supported voices: cloned voices of cosyvoice-v3.5-plus, cosyvoice-v3.5-flash, cosyvoice-v3-flash, cosyvoice-v3-plus, and cosyvoice-v2, and system voices marked as supported in CosyVoice Voice list. qwen-audio-3.0-tts-plus, qwen-audio-3.0-tts-flash, and cloned voices of other models do not support this feature.
Timestamps are returned in
all_responseof onStreamInputTtsEventCallback.seedintNo
A random seed for controlling variation in the synthesis output. When the model version, text, voice, and other parameters are unchanged, using the same seed produces identical results.
Default value: 0.
Valid values: [0, 65535].
cosyvoice-v1 doesn't support this parameter.
language_hintsarray[string]No
Important-
This parameter is an array, but the current version only processes the first element. Pass a single value.
-
This parameter specifies the target language for speech synthesis. It's unrelated to the language of the audio sample used in voice cloning. To set the source language for a cloning task, see the voice cloning API reference.
Specifies the target language for speech synthesis to improve output quality. cosyvoice-v1 doesn't support this feature.
When digit pronunciation, abbreviation expansion, symbol reading, or minority-language synthesis doesn't meet expectations, use this parameter. For example:
-
Unexpected digit pronunciation: "hello, this is 110" is read as "hello, this is one zero" instead of the expected Chinese pronunciation
-
Inaccurate symbol pronunciation: "@" is read as the Chinese equivalent instead of "at"
-
Poor minor language synthesis quality with unnatural results
Valid values:
-
zh: Chinese
-
en: English
-
fr: French
-
de: German
-
ja: Japanese
-
ko: Korean
-
ru: Russian
-
pt: Portuguese
-
th: Thai
-
id: Indonesian
-
vi: Vietnamese
-
it: Italian
-
ms: Malay
instructionstringNo
Controls synthesis characteristics such as dialect, emotion, or speaking style.
For usage details, see Instruction-based control.
enable_aigc_tag
booleanNo
Specifies whether to embed an AIGC watermark in the generated audio. When set to true, the watermark is embedded in audio files of supported formats (wav/mp3/opus).
Default value: false.
Only qwen-audio-3.0-tts-plus, qwen-audio-3.0-tts-flash, cosyvoice-v3-flash, cosyvoice-v3-plus, and cosyvoice-v2 support this feature.
aigc_propagator
stringNo
Sets the
ContentPropagatorfield in the AIGC watermark, identifying the content propagator. Takes effect only whenenable_aigc_tagistrue.Default value: Alibaba Cloud UID.
Only qwen-audio-3.0-tts-plus, qwen-audio-3.0-tts-flash, cosyvoice-v3-flash, cosyvoice-v3-plus, and cosyvoice-v2 support this feature.
aigc_propagate_id
stringNo
Sets the
PropagateIDfield in the AIGC watermark, uniquely identifying a specific propagation action. Takes effect only whenenable_aigc_tagistrue.Default value: The request ID of the current speech synthesis request.
Only qwen-audio-3.0-tts-plus, qwen-audio-3.0-tts-flash, cosyvoice-v3-flash, cosyvoice-v3-plus, and cosyvoice-v2 support this feature.
-
sendStreamInputTts
Sends text to be synthesized. Use this method together with startStreamInputTts.
After you call startStreamInputTts, use this method to push text continuously.
After all text is sent, call stopStreamInputTts or asyncStopStreamInputTts to signal end of input.
Method signature
- (int) sendStreamInputTts:(const char *)text;Parameters
Parameter
Type
Description
textchar*Text to synthesize. SSML is not supported. SSML tags in the input are read as plain text rather than parsed.
Return value
Returns an error code.
stopStreamInputTts
Synchronous method. Notifies the server that all text has been sent, then blocks until every audio chunk is synthesized and TTS_EVENT_SYNTHESIS_COMPLETE is received.
The block timeout is controlled by complete_waiting_ms.
Method signature
- (int) stopStreamInputTts;Return value
Returns an error code.
asyncStopStreamInputTts
Asynchronous method. Notifies the server that all text has been sent and returns immediately. Synthesis continues in the background.
Use TTS_EVENT_SYNTHESIS_COMPLETE to detect when synthesis finishes.
Method signature
- (int) asyncStopStreamInputTts;Return value
Returns an error code.
cancelStreamInputTts
Immediately drops the connection to the server and terminates the current synthesis task. After this method is called, no further audio data callbacks fire.
Method signature
- (int) cancelStreamInputTts;Return value
Returns an error code.
playStreamInputTts
Asynchronous one-shot synthesis method. Returns immediately and runs synthesis in the background; results are delivered through callbacks. You do not need to call stopStreamInputTts afterward.
This method enables SSML by default. To disable SSML, set the enable_ssml field in parameters to false.
Method signature
- (int) playStreamInputTts:(const char *)ticket parameters:(const char *)parameters text:(const char *)text sessionId:(const char *)sessionId logLevel:(NuiSdkLogLevel)logLevel saveLog:(BOOL)saveLog;Parameters
The
ticket,parameters, and other shared parameters use the same definitions as startStreamInputTts.Parameter
Type
Description
textchar*Text to synthesize. Supports SSML.
Return value
Returns an error code.
asyncPlayStreamInputTts
This method sends all text for synthesis asynchronously. It returns immediately without waiting for audio data. You do not need to call stopStreamInputTts afterward.
This method enables SSML by default. To disable SSML, set the enable_ssml field in parameters to false.
Method signature
- (int) asyncPlayStreamInputTts:(const char *)ticket parameters:(const char *)parameters text:(const char *)text sessionId:(const char *)sessionId logLevel:(NuiSdkLogLevel)logLevel saveLog:(BOOL)saveLog;Parameters
The
ticket,parameters, and other shared parameters use the same definitions as startStreamInputTts.Parameter
Type
Description
textchar*Text to synthesize. Supports SSML.
Return value
Returns an error code.
StreamInputTtsDelegate
Callback protocol for Qwen-Audio-TTS/CosyVoice streaming speech synthesis. Implement this protocol to receive synthesis events, audio data, and logs.
onStreamInputTtsEventCallback: listen for events
Method signature
- (void)onStreamInputTtsEventCallback:(StreamInputTtsCallbackEvent)event taskId:(char*)taskid sessionId:(char*)sessionId ret_code:(int)ret_code error_msg:(char*)error_msg timestamp:(char*)timestamp all_response:(char*)all_response;Parameters
Parameter
Type
Description
eventCallback event.
taskidchar*Speech synthesis task ID.
sessionIdchar*Session ID. The client-supplied value is returned as-is. If none was supplied, the server generates one.
ret_codeintError code. Valid only for the TTS_EVENT_TASK_FAILED event. See error codes.
error_msgchar*Error message. Valid only for the TTS_EVENT_TASK_FAILED event.
timestampchar*Timestamp information for the synthesis result.
all_responsechar*Full JSON response. Parse this string to extract the fields you need.
onStreamInputTtsDataCallback: listen for audio data
The SDK fires this callback repeatedly during synthesis. Read the audio data from the callback.
Method signature
- (void)onStreamInputTtsDataCallback:(char*)buffer len:(int)len;Parameters
Parameter
Type
Description
bufferchar*Audio data for the current segment. Use this data to:
Assemble a complete audio file and play it.
Stream the data to a player that supports streaming playback.
Note:
For the compressed mp3 and opus formats, use a streaming player. Playing segments frame by frame can cause decoding failures.
When assembling a complete file, append each segment to the same file.
For the wav and mp3 formats, only the first onStreamInputTtsDataCallback invocation includes the file header; later invocations return raw audio data. Concatenate all
buffervalues in order. For the opus format, each frame is a self-contained Ogg page that you can concatenate directly.
lenintLength of the audio data, in bytes.
onStreamInputTtsLogTrackCallback: listen for trace logs
This callback delivers detailed SDK-internal logs to help with troubleshooting and debugging.
Method signature
- (void)onStreamInputTtsLogTrackCallback:(NuiSdkLogLevel)level logMessage:(const char *)log;Parameters
Parameter
Type
Description
levelLog level.
logchar*Log content.
StreamInputTtsCallbackEvent
Event-type enum for Qwen-Audio-TTS/CosyVoice streaming speech synthesis.
Event | Description |
TTS_EVENT_SYNTHESIS_STARTED | The server accepted the request and started processing. |
TTS_EVENT_SENTENCE_SYNTHESIS | Progress information emitted during synthesis, including billing data. |
TTS_EVENT_SYNTHESIS_COMPLETE | The server has finished sending all audio data. |
TTS_EVENT_TASK_FAILED | The task failed. Read |
NuiSdkLogLevel
SDK log-level enum that controls log output.
Level | Description |
0: LOG_LEVEL_VERBOSE | Most detailed log level. Includes all debug information. |
1: LOG_LEVEL_DEBUG | Debug-level logs. |
2: LOG_LEVEL_INFO | General informational logs (default). |
3: LOG_LEVEL_WARNING | Warning-level logs. |
4: LOG_LEVEL_ERROR | Error-level logs. |
5: LOG_LEVEL_NONE | Disables log output. |
Sample code
Get your API key: Obtain an API key.
NoteFor third-party apps or end users that need temporary access, or when you want tight control over sensitive operations such as data access and deletion, use a temporary API key instead. A temporary API key is valid for a fixed 60 seconds and must be regenerated after it expires.
Download the SDK and run the sample code:
Extract the ZIP archive and add
nuisdk.frameworkto your Xcode project.In Build Phases > Link Binary With Libraries, add
nuisdk.framework.In General > Frameworks, Libraries, and Embedded Content, set
nuisdk.frameworkto Embed & Sign.Open the sample project in Xcode. The sample code is in
DashQwen-Audio-TTS/CosyVoiceStreamInputTTSViewController.m. Replace the placeholder API key with your own and run the app to try it out.
Call modes
Call mode | Description |
One-shot input | Steps:
Use cases:
|
Streaming input | Steps:
Use cases:
|
Advanced features
SSML markup
Purpose: Embed XML tags in the input text to precisely control pronunciation, speech rate, pauses, and other prosody details.
Limitations: SSML is supported only with One-shot input (the playStreamInputTts and asyncPlayStreamInputTts methods). It is not supported with Streaming input (the sendStreamInputTts method).
How to use: When you call playStreamInputTts or asyncPlayStreamInputTts, the SDK enables SSML automatically. Pass text that contains SSML tags directly in the text parameter.
For more details, see SSML.
Math expressions
Purpose: Make the model read common math formulas and expressions correctly.
How to use: Pass text that contains math expressions in LaTeX format directly in the text parameter. For more details, see Convert LaTeX formulas to speech (Chinese language only).