1. 双路识别

双路识别是一种特殊的识别模式,它允许开发者同时用本地引擎和云端引擎进行语音识别。双路识别是以提高响应速度为为设计初衷的,只针对实时识别模式。

2. 准备工作

详见ASR能力集成指南

3. 双路识别能力集成

3.1 通用模块初始化

在调用语音识别(ASR)能力之前,需要初始化灵云SDK的SYS通用模块。详见灵云SDK开发手册

  • Android代码

      // 创建初始化参数辅助类
      InitParam initparam = new InitParam();  
      // 授权文件所在路径,此项必填
      String authDirPath = context.getFilesDir().getAbsolutePath();;
      initparam.addParam(InitParam.PARAM_KEY_AUTH_PATH, authDirPath);
      // 灵云云服务的接口地址,此项必填
      initparam.addParam(InitParam.PARAM_KEY_CLOUD_URL, "http://api.hcicloud.com:8888");      
      // 开发者密钥,此项必填,由捷通华声提供
      initparam.addParam(InitParam.PARAM_KEY_DEVELOPER_KEY, "01234567890");
      // 应用程序序号,此项必填,由捷通华声提供
      initparam.addParam(InitParam.PARAM_KEY_APP_KEY, "1234abcd");
      // 日志的路径,可选,如果不传或者为空则不生成日志
      String logDirPath = "/storage/emulated/0/sinovoice/com.sinovoice.example/log";
      initparam.addParam(InitParam.PARAM_KEY_LOG_FILE_PATH, logDirPath);
      // 日志等级,0=无,1=错误,2=警告,3=信息,4=细节,5=调试,SDK将输出小于等于logLevel的日志信息
      initparam.addParam(InitParam.PARAM_KEY_LOG_LEVEL, "5");
      // 灵云系统初始化
      // 第二个参数在Android平台下,必须为当前的Context
      int errCode = HciCloudSys.hciInit(initparam.getStringConfig(), this);
      if(errCode != HciErrorCode.HCI_ERR_NONE) {
              // "系统初始化失败"
              return;
      }
    
  • C++代码

      HCI_ERR_CODE err_code = HCI_ERR_NONE;
      //配置串是由"字段=值"的形式给出的一个字符串,多个字段之间以','隔开。字段名不分大小写。
      string init_config = "";
      //灵云应用序号
      init_config += "appKey=1234abcd";
      //灵云开发者密钥
      init_config += ",developerKey=1234567890";
      //灵云云服务的接口地址
      init_config += ",cloudUrl=http://api.hcicloud.com:8888";
      //授权文件所在路径,保证可写
      init_config += ",authpath=../../bin";
      //日志的路径
      init_config += ",logfilepath=../../bin";
      //日志的等级
      init_config += ",loglevel=5";
      //日志文件的大小
      init_config += ",logfilesize=512";
      //其他配置使用默认值,不再添加,如果想设置可以参考开发手册
      err_code = hci_init( init_config.c_str() );
    
  • iOS代码

      HCI_ERR_CODE errCode = HCI_ERR_NONE;
      //appkey, developerKey, cloudUrl, authPath为必填项。其他可配置信息请查询灵云SDK开发手册hci_init函数说明。
      NSString *appkey = @"";               //开发者社区申请所得
      NSString *developerKey = @"";         //开发者社区申请所得
      NSString *cloudUrl = @"";             //开发者社区申请所得
      NSString *authPath = @"";             //授权文件所在路径,一般设置为沙盒Document路径
      NSString *config = [NSString stringWithFormat:@"appkey=%@,developerKey=%@,cloudUrl=%@,authPath=%@", appkey, developerKey, cloudUrl, authPath];
      errCode = hci_init(config.UTF8String);
      if (errCode != HCI_ERR_NONE &&
          errCode != HCI_ERR_SYS_ALREADY_INIT) {
          NSLog(@"hci_init failed, error: %@", errCode);
      }else{
          NSLog(@"hci_init success");
      }
    

3.2 授权检测

在初始化灵云SDK的SYS通用模块后,还需要调用授权检测函数去云端获取授权。

  • Android代码

      // 获取授权
      private int checkAuthAndUpdateAuth() {
    
      // 获取系统授权到期时间
      int initResult;
      AuthExpireTime objExpireTime = new AuthExpireTime();
      initResult = HciCloudSys.hciGetAuthExpireTime(objExpireTime);
      if (initResult == HciErrorCode.HCI_ERR_NONE) {
                // 显示授权日期,如用户不需要关注该值,此处代码可忽略
               Date date = new Date(objExpireTime.getExpireTime() * 1000);
               SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd",Locale.CHINA);
               Log.i(TAG, "expire time: " + sdf.format(date));
    
               if (objExpireTime.getExpireTime() * 1000 > System.currentTimeMillis()) {
                      // 已经成功获取了授权,并且距离授权到期有充足的时间(>7天)
                      Log.i(TAG, "checkAuth success");
                      return initResult;
                  }  
      } 
    
      // 获取过期时间失败或者已经过期
      initResult = HciCloudSys.hciCheckAuth();
       if (initResult == HciErrorCode.HCI_ERR_NONE) {
                  Log.i(TAG, "checkAuth success");
                  return initResult;
      } else {
                 Log.e(TAG, "checkAuth failed: " + initResult);
                 return initResult;
              }
      }
    
  • C++代码

      //获取过期时间
      int64 expire_time;
      int64 current_time = (int64)time( NULL );
      HCI_ERR_CODE err_code = hci_get_auth_expire_time( &expire_time );
      if( err_code == HCI_ERR_NONE )
      {
          //获取成功则判断是否过期
          if( expire_time > current_time )
          {
              //没有过期
              printf( "auth can use continue\n" );
              return true;
          }
      }
      //获取过期时间失败或已经过期
      //手动调用更新授权
      err_code = hci_check_auth();
      if( err_code == HCI_ERR_NONE )
      {
          //更新成功
          printf( "check auth success \n" );
          return true;
      }
      else
      {
          //更新失败
          printf( "check auth return (%d:%s)\n", err_code ,hci_get_error_info(err_code));
          return false;
      }
    
  • iOS代码

      //获取过期时间
      int64 expireTime;
      int64 currentTime = (int64)time(NULL);
      HCI_ERR_CODE errCode = hci_get_auth_expire_time(&expireTime);
      if (errCode == HCI_ERR_NONE) {
          if (expireTime < currentTime) {
              errCode = hci_check_auth();
              if(errCode == HCI_ERR_NONE){
                  NSLog(@"check auth success");
                  return YES;
              }else{
                  NSLog(@"check auth failed, error: %@", errCode);
                  return NO;
              }
          }else{
              //没有过期
              NSLog(@"auth can use continue");
              return YES;
          }
      }
      //读取授权文件出现错误
      else if(errCode == HCI_ERR_SYS_AUTHFILE_INVALID){
          errCode = hci_check_auth();
          if(errCode == HCI_ERR_NONE){
              NSLog(@"check auth success");
              return YES;
          }else{
              NSLog(@"check auth failed, error: %@", errCode);
              return NO;
          }
      }else{
          NSLog(@"check auth failed, error: %@", errCode);
          return NO;
      }
    

3.3 ASR 初始化

在初始化灵云SDK的SYS通用模块和授权检测成功后,需调用 ASR 初始化函数。详见灵云SDK开发手册

  • Android代码

      // 创建初始化参数辅助类
      AsrInitParam asrInitParam= new AsrInitParam ();
      // 设置本地资源库的路径
      asrInitParam.addParam(AsrInitParam .PARAM_KEY_DATA_PATH, "/storage/emulated/0/sinovoice/com.sinovoice.example/data");
      asrInitParam.addParam(AsrInitParam .PARAM_KEY_INIT_CAP_KEYS, "asr.local.grammar;asr.cloud.freetalk");
      int errCode = HciCloudAsr.hciAsrInit(asrInitParam.getStringConfig());
    
  • C++代码

      string asr_init_config = "";
      //建议在initcapkeys中添加需要使用的所有能力以提高第一次识别的效率
      asr_init_config += "initcapkeys=asr.local.grammar;asr.cloud.freetalk";
      asr_init_config += ",datapath=../../data";
      err_code = hci_asr_init(asr_init_config.c_str());
      if (err_code != HCI_ERR_NONE)
      {
          printf("hci_asr_init return (%d:%s) \n",err_code,hci_get_error_info(err_code));
          return;
      }
    
  • iOS代码

      //initCapKeys为必填项,如果为本地意图识别dataPath为必填项。其他可配置信息请查询开发手册hci_asr_init函数说明。
      NSString *dataPath = [[NSBundle mainBundle] pathForResource:@"data" ofType:Nil];  //本地意图识别识别所需本地资源所在路径
      NSString *initCapKeys = @"asr.local.grammar;asr.cloud.freetalk";  //语音识别(ASR)所需使用的能力列表,可以包含多种能力,用';'分号隔开
      NSString *config = [NSString stringWithFormat:@"dataPath =%@, initCapKeys =%@", dataPath, initCapKeys];
      HCI_ERR_CODE errCode = HCI_ERR_NONE;
      errCode = hci_asr_init(config.UTF8String);
      if (errCode != HCI_ERR_NONE){
          NSLog(@"hci_asr_init failed, error:%@", errCode);
          return NO;
      }
      NSLog(@"hci_asr_init success");
      return YES;
    

3.4 开启会话(session)

双路识别即会话(session)同时拥有本地和云端识别功能,双路识别只支持实时识别模式,只需要在hci_asr_session_start函数中进行相应配置

  • Android代码

      AsrConfig config = new AsrConfig();
      // 启动 ASR Session
      int errCode = -1;
      //会话开启的字符串配置
      String sSessionConfig =  "capKey=asr.local.grammar.v4,realtime=yes#capKey=asr.cloud.freetalk,realtime=yes";
      Session nSessionId = new Session();
      errCode = HciCloudAsr.hciAsrSessionStart(sSessionConfig, nSessionId);
    
  • C++代码

      int nSessionId = -1;
      string strSessionConfig = "capKey=asr.local.grammar.v4,realtime=yes#capKey=asr.cloud.freetalk,realtime=yes";
      //此处也可以传入其他配置,参见开发手册,此处其他配置采用默认值
      err_code = hci_asr_session_start( strSessionConfig.c_str(), &nSessionId );
      if( err_code != HCI_ERR_NONE )
      {
          printf( "hci_asr_session_start return (%d:%s)\n", err_code ,hci_get_error_info(err_code));
          return false;
      }
    
  • iOS代码

      //开启session
      HCI_ERR_CODE errCode = HCI_ERR_NONE;
      NSString *config = @"capKey=asr.local.grammar.v4,realtime=yes#capKey=asr.cloud.freetalk,realtime=yes";
      int sessionID;            //开启会话成功后,会返回的会话ID
      errCode = hci_asr_session_start(config.UTF8String, &sessionID);
      if (errCode != HCI_ERR_NONE){
              NSLog(@"hci_asr_session_start failed, error:%@", errCode);
              return NO;
      }
      NSLog(@"hci_asr_session_start success");
      return YES;
    

3.5 语音识别

在启动会话(session)成功后,即可可以进行 ASR 识别过程。识别功能通过调用识别函数完成,如果是流式识别/实时反馈,则需要多次调用识别函数将语音数据送入 SDK。。配置参数详见灵云SDK开发手册

  • Android代码

      String audioFile = "sinovoice.pcm";
      // 从assets资源目录获取sinovoice.pcm 语音数据文件
      byte[] voiceData = Tools.getAssetFileData(this,audioFile);
      if (null == voiceData) {
          // ShowMessage("Open input voice file" + audioFile + " error!");
          return;
      }
    
      if (HciErrorCode.HCI_ERR_NONE != errCode) {
          //    ShowMessage("hciAsrSessionStart error:" + HciCloudSys.hciGetErrorInfo(errCode));
          return;
      }
      ShowMessage("hciAsrSessionStart Success");
    
      // 识别结果
      AsrRecogResult asrResult = new AsrRecogResult();  
      String config =  "audioFormat=pcm16k16bit,encode=none,grammarType=id,grammarId=100";
    
       while (1) {
            errCode = HciCloudAsr.hciAsrRecog(nSessionId, voiceData, config, null, asrResult);
          if (errCode == HCI_ERR_ASR_REALTIME_END) {
              //正常检测到端点,传入NULL和0,获取识别结果,退出循环
              errCode = HciCloudAsr.hciAsrRecog(nSessionId, NULL,config, null, asrResult);
              break;
          } else if (errCode == HCI_ERR_ASR_REALTIME_WAITING){
              //等待识别数据,继续循环
              continue;
          } else {
                  // 其它错误,一般不会出现,出现很可能是由于输入数据无效,或实时识别过程错误。
                  // 如果实时识别过程错误,则自动取消该次实时识别
                  // 否则可以手动终止本次实时识别, 然后退出循环
                  // 也可以继续循环,则下次hci_asr_recog()发送的数据会作为前次数据的延续
                  break;
          }
    }
    
  • C++代码

      //每次获取音频文件后都可以传入hci_asr_recog进行识别,这里只是用while循环演示不断调用hci_asr_recog
      HCI_ERR_CODE errCode = HCI_ERR_NONE;
      ASR_RECOG_RESULT asrResult;  //识别结果保存
      string  config = @"audioFormat=pcm16k16bit,encode=none,grammarType=id,grammarId=100";
      //_sessionID:为开启会话(session)后获得的sessionID
      //voiceData:每次获取的音频数据文件,数据类型为NSData
      while (1) {
          errCode = hci_asr_recog(_sessionID, (void *) voiceData.bytes, (unsigned int) voiceData.length, config.c_str(), NULL, &asrResult);
          if (errCode == HCI_ERR_ASR_REALTIME_END) {
              //正常检测到端点,传入NULL和0,获取识别结果,退出循环
              errCode = hci_asr_recog(_sessionID,NULL,0, config.UTF8String, NULL, &asrResult);
              break;
          } else if (errCode == HCI_ERR_ASR_REALTIME_WAITING){
              //等待识别数据,继续循环
              continue;
          } else {
                  // 其它错误,一般不会出现,出现很可能是由于输入数据无效,或实时识别过程错误。
                  // 如果实时识别过程错误,则自动取消该次实时识别
                  // 否则可以手动终止本次实时识别, 然后退出循环
                  // 也可以继续循环,则下次hci_asr_recog()发送的数据会作为前次数据的延续
                  break;
          }
      }
    
  • iOS代码

      //每次获取音频文件后都可以传入hci_asr_recog进行识别,这里只是用while循环演示不断调用hci_asr_recog
      HCI_ERR_CODE errCode = HCI_ERR_NONE;
      ASR_RECOG_RESULT asrResult;  //识别结果保存
      NSString *config = @"audioFormat=pcm16k16bit,encode=none,grammarType=id,grammarId=100";
      //_sessionID:为开启会话(session)后获得的sessionID
      //voiceData:每次获取的音频数据文件,数据类型为NSData
      while (1) {
          errCode = hci_asr_recog(_sessionID, (void *) voiceData.bytes, (unsigned int) voiceData.length, config.UTF8String, NULL, &asrResult);
          if (errCode == HCI_ERR_ASR_REALTIME_END) {
              //正常检测到端点,传入NULL和0,获取识别结果,退出循环
              errCode = hci_asr_recog(_sessionID,NULL,0, config.UTF8String, NULL, &asrResult);
              break;
          } else if (errCode == HCI_ERR_ASR_REALTIME_WAITING) {
              //等待识别数据,继续循环
              continue;
          } else {
                  // 其它错误,一般不会出现,出现很可能是由于输入数据无效,或实时识别过程错误。
                  // 如果实时识别过程错误,则自动取消该次实时识别
                  // 否则可以手动终止本次实时识别, 然后退出循环
                  // 也可以继续循环,则下次hci_asr_recog()发送的数据会作为前次数据的延续
                  break;
          }
      }
    

3.6 结束识别

  • Android代码

      // 终止session
      HciCloudAsr.hciAsrSessionStop(nSessionId);
      //反初始化ASR
      HciCloudAsr.hciAsrRelease();
      //ShowMessage("hciAsrRelease");
      HciCloudSys.hciRelease();
    
  • C++代码

      HCI_ERR_CODE errCode = HCI_ERR_NONE;
      //关闭会话
      errCode = hci_asr_session_stop(sessionID);  //sessionID:已经开启的会话的sessionID
      //终止ASR能力
      errCode  = hci_asr_release();
      //关闭灵云系统
      errCode  = hci_release();
    
  • iOS代码

      //结束session后,调用hci_asr_release和hci_release函数结束能力调用
      HCI_ERR_CODE errCode = HCI_ERR_NONE;
      errCode = hci_asr_session_stop(sessionID);  //sessionID:已经开启的会话的sessionID
      if (errCode != HCI_ERR_NONE){
          NSLog(@"hci_asr_session_stop failed, error:%@", errCode);
          return NO;
      }
      NSLog(@"hci_asr_session_stop success");
      errCode  = hci_asr_release();
      if (errCode != HCI_ERR_NONE){
          NSLog(@"hci_asr_release failed, error:%@", errCode);
          return NO;
      }
      NSLog(@"hci_asr_release success");
      errCode  = hci_release();
      if (errCode != HCI_ERR_NONE){
          NSLog(@"hci_release failed, error:%@", errCode);
          return NO;
      }
      NSLog(@"hci_release success");
      return YES;
    

4. FAQ

results matching ""

    No results matching ""