相关文章推荐
乖乖的炒面  ·  Visibility 列挙型 ...·  2 年前    · 
爱逃课的啤酒  ·  SQL ...·  2 年前    · 
鼻子大的松鼠  ·  Apache ECharts 5 ...·  2 年前    · 
好帅的铁链  ·  Tomcat ...·  2 年前    · 

本文介紹Paraformer即時語音辨識Java SDK的參數和介面細節。

重要

本文檔僅適用於 “中國大陸(北京)” 地區。如需使用模型,需使用 “中國大陸(北京)” 地區的 API Key

使用者指南: 關於模型介紹和選型建議請參見 即時語音辨識

前提條件

  • 已開通服務並 擷取API Key 。請 配置API Key到環境變數(準備下線,併入配置 API Key) ,而非寫入程式碼在代碼中,防範因代碼泄露導致的安全風險。

    說明

    當您需要為第三方應用或使用者提供臨時存取權限,或者希望嚴格控制敏感性資料訪問、刪除等高風險操作時,建議使用 臨時鑒權Token

    與長期有效 API Key 相比,臨時鑒權 Token 具備時效性短(60秒)、安全性高的特點,適用於臨時調用情境,能有效降低API Key泄露的風險。

    使用方式:在代碼中,將原本用於鑒權的 API Key 替換為擷取到的臨時鑒權 Token 即可。

  • 安裝最新版DashScope SDK

模型列表

paraformer-realtime-v2

paraformer-realtime-8k-v2

適用情境

直播、會議等情境

電話客服、語音信箱等 8kHz 音訊識別情境

採樣率

任意

8kHz

語種

中文(包含中文普通話和各種方言)、英文、日語、韓語、德語、法語、俄語

支援的中文方言:上海話、吳語、閩南語、東北話、甘肅話、貴州話、河南話、湖北話、湖南話、江西話、寧夏話、山西話、陝西話、山東話、四川話、天津話、雲南話、粵語

中文

標點符號預測

✅ 預設支援,無需配置

✅ 預設支援,無需配置

逆文本正則化(ITN)

✅ 預設支援,無需配置

✅ 預設支援,無需配置

定製熱詞

✅ 參見 定製熱詞

✅ 參見 定製熱詞

指定待識別語種

✅ 通過 language_hints 參數指定

情感識別

✅ (點擊查看使用方式)

情感識別遵循如下約束:

  • 僅限 paraformer-realtime-8k-v2 模型。

  • 必須關閉語義斷句(可通過 請求參數 semantic_punctuation_enabled 控制)。語義斷句預設為關閉狀態。

  • 只有在 即時識別結果(RecognitionResult) isSentenceEnd 方法返回結果為 true 時才顯示情感識別結果。

情感識別結果擷取方式:調用 單句資訊(Sentence) getEmoTag getEmoConfidence 方法分別擷取當前句子的情感和情感信賴度。

快速開始

Recognition類 提供了同步調用和流式調用等介面。請根據實際需求選擇合適的調用方式:

  • 同步調用:針對本地檔案進行識別,並一次性返回完整的處理結果。適合處理錄製好的音頻。

  • 流式調用:可直接對音頻流進行識別,並即時輸出結果。音頻流可以來自外部裝置(如麥克風)或從本地檔案讀取。適合需要即時反饋的情境。

同步調用

提交單個語音即時轉寫任務,通過傳入本地檔案的方式同步阻塞地拿到轉寫結果。

執行個體化 Recognition類 ,調用 call 方法綁定 請求參數 和待識別檔案,進行識別並最終擷取識別結果。

點擊查看完整樣本

樣本中用到的音頻為: asr_example.wav

import com.alibaba.dashscope.audio.asr.recognition.Recognition;
import com.alibaba.dashscope.audio.asr.recognition.RecognitionParam;
import java.io.File;
public class Main {
    public static void main(String[] args) {
        // 建立Recognition執行個體
        Recognition recognizer = new Recognition();
        // 建立RecognitionParam
        RecognitionParam param =
                RecognitionParam.builder()
                        // 若沒有將API Key配置到環境變數中,需將下面這行代碼注釋放開,並將apiKey替換為自己的API Key
                        // .apiKey("yourApikey")
                        .model("paraformer-realtime-v2")
                        .format("wav")
                        .sampleRate(16000)
                        // “language_hints”只支援paraformer-realtime-v2模型
                        .parameter("language_hints", new String[]{"zh", "en"})
                        .build();
        try {
            System.out.println("識別結果:" + recognizer.call(param, new File("asr_example.wav")));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 任務結束後關閉 WebSocket 串連
            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);
}

流式調用:基於回調

提交單個語音即時轉寫任務,通過實現回調介面的方式流式輸出即時識別結果。

  1. 啟動流式語音辨識

    執行個體化 Recognition類 ,調用 call 方法綁定 請求參數 回調介面(ResultCallback) 並啟動流式語音辨識。

  2. 串流

    迴圈調用 Recognition類 sendAudioFrame 方法,將從本地檔案或裝置(如麥克風)讀取的二進位音頻流分段發送至服務端。

    在發送音頻資料的過程中,服務端會通過 回調介面(ResultCallback) onEvent 方法,將識別結果即時返回給用戶端。

    建議每次發送的音頻時間長度約為100毫秒,資料大小保持在1KB至16KB之間。

  3. 結束處理

    調用 Recognition類 stop 方法結束語音辨識。

    該方法會阻塞當前線程,直到 回調介面(ResultCallback) onComplete 或者 onError 回調觸發後才會釋放線程阻塞。

點擊查看完整樣本

識別傳入麥克風的語音

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 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 {
        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()
                // 若沒有將API Key配置到環境變數中,需將apiKey替換為自己的API Key
                // .apiKey("yourApikey")
                .model("paraformer-realtime-v2")
                .format("wav")
                .sampleRate(16000)
                // “language_hints”只支援paraformer-realtime-v2模型
                .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);
            // 建立音頻格式
            AudioFormat audioFormat = new AudioFormat(16000, 16, 1, true, false);
            // 根據格式匹配預設錄音裝置
            TargetDataLine targetDataLine =
                    AudioSystem.getTargetDataLine(audioFormat);
            targetDataLine.open(audioFormat);
            // 開始錄音
            targetDataLine.start();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            long start = System.currentTimeMillis();
            // 錄音50s並進行即時轉寫
            while (System.currentTimeMillis() - start < 50000) {
                int read = targetDataLine.read(buffer.array(), 0, buffer.capacity());
                if (read > 0) {
                    buffer.limit(read);
                    // 將錄音音頻資料發送給流式識別服務
                    recognizer.sendAudioFrame(buffer);
                    buffer = ByteBuffer.allocate(1024);
                    // 錄音速率有限,防止cpu佔用過高,休眠一小會兒
                    Thread.sleep(20);
            recognizer.stop();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 任務結束後關閉 Websocket 串連
            recognizer.getDuplexApi().close(1000, "bye");
        System.out.println(
                "[Metric] requestId: "
                        + recognizer.getLastRequestId()
                        + ", first package delay ms: "
                        + recognizer.getFirstPackageDelay()
                        + ", last package delay ms: "
                        + recognizer.getLastPackageDelay());
}

識別本地語音檔案

樣本中用到的音頻為: asr_example.wav

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 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 {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.submit(new RealtimeRecognitionTask(Paths.get(System.getProperty("user.dir"), "asr_example.wav")));
        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()
                // 若沒有將API Key配置到環境變數中,需將apiKey替換為自己的API Key
                // .apiKey("yourApikey")
                .model("paraformer-realtime-v2")
                .format("wav")
                .sampleRate(16000)
                // “language_hints”只支援paraformer-realtime-v2模型
                .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 {
            // 任務結束後關閉 Websocket 串連
            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());
}

流式調用:基於Flowable

提交單個語音即時轉寫任務,通過實現工作流程(Flowable)的方式流式輸出即時識別結果。

Flowable 是一個用於工作流程和商務程序管理的開源架構,它基於 Apache 2.0 許可證發布。關於Flowable的使用,請參見 Flowable API詳情

點擊查看完整樣本

直接調用 Recognition類 streamCall 方法開始識別。

streamCall 方法返回一個 Flowable<RecognitionResult> 執行個體,您可以調用 Flowable 執行個體的 blockingForEach subscribe 等方法處理識別結果。識別結果封裝在 RecognitionResult 中。

streamCall 方法需要傳入兩個參數:

  • RecognitionParam 執行個體( 請求參數 ):通過它可以設定語音辨識所需的模型、採樣率、音頻格式等參數。

  • Flowable<ByteBuffer> 執行個體:您需要建立一個 Flowable<ByteBuffer> 類型的執行個體,並在其中實現解析音頻流的方法。

import com.alibaba.dashscope.audio.asr.recognition.Recognition;
import com.alibaba.dashscope.audio.asr.recognition.RecognitionParam;
import com.alibaba.dashscope.exception.NoApiKeyException;
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 {
        // 建立一個Flowable<ByteBuffer>
        Flowable<ByteBuffer> audioSource =
                Flowable.create(
                        emitter -> {
                            new Thread(
                                    () -> {
                                        try {
                                            // 建立音頻格式
                                            AudioFormat audioFormat = new AudioFormat(16000, 16, 1, true, false);
                                            // 根據格式匹配預設錄音裝置
                                            TargetDataLine targetDataLine =
                                                    AudioSystem.getTargetDataLine(audioFormat);
                                            targetDataLine.open(audioFormat);
                                            // 開始錄音
                                            targetDataLine.start();
                                            ByteBuffer buffer = ByteBuffer.allocate(1024);
                                            long start = System.currentTimeMillis();
                                            // 錄音50s並進行即時轉寫
                                            while (System.currentTimeMillis() - start < 50000) {
                                                int read = targetDataLine.read(buffer.array(), 0, buffer.capacity());
                                                if (read > 0) {
                                                    buffer.limit(read);
                                                    // 將錄音音頻資料發送給流式識別服務
                                                    emitter.onNext(buffer);
                                                    buffer = ByteBuffer.allocate(1024);
                                                    // 錄音速率有限,防止cpu佔用過高,休眠一小會兒
                                                    Thread.sleep(20);
                                            // 通知結束轉寫
                                            emitter.onComplete();
                                        } catch (Exception e) {
                                            emitter.onError(e);
                                    .start();
                        BackpressureStrategy.BUFFER);
        // 建立Recognizer
        Recognition recognizer = new Recognition();
        // 建立RecognitionParam,audioFrames參數中傳入上面建立的Flowable<ByteBuffer>
        RecognitionParam param = RecognitionParam.builder()
                // 若沒有將API Key配置到環境變數中,需將apiKey替換為自己的API Key
                // .apiKey("yourApikey")
                .model("paraformer-realtime-v2")
                .format("pcm")
                .sampleRate(16000)
                // “language_hints”只支援paraformer-realtime-v2模型
                .parameter("language_hints", new String[]{"zh", "en"})
                .build();
        // 流式調用介面
        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());
        // 任務結束後關閉 Websocket 串連
        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);
}

高並發調用

在DashScope Java SDK中,採用了OkHttp3的串連池技術,以減少重複建立串連的開銷。詳情請參見 即時語音辨識高並發情境

請求參數

通過 RecognitionParam 的鏈式方法配置模型、採樣率、音頻格式等參數。配置完成的參數對象傳入 Recognition類 call / streamCall 方法中使用。

點擊查看樣本

RecognitionParam param = RecognitionParam.builder()
  .model("paraformer-realtime-v2")
  .format("pcm")
  .sampleRate(16000)
  // “language_hints”只支援paraformer-realtime-v2模型
  .parameter("language_hints", new String[]{"zh", "en"})
  .build();

參數

類型

預設值

是否必須

說明

model

String

-

用於即時語音辨識的模型。詳情請參見 模型列表

sampleRate

Integer

-

設定待識別音頻採樣率(單位Hz)。

因模型而異:

  • paraformer-realtime-v2支援任意採樣率。

  • paraformer-realtime-8k-v2僅支援8000Hz採樣率。

format

String

-

設定待識別音頻格式。

支援的音頻格式:pcm、wav、mp3、opus、speex、aac、amr。

重要

opus/speex:必須使用Ogg封裝;

wav:必須為PCM編碼;

amr:僅支援AMR-NB類型。

vocabularyId

String

-

設定熱詞ID,若未設定則不生效。v2及更高版本模型設定熱詞ID時使用該欄位。

在本次語音辨識中,將應用與該熱詞ID對應的熱詞資訊。具體使用方法請參見 定製熱詞

disfluencyRemovalEnabled

boolean

false

設定是否過濾語氣詞:

  • true:過濾語氣詞

  • false(預設):不過濾語氣詞

language_hints

String[]

["zh", "en"]

設定待識別語言代碼。如果無法提前確定語種,可不設定,模型會自動識別語種。

目前支援的語言代碼:

  • zh: 中文

  • en: 英文

  • ja: 日語

  • yue: 粵語

  • ko: 韓語

  • de:德語

  • fr:法語

  • ru:俄語

該參數僅對支援多語言的模型生效(參見 模型列表 )。

說明

language_hints 需要通過 RecognitionParam 執行個體的 parameter 方法或者 parameters 方法進行設定:

通過parameter設定

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

通過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

設定是否開啟語義斷句,預設關閉。

  • true:開啟語義斷句,關閉VAD(Voice Activity Detection,語音活動檢測)斷句。

  • false(預設):開啟VAD(Voice Activity Detection,語音活動檢測)斷句,關閉語義斷句。

語義斷句準確性更高,適合會議轉寫情境;VAD(Voice Activity Detection,語音活動檢測)斷句延遲較低,適合互動情境。

通過調整 semantic_punctuation_enabled 參數,可以靈活切換語音辨識的斷句方式以適應不同情境需求。

該參數僅在模型為v2及更高版本時生效。

說明

semantic_punctuation_enabled 需要通過 RecognitionParam 執行個體的 parameter 方法或者 parameters 方法進行設定:

通過parameter設定

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

通過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

設定VAD(Voice Activity Detection,語音活動檢測)斷句的靜音時間長度閾值(單位為ms)。

當一段語音後的靜音時間長度超過該閾值時,系統會判定該句子已結束。

參數範圍為200ms至6000ms,預設值為800ms。

該參數僅在 semantic_punctuation_enabled 參數為false(VAD斷句)且模型為v2及更高版本時生效。

說明

max_sentence_silence 需要通過 RecognitionParam 執行個體的 parameter 方法或者 parameters 方法進行設定:

通過parameter設定

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

通過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

該開關開啟時(true)可以防止VAD斷句切割過長。預設關閉。

該參數僅在 semantic_punctuation_enabled 參數為false(VAD斷句)且模型為v2及更高版本時生效。

說明

multi_threshold_mode_enabled 需要通過 RecognitionParam 執行個體的 parameter 方法或者 parameters 方法進行設定:

通過parameter設定

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

通過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

設定是否在識別結果中自動添加標點:

  • true(預設):是

  • false:否

該參數僅在模型為v2及更高版本時生效。

說明

punctuation_prediction_enabled 需要通過 RecognitionParam 執行個體的 parameter 方法或者 parameters 方法進行設定:

通過parameter設定

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

通過parameters設定

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

heartbeat

boolean

false

當需要與服務端保持長串連時,可通過該開關進行控制:

  • true:在持續發送靜音音訊情況下,可保持與服務端的串連不中斷。

  • false(預設):即使持續發送靜音音頻,串連也將在60秒後因逾時而斷開。

    靜音音頻指的是在音頻檔案或資料流中沒有聲音訊號的內容。靜音音頻可以通過多種方法產生,例如使用音頻編輯軟體如Audacity或Adobe Audition,或者通過命令列工具如FFmpeg。

該參數僅在模型為v2及更高版本時生效。

說明

使用該欄位時,SDK版本不能低於2.19.1。

heartbeat 需要通過 RecognitionParam 執行個體的 parameter 方法或者 parameters 方法進行設定:

通過parameter設定

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

通過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

設定是否開啟ITN(Inverse Text Normalization,逆文本正則化)。

預設開啟(true)。開啟後,中文數字將轉換為阿拉伯數字。

該參數僅在模型為v2及更高版本時生效。

說明

inverse_text_normalization_enabled 需要通過 RecognitionParam 執行個體的 parameter 方法或者 parameters 方法進行設定:

通過parameter設定

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

通過parameters設定

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

apiKey

String

-

使用者API Key。

關鍵介面

Recognition

Recognition 通過“ import com.alibaba.dashscope.audio.asr.recognition.Recognition; ”方式引入。它的關鍵介面如下:

介面/方法

參數

傳回值

描述

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

基於回調形式的流式即時識別,該方法不會阻塞當前線程。

public String call(RecognitionParam param, File file)

識別結果

基於本地檔案的同步調用,該方法會阻塞當前線程直到全部音頻讀完,該方法要求所識別檔案具有可讀許可權。

public Flowable<RecognitionResult> streamCall(RecognitionParam param, Flowable<ByteBuffer> audioFrame)
  • param 請求參數

  • audioFrame Flowable<ByteBuffer> 執行個體

Flowable<RecognitionResult>

基於Flowable的流式即時識別。

public void sendAudioFrame(ByteBuffer audioFrame)
  • audioFrame :二進位音頻流,為 ByteBuffer 類型

推送音頻,每次推送的音頻流不宜過大或過小,建議每包音頻時間長度為100ms左右,大小在1KB~16KB之間。

識別結果通過 回調介面(ResultCallback) 的onEvent方法擷取。

public void stop()

停止即時識別。

該方法會阻塞當前線程,直到回調執行個體 ResultCallback onComplete 或者 onError 被調用之後才會解除對當前線程的阻塞。

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

code: WebSocket關閉碼(Close Code)

reason:關閉原因

這兩個參數可參考 The WebSocket Protocol 文檔進行配置

true

在任務結束後,無論是否出現異常都需要關閉WebSocket串連,避免造成串連泄漏。關於如何複用串連提升效率請參考 即時語音辨識高並發情境

public String getLastRequestId()

requestId

擷取當前任務的requestId,在調用 call streamingCall 開始新任務之後可以使用。

說明

該方法自2.18.0版本及以後的SDK中才開始提供。

public long getFirstPackageDelay()

首包延遲

擷取首包延遲,從發送第一包音頻到收到首包識別結果延遲,在任務完成後使用。

說明

該方法自2.18.0版本及以後的SDK中才開始提供。

public long getLastPackageDelay()

尾包延遲

獲得尾包延遲,發送 stop 指令到最後一包識別結果下發耗時,在任務完成後使用。

說明

該方法自2.18.0版本及以後的SDK中才開始提供。

回調介面( ResultCallback

流式調用 時,服務端會通過回調的方式,將關鍵流程資訊和資料返回給用戶端。您需要實現回調方法,處理服務端返回的資訊或者資料。

回調方法的實現,通過繼承抽象類別 ResultCallback 完成,繼承該抽象類別時,您可以指定泛型為 RecognitionResult RecognitionResult 封裝了伺服器返回的資料結構。

由於Java支援串連複用,因此沒有 onClose onOpen

樣本

ResultCallback<RecognitionResult> callback = new ResultCallback<RecognitionResult>() {
    @Override
    public void onEvent(RecognitionResult result) {
        System.out.println("RequestId為:" + result.getRequestId());
        // 在此實現處理語音辨識結果的邏輯
    @Override
    public void onComplete() {
        System.out.println("任務完成");
    @Override
    public void onError(Exception e) {
        System.out.println("任務失敗:" + e.getMessage());
};

介面/方法

參數

傳回值

描述

public void onEvent(RecognitionResult result)

result 即時識別結果(RecognitionResult)

當服務有回複時會被回調。

public void onComplete()

任務完成後該介面被回調。

public void onError(Exception e)

e :異常資訊

發生異常時該介面被回調。

響應結果

即時識別結果( RecognitionResult

RecognitionResult 代表一次即時識別的結果。

介面/方法

參數

傳回值

描述

public String getRequestId()

requestId

擷取requestId。

public boolean isSentenceEnd()

是否是完整句子,即產生斷句

判斷給定句子是否已經結束。

public Sentence getSentence()

單句資訊(Sentence)

擷取單句資訊,包括時間戳記和文本資訊等。

單句資訊( Sentence

介面/方法

參數

傳回值

描述

public Long getBeginTime()

句子開始時間,單位為ms

返回句子開始時間。

public Long getEndTime()

句子結束時間,單位為ms

返回句子結束時間。

public String getText()

識別文本

返回識別文本。

public List<Word> getWords()

字時間戳記資訊(Word) 的List集合

返回字時間戳記資訊。

public String getEmoTag()

當前句子的情感

返回當前句子的情感:

  • positive:正面情感,如開心、滿意

  • negative:負面情感,如憤怒、沉悶

  • neutral:無明顯情感

情感識別遵循如下約束:

  • 僅限 paraformer-realtime-8k-v2 模型。

  • 必須關閉語義斷句(可通過 請求參數 semantic_punctuation_enabled 控制)。語義斷句預設為關閉狀態。

  • 只有在 即時識別結果(RecognitionResult) isSentenceEnd 方法返回結果為 true 時才顯示情感識別結果。

public Double getEmoConfidence()

當前句子識別情感的信賴度

返回當前句子識別情感的信賴度,取值範圍:[0.0,1.0],值越大表示信賴度越高。

情感識別遵循如下約束:

  • 僅限 paraformer-realtime-8k-v2 模型。

  • 必須關閉語義斷句(可通過 請求參數 semantic_punctuation_enabled 控制)。語義斷句預設為關閉狀態。

  • 只有在 即時識別結果(RecognitionResult) isSentenceEnd 方法返回結果為 true 時才顯示情感識別結果。

字時間戳記資訊( Word

介面/方法

參數

傳回值

描述

public long getBeginTime()

字開始時間,單位為ms

返回字開始時間。

public long getEndTime()

字結束時間,單位為ms

返回字結束時間。

public String getText()

返回識別的字。

public String getPunctuation()

標點

返回標點。

錯誤碼

如遇報錯問題,請參見 錯誤資訊 進行排查。

若問題仍未解決,請加入 開發人員群 反饋遇到的問題,並提供Request ID,以便進一步排查問題。

更多樣本

更多樣本,請參見 GitHub

常見問題

功能特性

Q:在長時間靜默的情況下,如何保持與服務端長串連?

將請求參數 heartbeat 設定為true,並持續向服務端發送靜音音頻。

靜音音頻指的是在音頻檔案或資料流中沒有聲音訊號的內容。靜音音頻可以通過多種方法產生,例如使用音頻編輯軟體如Audacity或Adobe Audition,或者通過命令列工具如FFmpeg。

Q:如何將音頻格式轉換為滿足要求的格式?

可使用 FFmpeg工具 ,更多用法請參見FFmpeg官網。

# 基礎轉換命令(萬能模板)
# -i,作用:輸入檔案路徑,常用值樣本:audio.wav
# -c:a,作用:音頻編碼器,常用值樣本:aac, libmp3lame, pcm_s16le
# -b:a,作用:位元速率(音質控制),常用值樣本:192k, 320k
# -ar,作用:採樣率,常用值樣本:44100 (CD), 48000, 16000
# -ac,作用:聲道數,常用值樣本:1(單聲道), 2(立體聲)
# -y,作用:覆蓋已存在檔案(無需值)
ffmpeg -i input_audio.ext -c:a 編碼器名 -b:a 位元速率 -ar 採樣率 -ac 聲道數 output.ext
# 例如:WAV → MP3(保持原始品質)
ffmpeg -i input.wav -c:a libmp3lame -q:a 0 output.mp3
# 例如:MP3 → WAV(16bit PCM標準格式)
ffmpeg -i input.mp3 -c:a pcm_s16le -ar 44100 -ac 2 output.wav
# 例如:M4A → AAC(提取/轉換蘋果音頻)
ffmpeg -i input.m4a -c:a copy output.aac  # 直接提取不重編碼
ffmpeg -i input.m4a -c:a aac -b:a 256k output.aac  # 重編碼提高品質
# 例如:FLAC無損 → Opus(高壓縮)
ffmpeg -i input.flac -c:a libopus -b:a 128k -vbr on output.opus

Q: 是否支援查看每句話對應的時間範圍?

支援。語音辨識結果中會包含每句話的開始時間戳和結束時間戳記,可通過它們確定每句話的時間範圍。

Q:如何識別本地檔案(錄音檔案)?

識別本地檔案有兩種方式:

  • 直接傳入本地檔案路徑:此種方式在最終識別結束後擷取完整識別結果,不適合即時反饋的情境。

    參見 同步調用 ,在 Recognition類 call 方法中傳入檔案路徑對錄音檔案直接進行識別。

  • 將本地檔案轉成二進位流進行識別:此種方式一邊識別檔案一邊流式擷取識別結果,適合即時反饋的情境。

故障排查

Q:無法識別語音(無識別結果)是什麼原因?

  1. 請檢查請求參數中的音頻格式( format )和採樣率( sampleRate / sample_rate )設定是否正確且符合參數約束。以下為常見錯誤樣本:

    • 音頻副檔名為 .wav,但實際為 MP3 格式,而請求參數 format 設定為 mp3(參數設定錯誤)。

    • 音頻採樣率為 3600Hz,但請求參數 sampleRate / sample_rate 設定為 48000(參數設定錯誤)。

    可以使用 ffprobe 工具擷取音訊容器、編碼、採樣率、聲道等資訊:

    ffprobe -v error -show_entries format=format_name -show_entries stream=codec_name,sample_rate,channels -of default=noprint_wrappers=1 input.xxx
  2. 使用 paraformer-realtime-v2 模型時,請檢查 language_hints 設定的語言是否與音頻實際語言一致。

    例如:音頻實際為中文,但 language_hints 設定為 en (英文)。

  3. 若以上檢查均無問題,可通過定製熱詞提升對特定詞語的識別效果。