本文介紹了如何使用阿里云智能語音服務提供的Android NUI SDK,包括SDK下載安裝、關鍵接口及代碼示例。
前提條件
下載安裝
下載SDK。
重要請下載后在樣例初始化代碼中替換您的阿里云賬號信息、Appkey和Token才可運行。
對象
說明
SDK名稱
智能語音交互移動端SDK
開發者
阿里云計算有限公司
SDK版本
2.6.3-01B
SDK包名
com.alibaba.idst.nui
SDK更新時間
2024-12-19
SDK大小
MinSizeRel/nuisdk-release.aar
7.2MB
RelWithDebugInfo/nuisdk-release.aar
9.7MB
SDK MD5值
MinSizeRel/nuisdk-release.aar
c8e84d882a776797179b07cb55325a17
RelWithDebugInfo/nuisdk-release.aar
3bd1e2c2423c23e6522b7bc3ac072ec9
隱私政策
SDK整合包下載
類別
兼容范圍
系統
支持Android 4.0 以上版本,API LEVEL 14
架構
armeabi-v7a,arm64-v8a,x86,x86_64
此SDK還包含如下功能,若未支持您想要的功能,請前往對應文檔獲取SDK。
功能
是否支持
一句話識別
是
實時語音識別
是
語音合成
是
實時長文本語音合成
是
流式文本語音合成
是
離線語音合成
否
錄音文件識別極速版
是
喚醒及命令詞
否
聽悟實時推流
是
解壓ZIP包,在
app/libs
目錄下獲取AAR格式的SDK包,將AAR包集成到您的工程項目中進行依賴。如果需要Android CPP接入方式,可在ZIP包的android_libs和android_include中獲得動態庫和頭文件。使用Android Studio打開此工程查看參考代碼實現,其中實時語音識別示例代碼為SpeechTranscriberActivity.java文件,替換Appkey和Token后可直接運行。
SDK關鍵接口
initialize:初始化SDK。
/** * 初始化SDK,SDK為單例,請先釋放后再次進行初始化。請勿在UI線程調用,可能會引起阻塞。 * @param callback:事件監聽回調,參見下文具體回調。 * @param parameters:json string形式的初始化參數,參見下方說明或接口說明:http://bestwisewords.com/document_detail/173528.html。 * @param level:log打印級別,值越小打印越多。 * @param save_log:是否保存log為文件,存儲目錄為ticket中的debug_path字段值。注意,log文件無上限,請注意持續存儲導致磁盤存滿。 * @return:參見錯誤碼:http://bestwisewords.com/document_detail/459864.html。 */ public synchronized int initialize(final INativeNuiCallback callback, String parameters, final Constants.LogLevel level, final boolean save_log)
其中,INativeNuiCallback類型包含如下回調。
onNuiAudioStateChanged:根據音頻狀態進行錄音功能的開關。
/** * 當start/stop/cancel等接口調用時,SDK通過此回調通知App進行錄音的開關操作。 * @param state:錄音需要的狀態(打開/關閉) */ void onNuiAudioStateChanged(AudioState state);
onNuiNeedAudioData:在回調中提供音頻數據。
/** * 開始識別時,此回調被連續調用,App需要在回調中進行語音數據填充。 * @param buffer:填充語音的存儲區。 * @param len:需要填充語音的字節數。 * @return:實際填充的字節數。 */ int onNuiNeedAudioData(byte[] buffer, int len);
onNuiEventCallback:SDK事件回調。
/** * SDK主要事件回調 * @param event:回調事件,參見如下事件列表。 * @param resultCode:參見錯誤碼,在出現EVENT_ASR_ERROR事件時有效。 * @param arg2:保留參數。 * @param kwsResult:語音喚醒功能(暫不支持)。 * @param asrResult:語音識別結果。 */ void onNuiEventCallback(NuiEvent event, final int resultCode, final int arg2, KwsResult kwsResult, AsrResult asrResult);
onNuiAudioRMSChanged:音頻能量值回調。
/** * 音頻能量值回調 * @param val: 音頻數據能量值回調,范圍-160至0,一般用于UI展示語音動效 */ public void onNuiAudioRMSChanged(float val);
事件列表:
名稱
說明
EVENT_VAD_START
檢測到人聲起點。
EVENT_VAD_END
檢測到人聲尾點。
EVENT_ASR_PARTIAL_RESULT
語音識別中間結果。
EVENT_ASR_ERROR
根據錯誤碼信息判斷出錯原因。
EVENT_MIC_ERROR
錄音錯誤,表示SDK連續2秒未收到任何音頻,可檢查錄音系統是否正常。
EVENT_SENTENCE_START
實時語音識別事件,表示檢測到一句話開始。
EVENT_SENTENCE_END
實時語音識別事件,表示檢測到一句話結束,返回一句完整的結果。
EVENT_SENTENCE_SEMANTICS
暫不使用。
EVENT_TRANSCRIBER_COMPLETE
停止語音識別后最終事件。
setParams:以JSON格式設置SDK參數。
/** * 以JSON格式設置參數 * @param params:參見接口說明:http://bestwisewords.com/document_detail/173528.html。 * @return:參見錯誤碼:http://bestwisewords.com/document_detail/459864.html。 */ public synchronized int setParams(String params);
startDialog:開始識別。
/** * 開始識別 * @param vad_mode:多種模式,對于識別場景,請使用P2T。 * @param dialog_params:json string形式的對話參數,參見接口說明:http://bestwisewords.com/document_detail/173528.html。 * @return:參見錯誤碼:http://bestwisewords.com/document_detail/459864.html。 */ public synchronized int startDialog(VadMode vad_mode, String dialog_params);
stopDialog:結束識別。
/** * 結束識別,調用該接口后,服務端將返回最終識別結果并結束任務。 * @return:參見錯誤碼:http://bestwisewords.com/document_detail/459864.html。 */ public synchronized int stopDialog();
cancelDialog:立即結束識別。
/** * 立即結束識別,調用該接口后,不等待服務端返回最終識別結果就立即結束任務。 * @return:參見錯誤碼:http://bestwisewords.com/document_detail/459864.html。 */ public synchronized int cancelDialog();
release:釋放SDK。
/** * 釋放SDK資源 * @return:參見錯誤碼:http://bestwisewords.com/document_detail/459864.html。 */ public synchronized int release();
GetVersion:獲得當前SDK版本信息。
/** * 獲得當前SDK版本信息 * @return: 字符串形式的SDK版本信息 */ public synchronized String GetVersion();
調用步驟
初始化SDK、錄音實例。
根據業務需求設置參數。
調用startDialog開始識別。
根據音頻狀態回調onNuiAudioStateChanged,打開錄音機。
在onNuiNeedAudioData回調中提供錄音數據。
在EVENT_SENTENCE_START事件回調中表示當前開始識別一個句子,在EVENT_ASR_PARTIAL_RESULT事件回調中獲取識別中間結果,在EVENT_SENTENCE_END事件回調中獲得這句話完整的識別結果和各相關信息。
調用stopDialog結束識別。并從EVENT_TRANSCRIBER_COMPLETE事件回調確認已停止識別。
結束調用,使用release接口釋放SDK資源。
Proguard配置
如果代碼使用了混淆,請在proguard-rules.pro中配置:
-keep class com.alibaba.idst.nui.*{*;}
代碼示例
您如果有多例需求,也可以直接new對象進行使用。也可采用GetInstance獲得單例。
NUI SDK初始化
//這里獲得資源路徑, 即工作路徑
// 內部通過context.getApplicationContext().getFilesDir().toString() + "/asr_my" 創建工作路徑,
// 例如 /data/user/0/mit.alibaba.nuidemo/files/asr_my
String workspace = CommonUtils.getModelPath(this);
//創建debug路徑
String debug_path = getExternalCacheDir().getAbsolutePath() + "/debug_" + System.currentTimeMillis();
Utils.createDir(debug_path);
//從nuisdk.aar中assets資源拷貝到workspace中
CommonUtils.copyAssetsData(this);
//初始化SDK,注意用戶需要在genInitParams中填入相關ID信息才可以使用。
NativeNui nui_instance = new NativeNui();
int ret = nui_instance.initialize(this, genInitParams(asset_path,debug_path), Constants.LogLevel.LOG_LEVEL_VERBOSE, true);
其中,genInitParams生成為String JSON字符串,包含資源目錄和用戶信息。其中用戶信息包含如下字段。
private String genInitParams(String workpath, String debugpath) {
String str = "";
try{
//獲取賬號訪問憑證:
// getTicket為示例工程中提供了多種可能的方式,請選擇適合自身業務的安全方式
//
//注意:
// 語音交互服務需要先準備好賬號,并開通相關服務。具體步驟請查看:
// http://bestwisewords.com/zh/isi/getting-started/start-here
//
//原始賬號:
// 賬號(子賬號)信息主要包括AccessKey ID(后續簡稱為ak_id)和AccessKey Secret(后續簡稱為ak_secret)。
// 此賬號信息一定不可存儲在app代碼中或移動端側,以防賬號信息泄露造成資費損失。
//
//STS臨時憑證:
// 由于賬號信息下發給客戶端存在泄露的可能,阿里云提供的一種臨時訪問權限管理服務STS(Security Token Service)。
// STS是由賬號信息ak_id和ak_secret,通過請求生成臨時的sts_ak_id/sts_ak_secret/sts_token
// (為了區別原始賬號信息和STS臨時憑證, 命名前綴sts_表示STS生成的臨時憑證信息)
//什么是STS:http://bestwisewords.com/zh/ram/product-overview/what-is-sts
//STS SDK概覽:http://bestwisewords.com/zh/ram/developer-reference/sts-sdk-overview
//STS Python SDK調用示例:http://bestwisewords.com/zh/ram/developer-reference/use-the-sts-openapi-example
//
//賬號需求說明:
// 若使用離線功能(離線語音合成、喚醒), 則必須app_key、ak_id和ak_secret,或app_key、sts_ak_id、sts_ak_secret和sts_token
// 若使用在線功能(語音合成、實時轉寫、一句話識別、錄音文件轉寫等), 則只需app_key和token
JSONObject object = Auth.getTicket(Auth.GetTicketMethod.GET_TOKEN_FROM_SERVER_FOR_ONLINE_FEATURES);
if (!object.containsKey("token")) {
Log.e(TAG, "Cannot get token!!!");
}
object.put("device_id", Utils.getDeviceId()); // 必填, 推薦填入具有唯一性的id, 方便定位問題
object.put("url", "wss://nls-gateway.cn-shanghai.aliyuncs.com:443/ws/v1"); // 默認
object.put("workspace", workpath); // 必填, 且需要有讀寫權限
//當初始化SDK時的save_log參數取值為true時,該參數生效。表示是否保存音頻debug,該數據保存在debug目錄中,需要確保debug_path有效可寫。
//object.put("save_wav", "true");
//debug目錄,當初始化SDK時的save_log參數取值為true時,該目錄用于保存中間音頻文件。
object.put("debug_path", debugpath);
object.put("service_mode", Constants.ModeFullCloud); // 必填
str = object.toString();
} catch (JSONException e) {
e.printStackTrace();
}
Log.i(TAG, "InsideUserContext:" + str);
return str;
}
參數設置
以JSON字符串形式進行設置。
//設置相關識別參數,具體參考API文檔
// initialize()之后startDialog之前調用
nui_instance.setParams(genParams());
private String genParams() {
String params = "";
try {
JSONObject nls_config = new JSONObject();
nls_config.put("enable_intermediate_result", true);
// 參數可根據實際業務進行配置
// 接口說明可見http://bestwisewords.com/document_detail/173528.html
// 查看 2.開始識別
// nls_config.put("enable_punctuation_prediction", true);
// nls_config.put("enable_inverse_text_normalization", true);
// nls_config.put("max_sentence_silence", 800);
// nls_config.put("enable_words", false);
// nls_config.put("sample_rate", 16000);
// nls_config.put("sr_format", "opus");
/*若文檔中不包含某些參數,但是此功能支持這個參數,可以用如下萬能接口設置參數*/
// JSONObject extend_config = new JSONObject();
// extend_config.put("custom_test", true);
// nls_config.put("extend_config", extend_config);
JSONObject parameters = new JSONObject();
parameters.put("nls_config", nls_config);
parameters.put("service_type", Constants.kServiceTypeSpeechTranscriber); // 必填
//如果有HttpDns則可進行設置
//parameters.put("direct_ip", Utils.getDirectIp());
params = parameters.toString();
} catch (JSONException e) {
e.printStackTrace();
}
return params;
}
開始識別
通過startDialog接口開啟監聽。
nui_instance.startDialog(Constants.VadMode.TYPE_P2T, genDialogParams());
private String genDialogParams() {
String params = "";
try {
JSONObject dialog_param = new JSONObject();
//運行過程中可以在startDialog時更新參數,尤其是更新過期token
//dialog_param.put("token", "");
params = dialog_param.toString();
} catch (JSONException e) {
e.printStackTrace();
}
return params;
}
回調處理
onNuiAudioStateChanged:錄音狀態回調,SDK內部維護錄音狀態,根據該狀態的回調進行錄音機的開關操作。
public void onNuiAudioStateChanged(Constants.AudioState state) { Log.i(TAG, "onNuiAudioStateChanged"); if (state == Constants.AudioState.STATE_OPEN) { Log.i(TAG, "audio recorder start"); mAudioRecorder.startRecording(); } else if (state == Constants.AudioState.STATE_CLOSE) { Log.i(TAG, "audio recorder close"); mAudioRecorder.release(); } else if (state == Constants.AudioState.STATE_PAUSE) { Log.i(TAG, "audio recorder pause"); mAudioRecorder.stop(); } }
onNuiNeedAudioData:錄音數據回調,在該回調中填充錄音數據。
public int onNuiNeedAudioData(byte[] buffer, int len) { int ret = 0; if (mAudioRecorder.getState() != AudioRecord.STATE_INITIALIZED) { Log.e(TAG, "audio recorder not init"); return -1; } ret = mAudioRecorder.read(buffer, 0, len); //返回值告知SDK讀到了多少數據。 //如果返回<0,則表示出錯。 //返回0,則表示無錄音數據,連續2s返回0,會觸發事件EVENT_MIC_ERROR。 return ret; }
onNuiEventCallback:NUI SDK事件回調,請勿在事件回調中調用SDK的接口,可能引起死鎖。
public void onNuiEventCallback(Constants.NuiEvent event, final int resultCode, final int arg2, KwsResult kwsResult, AsrResult asrResult) { Log.i(TAG, "event=" + event + " resultCode=" + resultCode); // asrResult包含task_id,task_id有助于排查問題,請用戶進行記錄保存。 // // 新版本新增asrResult.allResponse,若為非nullptr和非空,則給出json格式字符串的完整信息。 if (event == Constants.NuiEvent.EVENT_TRANSCRIBER_COMPLETE) { // 實時識別結束 } else if (event == Constants.NuiEvent.EVENT_ASR_PARTIAL_RESULT) { // 例如展示當前句子的識別中間結果 showText(asrView, asrResult.asrResult); } else if (event == Constants.NuiEvent.EVENT_SENTENCE_END) { // 例如展示當前句子的完整識別結果 showText(asrView, asrResult.asrResult); } else if (event == Constants.NuiEvent.EVENT_ASR_ERROR) { // asrResult在EVENT_ASR_ERROR中為錯誤信息,搭配錯誤碼resultCode和其中的task_id更易排查問題,請用戶進行記錄保存。 } else if (event == Constants.NuiEvent.EVENT_MIC_ERROR) { // EVENT_MIC_ERROR表示2s未傳入音頻數據,請檢查錄音相關代碼、權限或錄音模塊是否被其他應用占用。 } else if (event == Constants.NuiEvent.EVENT_DIALOG_EX) { /* unused */ // 此事件可不用關注 } }
結束識別
nui_instance.stopDialog();
釋放SDK
nui_instance.release();
常見問題
新版Android SDK實時語音識別,管控臺模型選擇8K,但是Demo中為什么將采樣率設置成16K才能識別正確?
建議您將該參數值nls_config.put("sr_format", "pcm")
配置成小寫,在代碼中確認public final static int SAMPLE_RATE = 8000
,模型選擇是8K。
使用onNuiNeedAudioData錄音數據回調,在該回調中填充錄音數據“ret = audioRecord.read(buffer, 0, len);” 實時錄音轉寫過程中突然斷網再聯網,錄音SDK會自動連接然后繼續轉寫嗎?
斷網后需要重新連接錄音SDK,不會自動連接,需要您增加一些重試機制。
實時音頻識別對安卓版本有要求嗎?
沒有具體要求,最新的SDK兼容最新版本。
Android SDK是否可以上傳OPUS音頻數據,實現實時語音轉文字?
ASR中一句話識別和錄音文件極速版支持OPUS數據,實時語音轉文字僅支持PCM編碼、16 bit采樣位數、單聲道(mono)。具體詳情請參見接口說明。
調用Android SDK時,手機報錯提示“audio recoder not init”如何解決?
您可以通過以下方式排查:
檢查AudioRecord是否初始化正常。
檢查語音播放器是否有問題。
系統的錄音模塊代碼如下,也可單獨編寫AudioRecord錄音代碼,測試是否正常。
int ret = nui_instance.initialize(this, genInitParams(assets_path,debug_path), Constants.LogLevel.LOG_LEVEL_VERBOSE, true)。錄音權限已打開,但代碼仍然報錯240021是什么原因?
240021表示FILE_ACCESS_FAIL文件訪問錯誤。請完成以下操作:
檢查是否有文件讀寫權限。
檢查是否完成SDK調用、是否完成SDK配置文件的拷貝。
if (CommonUtils.copyAssetsData(this)) {
Log.i(TAG, "copy assets data done");
} else {
Log.i(TAG, "copy assets failed");
return;
}