Paraformer Real-time Speech Recognition Java SDK

更新时间:
复制 MD 格式

This topic describes the parameters and interface details of the Paraformer real-time speech recognition Java SDK.

Important

Alibaba Cloud Model Studio has released a workspace-specific domain for the China (Beijing) region. The new dedicated domain delivers superior performance and higher stability for inference requests. We recommend migrating from dashscope.aliyuncs.com to {WorkspaceId}.cn-beijing.maas.aliyuncs.com.

Replace {WorkspaceId} with your actual Workspace ID. The existing domain remains fully functional.

User guide: For model introduction and selection recommendations, see Real-time speech recognition - Fun-ASR/Paraformer.

Online demo: Only paraformer-realtime-v2, paraformer-realtime-8k-v2, and paraformer-realtime-v1 support online demo.

Prerequisites

  • You have activated the service and Obtain an API key. Please Configure API key as an environment variable instead of hardcoding it in your code to prevent security risks caused by code leakage.

    Note

    When you need to provide temporary access to third-party applications or users, or when you want to strictly control high-risk operations such as accessing or deleting sensitive data, we recommend using temporary authentication tokens.

    Compared with long-term API Keys, temporary authentication tokens have a short validity period (60 seconds) and higher security, making them suitable for temporary call scenarios and effectively reducing the risk of API Key leakage.

    Usage: In your code, replace the API Key originally used for authentication with the obtained temporary authentication token.

  • Install the latest DashScope SDK.

Model list

paraformer-realtime-v2 (Recommended)

paraformer-realtime-8k-v2 (Recommended)

paraformer-realtime-v1

paraformer-realtime-8k-v1

Use case

Live streaming, meetings, and similar scenarios

Recognition of 8 kHz audio in scenarios such as telephone customer service and voicemail

Live streaming, meetings, and similar scenarios

Recognition of 8 kHz audio in scenarios such as telephone customer service and voicemail

Sample rate

Any

8kHz

16kHz

8kHz

Language

Chinese (including Mandarin and various dialects), English, Japanese, Korean, German, French, Russian

Supported Chinese dialects: Shanghainese, Wu, Minnan, Northeastern, Gansu, Guizhou, Henan, Hubei, Hunan, Jiangxi, Ningxia, Shanxi, Shaanxi, Shandong, Sichuan, Tianjin, Yunnan, Cantonese

Chinese

Chinese

Chinese

Punctuation prediction

Supported by default, no configuration required

Supported by default, no configuration required

Supported by default, no configuration required

Supported by default, no configuration required

Inverse text normalization (ITN)

Supported by default, no configuration required

Supported by default, no configuration required

Supported by default, no configuration required

Supported by default, no configuration required

Custom hot words

See Custom hotwords

See Custom hotwords

See Customize and manage hotwords for Paraformer speech recognition

See Customize and manage hotwords for Paraformer speech recognition

Specify recognition language

Specify via the language_hints parameter

Sentiment recognition

(Click to view usage)

Sentiment recognition follows these constraints:

  • Only available for the paraformer-realtime-8k-v2 model.

  • Semantic segmentation must be disabled (controlled via Request parameters semantic_punctuation_enabled). Semantic segmentation is disabled by default.

  • Sentiment recognition results are only shown when the isSentenceEnd method of Real-time recognition result (RecognitionResult) returns true.

How to obtain sentiment recognition results: Call the getEmoTag and getEmoConfidence methods of Sentence information (Sentence) to obtain the sentiment and sentiment confidence of the current sentence respectively.

Quick start

Recognition class provides non-streaming and bidirectional streaming call interfaces. Choose the appropriate call method based on your needs:

  • Non-streaming call: Recognizes local files and returns the complete result at once. Suitable for processing pre-recorded audio.

  • Bidirectional streaming call: Recognizes audio streams directly and outputs results in real time. The audio stream can come from external devices (such as a microphone) or be read from a local file. Suitable for scenarios that require immediate feedback.

Non-streaming call

Submit a single real-time speech-to-text task and synchronously obtain the transcription result by passing in a local file.

image

Instantiate Recognition class, call the call method with Request parameters and the file to be recognized, perform recognition, and obtain the recognition result.

Click to view complete example

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

import java.io.File;

public class Main {
    public static void main(String[] args) {
        // The following configuration is for the China (Beijing) region. Replace "{WorkspaceId}" with your actual workspace ID. The configuration varies by region.
        Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/inference";
        // Create a Recognition instance
        Recognition recognizer = new Recognition();
        // Create RecognitionParam
        RecognitionParam param =
                RecognitionParam.builder()
                        // If you have not configured the API Key as an environment variable, uncomment the following line and replace apiKey with your own API Key
                        // .apiKey("yourApikey")
                        .model("paraformer-realtime-v2")
                        .format("wav")
                        .sampleRate(16000)
                        // "language_hints" is only supported by the paraformer-realtime-v2 model
                        .parameter("language_hints", new String[]{"zh", "en"})
                        .build();

        try {
            System.out.println("Recognition result: " + recognizer.call(param, new File("{YOUR_AUDIO_FILE}")));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // Close the WebSocket connection after the task ends
            recognizer.getDuplexApi().close(1000, "bye");
        }
        System.out.println(
                "[Metric] requestId: "
                        + recognizer.getLastRequestId()
                        + ", first package delay ms: "
                        + recognizer.getFirstPackageDelay()
                        + ", last package delay ms: "
                        + recognizer.getLastPackageDelay());
        System.exit(0);
    }
}

Bidirectional streaming: callback-based

Submit a single real-time speech-to-text task and stream real-time recognition results through the callback interface.

image
  1. Start streaming speech recognition

    Instantiate Recognition class, call the call method with Request parameters and Callback interface (ResultCallback) to start streaming speech recognition.

  2. Stream audio data

    Call the sendAudioFrame method of Recognition class in a loop to send binary audio stream segments read from a local file or device (such as a microphone) to the server.

    During the audio data transmission, the server returns recognition results to the client in real time through the onEvent method of Callback interface (ResultCallback).

    It is recommended that each audio segment is approximately 100 milliseconds in duration, with a data size between 1 KB and 16 KB.

  3. Finish processing

    Call the stop method of Recognition class to end speech recognition.

    This method blocks the current thread until the onComplete or onError callback of Callback interface (ResultCallback) is triggered.

Click to view complete example

Recognize microphone audio

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 javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.TargetDataLine;

import java.nio.ByteBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        // The following configuration is for the China (Beijing) region. Replace "{WorkspaceId}" with your actual workspace ID. The configuration varies by region.
        Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/inference";
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.submit(new RealtimeRecognitionTask());
        executorService.shutdown();
        executorService.awaitTermination(1, TimeUnit.MINUTES);
        System.exit(0);
    }
}

class RealtimeRecognitionTask implements Runnable {
    @Override
    public void run() {
        RecognitionParam param = RecognitionParam.builder()
                // If you have not configured the API Key as an environment variable, replace apiKey with your own API Key
                // .apiKey("yourApikey")
                .model("paraformer-realtime-v2")
                .format("wav")
                .sampleRate(16000)
                // "language_hints" is only supported by the paraformer-realtime-v2 model
                .parameter("language_hints", new String[]{"zh", "en"})
                .build();
        Recognition recognizer = new Recognition();

        ResultCallback<RecognitionResult> callback = new ResultCallback<RecognitionResult>() {
            @Override
            public void onEvent(RecognitionResult result) {
                if (result.isSentenceEnd()) {
                    System.out.println("Final Result: " + result.getSentence().getText());
                } else {
                    System.out.println("Intermediate Result: " + result.getSentence().getText());
                }
            }

            @Override
            public void onComplete() {
                System.out.println("Recognition complete");
            }

            @Override
            public void onError(Exception e) {
                System.out.println("RecognitionCallback error: " + e.getMessage());
            }
        };
        try {
            recognizer.call(param, callback);
            // Create audio format
            AudioFormat audioFormat = new AudioFormat(16000, 16, 1, true, false);
            // Match the default recording device based on the format
            TargetDataLine targetDataLine =
                    AudioSystem.getTargetDataLine(audioFormat);
            targetDataLine.open(audioFormat);
            // Start recording
            targetDataLine.start();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            long start = System.currentTimeMillis();
            // Record for 50s and perform real-time transcription
            while (System.currentTimeMillis() - start < 50000) {
                int read = targetDataLine.read(buffer.array(), 0, buffer.capacity());
                if (read > 0) {
                    buffer.limit(read);
                    // Send the recorded audio data to the streaming recognition service
                    recognizer.sendAudioFrame(buffer);
                    buffer = ByteBuffer.allocate(1024);
                    // Recording rate is limited, sleep briefly to prevent high CPU usage
                    Thread.sleep(20);
                }
            }
            recognizer.stop();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // Close the WebSocket connection after the task ends
            recognizer.getDuplexApi().close(1000, "bye");
        }

        System.out.println(
                "[Metric] requestId: "
                        + recognizer.getLastRequestId()
                        + ", first package delay ms: "
                        + recognizer.getFirstPackageDelay()
                        + ", last package delay ms: "
                        + recognizer.getLastPackageDelay());
    }
}

Recognize local audio file

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.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

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 {
    public static void main(String[] args) throws InterruptedException {
        // The following configuration is for the China (Beijing) region. Replace "{WorkspaceId}" with your actual workspace ID. The configuration varies by region.
        Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/inference";
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.submit(new RealtimeRecognitionTask(Paths.get(System.getProperty("user.dir"), "{YOUR_AUDIO_FILE}")));
        executorService.shutdown();

        // wait for all tasks to complete
        executorService.awaitTermination(1, TimeUnit.MINUTES);
        System.exit(0);
    }
}

class RealtimeRecognitionTask implements Runnable {
    private Path filepath;

    public RealtimeRecognitionTask(Path filepath) {
        this.filepath = filepath;
    }

    @Override
    public void run() {
        RecognitionParam param = RecognitionParam.builder()
                // If you have not configured the API Key as an environment variable, replace apiKey with your own API Key
                // .apiKey("yourApikey")
                .model("paraformer-realtime-v2")
                .format("wav")
                .sampleRate(16000)
                // "language_hints" is only supported by the paraformer-realtime-v2 model
                .parameter("language_hints", new String[]{"zh", "en"})
                .build();
        Recognition recognizer = new Recognition();

        String threadName = Thread.currentThread().getName();

        ResultCallback<RecognitionResult> callback = new ResultCallback<RecognitionResult>() {
            @Override
            public void onEvent(RecognitionResult message) {
                if (message.isSentenceEnd()) {

                    System.out.println(TimeUtils.getTimestamp()+" "+
                            "[process " + threadName + "] Final Result:" + message.getSentence().getText());
                } else {
                    System.out.println(TimeUtils.getTimestamp()+" "+
                            "[process " + threadName + "] Intermediate Result: " + message.getSentence().getText());
                }
            }

            @Override
            public void onComplete() {
                System.out.println(TimeUtils.getTimestamp()+" "+"[" + threadName + "] Recognition complete");
            }

            @Override
            public void onError(Exception e) {
                System.out.println(TimeUtils.getTimestamp()+" "+
                        "[" + threadName + "] RecognitionCallback error: " + e.getMessage());
            }
        };

        try {
            recognizer.call(param, callback);
            // Please replace the path with your audio file path
            System.out.println(TimeUtils.getTimestamp()+" "+"[" + threadName + "] Input file_path is: " + this.filepath);
            // Read file and send audio by chunks
            FileInputStream fis = new FileInputStream(this.filepath.toFile());
            // chunk size set to 1 seconds for 16KHz sample rate
            byte[] buffer = new byte[3200];
            int bytesRead;
            // Loop to read chunks of the file
            while ((bytesRead = fis.read(buffer)) != -1) {
                ByteBuffer byteBuffer;
                // Handle the last chunk which might be smaller than the buffer size
                System.out.println(TimeUtils.getTimestamp()+" "+"[" + threadName + "] bytesRead: " + bytesRead);
                if (bytesRead < buffer.length) {
                    byteBuffer = ByteBuffer.wrap(buffer, 0, bytesRead);
                } else {
                    byteBuffer = ByteBuffer.wrap(buffer);
                }

                recognizer.sendAudioFrame(byteBuffer);
                buffer = new byte[3200];
                Thread.sleep(100);
            }
            System.out.println(TimeUtils.getTimestamp()+" "+LocalDateTime.now());
            recognizer.stop();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // Close the WebSocket connection after the task ends
            recognizer.getDuplexApi().close(1000, "bye");
        }

        System.out.println(
                "["
                        + threadName
                        + "][Metric] requestId: "
                        + recognizer.getLastRequestId()
                        + ", first package delay ms: "
                        + recognizer.getFirstPackageDelay()
                        + ", last package delay ms: "
                        + recognizer.getLastPackageDelay());
    }
}

Bidirectional streaming: Flowable-based

Submit a single real-time speech-to-text task and stream real-time recognition results through a Flowable workflow.

Flowable is an open-source framework for workflow and business process management, released under the Apache 2.0 license. For more information about Flowable, see Flowable API documentation.

Click to view complete example

Directly call the streamCall method of Recognition class to start recognition.

The streamCall method returns a Flowable<RecognitionResult> instance. You can call methods such as Flowable instance's blockingForEach and subscribe to process recognition results. The recognition results are encapsulated in RecognitionResult.

The streamCall method requires two parameters:

  • RecognitionParam instance (Request parameters): Use it to set parameters such as the model, sample rate, and audio format for speech recognition.

  • Flowable<ByteBuffer> instance: You need to create a Flowable<ByteBuffer> type instance and implement the audio stream parsing method within it.

import com.alibaba.dashscope.audio.asr.recognition.Recognition;
import com.alibaba.dashscope.audio.asr.recognition.RecognitionParam;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.utils.Constants;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.TargetDataLine;
import java.nio.ByteBuffer;

public class Main {
    public static void main(String[] args) throws NoApiKeyException {
        // The following configuration is for the China (Beijing) region. Replace "{WorkspaceId}" with your actual workspace ID. The configuration varies by region.
        Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/inference";
        // Create a Flowable<ByteBuffer>
        Flowable<ByteBuffer> audioSource =
                Flowable.create(
                        emitter -> {
                            new Thread(
                                    () -> {
                                        try {
                                            // Create audio format
                                            AudioFormat audioFormat = new AudioFormat(16000, 16, 1, true, false);
                                            // Match the default recording device based on the format
                                            TargetDataLine targetDataLine =
                                                    AudioSystem.getTargetDataLine(audioFormat);
                                            targetDataLine.open(audioFormat);
                                            // Start recording
                                            targetDataLine.start();
                                            ByteBuffer buffer = ByteBuffer.allocate(1024);
                                            long start = System.currentTimeMillis();
                                            // Record for 50s and perform real-time transcription
                                            while (System.currentTimeMillis() - start < 50000) {
                                                int read = targetDataLine.read(buffer.array(), 0, buffer.capacity());
                                                if (read > 0) {
                                                    buffer.limit(read);
                                                    // Send the recorded audio data to the streaming recognition service
                                                    emitter.onNext(buffer);
                                                    buffer = ByteBuffer.allocate(1024);
                                                    // Recording rate is limited, sleep briefly to prevent high CPU usage
                                                    Thread.sleep(20);
                                                }
                                            }
                                            // Notify the end of transcription
                                            emitter.onComplete();
                                        } catch (Exception e) {
                                            emitter.onError(e);
                                        }
                                    })
                                    .start();
                        },
                        BackpressureStrategy.BUFFER);

        // Create Recognizer
        Recognition recognizer = new Recognition();
        // Create RecognitionParam, pass the Flowable<ByteBuffer> created above to the audioFrames parameter
        RecognitionParam param = RecognitionParam.builder()
                // If you have not configured the API Key as an environment variable, replace apiKey with your own API Key
                // .apiKey("yourApikey")
                .model("paraformer-realtime-v2")
                .format("pcm")
                .sampleRate(16000)
                // "language_hints" is only supported by the paraformer-realtime-v2 model
                .parameter("language_hints", new String[]{"zh", "en"})
                .build();

        // Streaming call interface
        recognizer
                .streamCall(param, audioSource)
                .blockingForEach(
                        result -> {
                            // Subscribe to the output result
                            if (result.isSentenceEnd()) {
                                System.out.println("Final Result: " + result.getSentence().getText());
                            } else {
                                System.out.println("Intermediate Result: " + result.getSentence().getText());
                            }
                        });
        // Close the WebSocket connection after the task ends
        recognizer.getDuplexApi().close(1000, "bye");
        System.out.println(
                "[Metric] requestId: "
                        + recognizer.getLastRequestId()
                        + ", first package delay ms: "
                        + recognizer.getFirstPackageDelay()
                        + ", last package delay ms: "
                        + recognizer.getLastPackageDelay());
        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 Optimize Paraformer real-time speech recognition for high concurrency.

Request parameters

Configure parameters such as the model, sample rate, and audio format through the chained methods of RecognitionParam. Pass the configured parameter object to the call/streamCall method of Recognition class.

Click to view example

RecognitionParam param = RecognitionParam.builder()
  .model("paraformer-realtime-v2")
  .format("pcm")
  .sampleRate(16000)
  // "language_hints" is only supported by the paraformer-realtime-v2 model
  .parameter("language_hints", new String[]{"zh", "en"})
  .build();

Parameter

Type

Default

Required

Description

model

String

-

Yes

The model for real-time speech recognition. For more information, see Model list.

sampleRate

Integer

-

Yes

Set the sample rate (in Hz) of the audio to be recognized.

Varies by model:

  • paraformer-realtime-v2 supports any sample rate.

  • paraformer-realtime-v1 only supports 16000 Hz sampling.

  • paraformer-realtime-8k-v2 only supports 8000 Hz sample rate.

  • paraformer-realtime-8k-v1 only supports 8000 Hz sample rate.

format

String

-

Yes

Set the audio format to be recognized.

Supported audio formats: pcm, wav, mp3, opus, speex, aac, amr.

Important

opus/speex: Must use Ogg encapsulation.

wav: Must be PCM encoded.

amr: Only AMR-NB type is supported.

vocabularyId

String

-

No

Set the hot word ID. If not set, hot words will not take effect. Use this field to set the hot word ID for v2 and later models.

In the current speech recognition session, the hot word information corresponding to this hot word ID will be applied. For detailed usage, see Custom hotwords.

phraseId

String

-

No

Set the hot word ID. If not set, hot words will not take effect. Use this field to set the hot word ID for v1 series models.

In the current speech recognition session, the hot word information corresponding to this hot word ID will be applied. For detailed usage, see Customize and manage hotwords for Paraformer speech recognition.

disfluencyRemovalEnabled

boolean

false

No

Set whether to filter filler words:

  • true: Filter filler words

  • false (default): Do not filter filler words

language_hints

String[]

["zh", "en"]

No

Set the language codes for recognition. If you cannot determine the language in advance, you can leave this unset and the model will automatically detect the language.

Currently supported language codes:

  • zh: Chinese

  • en: English

  • ja: Japanese

  • yue: Cantonese

  • ko: Korean

  • de: German

  • fr: French

  • ru: Russian

This parameter only takes effect for models that support multiple languages (see Model list).

Note

language_hints must be set through the RecognitionParam instance's parameter method or parameters method:

Set via parameter

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameter("language_hints", new String[]{"zh", "en"})
 .build();

Set via parameters

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameters(Collections.singletonMap("language_hints", new String[]{"zh", "en"}))
 .build();

semantic_punctuation_enabled

boolean

false

No

Set whether to enable semantic segmentation. Disabled by default.

  • true: Enable semantic segmentation and disable VAD (Voice Activity Detection) segmentation.

  • false (default): Enable VAD (Voice Activity Detection) segmentation and disable semantic segmentation.

Semantic segmentation provides higher accuracy and is suitable for meeting transcription scenarios. VAD (Voice Activity Detection) segmentation has lower latency and is suitable for interactive scenarios.

By adjusting the semantic_punctuation_enabled parameter, you can flexibly switch the speech recognition segmentation method to suit different scenarios.

This parameter only takes effect when the model is v2 or later.

Note

semantic_punctuation_enabled must be set through the RecognitionParam instance's parameter method or parameters method:

Set via parameter

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameter("semantic_punctuation_enabled", true)
 .build();

Set via parameters

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameters(Collections.singletonMap("semantic_punctuation_enabled", true))
 .build();

max_sentence_silence

Integer

800

No

Set the silence duration threshold (in ms) for VAD (Voice Activity Detection) segmentation.

When the silence duration after a speech segment exceeds this threshold, the system determines that the sentence has ended.

The parameter range is 200 ms to 6000 ms, with a default value of 800 ms.

This parameter only takes effect when the semantic_punctuation_enabled parameter is false (VAD segmentation) and the model is v2 or later.

Note

max_sentence_silence must be set through the RecognitionParam instance's parameter method or parameters method:

Set via parameter

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameter("max_sentence_silence", 800)
 .build();

Set via parameters

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameters(Collections.singletonMap("max_sentence_silence", 800))
 .build();

multi_threshold_mode_enabled

boolean

false

No

When this switch is enabled (true), it prevents VAD segmentation from cutting sentences that are too long. Disabled by default.

This parameter only takes effect when the semantic_punctuation_enabled parameter is false (VAD segmentation) and the model is v2 or later.

Note

multi_threshold_mode_enabled must be set through the RecognitionParam instance's parameter method or parameters method:

Set via parameter

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameter("multi_threshold_mode_enabled", true)
 .build();

Set via parameters

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameters(Collections.singletonMap("multi_threshold_mode_enabled", true))
 .build();

punctuation_prediction_enabled

boolean

true

No

Set whether to automatically add punctuation in the recognition results:

  • true (default): Yes

  • false: No

This parameter only takes effect when the model is v2 or later.

Note

punctuation_prediction_enabled must be set through the RecognitionParam instance's parameter method or parameters method:

Set via parameter

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameter("punctuation_prediction_enabled", false)
 .build();

Set via parameters

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameters(Collections.singletonMap("punctuation_prediction_enabled", false))
 .build();

heartbeat

boolean

false

No

When you need to maintain a long connection with the server, use this switch to control the behavior:

  • true: The connection with the server can be maintained without interruption when continuously sending silent audio.

  • false (default): Even when continuously sending silent audio, the connection will be disconnected after 60 seconds due to timeout.

    Silent audio refers to audio files or data streams that contain no sound signal. Silent audio can be generated through various methods, such as using audio editing software like Audacity or Adobe Audition, or through command-line tools like FFmpeg.

This parameter only takes effect when the model is v2 or later.

Note

The SDK version must be 2.19.1 or later to use this field.

heartbeat must be set through the RecognitionParam instance's parameter method or parameters method:

Set via parameter

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameter("heartbeat", true)
 .build();

Set via parameters

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameters(Collections.singletonMap("heartbeat", true))
 .build();

inverse_text_normalization_enabled

boolean

true

No

Set whether to enable ITN (Inverse Text Normalization).

Enabled by default (true). When enabled, Chinese numerals are converted to Arabic numerals.

This parameter only takes effect when the model is v2 or later.

Note

inverse_text_normalization_enabled must be set through the RecognitionParam instance's parameter method or parameters method:

Set via parameter

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameter("inverse_text_normalization_enabled", false)
 .build();

Set via parameters

RecognitionParam param = RecognitionParam.builder()
 .model("paraformer-realtime-v2")
 .format("pcm")
 .sampleRate(16000)
 .parameters(Collections.singletonMap("inverse_text_normalization_enabled", false))
 .build();

apiKey

String

-

No

User API Key.

Key interfaces

Recognition class

Recognition is imported via "import com.alibaba.dashscope.audio.asr.recognition.Recognition;". Its key interfaces are as follows:

Interface/Method

Parameter

Return value

Description

public void call(RecognitionParam param, final ResultCallback<RecognitionResult> callback)

None

Callback-based streaming real-time recognition. This method does not block the current thread.

public String call(RecognitionParam param, File file)

Recognition result

Non-streaming call based on a local file. This method blocks the current thread until all audio has been read. The file to be recognized must have read permissions.

public Flowable<RecognitionResult> streamCall(RecognitionParam param, Flowable<ByteBuffer> audioFrame)

Flowable<RecognitionResult>

Flowable-based streaming real-time recognition.

public void sendAudioFrame(ByteBuffer audioFrame)
  • audioFrame: Binary audio stream of ByteBuffer type

None

Send audio data. Each audio packet should not be too large or too small. It is recommended that each packet is approximately 100 ms in duration, with a size between 1 KB and 16 KB.

Recognition results are obtained through the onEvent method of Callback interface (ResultCallback).

public void stop()

None

None

Stop real-time recognition.

This method blocks the current thread until the ResultCallback instance's onComplete or onError method is called.

recognizer.getDuplexApi().close(int code, String reason)

code: WebSocket close code

reason: Close reason

These two parameters can be configured according to The WebSocket Protocol documentation.

true

After the task ends, the WebSocket connection must be closed regardless of whether an exception occurred, to avoid connection leaks. For information on how to reuse connections to improve efficiency, see Optimize Paraformer real-time speech recognition for high concurrency.

public String getLastRequestId()

None

requestId

Get the requestId of the current task. Available after starting a new task with call or streamingCall.

Note

This method is available starting from SDK version 2.18.0.

public long getFirstPackageDelay()

None

First package delay

Get the first package delay, which is the latency from sending the first audio packet to receiving the first recognition result. Use after the task is complete.

Note

This method is available starting from SDK version 2.18.0.

public long getLastPackageDelay()

None

Last package delay

Get the last package delay, which is the latency from sending the stop command to receiving the last recognition result. Use after the task is complete.

Note

This method is available starting from SDK version 2.18.0.

Callback interface (ResultCallback)

During bidirectional streaming calls, the server returns key process information and data to the client through callbacks. You need to implement the callback methods to handle the information or data returned by the server.

Callback methods are implemented by extending the abstract class ResultCallback. When extending this abstract class, you can specify the generic type as RecognitionResult. RecognitionResult encapsulates the data structure returned by the server.

Since Java supports connection reuse, there are no onClose or onOpen callbacks.

Example

ResultCallback<RecognitionResult> callback = new ResultCallback<RecognitionResult>() {
    @Override
    public void onEvent(RecognitionResult result) {
        System.out.println("RequestId: " + result.getRequestId());
        // Implement your logic to process speech recognition results here
    }

    @Override
    public void onComplete() {
        System.out.println("Task completed");
    }

    @Override
    public void onError(Exception e) {
        System.out.println("Task failed: " + e.getMessage());
    }
};

Interface/Method

Parameter

Return value

Description

public void onEvent(RecognitionResult result)

result: Real-time recognition result (RecognitionResult)

None

Called when the server has a response.

public void onComplete()

None

None

Called when the task is complete.

public void onError(Exception e)

e: Exception information

None

Called when an exception occurs.

Response

Real-time recognition result (RecognitionResult)

RecognitionResult represents the result of a real-time recognition session.

Interface/Method

Parameter

Return value

Description

public String getRequestId()

None

requestId

Get the requestId.

public boolean isSentenceEnd()

None

Whether it is a complete sentence, i.e., a sentence boundary has been reached

Determine whether the given sentence has ended.

public Sentence getSentence()

None

Sentence information (Sentence)

Get sentence information, including timestamps and text.

Sentence information (Sentence)

Interface/Method

Parameter

Return value

Description

public Long getBeginTime()

None

Sentence start time in ms

Returns the sentence start time.

public Long getEndTime()

None

Sentence end time in ms

Returns the sentence end time.

public String getText()

None

Recognition text

Returns the recognized text.

public List<Word> getWords()

None

List of Word timestamp information (Word)

Returns word-level timestamp information.

public String getEmoTag()

None

Sentiment of the current sentence

Returns the sentiment of the current sentence:

  • positive: Positive sentiment, such as happy or satisfied

  • negative: Negative sentiment, such as angry or gloomy

  • neutral: No obvious sentiment

Sentiment recognition follows these constraints:

  • Only available for the paraformer-realtime-8k-v2 model.

  • Semantic segmentation must be disabled (controlled via Request parameters semantic_punctuation_enabled). Semantic segmentation is disabled by default.

  • Sentiment recognition results are only shown when the isSentenceEnd method of Real-time recognition result (RecognitionResult) returns true.

public Double getEmoConfidence()

None

Sentiment confidence of the current sentence

Returns the sentiment confidence of the current sentence. Value range: [0.0, 1.0]. A higher value indicates higher confidence.

Sentiment recognition follows these constraints:

  • Only available for the paraformer-realtime-8k-v2 model.

  • Semantic segmentation must be disabled (controlled via Request parameters semantic_punctuation_enabled). Semantic segmentation is disabled by default.

  • Sentiment recognition results are only shown when the isSentenceEnd method of Real-time recognition result (RecognitionResult) returns true.

Word timestamp information (Word)

Interface/Method

Parameter

Return value

Description

public long getBeginTime()

None

Word start time in ms

Returns the word start time.

public long getEndTime()

None

Word end time in ms

Returns the word end time.

public String getText()

None

Word

Returns the recognized word.

public String getPunctuation()

None

Punctuation

Returns the punctuation.

Error codes

If you encounter errors, see Error codes for troubleshooting.

If the issue persists, join the developer community to report your issue and provide the Request ID for further investigation.

More examples

For more examples, see GitHub.

FAQ

Feature questions

Q: How to maintain a long connection with the server during prolonged silence?

Set the request parameter heartbeat to true and continuously send silent audio to the server.

Silent audio refers to audio files or data streams that contain no sound signal. Silent audio can be generated through various methods, such as using audio editing software like Audacity or Adobe Audition, or through command-line tools like FFmpeg.

Q: How to convert audio to a supported format?

You can use the FFmpeg tool. For more usage, refer to the FFmpeg official website.

# Basic conversion command (universal template)
# -i: Input file path. Example: audio.wav
# -c:a: Audio codec. Example: aac, libmp3lame, pcm_s16le
# -b:a: Bitrate (quality control). Example: 192k, 320k
# -ar: Sample rate. Example: 44100 (CD), 48000, 16000
# -ac: Number of channels. Example: 1 (mono), 2 (stereo)
# -y: Overwrite existing file (no value needed)
ffmpeg -i input_audio.ext -c:a codec_name -b:a bitrate -ar sample_rate -ac channels output.ext

# Example: WAV -> MP3 (preserve original quality)
ffmpeg -i input.wav -c:a libmp3lame -q:a 0 output.mp3
# Example: MP3 -> WAV (16-bit PCM standard format)
ffmpeg -i input.mp3 -c:a pcm_s16le -ar 44100 -ac 2 output.wav
# Example: M4A -> AAC (extract/convert Apple audio)
ffmpeg -i input.m4a -c:a copy output.aac  # Direct extraction without re-encoding
ffmpeg -i input.m4a -c:a aac -b:a 256k output.aac  # Re-encode for higher quality
# Example: FLAC lossless -> Opus (high compression)
ffmpeg -i input.flac -c:a libopus -b:a 128k -vbr on output.opus

Q: Does it support viewing the time range for each sentence?

Yes. The speech recognition results include the start and end timestamps for each sentence, which can be used to determine the time range of each sentence.

Q: How to recognize a local file (recorded audio)?

There are two ways to recognize local files:

  • Pass the local file path directly: This method obtains the complete recognition result only after the entire recognition is finished, and is not suitable for scenarios requiring immediate feedback.

    See Non-streaming call. Pass the file path to the call method of Recognition class to directly recognize the recorded file.

  • Convert the local file to a binary stream for recognition: This method recognizes the file while streaming the recognition results, suitable for scenarios requiring immediate feedback.

Troubleshooting

Q: What causes the failure to recognize speech (no recognition results)?

  1. Check whether the audio format (format) and sample rate (sampleRate/sample_rate) in the request parameters are correctly set and comply with parameter constraints. The following are common error examples:

    • The audio file extension is .wav, but the actual format is MP3, and the request parameter format is set to mp3 (incorrect parameter setting).

    • The audio sample rate is 3600 Hz, but the request parameter sampleRate/sample_rate is set to 48000 (incorrect parameter setting).

    You can use the ffprobe tool to obtain the container, codec, sample rate, channel, and other information about the audio:

    ffprobe -v error -show_entries format=format_name -show_entries stream=codec_name,sample_rate,channels -of default=noprint_wrappers=1 input.xxx
  2. When using the paraformer-realtime-v2 model, check whether the language set in language_hints matches the actual language of the audio.

    For example: The audio is actually in Chinese, but language_hints is set to en (English).

  3. If all the above checks pass, you can use custom hot words to improve recognition accuracy for specific words.