Unity与讯飞的aiui交互

Unity与讯飞的aiui交互最近项目是做机器人 机器人最大的 普通的 AI 功能就是语音交流 所以 AIUI 就是一个很好的选择

大家好,欢迎来到IT知识分享网。

前言 最近项目是做机器人,机器人最大的(普通的)AI功能就是语音交流,所以AIUI就是一个很好的选择。AIUI是封装了,讯飞的语音合成、语音识别等功能,重点是它有个兜底功能选择,还有技能工作室的加持,虽然在开发应用中有很多的吐槽,但是本人对讯飞还是非常佩服的。而且在做项目时,发现目前unity跟aiui开发的技术文档少,所以还是想写个技术文档希望对看到的人有帮助。(第一次写技术博客,如果有不满,请多多包涵,多多指教,谢谢) 

提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

最近项目是做机器人,机器人最大的(普通的)AI功能就是语音交流,所以AIUI就是一个很好的选择。AIUI是封装了,讯飞的语音合成、语音识别等功能,重点是它有个兜底功能选择,还有技能工作室的加持,虽然在开发应用中有很多的吐槽,但是本人对讯飞还是非常佩服的。而且在做项目时,发现目前unity跟aiui开发的技术文档少,所以还是想写个技术文档希望对看到的人有帮助。(第一次写技术博客,如果有不满,请多多包涵,多多指教,谢谢)


一、AIUI平台配置

示例: 在讯飞申请的应用中—>其他—>AIUI平台,开通AIUI功能。上面有技术文档,是官方AIUI开发技术文档。(如下图)
在这里插入图片描述

二、开发步骤

1.开发环境

Unity,androidStudio

前面(示例):

2.开发代码

代码如下(示例):

AIUIListener mAIUILis=new AIUIListener() { 
      @Override public void onEvent(AIUIEvent aiuiEvent) { 
      switch (aiuiEvent.eventType) { 
      //唤醒事件 case AIUIConstant.EVENT_CONNECTED_TO_SERVER: tips = "已连接服务器"; break; case AIUIConstant.EVENT_SERVER_DISCONNECTED: tips = "与服务器断连" ; break; case AIUIConstant.EVENT_WAKEUP: tips = "进入识别状态" ; break; //结果事件(包含听写,语义,离线语法结果) case AIUIConstant.EVENT_RESULT: if (aiuiEvent.info != null) { 
      int node = 0;//结果解析事件 // s1 try { 
      JSONObject bizParamJson = new JSONObject(aiuiEvent.info); JSONObject data = bizParamJson.getJSONArray("data").getJSONObject(0); JSONObject params = data.getJSONObject("params"); node = 2; JSONObject content = data.getJSONArray("content").getJSONObject(0); long rspTime = aiuiEvent.data.getLong("eos_rslt", -1); //响应时间 // 听写结果(iat) 语义结果(nlp) 后处理服务结果(tpp) 云端tts结果(tts) 翻译结果(itrans) String sub = params.optString("sub"); if (content.has("cnt_id") && !"tts".equals(sub)) //查询对象是否包含该key,返回boolean,与Map.containsKey(key)用法一致 { 
      String cnt_id = content.getString("cnt_id"); node = 0; JSONObject cntJson = new JSONObject(new String(aiuiEvent.data.getByteArray(cnt_id), "utf-8")); // 语义结果 if ("nlp".equals(sub)) { 
      NLPResult(cntJson); } // 听写结果 else if ("iat".equals(sub)) { 
      IATResult(cntJson); } } else if ("tts".equals(sub)) { 
      TTSResult(aiuiEvent, content); //endregion } else { 
      tips = "cnt_id is null" ; } } catch (Throwable e) { 
      } } else { 
      tips = "info is null"; } break; case AIUIConstant.EVENT_TTS: switch (aiuiEvent.arg1) { 
      case AIUIConstant.TTS_SPEAK_BEGIN: tips = ("开始播放"); if (isRecording) { 
      String params = "data_type=audio,sample_rate=16000"; //停止写入 AIUIMessage msg = new AIUIMessage(AIUIConstant.CMD_STOP_RECORD, 0, 0, params, null); mAIUI.sendMessage(msg); } break; case AIUIConstant.TTS_SPEAK_COMPLETED: tips = ("播放完成"); } break; } break; //region START //休眠事件 case AIUIConstant.EVENT_SLEEP: tips = "休眠"; break; // 状态事件 case AIUIConstant.EVENT_STATE: mAIUIState = aiuiEvent.arg1; switch (aiuiEvent.arg1) { 
      // 闲置状态,AIUI未开启 case AIUIConstant.STATE_IDLE: tips = "0:未开启"; break; // AIUI已就绪,等待唤醒 case AIUIConstant.STATE_READY: tips = "1:等待唤醒"; break; // AIUI工作中,可进行交互 case AIUIConstant.STATE_WORKING: // tips="2:可进行交互"; break; } break; //错误事件 case AIUIConstant.EVENT_ERROR: tips = "错误: " + aiuiEvent.arg1 + "\n" + aiuiEvent.info; //aiuiEvent.arg1 =20006 没有开启录音 break; case AIUIConstant.EVENT_START_RECORD: { 
      //开始录音事件 // tips="开始录音 "; } break; case AIUIConstant.EVENT_STOP_RECORD: { 
      //停止录音事件 tips = "停止录音 "; } break; } } }; 

听写解析代码:

 void IATResult(JSONObject iatjson) { 
      JSONObject text=iatjson.optJSONObject("text"); // StringBuffer iatText=new StringBuffer(); try { 
      JSONArray words=text.getJSONArray("ws"); boolean iatResult=text.optBoolean("ls"); for(int node=0;node<words.length();node++) { 
      JSONArray cwWord=words.optJSONObject(node).optJSONArray("cw"); for(int snode=0;snode<cwWord.length();snode++) { 
      iatText.append(cwWord.optJSONObject(snode).opt("w")); } } if(!TextUtils.isEmpty(iatText)) { 
      // tips=iatText+"\n iat="+text.toString(); messageAS=new MessageAS("iat",iatText.toString()); tips=messageAS.ToString(); return; } }catch(Exception e) { 
      } } 

播报解析代码:

 ```java void TTSResult(AIUIEvent event,JSONObject content) { 
      if(content.has("cnt_id")) { 
      String sid = event.data.getString("sid"); try { 
      String cnt_id = content.getString("cnt_id"); byte[] audio = event.data.getByteArray(cnt_id); //合成音频数据 int id=content.getInt("frame_id"); seg =content.getString("text_seg"); if(seg.length()==0||seg==null||seg.equals(",")||seg.equals(" ,")) { 
      return; } else if(textMap.containsKey(id)) { 
      textMap.replace(id,seg); } else if(!textMap.containsValue(seg)) { 
      textMap.put(id,seg); } tips=textMap.values().ToString(); } catch (Exception e) { 
      } } } void NLPResult(JSONObject cntJson) { 
      JSONObject result = cntJson.optJSONObject("intent");//? if(result.length() != 0 && result!=null) return; tips=result.toString(); } 

前面说了讯飞的资源是根据你申请的AIUI配置,是一对一的,再调用讯飞接口时,你会明显感觉它的配置让你想:就不能简单一点。自己配置可以实现多元化的功能需求,但是也是操作麻烦(AIUI的工程师大神,这真的有些烦人)。资源里有配置文件aiui_phone.cfg,各种配置多是跟它有密切关系,请一定要把它放好到assets/scf中,然后解析读取,配置到讯飞的创建中。

private String getAIUIParams() { 
      String params = ""; AssetManager assetManager = getResources().getAssets(); try { 
      InputStream ins = assetManager.open( "cfg/aiui_phone.cfg" ); byte[] buffer = new byte[ins.available()]; ins.read(buffer); ins.close(); params = new String(buffer); } catch (IOException e) { 
      tips="cfg:"+e.toString(); OnTips(tips); } return params; } 

快结束了,申请收音代码:

 public void startVoice() { 
      AIUIMessage setMsg0=new AIUIMessage(AIUIConstant.CMD_TTS, AIUIConstant.PAUSE, 0, null, null); String params = "sample_rate=16000,data_type=audio"; params+=",vad={\"vad_enable\":\"1\",\"engine_type\":\"meta\", \"res_type\":\"assets\",\"res_path\":\"vad/meta_vad_16k.jet\"}"; AIUIMessage writeMsg = new AIUIMessage( AIUIConstant.CMD_START_RECORD, 0, 0, params, null ); String setParams = "{\"global\":{\"scene\":\"main_box\"}}"; AIUIMessage setMsg = new AIUIMessage(AIUIConstant.CMD_SET_PARAMS, 0 , 0, setParams, null); } //取消录音 public void stopVoice() { 
      String params = "data_type=audio,sample_rate=16000"; //停止写入 AIUIMessage msg = new AIUIMessage(AIUIConstant.CMD_STOP_RECORD, 0, 0, params, null); mAIUI.sendMessage(msg); } 

Unity调用讯飞接口跟AIUI SDK交接,你就可以聊天了。

 public AndroidJavaObject andObj; void Start() { 
      AndroidJavaClass jc = new  AndroidJavaClass("com.unity3d.player.UnityPlayer"); andObj = jc.GetStatic<AndroidJavaObject>("currentActivity"); } //调用接口跟讯飞语音交流 void OnVoiceNlp() { 
      // print("fff"); try { 
      andObj.Call("startVoice"; } catch (Exception e) { 
      tips = e.ToString(); } } //获取讯飞语音内容 public void UITips(string str) { 
      textjson.text =str; } 

把解析信息反馈到Unity。


总结

到这里Unity与讯飞的AIUISDK的交互就是完成了,你已经能够再快速的完成一款AI聊天设备。哦,一定要再Android Studio的AndroidManifest.xml里面添加需要的权限,权限代码在讯飞的开发文档里就可以找到。

在这里插入图片描述

补充

UnityPlayer 函数调用,在AS 的对应Module的lib加入Classes.jar

UnityPlayer.UnitySendMessage("ObjName","FunctionName","传递信息"); 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/135955.html

(0)
上一篇 2025-06-30 21:26
下一篇 2025-06-30 21:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信