Appearance
time speech synthesis API reference-CosyVoice speech synthesis Java SDK
Synthesize speech with CosyVoice using the DashScope Java SDK. User guide: For model introduction and selection recommendations, see Speech synthesis.
Service endpoints
By default, the SDK connects to the Beijing region endpoint. To use a different region, set Constants.baseWebsocketApiUrl before initializing the SDK.
International
If you select the International deployment scope, model inference compute resources are dynamically scheduled worldwide, excluding the Chinese mainland. Static data is stored in your selected region. Supported region: Singapore.
wss://dashscope-intl.aliyuncs.com/api-ws/v1/inference
Chinese mainland
If you select the Chinese mainland deployment scope, model inference compute resources are restricted to the Chinese mainland. Static data is stored in your selected region. Supported region: China (Beijing).
wss://dashscope.aliyuncs.com/api-ws/v1/inference
Switch to the Singapore region:
HELPCODEESCAPE-java
import com.alibaba.dashscope.common.Constants;
// Set this before any SDK initialization
Constants.baseWebsocketApiUrl = "wss://dashscope-intl.aliyuncs.com/api-ws/v1/inference";SpeechSynthesizer
Package : com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer
Constructor
HELPCODEESCAPE-java
public SpeechSynthesizer(SpeechSynthesisParam param, ResultCallback<SpeechSynthesisResult> callback)Parameters:
param: Speech synthesis parameters, built with SpeechSynthesisParam.builder()callback: Callback for streaming calls. Pass null for non-streaming calls.
call() - Non-streaming/unidirectional streaming synthesis
Method signature:
HELPCODEESCAPE-java
public ByteBuffer call(String text)Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| text | String | Yes | Text to synthesize. Maximum length: 20,000 characters. |
Return value : ByteBuffer or null. For non-streaming calls, returns the complete audio data. For unidirectional streaming calls, this method returns null; audio is delivered through the callback.
streamingCall() - Bidirectional streaming synthesis
Method signature:
HELPCODEESCAPE-java
public void streamingCall(String text)Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| text | String | Yes | Text to synthesize. Maximum length: 20,000 characters. You can call this method multiple times to append text. |
streamingComplete() - End bidirectional streaming
Method signature:
HELPCODEESCAPE-java
public void streamingComplete()Ends the bidirectional streaming call and notifies the server that all text has been sent.
callAsFlowable() - Unidirectional streaming synthesis (reactive)
Method signature:
HELPCODEESCAPE-java
public Flowable<SpeechSynthesisResult> callAsFlowable(String text)Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| text | String | Yes | Text to synthesize. |
Return value : Flowable<SpeechSynthesisResult> reactive stream.
streamingCallAsFlowable() - Bidirectional streaming synthesis (reactive)
Method signature:
HELPCODEESCAPE-java
public Flowable<SpeechSynthesisResult> streamingCallAsFlowable(Flowable<String> textStream)Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| textStream | Flowable | Yes | Reactive stream of text. |
Return value : Flowable<SpeechSynthesisResult> reactive stream.
getDuplexApi().close() - Close WebSocket connection
Method signature:
HELPCODEESCAPE-java
public boolean getDuplexApi().close(int code, String reason)Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| code | int | Yes | Close code. |
| reason | String | Yes | Close reason. |
Return value : boolean. Returns true if the connection was closed successfully, false otherwise.
getLastRequestId() - Get request ID
Method signature:
HELPCODEESCAPE-java
public String getLastRequestId()Return value : String, the request ID.
getFirstPackageDelay() - Get first-packet latency
Method signature:
HELPCODEESCAPE-java
public long getFirstPackageDelay()Return value : long. The first-packet latency in milliseconds, measured from sending the first text segment to receiving the first audio packet.
SpeechSynthesisParam
Package : com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam
Example:
HELPCODEESCAPE-java
SpeechSynthesisParam param = SpeechSynthesisParam.builder()
.model("cosyvoice-v3-flash") // Model
.voice("longanyang") // Voice
.format(SpeechSynthesisAudioFormat.WAV_8000HZ_MONO_16BIT) // Audio encoding format and sample rate
.volume(50) // Volume. Value range: [0, 100]
.speechRate(1.0f) // Speech rate. Value range: [0.5, 2]
.pitchRate(1.0f) // Pitch. Value range: [0.5, 2]
.build();Builder methods
Method Parameter type Required Description model(String) String Yes The model name. voice(String) String Yes **voice **string* *(required) The voice used for speech synthesis.
System voices: See Voice list
Cloned voices: Custom voices created through voice cloning
Custom voices: Custom voices created through voice design
format(SpeechSynthesisAudioFormat)enum No
Audio encoding format and sample rate. Default: SpeechSynthesisAudioFormat.MP3_22050HZ_MONO_256KBPS. SpeechSynthesisAudioFormat package: com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisAudioFormat. volume(int) int No The volume level. Default value: 50. Valid values: [0, 100]. speechRate(float) float No The speech rate. Default value: 1.0. Valid values: [0.5, 2.0]. pitchRate(float) float No The pitch. Default value: 1.0. Valid values: [0.5, 2.0]. enableWordTimestamp(boolean) boolean No Specifies whether to enable word-level timestamps. Default value: false.
Applies only to cloned voices of the cosyvoice-v3-flash, cosyvoice-v3-plus, and cosyvoice-v2 models, and to system voices marked as supported in Voice list. seed(int) int No 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]. For SDK versions earlier than 2.21.7, set seed through additional parameters. languageHints(List<String>) List 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. 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 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
instruction(String)String No Controls synthesis characteristics such as dialect, emotion, or speaking style. For usage details, see Instruction-based control.hotFix(ParamHotFix)ParamHotFix No Configures pronunciation corrections and text replacements applied before synthesis. Only cloned voices of cosyvoice-v3-flash support this feature. Parameters:pronunciation: Custom pronunciation. Specifies pinyin annotations for words to correct inaccurate default pronunciations.
replace: Text replacement. Replaces specified words with target text before synthesis. The replaced text is used as the actual synthesis input.
Example:
java
List\ pronunciationItems = new ArrayList\<\>();
pronunciationItems.add(new ParamHotFix.PronunciationItem("weather", "tian1 qi4"));
List\ replaceItems = new ArrayList\<\>();
replaceItems.add(new ParamHotFix.ReplaceItem("today", "gold day"));
ParamHotFix paramHotFix = new ParamHotFix();
paramHotFix.setPronunciation(pronunciationItems);
paramHotFix.setReplace(replaceItems);
SpeechSynthesisParam param = SpeechSynthesisParam.builder()
.model("cosyvoice-v3-flash") // Model
.voice("your_voice") // Replace with a cosyvoice-v3-flash cloned voice
.hotFix(paramHotFix)
.build();parameter(String key, Object value) String, Object No Sets Additional parameters. parameters(Map<String, Object>) Map No Sets Additional parameters.
Additional parameters
Set through parameter() or parameters().
Example:
HELPCODEESCAPE-java
SpeechSynthesisParam param = SpeechSynthesisParam.builder()
.model("cosyvoice-v3-flash")
.voice("longanyang")
.parameter("enable_markdown_filter", true)
.build();| Parameter | Type | Required | Description |
|---|---|---|---|
bit_rate | integer | No | The audio bit rate in kbps. When the audio format is opus, use bit_rate to adjust the bit rate. Default value: 32. Valid values: [6, 510]. |
enable_aigc_tag | boolean | No | 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 cosyvoice-v3-flash, cosyvoice-v3-plus, and cosyvoice-v2 support this feature. |
aigc_propagator | String | No | Sets the ContentPropagator field in the AIGC watermark, identifying the content propagator. Takes effect only when enable_aigc_tag is true. Default value: Alibaba Cloud UID. Only cosyvoice-v3-flash, cosyvoice-v3-plus, and cosyvoice-v2 support this feature. |
aigc_propagate_id | String | No | Sets the PropagateID field in the AIGC watermark, uniquely identifying a specific propagation action. Takes effect only when enable_aigc_tag is true. Default value: The request ID of the current speech synthesis request. Only cosyvoice-v3-flash, cosyvoice-v3-plus, and cosyvoice-v2 support this feature. |
enable_markdown_filter | boolean | No | ** **Important ** Only cloned voices of cosyvoice-v3-flash support this feature. Specifies whether to enable Markdown filtering. When enabled, the system automatically strips Markdown markup symbols from the input text before synthesis, preventing them from being read aloud. Default value: false. Valid values: - true: Enable Markdown filtering - false: Disable Markdown filtering |
ResultCallback
Package : com.alibaba.dashscope.common.ResultCallback
onEvent() - Receive audio data
Method signature:
HELPCODEESCAPE-java
public void onEvent(SpeechSynthesisResult result)Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| result | SpeechSynthesisResult | Yes | Triggered when a synthesis event is received. Contains the audio frame, timestamp information, and output information (event type, original text, etc.). |
onComplete() - Synthesis complete
Method signature:
HELPCODEESCAPE-java
public void onComplete()Triggered when speech synthesis completes.
onError() - Error handling
Method signature:
HELPCODEESCAPE-java
public void onError(Exception e)Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| e | Exception | Yes | Triggered when an error occurs. Contains the exception information. |
SpeechSynthesisResult
Package : com.alibaba.dashscope.audio.tts.SpeechSynthesisResult
getAudioFrame() - Get audio data frame
Method signature:
HELPCODEESCAPE-java
public ByteBuffer getAudioFrame()Return value : ByteBuffer, the audio data frame.
getTimestamp() - Get timestamp information
Method signature:
HELPCODEESCAPE-java
public Sentence getTimestamp()Return value : Sentence, the timestamp information.
getOutput() - Get output information
Method signature:
HELPCODEESCAPE-java
public JsonObject getOutput()Return value : com.google.gson.JsonObject, the output information of the synthesis event, containing event type and text content. Requires SDK version >= 2.22.0.
Sentence-level timestamp information (Sentence)
Sentence encapsulates sentence-level timestamp information.
getBeginTime() - Get sentence start time
Method signature:
HELPCODEESCAPE-java
public int getBeginTime()Return value: Sentence start time in milliseconds.
getEndTime() - Get sentence end time
Method signature:
HELPCODEESCAPE-java
public int getEndTime()Return value: Sentence end time in milliseconds.
getWords() - Get word-level timestamps
Method signature:
HELPCODEESCAPE-java
public List<Word> getWords()Return value : A List of Word objects containing word-level timestamp information. May be empty.
Word-level timestamp information (Word)
Word encapsulates word-level timestamp information.
getBeginTime() - Get word start time
Method signature:
HELPCODEESCAPE-java
public int getBeginTime()Return value: Word start time in milliseconds.
getEndTime() - Get word end time
Method signature:
HELPCODEESCAPE-java
public int getEndTime()Return value: Word end time in milliseconds.
getText() - Get text
Method signature:
HELPCODEESCAPE-java
public String getText()Return value : String, the text content.
getPhonemes() - Get phoneme-level timestamps
Method signature:
HELPCODEESCAPE-java
public List getPhonemes()Return value : A List of Phoneme objects containing phoneme-level timestamp information. May be empty.
Phoneme-level timestamp information (Phoneme)
Phoneme encapsulates phoneme-level timestamp information.
getBeginTime() - Get phoneme start time
Method signature:
HELPCODEESCAPE-java
public int getBeginTime()Return value: Phoneme start time in milliseconds.
getEndTime() - Get phoneme end time
Method signature:
HELPCODEESCAPE-java
public int getEndTime()Return value: Phoneme end time in milliseconds.
getText() - Get text
Method signature:
HELPCODEESCAPE-java
public String getText()Return value : String, the text content.
getTone() - Get tone
Method signature:
HELPCODEESCAPE-java
public int getTone()Return value: The tone value.
In English, 0, 1, and 2 represent unstressed, primary stress, and secondary stress respectively.
In Chinese pinyin, 1, 2, 3, 4, and 5 represent the first, second, third, fourth, and neutral tones respectively.
Output information (output)
getOutput() returns a JsonObject that encapsulates synthesis event output information. Retrieve it in the onEvent callback or the Flowable stream. It contains the following fields:
| Field | Type | Description |
|---|---|---|
| type | String | Event type. Possible values: sentence-begin (sentence start; returns the text to be synthesized), sentence-synthesis (audio synthesis in progress; returns an audio data chunk), sentence-end (sentence end; returns text content and word-level timestamps). |
| original_text | String | Original text of the current sentence. Returned in sentence-begin and sentence-end events. |
| sentence | JsonObject | Sentence information, containing the sentence index (index) and word-level timestamps (words). The sentence-end event includes full word-level timestamp information. |
Sample code
The SDK supports the following synthesis modes:
Non-streaming: A blocking call that sends the complete text at once and returns the full audio directly. Best suited for short-text speech synthesis.
Unidirectional streaming: A non-blocking call that sends the complete text at once and delivers audio data (potentially in chunks) through a callback function. Best suited for short-text scenarios that require low latency.
Bidirectional streaming: A non-blocking call that sends text in multiple segments and delivers incrementally synthesized audio through a callback function in real time. Best suited for long-text scenarios that require low latency.
Non-streaming calls
The text length per request must not exceed 20,000 characters. Important
Reinitialize the SpeechSynthesizer instance before each call to the call method.
HELPCODEESCAPE-java
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.utils.Constants;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
public class Main {
// Model
private static String model = "cosyvoice-v3-flash";
// Voice
private static String voice = "longanyang";
public static void streamAudioDataToSpeaker() {
// Request parameters
SpeechSynthesisParam param =
SpeechSynthesisParam.builder()
// The API Keys for the Singapore and Beijing regions are different. Get an API Key: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
// If the environment variable is not configured, replace the following line with your Model Studio API Key: .apiKey("sk-xxx")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model(model) // Model
.voice(voice) // Voice
.build();
// Synchronous mode: disable callback (second parameter is null)
SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, null);
ByteBuffer audio = null;
try {
// Block until audio is returned
audio = synthesizer.call("What's the weather like today?");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// Close the WebSocket connection after the task is completed
synthesizer.getDuplexApi().close(1000, "bye");
}
if (audio != null) {
// Save the audio data to a local file "output.mp3"
File file = new File("output.mp3");
// The first text transmission requires establishing a WebSocket connection, so the first packet latency includes the connection setup time
System.out.println(
"[Metric] requestId: "
+ synthesizer.getLastRequestId()
+ ", first packet latency (ms): "
+ synthesizer.getFirstPackageDelay());
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(audio.array());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
// The following is the Singapore region URL. To use a model in the Beijing region, replace the URL with: wss://dashscope.aliyuncs.com/api-ws/v1/inference
Constants.baseWebsocketApiUrl = "wss://dashscope-intl.aliyuncs.com/api-ws/v1/inference";
streamAudioDataToSpeaker();
System.exit(0);
}
}Unidirectional streaming calls
The text length per request must not exceed 20,000 characters. Important
Reinitialize the SpeechSynthesizer instance before each call to the call method.
HELPCODEESCAPE-java
import com.alibaba.dashscope.audio.tts.SpeechSynthesisResult;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.utils.Constants;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;
class TimeUtils {
private static final DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
public static String getTimestamp() {
return LocalDateTime.now().format(formatter);
}
}
public class Main {
// Model
private static String model = "cosyvoice-v3-flash";
// Voice
private static String voice = "longanyang";
public static void streamAudioDataToSpeaker() {
CountDownLatch latch = new CountDownLatch(1);
// Implement the ResultCallback interface
ResultCallback<SpeechSynthesisResult> callback = new ResultCallback<SpeechSynthesisResult>() {
@Override
public void onEvent(SpeechSynthesisResult result) {
if (result.getAudioFrame() != null) {
// Implement the logic to save audio data locally here
System.out.println(TimeUtils.getTimestamp() + " Audio received");
}
// Get output information, including event type and original text
if (result.getOutput() != null && result.getOutput().has("type")) {
System.out.println("Event type: " + result.getOutput().get("type").getAsString()
+ ", Original text: " + (result.getOutput().has("original_text") ? result.getOutput().get("original_text").getAsString() : ""));
}
}
@Override
public void onComplete() {
System.out.println(TimeUtils.getTimestamp() + " Complete received, speech synthesis finished");
latch.countDown();
}
@Override
public void onError(Exception e) {
System.out.println("Exception occurred: " + e.toString());
latch.countDown();
}
};
// Request parameters
SpeechSynthesisParam param =
SpeechSynthesisParam.builder()
// The API Keys for the Singapore and Beijing regions are different. Get an API Key: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
// If the environment variable is not configured, replace the following line with your Model Studio API Key: .apiKey("sk-xxx")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model(model) // Model
.voice(voice) // Voice
.build();
// Passing "callback" as the second parameter enables asynchronous mode
SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, callback);
// Non-blocking call that returns null immediately (actual results are delivered asynchronously via the callback interface). Binary audio is received in real time through the onEvent method of the callback interface
try {
synthesizer.call("What's the weather like today?");
// Wait for synthesis to complete
latch.await();
// Wait for playback thread to finish playing
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// Close the WebSocket connection after the task is completed
synthesizer.getDuplexApi().close(1000, "bye");
}
// The first text transmission requires establishing a WebSocket connection, so the first packet latency includes the connection setup time
System.out.println(
"[Metric] requestId: "
+ synthesizer.getLastRequestId()
+ ", first packet latency (ms): "
+ synthesizer.getFirstPackageDelay());
}
public static void main(String[] args) {
// The following is the Singapore region URL. To use a model in the Beijing region, replace the URL with: wss://dashscope.aliyuncs.com/api-ws/v1/inference
Constants.baseWebsocketApiUrl = "wss://dashscope-intl.aliyuncs.com/api-ws/v1/inference";
streamAudioDataToSpeaker();
System.exit(0);
}
}Bidirectional streaming calls
The text length per individual call must not exceed 20,000 characters, and the cumulative text length across all calls must not exceed 200,000 characters.
During streaming input, call
streamingCallmultiple times to submit text segments in order. The server automatically splits received text into sentences:Complete sentences are synthesized immediately.
Incomplete sentences are buffered until they form a complete sentence.
When
streamingCompleteis called, the server force-synthesizes all received but unprocessed text segments, including incomplete sentences.The interval between consecutive text segments must not exceed 23 seconds; exceeding this limit triggers a "request timeout after 23 seconds" exception.
If no text is pending, call
streamingCompletepromptly to end the task. ImportantAlways call the
streamingCompletemethod. Otherwise, trailing text segments may not be converted to speech.The server enforces a 23-second timeout that cannot be changed on the client side.
HELPCODEESCAPE-java
import com.alibaba.dashscope.audio.tts.SpeechSynthesisResult;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisAudioFormat;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.utils.Constants;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
class TimeUtils {
private static final DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
public static String getTimestamp() {
return LocalDateTime.now().format(formatter);
}
}
public class Main {
private static String[] textArray = {"Streaming text-to-speech SDK, ",
"can convert input text ", "into audio binary data. ", "Compared to non-streaming speech synthesis, ",
"streaming synthesis offers better real-time performance. ", "While users input text, ",
"they can hear nearly synchronous audio output, ", "greatly enhancing the interactive experience ",
"and reducing user wait time. ", "It is suitable for calling large-scale ", "language models (LLMs) to ",
"perform speech synthesis ", "with streaming text input."};
private static String model = "cosyvoice-v3-flash"; // Model
private static String voice = "longanyang"; // Voice
public static void streamAudioDataToSpeaker() {
// Configure the callback function
ResultCallback<SpeechSynthesisResult> callback = new ResultCallback<SpeechSynthesisResult>() {
@Override
public void onEvent(SpeechSynthesisResult result) {
// System.out.println("Message received: " + result);
if (result.getAudioFrame() != null) {
// Implement the logic to process audio data here
System.out.println(TimeUtils.getTimestamp() + " Audio received");
}
}
@Override
public void onComplete() {
System.out.println(TimeUtils.getTimestamp() + " Complete received, speech synthesis finished");
}
@Override
public void onError(Exception e) {
System.out.println("Exception occurred: " + e.toString());
}
};
// Request parameters
SpeechSynthesisParam param =
SpeechSynthesisParam.builder()
// The API Keys for the Singapore and Beijing regions are different. Get an API Key: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
// If the environment variable is not configured, replace the following line with your Model Studio API Key: .apiKey("sk-xxx")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model(model)
.voice(voice)
.format(SpeechSynthesisAudioFormat
.PCM_22050HZ_MONO_16BIT) // Use PCM or MP3 for streaming synthesis
.build();
SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, callback);
// The call method with Callback will not block the current thread
try {
for (String text : textArray) {
// Send text fragments and receive binary audio in real time through the onEvent method of the callback interface
synthesizer.streamingCall(text);
}
// Wait for streaming speech synthesis to finish
synthesizer.streamingComplete();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// Close the WebSocket connection after the task is completed
synthesizer.getDuplexApi().close(1000, "bye");
}
// The first text transmission requires establishing a WebSocket connection, so the first packet latency includes the connection setup time
System.out.println(
"[Metric] requestId: "
+ synthesizer.getLastRequestId()
+ ", first packet latency (ms): "
+ synthesizer.getFirstPackageDelay());
}
public static void main(String[] args) {
// The following is the Singapore region URL. To use a model in the Beijing region, replace the URL with: wss://dashscope.aliyuncs.com/api-ws/v1/inference
Constants.baseWebsocketApiUrl = "wss://dashscope-intl.aliyuncs.com/api-ws/v1/inference";
streamAudioDataToSpeaker();
System.exit(0);
}
}Flowable-based calls
Flowable is an RxJava type representing a reactive stream that supports backpressure. For more information, see RxJava Flowable documentation.
Before using Flowable, make sure the RxJava library is integrated and you understand the basics of reactive programming.
The text length per individual call must not exceed 20,000 characters, and the cumulative text length across all calls must not exceed 200,000 characters.
Unidirectional streaming calls
The following example shows how to use the blockingForEach interface of a Flowable object to retrieve each streamed SpeechSynthesisResult object in a blocking manner.
HELPCODEESCAPE-java
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.utils.Constants;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
class TimeUtils {
private static final DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
public static String getTimestamp() {
return LocalDateTime.now().format(formatter);
}
}
public class Main {
private static String model = "cosyvoice-v3-flash"; // Model
private static String voice = "longanyang"; // Voice
public static void streamAudioDataToSpeaker() throws NoApiKeyException {
// Request parameters
SpeechSynthesisParam param =
SpeechSynthesisParam.builder()
// The API Keys for the Singapore and Beijing regions are different. Get an API Key: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
// If the environment variable is not configured, replace the following line with your Model Studio API Key: .apiKey("sk-xxx")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model(model) // Model
.voice(voice) // Voice
.build();
SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, null);
synthesizer.callAsFlowable("What's the weather like today?").blockingForEach(result -> {
if (result.getAudioFrame() != null) {
// Implement the logic to process audio data here
System.out.println(TimeUtils.getTimestamp() + " Audio received");
}
// Get output information, including event type and original text
if (result.getOutput() != null && result.getOutput().has("type")) {
System.out.println("Event type: " + result.getOutput().get("type").getAsString()
+ ", Original text: " + (result.getOutput().has("original_text") ? result.getOutput().get("original_text").getAsString() : ""));
}
});
// Close the WebSocket connection after the task is completed
synthesizer.getDuplexApi().close(1000, "bye");
// The first text transmission requires establishing a WebSocket connection, so the first packet latency includes the connection setup time
System.out.println(
"[Metric] requestId: "
+ synthesizer.getLastRequestId()
+ ", first packet latency (ms): "
+ synthesizer.getFirstPackageDelay());
}
public static void main(String[] args) throws NoApiKeyException {
// The following is the Singapore region URL. To use a model in the Beijing region, replace the URL with: wss://dashscope.aliyuncs.com/api-ws/v1/inference
Constants.baseWebsocketApiUrl = "wss://dashscope-intl.aliyuncs.com/api-ws/v1/inference";
streamAudioDataToSpeaker();
System.exit(0);
}
}Bidirectional streaming calls
The following example shows how to use a Flowable object as an input parameter for text streaming, and use the blockingForEach interface of the returned Flowable object to retrieve each streamed SpeechSynthesisResult object in a blocking manner.
HELPCODEESCAPE-java
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.utils.Constants;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
class TimeUtils {
private static final DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
public static String getTimestamp() {
return LocalDateTime.now().format(formatter);
}
}
public class Main {
private static String[] textArray = {"Streaming text-to-speech SDK, ",
"can convert input text ", "into audio binary data. ", "Compared to non-streaming speech synthesis, ",
"streaming synthesis offers better real-time performance. ", "While users input text, ",
"they can hear nearly synchronous audio output, ", "greatly enhancing the interactive experience ",
"and reducing user wait time. ", "It is suitable for calling large-scale ", "language models (LLMs) to ",
"perform speech synthesis ", "with streaming text input."};
private static String model = "cosyvoice-v3-flash";
private static String voice = "longanyang";
public static void streamAudioDataToSpeaker() throws NoApiKeyException {
// Simulate streaming input
Flowable<String> textSource = Flowable.create(emitter -> {
new Thread(() -> {
for (int i = 0; i < textArray.length; i++) {
emitter.onNext(textArray[i]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
emitter.onComplete();
}).start();
}, BackpressureStrategy.BUFFER);
// Request parameters
SpeechSynthesisParam param =
SpeechSynthesisParam.builder()
// The API Keys for the Singapore and Beijing regions are different. Get an API Key: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
// If the environment variable is not configured, replace the following line with your Model Studio API Key: .apiKey("sk-xxx")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model(model) // Model
.voice(voice) // Voice
.build();
SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, null);
synthesizer.streamingCallAsFlowable(textSource).blockingForEach(result -> {
if (result.getAudioFrame() != null) {
// Implement the logic to play audio here
System.out.println(
TimeUtils.getTimestamp() +
" Binary audio size: " + result.getAudioFrame().capacity());
}
// Get output information, including event type and original text
if (result.getOutput() != null && result.getOutput().has("type")) {
System.out.println("Event type: " + result.getOutput().get("type").getAsString()
+ ", Original text: " + (result.getOutput().has("original_text") ? result.getOutput().get("original_text").getAsString() : ""));
}
});
synthesizer.getDuplexApi().close(1000, "bye");
// The first text transmission requires establishing a WebSocket connection, so the first packet latency includes the connection setup time
System.out.println(
"[Metric] requestId: "
+ synthesizer.getLastRequestId()
+ ", first packet latency (ms): "
+ synthesizer.getFirstPackageDelay());
}
public static void main(String[] args) throws NoApiKeyException {
// The following is the Singapore region URL. To use a model in the Beijing region, replace the URL with: wss://dashscope.aliyuncs.com/api-ws/v1/inference
Constants.baseWebsocketApiUrl = "wss://dashscope-intl.aliyuncs.com/api-ws/v1/inference";
streamAudioDataToSpeaker();
System.exit(0);
}
}High-concurrency calls
The DashScope Java SDK uses OkHttp3 connection pooling to reduce the overhead of repeatedly establishing connections. For more information, see High-concurrency best practices.