All Products
Search
Document Center

Alibaba Cloud Model Studio:Real-time speech recognition - Qwen

Last Updated:Nov 11, 2026

Learn about real-time speech recognition capabilities, streaming audio calls, and ways to improve recognition results.

Features

Real-time speech recognition accepts a continuous audio stream and returns transcribed text for voice input, meeting notes, live captions, and similar applications.

  • Languages and dialects: Automatically detect the language and recognize multiple languages and Chinese dialects. For the supported range, see Speech recognition overview.
  • Speech detection: Detect speech boundaries automatically and adjust speech-versus-noise thresholds for different recording environments.
  • Text processing: Predict punctuation, preserve Chinese dialect expressions, or remove fillers, repetitions, and self-corrections through text polishing.
  • Accuracy improvements: Use hotwords for specific names and terms, and provide context from earlier conversation turns.
  • Structured results: Use sentence results and timestamps to display captions, save text, and locate segments in audio.
  • Audio input: Use multiple audio formats and select a sample rate supported by the model.

NoteCapabilities vary by model. Check the supported models for each feature. To submit a complete recording in one request, see Non-real-time speech recognition.

Use caseRecommended modelResult behavior

Continuous transcription for meetings, classes, and captions

qwen-audio-3.1-asr-flash-streaming

Returns intermediate and final results for text display and updates while a user speaks.

Short voice input, such as voice input methods and voice messages

qwen-audio-3.1-asr-flash-message

Returns final sentence results by default. Intermediate results and text polishing can be enabled separately.

Get started

Install the DashScope SDK, then get your API key and Base URL from the console. Set them as DASHSCOPE_API_KEY and DASHSCOPE_BASE_URL.

Download the sample audio as asr_example.wav in the working directory. It is an English, 16 kHz, mono WAV file with 16-bit PCM encoding. The examples send the file in chunks to simulate real-time input, without requiring a microphone.

Qwen-Audio-ASR-Streaming

This example uses qwen-audio-3.1-asr-flash-streaming to send audio continuously through the DashScope SDK while receiving and printing interim and final results. After the audio ends, wait for the remaining results and task completion before closing the connection.

import com.alibaba.dashscope.audio.asr.recognition.Recognition;
import com.alibaba.dashscope.audio.asr.recognition.RecognitionParam;
import com.alibaba.dashscope.audio.asr.recognition.RecognitionResult;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.utils.Constants;

import java.io.InputStream;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicReference;

public class Main {
    public static void main(String[] args) throws Exception {
        Constants.baseWebsocketApiUrl =
            "wss://" + URI.create(System.getenv("DASHSCOPE_BASE_URL")).getHost()
            + "/api-ws/v1/inference";
        RecognitionParam param = RecognitionParam.builder()
            .apiKey(System.getenv("DASHSCOPE_API_KEY"))
            .model("qwen-audio-3.1-asr-flash-streaming")
            .format("wav")
            .sampleRate(16000)
            .build();
        Recognition recognition = new Recognition();
        AtomicReference<Exception> failure = new AtomicReference<>();
        ResultCallback<RecognitionResult> callback = new ResultCallback<RecognitionResult>() {
            @Override
            public void onEvent(RecognitionResult result) {
                if (result.getSentence() != null && result.getSentence().getText() != null
                        && !result.getSentence().getText().isEmpty()) {
                    System.out.println(result.getSentence());
                }
            }
            @Override
            public void onComplete() {}
            @Override
            public void onError(Exception error) {
                failure.set(error);
            }
        };
        try {
            recognition.call(param, callback);
            try (InputStream audio = Files.newInputStream(Paths.get("asr_example.wav"))) {
                byte[] buffer = new byte[3200];
                int size;
                while ((size = audio.read(buffer)) != -1) {
                    recognition.sendAudioFrame(ByteBuffer.wrap(buffer, 0, size));
                    Thread.sleep(100);
                }
            }
            recognition.stop();
            if (failure.get() != null) throw failure.get();
        } finally {
            if (recognition.getDuplexApi() != null) {
                recognition.getDuplexApi().close(1000, "bye");
            }
        }
        System.exit(0);
    }
}
import os
import time
from concurrent.futures import ThreadPoolExecutor
import dashscope
from urllib.parse import urlsplit

client = dashscope.Client(
    api_key=os.environ["DASHSCOPE_API_KEY"],
    base_url=os.environ["DASHSCOPE_BASE_URL"],
)

def receive_results(recognition):
    for event in recognition.events():
        payload = event.get("payload") or {}
        sentence = (payload.get("output") or {}).get("sentence") or {}
        if sentence.get("text") and not sentence.get("heartbeat"):
            print(sentence)

with client.audio.asr.recognize(
    ws_url=f"wss://{urlsplit(os.environ['DASHSCOPE_BASE_URL']).netloc}/api-ws/v1/inference",
    model="qwen-audio-3.1-asr-flash-streaming",
    format="wav",
    sample_rate=16000,
) as recognition:
    with ThreadPoolExecutor(max_workers=1) as pool:
        receiver = pool.submit(receive_results, recognition)
        try:
            with open("asr_example.wav", "rb") as audio:
                while chunk := audio.read(3200):
                    recognition.send_audio_frame(chunk)
                    time.sleep(0.1)
            recognition.stop()
            receiver.result()
        finally:
            recognition.close()

Qwen-Audio-ASR-Message

This example uses qwen-audio-3.1-asr-flash-message to send audio continuously through the DashScope SDK and receive and print final utterance results by default. After the audio ends, wait for the remaining results and task completion before closing the connection.

import com.alibaba.dashscope.audio.asr.recognition.Recognition;
import com.alibaba.dashscope.audio.asr.recognition.RecognitionParam;
import com.alibaba.dashscope.audio.asr.recognition.RecognitionResult;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.utils.Constants;

import java.io.InputStream;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicReference;

public class Main {
    public static void main(String[] args) throws Exception {
        Constants.baseWebsocketApiUrl =
            "wss://" + URI.create(System.getenv("DASHSCOPE_BASE_URL")).getHost()
            + "/api-ws/v1/inference";
        RecognitionParam param = RecognitionParam.builder()
            .apiKey(System.getenv("DASHSCOPE_API_KEY"))
            .model("qwen-audio-3.1-asr-flash-message")
            .format("wav")
            .sampleRate(16000)
            .build();
        Recognition recognition = new Recognition();
        AtomicReference<Exception> failure = new AtomicReference<>();
        ResultCallback<RecognitionResult> callback = new ResultCallback<RecognitionResult>() {
            @Override
            public void onEvent(RecognitionResult result) {
                if (result.getSentence() != null && result.getSentence().getText() != null
                        && !result.getSentence().getText().isEmpty()) {
                    System.out.println(result.getSentence());
                }
            }
            @Override
            public void onComplete() {}
            @Override
            public void onError(Exception error) {
                failure.set(error);
            }
        };
        try {
            recognition.call(param, callback);
            try (InputStream audio = Files.newInputStream(Paths.get("asr_example.wav"))) {
                byte[] buffer = new byte[3200];
                int size;
                while ((size = audio.read(buffer)) != -1) {
                    recognition.sendAudioFrame(ByteBuffer.wrap(buffer, 0, size));
                    Thread.sleep(100);
                }
            }
            recognition.stop();
            if (failure.get() != null) throw failure.get();
        } finally {
            if (recognition.getDuplexApi() != null) {
                recognition.getDuplexApi().close(1000, "bye");
            }
        }
        System.exit(0);
    }
}
import os
import time
from concurrent.futures import ThreadPoolExecutor
import dashscope
from urllib.parse import urlsplit

client = dashscope.Client(
    api_key=os.environ["DASHSCOPE_API_KEY"],
    base_url=os.environ["DASHSCOPE_BASE_URL"],
)

def receive_results(recognition):
    for event in recognition.events():
        payload = event.get("payload") or {}
        sentence = (payload.get("output") or {}).get("sentence") or {}
        if sentence.get("text") and not sentence.get("heartbeat"):
            print(sentence)

with client.audio.asr.recognize(
    ws_url=f"wss://{urlsplit(os.environ['DASHSCOPE_BASE_URL']).netloc}/api-ws/v1/inference",
    model="qwen-audio-3.1-asr-flash-message",
    format="wav",
    sample_rate=16000,
) as recognition:
    with ThreadPoolExecutor(max_workers=1) as pool:
        receiver = pool.submit(receive_results, recognition)
        try:
            with open("asr_example.wav", "rb") as audio:
                while chunk := audio.read(3200):
                    recognition.send_audio_frame(chunk)
                    time.sleep(0.1)
            recognition.stop()
            receiver.result()
        finally:
            recognition.close()

Process recognition results

  • Interim results: Use these for live subtitles or input previews. The text for an utterance may be revised during recognition. Update the displayed utterance instead of appending every result.

  • Final results: When an utterance ends, replace its interim text with the final result for stored transcripts, subtitles, or downstream processing.

    NoteQwen-Audio-ASR-Message returns only final results by default; enable intermediate_result_enabled if a live preview is needed.

  • Timestamps: Link text to audio positions for subtitle alignment, keyword highlighting, or audio seeking. Use utterance-level and word-level timestamps from final results rather than an interim end time that is not yet confirmed. Timestamps are in milliseconds.

    NoteQwen3-ASR-Flash-Realtime does not return transcript timestamps.

Improve recognition results

Adjust utterance boundaries, polish or preserve spoken expressions, and configure hotwords and context to improve segmentation, text readability, and recognition of specific terms.

Adjust sentence segmentation

Voice activity detection (VAD) uses silence after speech to determine when an utterance ends and trigger a final result. A shorter silence threshold suits responsive voice interactions. A longer threshold accommodates pauses within a sentence but increases the wait for a final result. Adjust it to the speaker’s pace and your interaction flow.

ModelConfiguration

qwen-audio-3.1-asr-flash-streaming, qwen-audio-3.1-asr-flash-message

Set max_sentence_silence to adjust the silence threshold. Use vad_model to select a near-field or far-field VAD model.

qwen-audio-3.0-asr-flash-streaming, Fun-ASR-Realtime series

Set max_sentence_silence to adjust the silence threshold.

Paraformer

For VAD segmentation, adjust max_sentence_silence. Alternatively, use semantic_punctuation_enabled to switch to semantic segmentation.

Qwen3-ASR-Flash-Realtime

Set silence_duration_ms and threshold in session.turn_detection to adjust the silence threshold and detection sensitivity. You can also disable VAD and let the client commit audio to control utterance boundaries.

Polish text

Spoken input often contains fillers, repetitions, and self-corrections. Text polishing cleans up these expressions for uses such as voice messages and speech input.

In qwen-audio-3.1-asr-flash-message, disfluency_removal_enabled controls polishing. Polishing applies to final results; update the displayed text when the utterance ends.

Preserve dialect expressions

When recognizing a Chinese dialect, choose whether to preserve dialect expressions or transcribe them into Standard Chinese. Dialect subtitles may need the original expressions, while written records for a broader audience may need Standard Chinese.

In qwen-audio-3.1-asr-flash-streaming and qwen-audio-3.1-asr-flash-message, keep_dialect controls whether dialect expressions are preserved. For the latter model, it applies only to final results.

Hotwords and context enhancement

Hotwords help recognize specific vocabulary, such as brands, personal names, and domain terms. Context enhancement provides terms and background from earlier conversation turns. For configuration, supported models, and tuning, see Improve recognition accuracy.

Sensitive word filtering

Sensitive-word filtering replaces specified words with the same number of asterisks or removes them from the transcript, for example when masking subtitle or transcript content. Qwen-Audio-ASR-Streaming and Fun-ASR-Realtime configure these rules with special_word_filter.

Use in production

For production use, manage connections and concurrency according to your traffic, and handle long silence, retries, and resource cleanup. See Speech recognition best practices for audio preparation, task and connection management, Java concurrency, and complete examples.

Supported models and regions

Singapore

To call the following models, use an API Key for the Singapore region:

  • Qwen-Audio-ASR-Message: qwen-audio-3.1-asr-flash-message
  • Qwen-Audio-ASR-Streaming: qwen-audio-3.1-asr-flash-streaming, qwen-audio-3.0-asr-flash-streaming
  • Fun-ASR-Realtime: fun-asr-realtime (stable version)
  • Qwen-ASR-Realtime: qwen3-asr-flash-realtime (stable version)

China (Beijing)

To call the following models, use an API Key for the China (Beijing) region:

  • Qwen-Audio-ASR-Message: qwen-audio-3.1-asr-flash-message

  • Qwen-Audio-ASR-Streaming: qwen-audio-3.1-asr-flash-streaming, qwen-audio-3.0-asr-flash-streaming

  • Fun-ASR-Realtime: fun-asr-realtime (stable version), fun-asr-realtime-2026-02-28 (latest snapshot version)

    • fun-asr-flash-8k-realtime (stable version, currently equivalent to fun-asr-flash-8k-realtime-2026-01-28), fun-asr-flash-8k-realtime-2026-01-28
  • Qwen-ASR-Realtime: qwen3-asr-flash-realtime (stable version)

  • Paraformer: paraformer-realtime-v2, paraformer-realtime-8k-v2

Usage limits

Real-time audio must be mono. Select an audio format and sample rate from the table below, and set format and sample_rate to match the actual audio.

ModelInput methodAudio formatSample rateSize/duration

qwen-audio-3.1-asr-flash-streaming, qwen-audio-3.0-asr-flash-streaming

Binary stream

pcm, wav, mp3, opus, speex, aac, amr

Any

Unlimited

qwen-audio-3.1-asr-flash-message

Binary stream

pcm, wav, mp3, opus, speex, aac, amr

16 kHz

—

Fun-ASR-Realtime series (fun-asr-realtime)

Binary stream

pcm, wav, mp3, opus, speex, aac, amr

Any

Unlimited

Fun-ASR-Flash-8K-Realtime series (fun-asr-flash-8k-realtime)

Binary stream

pcm, wav, mp3, opus, speex, aac, amr

8 kHz

Unlimited

qwen3-asr-flash-realtime

Base64 audio in JSON events

pcm, opus

8 kHz, 16 kHz

Unlimited

paraformer-realtime-v2

Binary stream

pcm, wav, mp3, opus, speex, aac, amr

Any

Unlimited

paraformer-realtime-8k-v2

Binary stream

pcm, wav, mp3, opus, speex, aac, amr

8 kHz

Unlimited

For audio checks and conversion, see Prepare input audio.

API reference

For real-time audio that needs low-latency transport, resilience on weak networks, echo cancellation, and noise suppression, consider AOQ. See the Realtime API overview for protocol selection, supported models, and integration.