Skip to main content

Qwen-Audio-ASR-Streaming Java SDK

本文介紹Qwen-Audio-ASR-Streaming即時語音辨識Java SDK的參數和介面細節。

前提條件

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

快速開始

Recognition類提供了非流式調用和雙向流式調用等介面。請根據實際需求選擇合適的調用方式:
  • 非流式調用:針對本地檔案進行識別,並一次性返回完整的處理結果。適合處理錄製好的音頻。
  • 雙向流式調用:可直接對音頻流進行識別,並即時輸出結果。音頻流可以來自外部裝置(如麥克風)或從本地檔案讀取。適合需要即時反饋的情境。
  • 非流式調用
  • 雙向流式調用:基於回調
  • 雙向流式調用:基於Flowable
提交單個語音即時轉寫任務,通過傳入本地檔案的方式同步阻塞地拿到轉寫結果。執行個體化Recognition類,調用call方法綁定請求參數和待識別檔案,進行識別並最終擷取識別結果。
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) {
        // 以下為新加坡地區的配置,調用時請將"{WorkspaceId}"替換為真實的業務空間ID,各地區的配置不同。
        Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference";
        // 建立Recognition執行個體
        Recognition recognizer = new Recognition();
        // 建立RecognitionParam
        RecognitionParam param =
                RecognitionParam.builder()
                        .model("qwen-audio-3.0-asr-flash-streaming")
                        // 新加坡地區和北京地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/zh/model-studio/get-api-key
                        // 若沒有配置環境變數,請用百鍊API Key將下行替換為:.apiKey("sk-xxx")
                        .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                        .format("wav")
                        .sampleRate(16000)
                        //.parameter("language_hints", new String[]{"zh"})
                        .build();

        try {
            System.out.println("識別結果:" + recognizer.call(param, new File("{YOUR_AUDIO_FILE}")));
        } 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);
    }
}

高並發調用

在DashScope Java SDK中,採用了OkHttp3的串連池技術,以減少重複建立串連的開銷。詳情請參見高並發最佳實務。

介面地址

SDK的介面地址需在初始化前設定為下方地址(包含WorkspaceId)。如需切換到其他地區,請修改 Constants.baseWebsocketApiUrl為對應地區的URL。
  • 新加坡
  • 華北2(北京)
wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference調用時請將{WorkspaceId}替換為真實的Workspace ID。
切換到新加坡地區:
import com.alibaba.dashscope.utils.Constants;

// 調用時請將"{WorkspaceId}"替換為真實的業務空間ID
Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference";
阿里雲百鍊為華北2(北京)、新加坡地區推出了業務空間專屬網域名稱,能夠為推理請求提供卓越的效能和更高的穩定性,建議遷移至新網域名稱:
  • 華北2(北京)地區:從 dashscope.aliyuncs.com 遷移至 {WorkspaceId}.cn-beijing.maas.aliyuncs.com
  • 新加坡地區:從 dashscope-intl.aliyuncs.com 遷移至 {WorkspaceId}.ap-southeast-1.maas.aliyuncs.com

請求參數

通過RecognitionParam的鏈式方法配置模型、採樣率、音頻格式等參數。配置完成的參數對象傳入Recognition類的call/streamCall方法中使用。
RecognitionParam param = RecognitionParam.builder()
  .model("qwen-audio-3.0-asr-flash-streaming")
  .format("pcm")
  .sampleRate(16000)
  //.parameter("language_hints", new String[]{"zh"})
  .build();
參數類型是否必須說明
modelString是模型名稱。
sampleRateInteger是採樣率(Hz),支援任意採樣率。
formatString是音頻格式。取值範圍:
  • pcm
  • wav
  • mp3
  • opus
  • speex
  • aac
  • amr
opus/speex:必須使用Ogg封裝;wav:必須為PCM編碼;amr:僅支援AMR-NB類型。
keep_dialectboolean否
僅適用於 qwen-audio-3.1-asr-flash-streaming。
預設為 false,將方言轉寫為普通話文本。設為 true 時保留方言表達。 透過 .parameter("keep_dialect", value) 設定。
vad_modelString否
僅適用於 qwen-audio-3.1-asr-flash-streaming。
VAD 模型。取值為 near_meeting_16k(近場)或 far_field_meeting_16k(遠場,預設值)。 透過 .parameter("vad_model", value) 設定。
vocabularyIdString否先行編譯熱詞列表 ID。需預先調用建立熱詞列表介面產生,識別時傳入該 ID 即可使用列表中的熱詞。適用於詞彙已知且相對穩定、需要跨請求複用同一詞表的情境。使用方法請參見先行編譯熱詞。
vocabularyMap<String, Integer>否即時熱詞。以索引值對形式傳入,鍵為熱詞文本(string),值為熱詞權重(integer),無需預先建立熱詞列表。權重取值範圍為 [1, 5] 或 50:取 [1, 5] 時值越大模型越傾向輸出該詞;取 50 時為超級熱詞,召回率大幅提升,但超級熱詞數量最多不超過 50 個。適用於臨時性、會話層級的熱詞最佳化。與先行編譯熱詞同時配置時,僅即時熱詞生效。使用方法請參見即時熱詞。vocabulary需要通過 RecognitionParam 執行個體的 parameter 方法或者 parameters 方法進行設定:
Map<String, Integer> vocab = new HashMap<>();
vocab.put("張三", 5);
vocab.put("李四", 5);

RecognitionParam param = RecognitionParam.builder()
        .model("qwen-audio-3.0-asr-flash-streaming")
        .format("pcm")
        .sampleRate(16000)
        .parameter("vocabulary", vocab)
        .build();
max_sentence_silenceInteger否VAD 斷句靜音閾值(ms)。當一段語音後的靜音時間長度超過該閾值時,系統會判定該句子已結束。預設值:800。取值範圍:[200, 6000]。max_sentence_silence需要通過RecognitionParam執行個體的parameter方法或者parameters方法進行設定:
RecognitionParam param = RecognitionParam.builder()
 .model("qwen-audio-3.0-asr-flash-streaming")
 .format("pcm")
 .sampleRate(16000)
 .parameter("max_sentence_silence", 800)
 .build();
multi_threshold_mode_enabledboolean否是否啟用多閾值模式。啟用後可防止 VAD 斷句切割過長。預設值:false。multi_threshold_mode_enabled需要通過RecognitionParam執行個體的parameter方法或者parameters方法進行設定:
RecognitionParam param = RecognitionParam.builder()
 .model("qwen-audio-3.0-asr-flash-streaming")
 .format("pcm")
 .sampleRate(16000)
 .parameter("multi_threshold_mode_enabled", true)
 .build();
punctuation_prediction_enabledboolean否設定是否在識別結果中自動添加標點:
  • true(預設):是,不支援修改。
punctuation_prediction_enabled需要通過RecognitionParam執行個體的parameter方法或者parameters方法進行設定:
RecognitionParam param = RecognitionParam.builder()
 .model("qwen-audio-3.0-asr-flash-streaming")
 .format("pcm")
 .sampleRate(16000)
 .parameter("punctuation_prediction_enabled", false)
 .build();
heartbeatboolean否是否啟用心跳包。預設值:false。
  • true:在持續發送靜音音訊情況下,可保持與服務端的串連不中斷。
  • false(預設):即使持續發送靜音音頻,串連也將在一定時間後因逾時而斷開。
靜音音頻指的是在音頻檔案或資料流中沒有聲音訊號的內容。靜音音頻可以通過多種方法產生,例如使用音頻編輯軟體如Audacity或Adobe Audition,或者通過命令列工具如FFmpeg。
使用該欄位時,SDK版本不能低於2.19.1。
heartbeat需要通過RecognitionParam執行個體的parameter方法或者parameters方法進行設定:
RecognitionParam param = RecognitionParam.builder()
 .model("qwen-audio-3.0-asr-flash-streaming")
 .format("pcm")
 .sampleRate(16000)
 .parameter("heartbeat", true)
 .build();
language_hintsString[]否待識別音頻語種。無預設值,不設定時模型自動識別。最多支援設定 4 個值,超出時僅前 4 個生效。
  • zh: 中文
  • en: 英文
  • ja: 日語
  • ko:韓語
  • vi:越南語
  • th:泰語
  • id:印尼語
  • ms:馬來語
  • tl:菲律賓語
  • hi:印地語
  • ar:阿拉伯語
  • fr:法語
  • de:德語
  • es:西班牙語
  • pt:葡萄牙語
  • ru:俄語
  • it:意大利語
  • nl:荷蘭語
  • sv:瑞典語
  • da:丹麥語
  • fi:芬蘭語
  • no:挪威語
  • el:希臘語
  • pl:波蘭語
  • cs:捷克語
  • hu:匈牙利語
  • ro:羅馬尼亞語
  • bg:保加利亞語
  • hr:克羅地亞語
  • sk:斯洛伐克語
language_hints需要通過RecognitionParam執行個體的parameter方法或者parameters方法進行設定:
RecognitionParam param = RecognitionParam.builder()
 .model("qwen-audio-3.0-asr-flash-streaming")
 .format("pcm")
 .sampleRate(16000)
 .parameter("language_hints", new String[]{"zh"})
 .build();
speech_noise_thresholdfloat否語音與噪音的判定閾值,用於調整語音活動檢測(VAD)的靈敏度。取值範圍:[-1.0, 1.0]。取值說明:
  • 取值越接近 -1:降低噪音判定閾值,噪音被識別為語音的機率增大,可能導致更多噪音被轉寫
  • 取值越接近 +1:提高噪音判定閾值,語音被誤判為噪音的機率增大,可能導致部分語音被過濾
此參數為進階配置參數,調整可能顯著影響識別效果,建議:
  • 調整前充分測實驗證效果
  • 根據實際音頻環境小幅度調整(建議步長 0.1)
speech_noise_threshold需要通過RecognitionParam執行個體的parameter方法或者parameters方法進行設定:
RecognitionParam param = RecognitionParam.builder()
 .model("qwen-audio-3.0-asr-flash-streaming")
 .format("pcm")
 .sampleRate(16000)
 .parameter("speech_noise_threshold", -0.5)
 .build();
special_word_filterString否指定在語音辨識過程中需要處理的敏感詞,並支援對不同敏感詞設定不同的處理方式。詳情請參見敏感詞過濾。special_word_filter需要通過RecognitionParam執行個體的parameter方法或者parameters方法進行設定:
// 1. 構建最外層對象
JSONObject root = new JSONObject();
root.put("system_reserved_filter", true);

// 2. 構建“從結果中完全移除”的配置
JSONObject root1 = new JSONObject();
JSONArray array1 = new JSONArray();
array1.put("開始");
array1.put("進行");
root1.put("word_list", array1);

// 3. 構建“替換為等長 *”的配置
JSONObject root2 = new JSONObject();
JSONArray array2 = new JSONArray();
array2.put("測試");
root2.put("word_list", array2);

// 4. 組裝
root.put("filter_with_empty", root1);
root.put("filter_with_signed", root2);

RecognitionParam param = RecognitionParam.builder()
 .model("qwen-audio-3.0-asr-flash-streaming")
 .format("pcm")
 .sampleRate(16000)
 .parameter("special_word_filter", root.toString())
 .build();
inputMap<String, Object>否輸入對象,用於傳入對話上下文(context)。上下文用於輔助識別、提升專有詞彙的識別準確率。使用方法詳見快速開始。Map 中需包含 context 鍵,值為 List<Map<String, Object>> 類型的訊息數組,每條訊息包含以下欄位:
  • role(String,必選):訊息角色。user 表示前幾輪使用者語音的識別結果或領域相關的詞表;assistant 表示前幾輪大語言模型的回複內容。
  • content(List<Map>,必選):訊息內容列表。每個元素包含 type(String,role 為 user 時填 input_text,role 為 assistant 時填 text)和 text(String,常值內容)。
約束:上下文訊息(input_text 和 text 類型)各最多 5 條,超出時保留最近的 5 條。每輪上下文文本總長度不超過 400 個字元,超出部分從末尾截斷。
攜帶上下文時,context 中的訊息順序有要求:上下文訊息必須按對話輪次排列,每輪中 user(input_text 類型)必須在對應的 assistant(text 類型)之前。
使用該欄位時,SDK版本不能低於2.22.23。
input通過RecognitionParam執行個體的input方法進行設定:
// 1. 構建 input 結構體
Map<String, Object> userContent = new HashMap<>();
userContent.put("type", "input_text");
userContent.put("text", "你好啊");

Map<String, Object> assistantContent = new HashMap<>();
assistantContent.put("type", "text");
assistantContent.put("text", "你好啊,我是通義千問,有什麼可以協助你的?");

Map<String, Object> userMessage = new HashMap<>();
userMessage.put("role", "user");
userMessage.put("content", Arrays.asList(userContent));

Map<String, Object> assistantMessage = new HashMap<>();
assistantMessage.put("role", "assistant");
assistantMessage.put("content", Arrays.asList(assistantContent));

Map<String, Object> input = new HashMap<>();
input.put("context", Arrays.asList(userMessage, assistantMessage));

// 2. 通過 input 方法傳入
RecognitionParam param = RecognitionParam.builder()
 .model("qwen-audio-3.0-asr-flash-streaming")
 .format("pcm")
 .sampleRate(16000)
 .input(input)
 .build();
apiKeyString否使用者API Key。

關鍵介面

Recognition類

Recognition通過import com.alibaba.dashscope.audio.asr.recognition.Recognition;方式引入。它的關鍵介面如下:
介面/方法參數傳回值描述
public void call(RecognitionParam param, final ResultCallback<RecognitionResult> callback)
  • param:請求參數
  • callback:回調介面(ResultCallback)
無基於回調形式的流式即時識別,該方法不會阻塞當前線程。
public String call(RecognitionParam param, File file)
  • param:請求參數
  • 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集合返回字時間戳記資訊。

字時間戳記資訊(Word)

介面/方法參數傳回值描述
public long getBeginTime()
無字開始時間,單位為ms返回字開始時間。
public long getEndTime()
無字結束時間,單位為ms返回字結束時間。
public String getText()
無字返回識別的字。
public String getPunctuation()
無標點返回標點。

錯誤碼

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

常見問題

功能特性

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:如何識別本地檔案(錄音檔案)?

識別本地檔案有兩種方式:
  • 直接傳入本地檔案路徑:此種方式在最終識別結束後擷取完整識別結果,不適合即時反饋的情境。 參見非流式調用,在Recognition類的call方法中傳入檔案路徑對錄音檔案直接進行識別。
  • 將本地檔案轉成二進位流進行識別:此種方式一邊識別檔案一邊流式擷取識別結果,適合即時反饋的情境。
    • 參見雙向流式調用:基於回調,通過Recognition類的sendAudioFrame方法向服務端發送二進位流對其進行識別。
    • 參見雙向流式調用:基於Flowable,通過Recognition類的streamCall方法向服務端發送二進位流對其進行識別。

故障排查

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
  1. 請檢查language_hints設定的語言是否與音頻實際語言一致。 例如:音頻實際為中文,但language_hints設定為en(英文)。
  2. 若以上檢查均無問題,可通過定製熱詞提升對特定詞語的識別效果。