Qwen-ASR-Realtime Java SDK - API reference
Use the DashScope Java SDK to call Qwen-ASR-Realtime.
Prerequisites
- DashScope SDK 2.22.5 or later (Install the SDK)
- Obtain an API key
- Understand the interaction flow between client and server
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
dashscope.aliyuncs.comto{WorkspaceId}.cn-beijing.maas.aliyuncs.com - Singapore: from
dashscope-intl.aliyuncs.comto{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com
Replace {WorkspaceId} with your actual Workspace ID. The existing domains remain fully functional.
Interaction modes
Qwen-ASR-Realtime supports two modes for deciding when to process audio:
Mode |
| How it works |
|---|---|---|
VAD mode (default) |
| The server detects speech boundaries using voice activity detection (VAD) and decides when to commit the audio buffer for recognition. |
Manual mode |
| The client controls when to commit audio by calling |
For details on each mode, see VAD mode and Manual mode.
Complete example
NoteThe example code reads your_audio_file.pcm (PCM16, 16 kHz, mono). If you only have an MP3, WAV, or similar format, convert it with ffmpeg:
ffmpeg -i your_audio.mp3 -ar 16000 -ac 1 -f s16le your_audio_file.pcm
import com.alibaba.dashscope.audio.omni.*;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.google.gson.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sound.sampled.LineUnavailableException;
import java.io.File;
import java.io.FileInputStream;
import java.util.Base64;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
public class Qwen3AsrRealtimeUsage {
private static final Logger log = LoggerFactory.getLogger(Qwen3AsrRealtimeUsage.class);
private static final int AUDIO_CHUNK_SIZE = 1024; // Audio chunk size in bytes
private static final int SLEEP_INTERVAL_MS = 30; // Sleep interval in milliseconds
public static void main(String[] args) throws InterruptedException, LineUnavailableException {
CountDownLatch finishLatch = new CountDownLatch(1);
OmniRealtimeParam param = OmniRealtimeParam.builder()
.model("qwen3-asr-flash-realtime")
// The following is the configuration for the China (Beijing) region. When calling, replace "{WorkspaceId}" with your actual workspace ID. Configurations differ by region.
.url("wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/realtime")
// The API Key differs between the Singapore and Beijing regions. Get your API Key: https://help.aliyun.com/zh/model-studio/get-api-key
// If you have not configured the environment variable, replace the following line with your Alibaba Cloud Model Studio API Key: .apikey("sk-xxx")
.apikey(System.getenv("DASHSCOPE_API_KEY"))
.build();
OmniRealtimeConversation conversation = null;
final AtomicReference<OmniRealtimeConversation> conversationRef = new AtomicReference<>(null);
conversation = new OmniRealtimeConversation(param, new OmniRealtimeCallback() {
@Override
public void onOpen() {
System.out.println("connection opened");
}
@Override
public void onEvent(JsonObject message) {
String type = message.get("type").getAsString();
switch(type) {
case "session.created":
System.out.println("start session: " + message.get("session").getAsJsonObject().get("id").getAsString());
break;
case "conversation.item.input_audio_transcription.completed":
System.out.println("transcription: " + message.get("transcript").getAsString());
finishLatch.countDown();
break;
case "input_audio_buffer.speech_started":
System.out.println("======VAD Speech Start======");
break;
case "input_audio_buffer.speech_stopped":
System.out.println("======VAD Speech Stop======");
break;
case "conversation.item.input_audio_transcription.text":
System.out.println("transcription: " + message.get("text").getAsString() + message.get("stash").getAsString());
break;
default:
break;
}
}
@Override
public void onClose(int code, String reason) {
System.out.println("connection closed code: " + code + ", reason: " + reason);
}
});
conversationRef.set(conversation);
try {
conversation.connect();
} catch (NoApiKeyException e) {
throw new RuntimeException(e);
}
OmniRealtimeTranscriptionParam transcriptionParam = new OmniRealtimeTranscriptionParam();
transcriptionParam.setLanguage("zh");
transcriptionParam.setInputAudioFormat("pcm");
transcriptionParam.setInputSampleRate(16000);
OmniRealtimeConfig config = OmniRealtimeConfig.builder()
.modalities(Collections.singletonList(OmniRealtimeModality.TEXT))
.transcriptionConfig(transcriptionParam)
.build();
conversation.updateSession(config);
String filePath = "your_audio_file.pcm";
File audioFile = new File(filePath);
if (!audioFile.exists()) {
log.error("Audio file not found: {}", filePath);
return;
}
try (FileInputStream audioInputStream = new FileInputStream(audioFile)) {
byte[] audioBuffer = new byte[AUDIO_CHUNK_SIZE];
int bytesRead;
int totalBytesRead = 0;
log.info("Starting to send audio data from: {}", filePath);
// Read and send audio data in chunks
while ((bytesRead = audioInputStream.read(audioBuffer)) != -1) {
totalBytesRead += bytesRead;
byte[] chunk = new byte[bytesRead];
System.arraycopy(audioBuffer, 0, chunk, 0, bytesRead);
String audioB64 = Base64.getEncoder().encodeToString(chunk);
// Send audio chunk to conversation
conversation.appendAudio(audioB64);
// Add small delay to simulate real-time audio streaming
Thread.sleep(SLEEP_INTERVAL_MS);
}
log.info("Finished sending audio data. Total bytes sent: {}", totalBytesRead);
} catch (Exception e) {
log.error("Error sending audio from file: {}", filePath, e);
}
//send session.finish and wait for finish and close
conversation.endSession();
log.info("task finished");
System.exit(0);
}
}
Request parameters
Connection parameters (OmniRealtimeParam)
Set these parameters with the chained methods of the OmniRealtimeParam class.
Click to view sample code
OmniRealtimeParam param = OmniRealtimeParam.builder()
.model("qwen3-asr-flash-realtime")
// The following URL is for the China (Beijing) region. The URLs vary by region.
.url("wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/realtime")
// The API keys for the Singapore and Beijing regions are different. To obtain an API key, visit https://help.aliyun.com/en/model-studio/get-api-key.
// If you have not configured an environment variable, replace the following line with .apikey("sk-xxx") and use your Model Studio API key.
.apikey(System.getenv("DASHSCOPE_API_KEY"))
.build();
Parameter | Type | Required | Description |
|---|---|---|---|
|
| Yes | The model to use. Example: |
|
| Yes | The service endpoint. China (Beijing): |
|
| No | The API key. |
Session configuration (OmniRealtimeConfig)
Set these parameters with the chained methods of the OmniRealtimeConfig class.
Click to view sample code
OmniRealtimeTranscriptionParam transcriptionParam = new OmniRealtimeTranscriptionParam();
transcriptionParam.setLanguage("zh");
transcriptionParam.setInputSampleRate(16000);
transcriptionParam.setInputAudioFormat("pcm");
OmniRealtimeConfig config = OmniRealtimeConfig.builder()
.modalities(Collections.singletonList(OmniRealtimeModality.TEXT))
.enableTurnDetection(true)
.turnDetectionType("server_vad")
.turnDetectionThreshold(0.0f)
.turnDetectionSilenceDurationMs(400)
.transcriptionConfig(transcriptionParam)
.build();
Parameter | Type | Required | Description |
|---|---|---|---|
|
| Yes | Output modality. Fixed to |
|
| No | Enables server-side VAD. When disabled, call |
|
| No | VAD type. Fixed to |
|
| No | VAD sensitivity threshold. Recommended value: Default: Lower values increase sensitivity (may trigger on background noise). Higher values reduce sensitivity and help avoid false triggers in noisy environments. |
|
| No | Silence duration in milliseconds that marks the end of an utterance. Recommended value: Default: Shorter durations (e.g., 300 ms) speed up responses but may split natural pauses. Longer durations (e.g., 1200 ms) handle pauses better but increase latency. |
|
| No | Speech recognition settings. See Transcription parameters. |
Transcription parameters (OmniRealtimeTranscriptionParam)
Set these parameters with the setter methods of the OmniRealtimeTranscriptionParam class.
Click to view sample code
OmniRealtimeTranscriptionParam transcriptionParam = new OmniRealtimeTranscriptionParam();
transcriptionParam.setLanguage("zh");
transcriptionParam.setInputSampleRate(16000);
transcriptionParam.setInputAudioFormat("pcm");
Parameter | Type | Required | Description |
|---|---|---|---|
|
| No | Language of the audio source. For supported languages, see Supported languages. |
|
| No | Audio sampling rate in Hz. Valid values: Default: Setting |
|
| No | Audio encoding format. Valid values: |
|
| No | Context text for contextual biasing. Provide background text, entity vocabularies, or reference material to improve recognition accuracy. Maximum: 10,000 tokens. |
Key interfaces
OmniRealtimeConversation
Import: com.alibaba.dashscope.audio.omni.OmniRealtimeConversation
This class manages the WebSocket lifecycle: connecting to the server, sending audio, and ending the session.
Create a conversation
OmniRealtimeConversation conversation =
new OmniRealtimeConversation(param, callback);
Creates a new conversation instance with the specified connection parameters and callback handler.
Connect to the server
conversation.connect();
Opens a WebSocket connection. The server responds with session.created and session.updated events.
Throws: NoApiKeyException, InterruptedException.
Configure the session
conversation.updateSession(config);
Updates the session configuration after the connection is established. The server responds with a session.updated event. If not called, the server uses default settings.
Send audio data
conversation.appendAudio(audioBase64);
Appends a Base64-encoded audio segment to the server-side audio buffer.
- VAD mode (
enableTurnDetection=true): The server detects speech boundaries and decides when to process the buffer. - Manual mode (
enableTurnDetection=false): Audio accumulates in the buffer until you callcommit()to trigger recognition. Each event can contain up to 15 MiB of audio data.
Commit the audio buffer
conversation.commit();
Submits the buffered audio for recognition. The server responds with an input_audio_buffer.committed event.
This method is only available in manual mode (
enableTurnDetection=false). An error occurs if the audio buffer is empty.
End the session
conversation.endSession(); // synchronous
// or
conversation.endSessionAsync(); // asynchronous
Notifies the server to finish processing any remaining audio and end the session. The server responds with a session.finished event.
When to call:
- VAD mode: After you finish sending audio.
- Manual mode: After you call
commit().
Close the connection
conversation.close();
Stops the task and closes the WebSocket connection immediately.
Get session and response IDs
String sessionId = conversation.getSessionId();
String responseId = conversation.getResponseId();
getSessionId()returns the session ID for the current task.getResponseId()returns the response ID of the most recent server response.
OmniRealtimeCallback
Import: com.alibaba.dashscope.audio.omni.OmniRealtimeCallback
Inherit this class and implement the callback methods to handle server events.
Method | Parameters | Triggered when |
|---|---|---|
| None | The WebSocket connection is established. |
|
| A server event is received. Parse the |
|
| The WebSocket connection is closed. |