本文介紹Fun-ASR-Realtime即時語音辨識Java SDK的參數和介面細節。
前提條件
已開通服務並擷取與配置 API Key。請配置API Key到環境變數,而非寫入程式碼在代碼中,防範因代碼泄露導致的安全風險。
快速開始
Recognition類提供了非流式調用和雙向流式調用等介面。請根據實際需求選擇合適的調用方式:
- 非流式調用:針對本地檔案進行識別,並一次性返回完整的處理結果。適合處理錄製好的音頻。
- 雙向流式調用:可直接對音頻流進行識別,並即時輸出結果。音頻流可以來自外部裝置(如麥克風)或從本地檔案讀取。適合需要即時反饋的情境。
非流式調用
提交單個語音即時轉寫任務,通過傳入本地檔案的方式同步阻塞地拿到轉寫結果。
執行個體化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("fun-asr-realtime")
// 新加坡地區和北京地區的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);
}
}
雙向流式調用:基於回調
提交單個語音即時轉寫任務,通過實現回調介面的方式流式輸出即時識別結果。
-
啟動流式語音辨識
執行個體化Recognition類,調用
call方法綁定請求參數和回調介面(ResultCallback)並啟動流式語音辨識。 -
串流
迴圈調用Recognition類的
sendAudioFrame方法,將從本地檔案或裝置(如麥克風)讀取的二進位音頻流分段發送至服務端。在發送音頻資料的過程中,服務端會通過回調介面(ResultCallback)的
onEvent方法,將識別結果即時返回給用戶端。建議每次發送的音頻時間長度約為100毫秒,資料大小保持在1KB至16KB之間。
-
結束處理
調用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 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 {
// 以下為新加坡地區的配置,調用時請將"{WorkspaceId}"替換為真實的業務空間ID,各地區的配置不同。
Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.ap-southeast-1.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()
.model("fun-asr-realtime")
// 新加坡地區和北京地區的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("pcm")
.sampleRate(16000)
.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());
}
}
import com.alibaba.dashscope.api.GeneralApi;
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.base.HalfDuplexParamBase;
import com.alibaba.dashscope.common.GeneralListParam;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.protocol.GeneralServiceOption;
import com.alibaba.dashscope.protocol.HttpMethod;
import com.alibaba.dashscope.protocol.Protocol;
import com.alibaba.dashscope.protocol.StreamingMode;
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.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 {
// 以下為新加坡地區的配置,調用時請將"{WorkspaceId}"替換為真實的業務空間ID,各地區的配置不同。
Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference";
// 實際應用中,該方法僅在程式最開始執行一次即可,不必多次執行該方法。
warmUp();
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);
}
public static void warmUp() {
try {
// Lightweight GET request to establish connection
GeneralServiceOption warmupOption = GeneralServiceOption.builder()
.protocol(Protocol.HTTP)
.httpMethod(HttpMethod.GET)
.streamingMode(StreamingMode.OUT)
.path("assistants")
.build();
warmupOption.setBaseHttpUrl(Constants.baseHttpApiUrl);
GeneralApi<HalfDuplexParamBase> api = new GeneralApi<>();
api.get(GeneralListParam.builder().limit(1L).build(), warmupOption);
} catch (Exception e) {
// Reset flag to allow retry if pre-warming failed
}
}
}
class RealtimeRecognitionTask implements Runnable {
private Path filepath;
public RealtimeRecognitionTask(Path filepath) {
this.filepath = filepath;
}
@Override
public void run() {
RecognitionParam param = RecognitionParam.builder()
.model("fun-asr-realtime")
// 新加坡地區和北京地區的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)
.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());
byte[] allData = new byte[fis.available()];
int ret = fis.read(allData);
fis.close();
int sendFrameLength = 3200;
for (int i = 0; i * sendFrameLength < allData.length; i ++) {
int start = i * sendFrameLength;
int end = Math.min(start + sendFrameLength, allData.length);
ByteBuffer byteBuffer = ByteBuffer.wrap(allData, start, end - start);
recognizer.sendAudioFrame(byteBuffer);
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 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 {
// 以下為新加坡地區的配置,調用時請將"{WorkspaceId}"替換為真實的業務空間ID,各地區的配置不同。
Constants.baseWebsocketApiUrl = "wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference";
// 建立一個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()
.model("fun-asr-realtime")
// 新加坡地區和北京地區的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("pcm")
.sampleRate(16000)
.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的串連池技術,以減少重複建立串連的開銷。詳情請參見高並發最佳實務。
介面地址
SDK的介面地址需在初始化前設定為下方地址(包含WorkspaceId)。如需切換到其他地區,請修改 Constants.baseWebsocketApiUrl為對應地區的URL。
新加坡
wss://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api-ws/v1/inference
調用時請將{WorkspaceId}替換為真實的Workspace ID。
華北2(北京)
wss://{WorkspaceId}.cn-beijing.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("fun-asr-realtime")
.format("pcm")
.sampleRate(16000)
//.parameter("language_hints", new String[]{"zh"})
.build();
| 參數 | 類型 | 是否必須 | 說明 |
|---|---|---|---|
model | String | 是 | 模型名稱。 |
sampleRate | Integer | 是 | 採樣率(Hz)。 取值範圍:8k模型僅支援 8000 Hz,其他模型支援任意採樣率。 |
format | String | 是 | 音頻格式。 取值範圍:
重要opus/speex:必須使用Ogg封裝; wav:必須為PCM編碼; amr:僅支援AMR-NB類型。 |
vocabularyId | String | 否 | 先行編譯熱詞列表 ID。 需預先調用建立熱詞列表介面產生,識別時傳入該 ID 即可使用列表中的熱詞。 適用於詞彙已知且相對穩定、需要跨請求複用同一詞表的情境。 使用方法請參見先行編譯熱詞。 |
semantic_punctuation_enabled | boolean | 否 | 是否啟用語義斷句。 預設值:false。
語義斷句準確性更高,適合會議轉寫情境;VAD(Voice Activity Detection,語音活動檢測)斷句延遲較低,適合互動情境。
|
max_sentence_silence | Integer | 否 | VAD 斷句靜音閾值(ms)。當一段語音後的靜音時間長度超過該閾值時,系統會判定該句子已結束。當 預設值:1300。 取值範圍:[200, 6000]。
|
multi_threshold_mode_enabled | boolean | 否 | 重要僅在 是否啟用多閾值模式。啟用後可防止 VAD 斷句切割過長。 預設值:false。
|
punctuation_prediction_enabled | boolean | 否 | 設定是否在識別結果中自動添加標點:
|
heartbeat | boolean | 否 | 是否啟用心跳包。 預設值:false。
靜音音頻指的是在音頻檔案或資料流中沒有聲音訊號的內容。靜音音頻可以通過多種方法產生,例如使用音頻編輯軟體如Audacity或Adobe Audition,或者通過命令列工具如FFmpeg。 說明使用該欄位時,SDK版本不能低於2.19.1。
|
language_hints | String[] | 否 | 待識別音頻語種。無預設值,不設定時模型自動識別。 僅支援設定 1 個值,設定多個時僅第一個生效。 點擊查看支援的語言代碼
|
speech_noise_threshold | float | 否 | 語音與噪音的判定閾值,用於調整語音活動檢測(VAD)的靈敏度。 取值範圍:[-1.0, 1.0]。 取值說明:
此參數為進階配置參數,調整可能顯著影響識別效果,建議:
|
special_word_filter | String | 否 | 指定在語音辨識過程中需要處理的敏感詞,並支援對不同敏感詞設定不同的處理方式。詳情請參見敏感詞過濾。
|
input | Map<String, Object> | 否 | 輸入對象,用於傳入對話上下文(context)。上下文用於輔助識別、提升專有詞彙的識別準確率。使用方法詳見快速開始。 重要僅 Map 中需包含
重要約束:上下文訊息( 重要攜帶上下文時, 說明使用該欄位時,SDK版本不能低於2.22.23。
|
apiKey | String | 否 | 使用者API Key。 |
關鍵介面
Recognition類
Recognition通過import com.alibaba.dashscope.audio.asr.recognition.Recognition;方式引入。它的關鍵介面如下:
| 介面/方法 | 參數 | 傳回值 | 描述 |
|---|---|---|---|
|
| 無 | 基於回調形式的流式即時識別,該方法不會阻塞當前線程。 |
|
| 識別結果 | 基於本地檔案的非流式調用,該方法會阻塞當前線程直到全部音頻讀完,該方法要求所識別檔案具有可讀許可權。 |
|
|
| 基於Flowable的流式即時識別。 |
|
| 無 | 推送音頻,每次推送的音頻流不宜過大或過小,建議每包音頻時間長度為100ms左右,大小在1KB~16KB之間。 識別結果通過回調介面(ResultCallback)的onEvent方法擷取。 |
| 無 | 無 | 停止即時識別。 該方法會阻塞當前線程,直到回調執行個體 |
| code: WebSocket關閉碼(Close Code) reason:關閉原因 這兩個參數可參考The WebSocket Protocol文檔進行配置 | true | 在任務結束後,無論是否出現異常都需要關閉WebSocket串連,避免造成串連泄漏。關於如何複用串連提升效率請參考即時語音辨識高並發情境。 |
| 無 | requestId | 擷取當前任務的requestId,在調用 說明該方法自2.18.0版本及以後的SDK中才開始提供。 |
| 無 | 首包延遲 | 擷取首包延遲,從發送第一包音頻到收到首包識別結果延遲,在任務完成後使用。 說明該方法自2.18.0版本及以後的SDK中才開始提供。 |
| 無 | 尾包延遲 | 獲得尾包延遲,發送 說明該方法自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());
}
};
| 介面/方法 | 參數 | 傳回值 | 描述 |
|---|---|---|---|
|
| 無 | 當服務有回複時會被回調。 |
| 無 | 無 | 任務完成後該介面被回調。 |
|
| 無 | 發生異常時該介面被回調。 |
響應結果
即時識別結果(RecognitionResult)
RecognitionResult代表一次即時識別的結果。
| 介面/方法 | 參數 | 傳回值 | 描述 |
|---|---|---|---|
| 無 | requestId | 擷取requestId。 |
| 無 | 是否是完整句子,即產生斷句 | 判斷給定句子是否已經結束。 |
| 無 | 擷取單句資訊,包括時間戳記和文本資訊等。 |
單句資訊(Sentence)
| 介面/方法 | 參數 | 傳回值 | 描述 |
|---|---|---|---|
| 無 | 句子開始時間,單位為ms | 返回句子開始時間。 |
| 無 | 句子結束時間,單位為ms | 返回句子結束時間。 |
| 無 | 識別文本 | 返回識別文本。 |
| 無 | 字時間戳記資訊(Word)的List集合 | 返回字時間戳記資訊。 |
字時間戳記資訊(Word)
| 介面/方法 | 參數 | 傳回值 | 描述 |
|---|---|---|---|
| 無 | 字開始時間,單位為ms | 返回字開始時間。 |
| 無 | 字結束時間,單位為ms | 返回字結束時間。 |
| 無 | 字 | 返回識別的字。 |
| 無 | 標點 | 返回標點。 |
錯誤碼
如遇報錯問題,請參見錯誤碼進行排查。
若問題仍未解決,請加入開發人員群反饋遇到的問題,並提供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方法向服務端發送二進位流對其進行識別。
- 參見雙向流式調用:基於回調,通過Recognition類的
故障排查
Q:無法識別語音(無識別結果)是什麼原因?
-
請檢查請求參數中的音頻格式(
format)和採樣率(sampleRate/sample_rate)設定是否正確且符合參數約束。以下為常見錯誤樣本:- 音頻副檔名為 .wav,但實際為 MP3 格式,而請求參數
format設定為 mp3(參數設定錯誤)。 - 音頻採樣率為 3600Hz,但請求參數
sampleRate/sample_rate設定為 48000(參數設定錯誤)。
可以使用ffprobe工具擷取音訊容器、編碼、採樣率、聲道等資訊:
- 音頻副檔名為 .wav,但實際為 MP3 格式,而請求參數
ffprobe -v error -show_entries format=format_name -show_entries stream=codec_name,sample_rate,channels -of default=noprint_wrappers=1 input.xxx
-
請檢查
language_hints設定的語言是否與音頻實際語言一致。例如:音頻實際為中文,但
language_hints設定為en(英文)。 -
若以上檢查均無問題,可通過定製熱詞提升對特定詞語的識別效果。