移動(dòng)端Harmony推流
本文介紹如何使用移動(dòng)端Harmony SDK來(lái)支持實(shí)時(shí)記錄場(chǎng)景下的音頻識(shí)別流程。
前提條件
SDK關(guān)鍵接口
initialize:初始化SDK。
/** * 初始化SDK,SDK可多實(shí)例,請(qǐng)先釋放后再次進(jìn)行初始化。請(qǐng)勿在UI線(xiàn)程調(diào)用,可能會(huì)引起阻塞。 * @param callback:事件監(jiān)聽(tīng)回調(diào),參見(jiàn)下文具體回調(diào)。 * @param parameters:json string形式的初始化參數(shù),參見(jiàn)下方說(shuō)明或接口說(shuō)明:http://bestwisewords.com/document_detail/173298.html。 * @param level:log打印級(jí)別,值越小打印越多。 * @param save_log:是否保存log為文件,存儲(chǔ)目錄為ticket中的debug_path字段值。注意,log文件無(wú)上限,請(qǐng)注意持續(xù)存儲(chǔ)導(dǎo)致磁盤(pán)存滿(mǎn)。 * @return:參見(jiàn)錯(cuò)誤碼:http://bestwisewords.com/document_detail/459864.html。 */ public initialize(callback:INativeNuiCallback , parameters:string , level:number , save_log:boolean=false ):number
其中,parameters詳細(xì)說(shuō)明:
參數(shù)
類(lèi)型
是否必選
說(shuō)明
workspace
String
是
工作目錄路徑,SDK從該路徑讀取配置文件。
app_key
String
是
必須填“default”。
token
String
是
必須填“default”。
url
String
是
創(chuàng)建聽(tīng)悟?qū)崟r(shí)記錄任務(wù)時(shí)返回的會(huì)議MeetingJoinUrl作為音頻流推送地址,在后續(xù)實(shí)時(shí)音頻流識(shí)別時(shí)通過(guò)該地址進(jìn)行推流。
service_mode
String
是
必須填“1”,表示啟用在線(xiàn)功能。
device_id
String
是
設(shè)備標(biāo)識(shí),唯一表示一臺(tái)設(shè)備(如Mac地址/SN/UniquePsuedoID等)。
debug_path
String
否
debug目錄。當(dāng)初始化SDK時(shí)的save_log參數(shù)取值為true時(shí),該目錄用于保存日志文件。
save_wav
String
否
當(dāng)初始化SDK時(shí)的save_log參數(shù)取值為true時(shí),該參數(shù)生效。表示是否保存音頻debug,該數(shù)據(jù)保存在debug目錄中,需要確保debug_path有效可寫(xiě)。
注意,音頻文件無(wú)上限,請(qǐng)注意持續(xù)存儲(chǔ)導(dǎo)致磁盤(pán)存滿(mǎn)。
其中,INativeNuiCallback類(lèi)型包含如下回調(diào)。
onNuiAudioStateChanged:根據(jù)音頻狀態(tài)進(jìn)行錄音功能的開(kāi)關(guān)。
/** * 當(dāng)start/stop/cancel等接口調(diào)用時(shí),SDK通過(guò)此回調(diào)通知App進(jìn)行錄音的開(kāi)關(guān)操作。 * @param state:錄音需要的狀態(tài)(打開(kāi)/停止/關(guān)閉) */ onNuiAudioStateChanged:(state:Constants.AudioState)=>void
onNuiNeedAudioData:在回調(diào)中提供音頻數(shù)據(jù)。
/** * 開(kāi)始識(shí)別時(shí),此回調(diào)被連續(xù)調(diào)用,App需要在回調(diào)中進(jìn)行語(yǔ)音數(shù)據(jù)填充。 * @param buffer:填充語(yǔ)音的存儲(chǔ)區(qū)。 * @return:實(shí)際填充的字節(jié)數(shù)。 */ onNuiNeedAudioData:(buffer:ArrayBuffer)=>number;
onNuiEventCallback:SDK事件回調(diào)。
/** * SDK主要事件回調(diào) * @param event:回調(diào)事件,參見(jiàn)如下事件列表。 * @param resultCode:參見(jiàn)錯(cuò)誤碼,在出現(xiàn)EVENT_ASR_ERROR事件時(shí)有效。 * @param arg2:保留參數(shù)。 * @param kwsResult:語(yǔ)音喚醒功能(暫不支持)。 * @param asrResult:語(yǔ)音識(shí)別結(jié)果。 */ onNuiEventCallback:(event:Constants.NuiEvent, resultCode:number, arg2:number, kwsResult:KwsResult, asrResult:AsrResult)=>void;
事件列表:
名稱(chēng)
說(shuō)明
EVENT_VAD_START
檢測(cè)到人聲起點(diǎn)。
EVENT_VAD_END
檢測(cè)到人聲尾點(diǎn)。
EVENT_ASR_PARTIAL_RESULT
語(yǔ)音識(shí)別中間結(jié)果。
EVENT_ASR_ERROR
根據(jù)錯(cuò)誤碼信息判斷出錯(cuò)原因。
EVENT_MIC_ERROR
錄音錯(cuò)誤,表示SDK連續(xù)2秒未收到任何音頻,可檢查錄音系統(tǒng)是否正常。
EVENT_SENTENCE_START
實(shí)時(shí)語(yǔ)音識(shí)別事件,表示檢測(cè)到一句話(huà)開(kāi)始。
EVENT_SENTENCE_END
實(shí)時(shí)語(yǔ)音識(shí)別事件,表示檢測(cè)到一句話(huà)結(jié)束,返回一句完整的結(jié)果。
EVENT_SENTENCE_SEMANTICS
暫不使用。
EVENT_RESULT_TRANSLATED
翻譯結(jié)果。
EVENT_TRANSCRIBER_COMPLETE
停止語(yǔ)音識(shí)別后最終事件
onNuiAudioRMSChanged:音頻能量值回調(diào)。
/** * 音頻能量值回調(diào) * @param val: 音頻數(shù)據(jù)能量值回調(diào),范圍-160至0,一般用于UI展示語(yǔ)音動(dòng)效 */ onNuiAudioRMSChanged:(val:number)=>number;
setParams:以JSON格式設(shè)置SDK參數(shù)。
/** * 以JSON格式設(shè)置參數(shù) * @param params:參見(jiàn)接口說(shuō)明:http://bestwisewords.com/document_detail/173298.html。 * @return:參見(jiàn)錯(cuò)誤碼:http://bestwisewords.com/document_detail/459864.html。 */ public setParams(params:string):number
params詳細(xì)說(shuō)明:
參數(shù)
類(lèi)型
是否必選
說(shuō)明
service_type
Integer
是
必須填“4”。此為需要請(qǐng)求的語(yǔ)音服務(wù)類(lèi)型,聽(tīng)悟?qū)崟r(shí)推流為“4”。
nls_config
JsonObject
是
訪(fǎng)問(wèn)語(yǔ)音服務(wù)相關(guān)的參數(shù)配置,詳見(jiàn)如下。
nls_config.sr_format
String
是
必須填“pcm”。對(duì)應(yīng)的《CreateTask - 創(chuàng)建聽(tīng)悟任務(wù)》中,創(chuàng)建聽(tīng)悟任務(wù)時(shí)也請(qǐng)指定音頻流數(shù)據(jù)的編碼格式為pcm。
nls_config.sample_rate
Integer
是
音頻采樣率,默認(rèn)值:16000Hz。對(duì)應(yīng)的《CreateTask - 創(chuàng)建聽(tīng)悟任務(wù)》中,創(chuàng)建聽(tīng)悟任務(wù)時(shí)也請(qǐng)指定音頻流數(shù)據(jù)的采樣率,當(dāng)前支持 8000 和 16000。
startDialog:開(kāi)始識(shí)別。
/** * 開(kāi)始識(shí)別 * @param vad_mode:多種模式,對(duì)于識(shí)別場(chǎng)景,請(qǐng)使用P2T。 * @param dialog_params:json string形式的對(duì)話(huà)參數(shù),參見(jiàn)接口說(shuō)明:http://bestwisewords.com/document_detail/173298.html。 * @return:參見(jiàn)錯(cuò)誤碼:http://bestwisewords.com/document_detail/459864.html。 */ public startDialog(vad_mode:Constants.VadMode, dialog_params:string):number
stopDialog:結(jié)束識(shí)別。
/** * 結(jié)束識(shí)別,調(diào)用該接口后,服務(wù)端將返回最終識(shí)別結(jié)果并結(jié)束任務(wù)。 * @return:參見(jiàn)錯(cuò)誤碼:http://bestwisewords.com/document_detail/459864.html。 */ public stopDialog():number
cancelDialog:立即結(jié)束識(shí)別。
/** * 立即結(jié)束識(shí)別,調(diào)用該接口后,不等待服務(wù)端返回最終識(shí)別結(jié)果就立即結(jié)束任務(wù)。 * @return:參見(jiàn)錯(cuò)誤碼:http://bestwisewords.com/document_detail/459864.html。 */ public cancelDialog():number
release:釋放SDK。
/** * 釋放SDK資源 * @return:參見(jiàn)錯(cuò)誤碼:http://bestwisewords.com/document_detail/459864.html。 */ public release():number
GetVersion:獲得當(dāng)前SDK版本信息。
/** * 獲得當(dāng)前SDK版本信息 * @return: 字符串形式的SDK版本信息 */ public GetVersion():string
調(diào)用步驟
請(qǐng)下載后在聽(tīng)悟的樣例初始化代碼中將Appkey和Token置為default,url置為您創(chuàng)建聽(tīng)悟?qū)崟r(shí)記錄返回的會(huì)議MeetingJoinUrl。
初始化SDK、錄音實(shí)例。
根據(jù)業(yè)務(wù)需求設(shè)置參數(shù)。
調(diào)用startDialog開(kāi)始識(shí)別。
根據(jù)音頻狀態(tài)回調(diào)onNuiAudioStateChanged,打開(kāi)錄音機(jī)。
在onNuiNeedAudioData回調(diào)中提供錄音數(shù)據(jù)。
在EVENT_SENTENCE_START事件回調(diào)中表示當(dāng)前開(kāi)始識(shí)別一個(gè)句子,在EVENT_ASR_PARTIAL_RESULT事件回調(diào)中獲取識(shí)別中間結(jié)果,在EVENT_SENTENCE_END事件回調(diào)中獲得這句話(huà)完整的識(shí)別結(jié)果和各相關(guān)信息,在EVENT_RESULT_TRANSLATED事件回調(diào)中獲得翻譯結(jié)果。
調(diào)用stopDialog結(jié)束識(shí)別。并從EVENT_TRANSCRIBER_COMPLETE事件回調(diào)確認(rèn)已停止識(shí)別。
結(jié)束調(diào)用,使用release接口釋放SDK資源。
代碼示例
您如果有多例需求,也可以直接new對(duì)象進(jìn)行使用。也可采用GetInstance獲得單例。
NUI SDK初始化
//定義類(lèi)NativeNuiCallbackHandle 實(shí)現(xiàn)回調(diào)接口INativeNuiCallback
class NativeNuiCallbackHandle implements INativeNuiCallback{
//內(nèi)部實(shí)現(xiàn)INativeNuiCallback中的5個(gè)接口函數(shù)
//此處省略
}
let context = getContext(this) as common.UIAbilityContext;
this.filesDir = context.filesDir;
this.resourceDir = context.resourceDir;
//這里獲得資源路徑, 由于資源文件存放在工程的resfiles目錄下,所以使用沙箱路徑下的resfiles目錄
let asset_path:string = this.resourceDir+"/resources_cloud"
//由于用戶(hù)無(wú)法直接操作設(shè)備目錄,因此調(diào)試路徑設(shè)置為APP所在的沙箱路徑下的公共目錄filesDir
let debug_path:string = this.filesDir
//初始化SDK,注意用戶(hù)需要在genInitParams中填入相關(guān)ID信息才可以使用。
cbhandle:NativeNuiCallbackHandle = new NativeNuiCallbackHandle()
g_asrinstance:NativeNui = new NativeNui(Constants.ModeType.MODE_DIALOG, "asr")
let ret:number = this.g_asrinstance.initialize(this.cbhandle, this.genInitParams(asset_path,debug_path), Constants.LogLevel.LOG_LEVEL_VERBOSE, false);
console.info("result = " + ret);
if (ret == Constants.NuiResultCode.SUCCESS) {
console.error(`call g_asrinstance.initialize() return success`);
} else {
//拋出錯(cuò)誤異常信息。
console.error(`call g_asrinstance.initialize() return error:${ret}`);
}
其中,genInitParams生成為String JSON字符串,包含資源目錄和用戶(hù)信息。其中用戶(hù)信息包含如下字段。
genInitParams(workpath:string, debugpath:string):string {
let str:string = "";
let object:Map<string, string|number|boolean|object> = new Map();
//賬號(hào)和項(xiàng)目創(chuàng)建
// ak_id ak_secret app_key如何獲得,請(qǐng)查看http://bestwisewords.com/document_detail/72138.html
object.set("app_key","default"); // 必填
object.set("token", "default"); // 必填
object.set("device_id", "meta60protestdevice"/*Utils.getDeviceId()*/); // 必填, 推薦填入具有唯一性的id, 方便定位問(wèn)題
// url中填入生成的MeetingJoinUrl。
// 由于MeetingJoinUrl生成過(guò)程涉及ak/sk,移動(dòng)端不可存儲(chǔ)賬號(hào)信息,故需要在服務(wù)端生成,并下發(fā)給移動(dòng)端。
// 詳細(xì)請(qǐng)看: http://bestwisewords.com/zh/tingwu/api-tingwu-2023-09-30-createtask?spm=a2c4g.11186623.0.i32
object.set("url", "wss://tingwu-realtime-cn-hangzhou-pre.aliyuncs.com/api/ws/v1?XXXX"); // 必填
object.set("workspace", workpath); // 必填, 且需要有讀寫(xiě)權(quán)限
//當(dāng)初始化SDK時(shí)的save_log參數(shù)取值為true時(shí),該參數(shù)生效。表示是否保存音頻debug,該數(shù)據(jù)保存在debug目錄中,需要確保debug_path有效可寫(xiě)。
// object.put("save_wav", "true");
//debug目錄,當(dāng)初始化SDK時(shí)的save_log參數(shù)取值為true時(shí),該目錄用于保存中間音頻文件。
object.set("debug_path", debugpath);
object.set("service_mode", Constants.ModeFullCloud); // 必填
str = MapToJson(object)
console.info("configinfo genInitParams:" + str);
return str;
}
參數(shù)設(shè)置
以JSON字符串形式進(jìn)行設(shè)置。
import {MapToJson} from 'neonui'
//設(shè)置相關(guān)識(shí)別參數(shù),具體參考API文檔
// initialize()之后startDialog之前調(diào)用
this.g_asrinstance.setParams(this.genParams());
genParams():string {
let params:string = "";
let nls_config:Map<string, string|number|boolean|object> = new Map();
nls_config.set("sample_rate", 16000);
nls_config.set("sr_format", "pcm");
let parameters:Map<string, string|number|boolean|object> = new Map();
parameters.set("nls_config", Object( JSON.parse(MapToJson(nls_config)) ) );
parameters.set("service_type", Constants.kServiceTypeSpeechTranscriber); // 必填
params = MapToJson(parameters);
console.log("configinfo genParams" + params)
return params;
}
開(kāi)始識(shí)別
通過(guò)startDialog接口開(kāi)啟監(jiān)聽(tīng)。
import {MapToJson} from 'neonui'
let ret:number = this.g_asrinstance.startDialog(Constants.VadMode.TYPE_P2T,
this.genDialogParams());
console.info("start done . ret = ", ret);
if (ret != 0) {
console.info("call startDialog return error. ", ret);
}
nui_instance.startDialog(Constants.VadMode.TYPE_P2T, genDialogParams());
genDialogParams():string {
let params:string = "";
let dialog_param:Map<string, string|number|boolean|object> = new Map();
params = MapToJson(dialog_param);
console.info("configinfo dialog params: " + params);
return params;
}
推送錄音數(shù)據(jù)
updateAudio:在AudioCapturer的on('readData',)注冊(cè)的回調(diào)函數(shù)中,直接調(diào)用updateAudio接口把錄音數(shù)據(jù)送入SDK內(nèi)部。
//g_asrinstance.updateAudio(buffer,false) /*AudioCapturer中注冊(cè)的'readData'接口是AudioCapturer.readDataCallback *AudioCapturer.audioCapturer.on('readData', AudioCapturer.readDataCallback); */ class AudioCapturer{ static readDataCallback = (buffer: ArrayBuffer) => { console.log(`${TAG} read data bytelength is ${buffer.byteLength}. uid[${process.uid}] pid[${process.pid}] tid[${process.tid}]`); AudioCapturer.g_asrinstance.updateAudio(buffer,false) } }
回調(diào)處理
onNuiAudioStateChanged:錄音狀態(tài)回調(diào),SDK內(nèi)部維護(hù)錄音狀態(tài),根據(jù)該狀態(tài)的回調(diào)進(jìn)行錄音機(jī)的開(kāi)關(guān)操作。
/* 對(duì)于鴻蒙開(kāi)發(fā)環(huán)境IDE版本5.0.3.403 以前的版本,AudioCapturer模塊如果使用注冊(cè)回調(diào)[on("readData",)]的方式讀取錄音數(shù)據(jù), 存在AudioCapturer.stop后直接start不會(huì)觸發(fā)回調(diào)的情況。此時(shí)必須按照 (stop,realease)再(createAudioCapturer,start)的流程才能正常工作。 升級(jí)為 IDE版本5.0.3.403版本后,以上問(wèn)題已經(jīng)解決。所以以下示例代碼中注釋掉了create/release相關(guān)接口的調(diào)用。 */ onNuiAudioStateChanged(state:Constants.AudioState):void { console.info(`womx onUsrNuiAudioStateChanged(${state})`) if (state === Constants.AudioState.STATE_OPEN){ console.info(`womx onUsrNuiAudioStateChanged(${state}) audio recorder start`) //AudioCapturer.init(g_asrinstance) AudioCapturer.start() console.info(`womx onUsrNuiAudioStateChanged(${state}) audio recorder start done`) } else if (state === Constants.AudioState.STATE_CLOSE){ console.info(`womx onUsrNuiAudioStateChanged(${state}) audio recorder close`) AudioCapturer.stop() //AudioCapturer.release() console.info(`womx onUsrNuiAudioStateChanged(${state}) audio recorder close done`) } else if (state === Constants.AudioState.STATE_PAUSE){ console.info(`womx onUsrNuiAudioStateChanged(${state}) audio recorder pause`) AudioCapturer.stop() //AudioCapturer.release() console.info(`womx onUsrNuiAudioStateChanged(${state}) audio recorder pause done`) } }
onNuiNeedAudioData:錄音數(shù)據(jù)回調(diào),在該回調(diào)中填充錄音數(shù)據(jù)。
public int onNuiNeedAudioData(byte[] buffer, int len) { console.info(`warning,this callback should not be called in HarmonyOS Next`) return 0; }
onNuiEventCallback:NUI SDK事件回調(diào),請(qǐng)勿在事件回調(diào)中調(diào)用SDK的接口,可能引起死鎖。
//以下幾個(gè)變量,用于在event回調(diào)過(guò)程中,進(jìn)行實(shí)時(shí)識(shí)別結(jié)果、歷史識(shí)別結(jié)果、實(shí)時(shí)翻譯結(jié)果、歷史翻譯結(jié)果的匯總相關(guān)工作。 asrspeechrealtimeResultOld:string="" asrmessage:string=""; message:string=""; //保存當(dāng)前回調(diào)的事件信息 asr_message_id:string=""; asrspeechrealtimeResultTranslatedOld:string="" asrmessageTranslated:string=""; onNuiEventCallback(event:Constants.NuiEvent, resultCode:number, arg2:number, kwsResult:KwsResult, asrResult:AsrResult):void { let asrinfo:string = "" console.log("onUsrNuiEventCallback last this callback handle.asrmessage is " + this.asrmessage) console.log("onUsrNuiEventCallback new this callback handle is " + JSON.stringify(this)) console.log("onUsrNuiEventCallback event is " + event) if (event === Constants.NuiEvent.EVENT_TRANSCRIBER_COMPLETE){ // 實(shí)時(shí)識(shí)別結(jié)束 this.message = "EVENT_TRANSCRIBER_COMPLETE" this.asrspeechrealtimeResultOld="" this.asrspeechrealtimeResultTranslatedOld="" } else if (event === Constants.NuiEvent.EVENT_SENTENCE_START){ this.message = "EVENT_SENTENCE_START" } else if (event === Constants.NuiEvent.EVENT_ASR_PARTIAL_RESULT || event === Constants.NuiEvent.EVENT_SENTENCE_END){ if (event === Constants.NuiEvent.EVENT_ASR_PARTIAL_RESULT ) { // 例如展示當(dāng)前句子的識(shí)別中間結(jié)果 this.message = "EVENT_ASR_PARTIAL_RESULT" } else if(event === Constants.NuiEvent.EVENT_SENTENCE_END){ // 例如展示當(dāng)前句子的完整識(shí)別結(jié)果 this.message = "EVENT_SENTENCE_END" } } else if (event === Constants.NuiEvent.EVENT_RESULT_TRANSLATED){ // 例如展示當(dāng)前句子的翻譯結(jié)果 this.message = "EVENT_RESULT_TRANSLATED" } else if (event === Constants.NuiEvent.EVENT_ASR_ERROR){ // asrResult在EVENT_ASR_ERROR中為錯(cuò)誤信息,搭配錯(cuò)誤碼resultCode和其中的task_id更易排查問(wèn)題,請(qǐng)用戶(hù)進(jìn)行記錄保存。 this.message = "EVENT_ASR_ERROR" } else if (event === Constants.NuiEvent.EVENT_MIC_ERROR){ // EVENT_MIC_ERROR表示2s未傳入音頻數(shù)據(jù),請(qǐng)檢查錄音相關(guān)代碼、權(quán)限或錄音模塊是否被其他應(yīng)用占用。 this.message = "EVENT_MIC_ERROR" } else if (event === Constants.NuiEvent.EVENT_DIALOG_EX){ /* unused */ // 此事件可不用關(guān)注 this.message = "EVENT_DIALOG_EX" } if (asrResult) { asrinfo = asrResult.asrResult console.log(`asrinfo asrResult string is ${asrinfo}. all response is [${asrResult.allResponse}]`) if (asrinfo) { try { let asrresult_json:object|null = JSON.parse(asrinfo) //console.log(JSON.stringify(asrresult_json)) if (asrresult_json) { let payload:object|null = asrresult_json["payload"]; if (payload) { //console.log(JSON.stringify(payload)) if (event === Constants.NuiEvent.EVENT_RESULT_TRANSLATED) { //出現(xiàn)翻譯結(jié)果事件時(shí),進(jìn)行翻譯結(jié)果的實(shí)時(shí)更新。 if (payload["translate_result"]) { //實(shí)時(shí)更新當(dāng)前的翻譯結(jié)果。 console.log(`translate_result is [${payload["translate_result"][0]["text"]}], with oldinfo [${this.asrspeechrealtimeResultTranslatedOld}]`) //this.asrmessageTranslated中保存的是start以后所有句子的翻譯結(jié)果。包括歷史句子的翻譯匯總結(jié)果 + 當(dāng)前句子的實(shí)時(shí)翻譯結(jié)果。 this.asrmessageTranslated = this.asrspeechrealtimeResultTranslatedOld + payload["translate_result"][0]["text"]; } if (this.asr_message_id == asrresult_json["header"]["source_message_id"]){ //當(dāng)翻譯結(jié)果對(duì)應(yīng)的source_message_id 是 EVENT_SENTENCE_END對(duì)應(yīng)的message_id時(shí),說(shuō)明EVENT_SENTENCE_END對(duì)應(yīng)語(yǔ)句的翻譯結(jié)束。此時(shí)可以更新歷史句子的總翻譯結(jié)果。 this.asrspeechrealtimeResultTranslatedOld = this.asrmessageTranslated } } else { //出現(xiàn)識(shí)別結(jié)果事件時(shí),進(jìn)行識(shí)別結(jié)果的實(shí)時(shí)更新。 if (payload["result"]) { //this.asrmessage中保存的是start以后所有句子的識(shí)別結(jié)果。包括歷史句子的識(shí)別匯總結(jié)果 + 當(dāng)前句子的實(shí)時(shí)識(shí)別結(jié)果。 this.asrmessage = this.asrspeechrealtimeResultOld + payload["result"]; } } if(event === Constants.NuiEvent.EVENT_SENTENCE_END){ //出現(xiàn)EVENT_SENTENCE_END事件事,進(jìn)行歷史識(shí)別結(jié)果的匯總、暫存最后一句識(shí)別結(jié)果的message_id作為該句識(shí)別結(jié)果的翻譯結(jié)果過(guò)濾依據(jù) //進(jìn)行歷史識(shí)別結(jié)果的匯總 this.asrspeechrealtimeResultOld = this.asrmessage //暫存最后一句識(shí)別結(jié)果的message_id作為該句識(shí)別結(jié)果的翻譯結(jié)果過(guò)濾依據(jù) this.asr_message_id = asrresult_json["header"]["message_id"] } } } } catch (e){ console.error("got asrinfo asrResult not json, so donot fresh asrinfo." + JSON.stringify(e)) } } } console.info(`womx onUsrNuiEventCallback(${event}, ${resultCode},${arg2}, kwsResult:${kwsResult},asrResult:"${this.asrmessage}") done`) }
結(jié)束識(shí)別
nui_instance.stopDialog();
釋放SDK
nui_instance.release();