本文为您介绍如何使用阿里云智能语音服务提供的HarmonyOS Next NUI SDK,包括SDK下载安装、关键接口及代码示例。
前提条件
下载安装
下载harmony.zip。
以arkts HAR包的形式进行集成。解压ZIP包,其中nuisdk-release/neonui.har 是SDK生成的HAR包文件,在用户工程项目中导入调用即可。如果需要HarmonyOS Next CPP接入方式,可在ZIP包的harmonyos_libs和harmonyos_include中获得动态库和头文件。
使用DevEco Studio打开harmony_nlsdemo目录下工程查看参考代码实现,其中一句话识别示例代码为FileTranscriber.ets文件,替换UserKey.ets中 UserKey类的Appkey和Token后,即可直接运行。
SDK关键接口
initialize:初始化SDK。
/** * 初始化SDK,SDK为单例,请先释放后再次进行初始化。请勿在UI线程调用,可能会引起阻塞 * @param callback: 事件监听回调,参见下文回调说明 * @param parameters: 初始化参数,参见接口说明 * @param level: log打印级别,值越小打印越多 * @param save_log: 是否保存log信息,使用默认值false即可。 * @return: 参见错误码 */ public initializeFileTrans(callback:INativeFileTransCallback , parameters:string , level:number , save_log:boolean=false):number
其中,INativeFileTransCallback类型需要实现的回调是onFileTransEventCallback。
onFileTransEventCallback:文件识别事件回调。
/** * SDK主要事件回调 * @param event: 回调事件,参见如下事件列表 * @param resultCode: 参见错误码,在出现EVENT_ASR_ERROR事件时有效 * @param arg2: 保留参数 * @param asrResult: 语音识别结果 * @param taskId: 转写任务ID */ onFileTransEventCallback(event:Constants.NuiEvent, resultCode:number, arg2:number, asrResult:AsrResult, taskId:string):void
事件列表:
名称
说明
EVENT_FILE_TRANS_CONNECTED
连接文件识别服务成功
EVENT_FILE_TRANS_UPLOADED
上传文件成功
EVENT_FILE_TRANS_RESULT
识别最终结果
EVENT_ASR_ERROR
根据错误码信息判断出错原因
setParams:以JSON格式设置SDK参数。
/** * 以JSON格式设置参数 * @param params: 参见接口说明 * @return: 参见错误码 */ public setParams(params:string):number
startFileTranscriber:开始文件识别。
/** * 开始识别 * @param params: 识别参数,参见接口说明 * @param taskId: 开始转写的任务ID,SDK生成随机字符串 * @return: 参见错误码 */ public startFileTranscriber(params:string, task_id:ArrayBuffer):number
cancelFileTranscriber:结束识别。
/** * 结束识别 * @return: 参见错误码 */ public cancelFileTranscriber(task_id:string):number
release:释放SDK。
/** * 释放SDK资源 * @return: 参见错误码 */ public release():number
调用步骤
创建SDK类对象实例
初始化SDK。
根据业务需求设置参数。
调用startFileTranscriber开始识别。
在EVENT_FILE_TRANS_RESULT事件中获取最终识别结果。
结束调用,使用release接口释放SDK资源。
代码示例
接口默认采用GetInstance获得单例,您如果有多例需求,也可以直接new对象进行使用。
NUI SDK初始化
//初始化SDK,注意用户需要在Auth.getAliYunTicket中填入相关ID信息才可以使用。
let ret:number = this.g_asrinstance.initializeFileTrans(this.cbhandle, this.genInitParams(asset_path,debug_path), Constants.LogLevel.LOG_LEVEL_VERBOSE, false);
console.info("result = " + ret);
if (ret == Constants.NuiResultCode.SUCCESS) {
} else {
//抛出错误异常信息。
}
//设置相关识别参数,具体参考API文档
this.g_asrinstance.setParams(this.genParams());
其中,genInitParams生成为String JSON字符串,包含资源目录和用户信息。其中用户信息包含如下字段。 genParams生成String JSON字符串格式的部分参数,在initializeFileTrans()之后, start之前进行设置。
genInitParams(workpath:string, debugpath:string):string {
let str:string = "";
//获取token方式:
let object:Map<string, string|number|boolean|object> = new Map();
//账号和项目创建
// ak_id ak_secret app_key如何获得,请查看https://help.aliyun.com/document_detail/72138.html
object.set("app_key", UserKey.app_key); // 必填
//方法1:
// 首先ak_id ak_secret app_key如何获得,请查看https://help.aliyun.com/document_detail/72138.html
// 然后请看 https://help.aliyun.com/document_detail/466615.html 使用其中方案一获取临时凭证
// 此方案简介: 远端服务器生成具有有效时限的临时凭证, 下发给移动端进行使用, 保证账号信息ak_id和ak_secret不被泄露
// 获得Token方法(运行在APP服务端): https://help.aliyun.com/document_detail/450255.html?spm=a2c4g.72153.0.0.79176297EyBj4k
object.set("token", UserKey.token); // 必填
//方法2:
// STS获取临时凭证方法暂不支持
//方法3:(强烈不推荐,存在阿里云账号泄露风险)
// 参考Auth类的实现在端上访问阿里云Token服务获取SDK进行获取。请勿将ak/sk存在本地或端侧环境。
// 此方法优点: 端侧获得Token, 无需搭建APP服务器。
// 此方法缺点: 端侧获得ak/sk账号信息, 极易泄露。
// JSONObject object = Auth.getAliYunTicket();
object.set("device_id", "***"/*Utils.getDeviceId()*/); // 必填, 推荐填入具有唯一性的id, 方便定位问题
object.set("url", UserKey.url_file_trans); // 默认
object.set("workspace", workpath); // 必填, 且需要有读写权限
//当初始化SDK时的save_log参数取值为true时,该参数生效。表示是否保存音频debug,该数据保存在debug目录中,需要确保debug_path有效可写。
// object.put("save_wav", "true");
//debug目录,当初始化SDK时的save_log参数取值为true时,该目录用于保存中间音频文件。
object.set("debug_path", debugpath);
// FullMix = 0 // 选用此模式开启本地功能并需要进行鉴权注册
// FullCloud = 1
// FullLocal = 2 // 选用此模式开启本地功能并需要进行鉴权注册
// AsrMix = 3 // 选用此模式开启本地功能并需要进行鉴权注册
// AsrCloud = 4
// AsrLocal = 5 // 选用此模式开启本地功能并需要进行鉴权注册
object.set("service_mode", Constants.ModeFullCloud); // 必填
str = MapToJson(object)
console.info("configinfo genInitParams:" + str);
return str;
}
genParams():string {
let params:string = "";
let nls_config:Map<string, string|number|boolean|object> = new Map();
nls_config.set("enable_intermediate_result", true);
let parameters:Map<string, string|number|boolean|object> = new Map();
parameters.set("nls_config", Object( JSON.parse(MapToJson(nls_config)) ) );
params = MapToJson(parameters);//parameters.toString();
console.log("configinfo genParams" + params)
return params;
}
开始识别
调用startFileTranscriber方法开启识别。
let task_id:ArrayBuffer = new ArrayBuffer(32);
let ret:number = this.g_asrinstance.startFileTranscriber(this.genDialogParams(), task_id);
genDialogParams():string {
let params:string = "";
let dialog_param:Map<string, string|number|boolean|object> = new Map();
//若想在运行时切换app_key
//dialog_param.put("app_key", "");
let debug_path:string = this.resourceDir
dialog_param.set("file_path", debug_path + "/2.wav"); //使用DevEcoStudio工程目录resources/resfile/2.wav文件作为输入文件进行转写
let nls_config:Map<string, string|number|boolean|object> = new Map();
nls_config.set("format", "wav"); //和 "file_path"字段的语音文件编码格式匹配。
dialog_param.set("nls_config", Object( JSON.parse(MapToJson(nls_config)) ) );
params = MapToJson(dialog_param);
console.info("configinfo dialog params: " + params);
return params;
}
回调处理
onFileTransEventCallback:NUI SDK事件回调,请勿在事件回调中调用SDK的接口,可能引起死锁。
class NativeNuiCallbackHandle implements INativeFileTransCallback{
asrmessage:string;
message:string;
task_result: Map<string, string> = new Map(); //缓存多个文件的识别结果
task_result_all:string=""; //所有文件的识别结果汇总字符串
constructor() {
this.asrmessage=""
this.message=""
}
onFileTransEventCallback(event:Constants.NuiEvent, resultCode:number, finish:number,
asrResult:AsrResult, taskId:string):void{
let asrinfo:string = ""
console.info("event=" + event + " task_id " + taskId);
if (event == Constants.NuiEvent.EVENT_FILE_TRANS_UPLOADED) {
this.message = "EVENT_FILE_TRANS_UPLOADED"
showToast("完成上传,正在转写...");
} else if (event == Constants.NuiEvent.EVENT_FILE_TRANS_RESULT) {
this.message = "EVENT_FILE_TRANS_RESULT"
showToast("转写完成");
} else if (event == Constants.NuiEvent.EVENT_ASR_ERROR) {
this.message = "EVENT_ASR_ERROR"
console.info("error happened: " + resultCode);
showToast("error happened: " + resultCode);
}
if (asrResult) {
asrinfo = asrResult.asrResult
console.log(`asrinfo is ${asrinfo}`)
if (!asrinfo){
console.log(`asrinfo is null, with event ${event}`)
return
}
let asrresult_json:object|null = JSON.parse(asrResult.asrResult)
console.log(JSON.stringify(asrresult_json))
if (asrresult_json) {
let payload:object|null = asrresult_json["flash_result"];
if (payload) {
//console.log(JSON.stringify(payload))
let filetransresultarray:Array<object> = payload["sentences"]
let result_temp:string=""
for (let i=0;i<filetransresultarray.length;i++){
result_temp = result_temp +filetransresultarray[i]["text"]
}
this.asrmessage=result_temp
this.task_result.set(taskId, this.asrmessage)
}
}
}
this.task_result_all=""
let index:number = 0
this.task_result.forEach((value:string, key:string)=>{
this.task_result_all += `${index}==>${key}:${value};;\n`
index += 1
})
}
}
取消识别