HarmonyOS Next SDK

本文为您介绍如何使用阿里云智能语音服务提供的HarmonyOS Next  NUI SDK,包括SDK下载安装、关键接口及代码示例。

前提条件

下载安装

  1. 下载harmony.zip

  2. 以arkts HAR包的形式进行集成。解压ZIP包,其中nuisdk-release/neonui.har 是SDK生成的HAR包文件,在用户工程项目中导入调用即可。如果需要HarmonyOS Next CPP接入方式,可在ZIP包的harmonyos_libs和harmonyos_include中获得动态库和头文件。

  3. 使用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

调用步骤

  1. 创建SDK类对象实例

  2. 初始化SDK。

  3. 根据业务需求设置参数。

  4. 调用startFileTranscriber开始识别。

  5. 在EVENT_FILE_TRANS_RESULT事件中获取最终识别结果。

  6. 结束调用,使用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
    })
  }
}

取消识别

常见问题

鸿蒙NEXT SDK录音文件识别极速版,通过任务ID查询任务状态用哪个API?

不支持通过任务ID查询任务状态,任务中处理安卓端回调就是当前任务的状态。

鸿蒙NEXT SDK是否可以上传OPUS音频数据,实现实时语音转文字?

ASR中一句话识别和录音文件极速版支持OPUS数据,实时语音转文字仅支持PCM编码、16 bit采样位数、单声道(mono)。具体详情,请参见接口说明

调用鸿蒙NEXT SDK时,手机报错提示“audio recoder not init”如何解决?

您可以通过以下方式排查:

  • 检查AudioRecord是否初始化正常。

  • 检查语音播放器是否有问题。

  • 系统的录音模块代码如下,也可单独编写AudioRecord录音代码,测试是否正常。编写AudioRecord录音代码