Translate speech in real time using the DashScope Java SDK and the qwen3.5-livetranslate-flash-realtime model. The SDK connects over WebSocket, streams audio input, and returns translated text and synthesized speech.
Before you begin
- Install DashScope SDK version 2.22.5 or later.
- Get an API key.
- Set the API key as an environment variable:
# Linux / macOS
export DASHSCOPE_API_KEY=<your-api-key>
source ~/.bashrc
# Windows
set DASHSCOPE_API_KEY=<your-api-key>
- Review the Qwen-LiveTranslate model overview for supported languages and voices.
ImportantAlibaba Cloud Model Studio has released workspace-specific domains for the China (Beijing) and Singapore regions. The new dedicated domains deliver superior performance and higher stability for inference requests. We recommend migrating to the new domains:
- China (Beijing): from
wss://dashscope.aliyuncs.comtowss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com - Singapore: from
wss://dashscope-intl.aliyuncs.comtowss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com
{WorkspaceId} is your workspace ID, which can be found on the Workspace Details page in the Alibaba Cloud Model Studio console. The existing domain remains fully functional.
Quick start
Connect, send audio, and receive translated text:
import com.alibaba.dashscope.audio.omni.*;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.google.gson.JsonObject;
import java.util.Arrays;
// 1. Build connection parameters
OmniRealtimeParam param = OmniRealtimeParam.builder()
.model("qwen3.5-livetranslate-flash-realtime")
// The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
.url("wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtime")
.apikey(System.getenv("DASHSCOPE_API_KEY"))
.build();
// 2. Define a callback to handle server events
OmniRealtimeCallback callback = new OmniRealtimeCallback() {
@Override public void onOpen() { System.out.println("Connected"); }
@Override
public void onEvent(JsonObject message) {
String type = message.get("type").getAsString();
if ("response.audio_transcript.done".equals(type)) {
System.out.println("Translation: " + message.get("transcript").getAsString());
}
}
@Override
public void onClose(int code, String reason) {
System.out.println("Closed: " + code + " " + reason);
}
};
// 3. Open a session and start streaming audio
OmniRealtimeConversation conversation = new OmniRealtimeConversation(param, callback);
conversation.connect();
// 4. Configure translation target language
OmniRealtimeConfig config = OmniRealtimeConfig.builder()
.modalities(Arrays.asList(OmniRealtimeModality.AUDIO, OmniRealtimeModality.TEXT))
.translationConfig(OmniRealtimeTranslationParam.builder()
.language("en")
.build())
.build();
conversation.updateSession(config);
// 5. Send Base64-encoded audio chunks (PCM 16 kHz, 16-bit, mono)
conversation.appendAudio(audioBase64);
// 6. End the session when done
conversation.endSession();
Request parameters
OmniRealtimeParam
Build these with OmniRealtimeParam.builder() to establish the WebSocket connection.
Click to view the sample code
OmniRealtimeParam param = OmniRealtimeParam.builder()
.model("qwen3.5-livetranslate-flash-realtime")
// The following is the Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
.url("wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtime")
// API keys vary by region. To obtain an API key, see https://www.alibabacloud.com/help/model-studio/get-api-key
// If an environment variable is not configured, replace the next line with your Model Studio API key: .apikey("sk-xxx")
.apikey(System.getenv("DASHSCOPE_API_KEY"))
.build();
Parameter | Type | Required | Description |
|---|---|---|---|
|
| Yes | Model name. We recommend |
|
| Yes | WebSocket endpoint. Use Replace |
|
| No | API key for authentication. If not set, configure it via the |
OmniRealtimeConfig
Build these with OmniRealtimeConfig.builder() and then call conversation.updateSession(config) after connecting.
Click to view the sample code
// Set custom translation phrases
Map<String, Object> phrases = new HashMap<>();
phrases.put("Inteligencia Artificial", "Artificial Intelligence");
phrases.put("Aprendizaje Automático", "Machine Learning");
OmniRealtimeConfig config = OmniRealtimeConfig.builder()
.modalities(Arrays.asList(OmniRealtimeModality.AUDIO, OmniRealtimeModality.TEXT))
.voice("Cherry")
.inputAudioFormat(OmniRealtimeAudioFormat.PCM_16000HZ_MONO_16BIT)
.outputAudioFormat(OmniRealtimeAudioFormat.PCM_24000HZ_MONO_16BIT)
.InputAudioTranscription("qwen3-asr-flash-realtime")
.translationConfig(OmniRealtimeTranslationParam.builder()
.language("en")
.corpus(OmniRealtimeTranslationParam.Corpus.builder()
.phrases(phrases)
.build())
.build())
.build();
conversation.updateSession(config);
Parameter | Type | Required | Description |
|---|---|---|---|
|
| No | Output modalities. Default: |
|
| No | Voice for synthesized speech. The default voice varies by model: |
|
| No | Input audio format. Default: |
|
| No | Output audio format. Default: |
|
| No | ASR model for transcribing original speech. Set to |
|
| No | Translation settings. See OmniRealtimeTranslationParam below. |
|
| No | Whether to enable VAD (Voice Activity Detection). Default value: Set to |
OmniRealtimeTranslationParam
Build target language and custom terminology with OmniRealtimeTranslationParam.builder().
Click to view the sample code
// Set translation phrases
Map<String, Object> phrases = new HashMap<>();
phrases.put("Inteligencia Artificial", "Artificial Intelligence"); // Source language word: Target language translation
phrases.put("Aprendizaje Automático", "Machine Learning");
OmniRealtimeTranslationParam translationParam = OmniRealtimeTranslationParam.builder()
.language("en") // Target language code
.corpus(OmniRealtimeTranslationParam.Corpus.builder()
.phrases(phrases)
.build())
.build();
Parameter | Type | Required | Description |
|---|---|---|---|
|
| No | Target language code. Default: |
|
| No | Custom terminology for domain-specific terms. |
|
| No | Term mapping: keys are source terms, values are target translations. Example: |
Key interfaces
OmniRealtimeConversation
Manages the WebSocket connection and audio streaming lifecycle.
Import: com.alibaba.dashscope.audio.omni.OmniRealtimeConversation
Method | Description |
|---|---|
| Creates a conversation instance with connection parameters and an event callback. |
| Opens WebSocket connection. Triggers session.created and session.updated events. Throws |
| Updates session configuration after connecting. Triggers session.updated event. Only set parameters you need; defaults apply for omitted parameters. |
| Sends Base64-encoded audio chunk to the server. The server automatically detects speech boundaries and triggers translation. |
| In Manual mode, commits audio previously appended to the server buffer via the |
| Clears uncommitted audio data from the server buffer. Triggers input_audio_buffer.cleared event. |
| Ends session gracefully. The server completes in-progress translation before sending session.finished. Throws |
| Stops the task and closes WebSocket connection. |
| Returns session ID. |
| Returns response ID of the most recent server response. |
| Returns first text delay of the most recent response (milliseconds). |
| Returns first audio delay of the most recent response (milliseconds). |
OmniRealtimeCallback
Handles server events delivered over WebSocket. Extend this class and implement each method to process events.
Import: com.alibaba.dashscope.audio.omni.OmniRealtimeCallback
Method | Parameters | Description |
|---|---|---|
| None | Called when WebSocket connection is established. |
|
| Called for each server event. Parse the |
|
| Called when WebSocket connection closes. |
Common event types received in onEvent:
Event type | Description |
|---|---|
| Server detected speech in audio stream. |
| Server detected end of speech segment. |
| Source-language transcription is ready. Read |
| Translated text is ready. Read |
| A chunk of translated audio is available. Read |
| Error occurred. Read |
Complete example
This example captures microphone audio, translates it in real time, and plays translated speech through the system speaker.
What it does:
- Connects to Qwen-LiveTranslate over WebSocket.
- Configures Spanish-to-English translation with custom terminology.
- Streams microphone audio in 100 ms chunks.
- Prints original transcription and translated text.
- Plays translated audio through speaker.
Sample code for real-time microphone translation
import com.alibaba.dashscope.audio.omni.*;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.google.gson.JsonObject;
import javax.sound.sampled.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Example of using a microphone with the real-time audio and video translation model.
*/
public class Main {
private static final int INPUT_CHUNK_SIZE = 3200; // 100 ms of 16 kHz, 16-bit, mono audio
private static final int OUTPUT_CHUNK_SIZE = 4800; // 100 ms of 24 kHz, 16-bit, mono audio
private static final AtomicBoolean running = new AtomicBoolean(true);
private static SourceDataLine speaker; // Speaker
public static void main(String[] args) throws InterruptedException {
String apiKey = System.getenv("DASHSCOPE_API_KEY");
if (apiKey == null || apiKey.isEmpty()) {
System.err.println("Set the DASHSCOPE_API_KEY environment variable.");
System.exit(1);
}
// Create connection parameters.
OmniRealtimeParam param = OmniRealtimeParam.builder()
.model("qwen3.5-livetranslate-flash-realtime")
.url("wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/realtime")
.apikey(apiKey)
.build();
// Create a callback handler.
OmniRealtimeCallback callback = new OmniRealtimeCallback() {
@Override
public void onOpen() {
System.out.println("[Connection established]");
}
@Override
public void onEvent(JsonObject message) {
String type = message.get("type").getAsString();
switch (type) {
case "input_audio_buffer.speech_started":
System.out.println("====== Speech input detected ======");
break;
case "input_audio_buffer.speech_stopped":
System.out.println("====== Speech input ended ======");
break;
case "conversation.item.input_audio_transcription.completed":
String originalText = message.get("transcript").getAsString();
System.out.println("[Original text] " + originalText);
break;
case "response.audio_transcript.done":
String translatedText = message.get("transcript").getAsString();
System.out.println("[Translation result] " + translatedText);
break;
case "response.audio.delta":
// Decode and play the translated audio.
String audioB64 = message.get("delta").getAsString();
byte[] audioBytes = Base64.getDecoder().decode(audioB64);
if (speaker != null) {
speaker.write(audioBytes, 0, audioBytes.length);
}
break;
case "error":
JsonObject error = message.get("error").getAsJsonObject();
System.err.println("[Error] " + error.get("message").getAsString());
break;
}
}
@Override
public void onClose(int code, String reason) {
System.out.println("[Connection closed] code: " + code + ", reason: " + reason);
}
};
// Create a session.
OmniRealtimeConversation conversation = new OmniRealtimeConversation(param, callback);
try {
// Initialize the speaker (for playing the translated speech).
AudioFormat speakerFormat = new AudioFormat(24000, 16, 1, true, false);
DataLine.Info speakerInfo = new DataLine.Info(SourceDataLine.class, speakerFormat);
speaker = (SourceDataLine) AudioSystem.getLine(speakerInfo);
speaker.open(speakerFormat, OUTPUT_CHUNK_SIZE * 4);
speaker.start();
// Initialize the microphone (for capturing speech input).
AudioFormat micFormat = new AudioFormat(16000, 16, 1, true, false);
DataLine.Info micInfo = new DataLine.Info(TargetDataLine.class, micFormat);
if (!AudioSystem.isLineSupported(micInfo)) {
System.err.println("Microphone is not available.");
System.exit(1);
}
TargetDataLine microphone = (TargetDataLine) AudioSystem.getLine(micInfo);
microphone.open(micFormat);
microphone.start();
// Connect to the server.
conversation.connect();
// Configure translation parameters.
Map<String, Object> phrases = new HashMap<>();
phrases.put("Inteligencia Artificial", "Artificial Intelligence");
phrases.put("Aprendizaje Automático", "Machine Learning");
OmniRealtimeConfig config = OmniRealtimeConfig.builder()
.modalities(Arrays.asList(OmniRealtimeModality.AUDIO, OmniRealtimeModality.TEXT))
.voice("Cherry")
.inputAudioFormat(OmniRealtimeAudioFormat.PCM_16000HZ_MONO_16BIT)
.outputAudioFormat(OmniRealtimeAudioFormat.PCM_24000HZ_MONO_16BIT)
.InputAudioTranscription("qwen3-asr-flash-realtime")
.translationConfig(OmniRealtimeTranslationParam.builder()
.language("en")
.corpus(OmniRealtimeTranslationParam.Corpus.builder()
.phrases(phrases)
.build())
.build())
.build();
conversation.updateSession(config);
// Register a shutdown hook.
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("\n[Exiting...]");
running.set(false);
microphone.stop();
microphone.close();
speaker.stop();
speaker.close();
try {
conversation.endSession();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
conversation.close(1000, "User stopped");
}));
System.out.println("[Starting real-time translation] Speak into the microphone. Press Ctrl+C to exit.");
// Continuously capture and send microphone audio.
byte[] buffer = new byte[INPUT_CHUNK_SIZE];
while (running.get()) {
int bytesRead = microphone.read(buffer, 0, buffer.length);
if (bytesRead > 0) {
conversation.appendAudio(Base64.getEncoder().encodeToString(buffer));
}
}
} catch (NoApiKeyException e) {
System.err.println("API Key error: " + e.getMessage());
} catch (Exception e) {
System.err.println("An exception occurred: " + e.getMessage());
e.printStackTrace();
}
}
}
Replace placeholders with your values:
Placeholder | Description | Example |
|---|---|---|
| Model Studio API key |
|
Related topics
- Qwen-LiveTranslate model overview -- Supported languages, voices, and capabilities
- Server-side events reference -- Event types, JSON schemas, and error codes
- Install DashScope SDK -- Installation and dependency setup
- Get an API key -- Creation and management