第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > Unity3D接入百度语音识别实时识别带唤醒SDK(安卓版)

Unity3D接入百度语音识别实时识别带唤醒SDK(安卓版)

时间:2021-01-31 15:00:03

相关推荐

Unity3D接入百度语音识别实时识别带唤醒SDK(安卓版)

一、首先下载官方Demo

/sdk#tts

二、版本介绍

本教程使用AndroidStudio3.6.3版本

由于是第三方插件,并且项目中已经有了一个第三方的插件,众所周知,Unity与安卓交互时,安卓端只能有一个Activity继承自UnityPlayerActivity,所以为了不与其他人的sdk冲突,我们便使用不继承UnityPlayerActivity的Java类

三、注册百度云账号

并且创建安卓版语音技术应用

四、导入官方demo中的sdk以及库文件

jar包位于core/libs/目录下

在我们创建好的项目中导入该sdk,

如何创建项目请参考我的另一篇博文

/weixin_43271060/article/details/90318254

导入步骤

选中jar包,然后按下Ctrl+C,在我们创建好的项目中选择Libs目录,然后按下Ctrl+V,这是导入,然后就是引用

1、选择File->Project Structure打开Project Structure窗口

2、选择Dependencies->我们自己创建的Module

选择我们导入的jar包

最后点击Apply

导入官方的库文件,位于core->src-main下方

jniLibs目录下就是我们所需的库文件,然后复制jniLibs文件夹,然后粘贴到我们的项目中的src->main目录下

五、代码部分

1、创建百度语音主类,然后将它制成单利

public static CientBaiDuVoiceMainActivity _instance;public static CientBaiDuVoiceMainActivity getInstance() {if (_instance == null) {_instance = new CientBaiDuVoiceMainActivity();}return _instance;}

2、编写语音识别

选择包名,然后右键创建一个Package,名字为Recogn

3、创建语音识别监听识别后回调的类

package com.xxx.xxx.Recogn;//填写自己的包名import com.baidu.speech.EventListener;import com.baidu.speech.asr.SpeechConstant;import com.unity3d.player.UnityPlayer;public class RecognListener implements EventListener {@Overridepublic void onEvent(String name, String params, byte[] data, int i, int i1) {if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)) {// 识别相关的结果都在这里if (params == null || params.isEmpty()) {return;}if (params.contains("\"partial_result\"")) {UnityPlayer.UnitySendMessage("NetLogic", "RecognResult", name + "&" + params);// 一句话的临时识别结果} else if (params.contains("\"final_result\"")) {UnityPlayer.UnitySendMessage("NetLogic", "RecognResult", name + "&" + params);// 一句话的最终识别结果} else {// 一般这里不会运行if (data != null) {}}} else {// 识别开始,结束,音量,音频数据回调if (params != null && !params.isEmpty()) {}if (data != null) {}}}};

4、编写语音识别处理类

package com.xxx.xxx.Recogn;//自己的包名import android.Manifest;import android.content.Context;import android.content.pm.PackageManager;import android.os.Build;import com.baidu.speech.EventListener;import com.baidu.speech.EventManager;import com.baidu.speech.EventManagerFactory;import com.baidu.speech.asr.SpeechConstant;import org.json.JSONObject;import java.util.LinkedHashMap;import java.util.Map;import static com.xxx.xxx.Util.GetActivity.getActivityByContext;public class RecognHandler {private boolean mIsInit = false;private EventManager asr;private EventListener mEventLisener;public RecognHandler(Context context, EventListener listener) {if (mIsInit) {listener=null;return;}mIsInit = true;mEventLisener = listener;//动态申请权限initPermission(context);asr = EventManagerFactory.create(context, "asr");asr.registerListener(listener);}//开始识别public void Start() {Map<String, Object> params = new LinkedHashMap<String, Object>();// 基于SDK集成2.1 设置识别参数params.put(SpeechConstant.ACCEPT_AUDIO_VOLUME, true);params.put(SpeechConstant.DISABLE_PUNCTUATION, false);params.put(SpeechConstant.ACCEPT_AUDIO_DATA, false);params.put(SpeechConstant.PID, 1537); // 中文输入法模型,有逗号String json = null; // 可以替换成自己的jsonjson = new JSONObject(params).toString(); // 这里可以替换成你需要测试的jsonasr.send(SpeechConstant.ASR_START, json, null, 0, 0);}//停止识别public void Stop() {asr.send(SpeechConstant.ASR_STOP, null, null, 0, 0);}//释放实例public void Release() {asr.unregisterListener(mEventLisener);mIsInit = false;asr=null;}/*** android 6.0 以上需要动态申请权限*/private void initPermission(Context context) {String permissions[] = {Manifest.permission.RECORD_AUDIO,Manifest.permission.ACCESS_NETWORK_STATE,Manifest.permission.INTERNET,Manifest.permission.WRITE_EXTERNAL_STORAGE};PackageManager pm = getActivityByContext(context).getPackageManager();boolean permission_readStorage = (PackageManager.PERMISSION_GRANTED ==pm.checkPermission("android.permission.RECORD_AUDIO", "com.cientx.tianguo"));boolean permission_network_state = (PackageManager.PERMISSION_GRANTED ==pm.checkPermission("android.permission.ACCESS_NETWORK_STATE", "com.cientx.tianguo"));boolean permission_internet = (PackageManager.PERMISSION_GRANTED ==pm.checkPermission("android.permission.INTERNET", "com.cientx.tianguo"));boolean permission_writeStorage = (PackageManager.PERMISSION_GRANTED ==pm.checkPermission("android.permission.WRITE_EXTERNAL_STORAGE", "com.cientx.tianguo"));if (!(permission_readStorage && permission_writeStorage && permission_network_state && permission_internet)) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {getActivityByContext(context).requestPermissions(permissions, 0x01);}}}}

5、创建一个工具Package名字叫Util

里面添加两个类,GetActivity用户根据Context获取Activity,LogPrint用于输出日志

package com.xxx.xxx.Util;//自己的包名import android.app.Activity;import android.content.Context;import android.content.ContextWrapper;public class GetActivity {public static Activity getActivityByContext(Context context){while(context instanceof ContextWrapper){if(context instanceof Activity){return (Activity) context;}context = ((ContextWrapper) context).getBaseContext();}return null;}}

package com.xxx.xxx.Util;//自己的包名import com.tencent.mm.opensdk.utils.Log;public class LogPrint {public static void Log(String logStr){Log.d("AndroidLog",logStr);}}

6、创建一个用于语音唤醒的Package名字叫Wakeup,并且创建三个类WakeupHandler(处理唤醒)、WakeupListener(监听唤醒结果)、WakeUpResult(唤醒结果解析获取)

package com.xxx.xxx.Wakeup;//自己的包名import com.baidu.speech.EventListener;import com.baidu.speech.asr.SpeechConstant;import com.unity3d.player.UnityPlayer;public class WakeupListener implements EventListener {@Overridepublic void onEvent(String name, String params, byte[] bytes, int i, int i1) {if (SpeechConstant.CALLBACK_EVENT_WAKEUP_SUCCESS.equals(name)) { // 识别唤醒词成功WakeUpResult result = WakeUpResult.parseJson(name, params);int errorCode = result.getErrorCode();if (result.hasError()) { // error不为0依旧有可能是异常情况} else {String word = result.getWord();//将结果发送给UnityUnityPlayer.UnitySendMessage("NetLogic", "WakeupResult", name+"&"+params);}} else if (SpeechConstant.CALLBACK_EVENT_WAKEUP_ERROR.equals(name)) { // 识别唤醒词报错WakeUpResult result = WakeUpResult.parseJson(name, params);int errorCode = result.getErrorCode();if (result.hasError()) {}} else if (SpeechConstant.CALLBACK_EVENT_WAKEUP_STOPED.equals(name)) { // 关闭唤醒词} else if (SpeechConstant.CALLBACK_EVENT_WAKEUP_AUDIO.equals(name)) { // 音频回调}}}

package com.xxx.xxx.Wakeup;import com.baidu.speech.asr.SpeechConstant;import org.json.JSONException;import org.json.JSONObject;public class WakeUpResult {private String name;private String origalJson;private String word;private String desc;private int errorCode;private static int ERROR_NONE = 0;private static final String TAG = "WakeUpResult";public boolean hasError() {return errorCode != ERROR_NONE;}public String getOrigalJson() {return origalJson;}public void setOrigalJson(String origalJson) {this.origalJson = origalJson;}public String getWord() {return word;}public void setWord(String word) {this.word = word;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}public int getErrorCode() {return errorCode;}public void setErrorCode(int errorCode) {this.errorCode = errorCode;}public String getName() {return name;}public void setName(String name) {this.name = name;}public static WakeUpResult parseJson(String name, String jsonStr) {WakeUpResult result = new WakeUpResult();result.setOrigalJson(jsonStr);try {JSONObject json = new JSONObject(jsonStr);if (SpeechConstant.CALLBACK_EVENT_WAKEUP_SUCCESS.equals(name)) {int error = json.optInt("errorCode");result.setErrorCode(error);result.setDesc(json.optString("errorDesc"));if (!result.hasError()) {result.setWord(json.optString("word"));}} else {int error = json.optInt("error");result.setErrorCode(error);result.setDesc(json.optString("desc"));}} catch (JSONException e) {e.printStackTrace();}return result;}}

package com.xxx.xxx.Wakeup;//自己的包名import android.Manifest;import android.content.Context;import android.content.pm.PackageManager;import android.os.Build;import com.baidu.speech.EventListener;import com.baidu.speech.EventManager;import com.baidu.speech.EventManagerFactory;import com.baidu.speech.asr.SpeechConstant;import org.json.JSONObject;import java.util.HashMap;import java.util.Map;import static com.xxx.xxx.Util.GetActivity.getActivityByContext;public class WakeupHandler {private static boolean isInited = false;private EventManager wp;private EventListener eventListener;private static final String TAG = "MyWakeup";public WakeupHandler(Context context, EventListener eventListener) {if (isInited) {eventListener = null;return;}isInited = true;this.eventListener = eventListener;//动态申请权限initPermission(context);wp = EventManagerFactory.create(context, "wp");wp.registerListener(eventListener);}//开始唤醒public void Start() {Map<String, Object> params = new HashMap<String, Object>();params.put(SpeechConstant.WP_WORDS_FILE, "assets:///WakeUp.bin");params.put(SpeechConstant.APP_ID, "22328262");params.put(SpeechConstant.APP_KEY, "At03gUWQMzSysSmWHixFZ098");params.put(SpeechConstant.SECRET, "4z1Cuow14AF4jAQmmlS1P7BiZ5HA15Vb");String json = new JSONObject(params).toString();wp.send(SpeechConstant.WAKEUP_START, json, null, 0, 0);}// 停止唤醒public void Stop() {wp.send(SpeechConstant.WAKEUP_STOP, null, null, 0, 0);}//释放实例public void Release() {wp.unregisterListener(eventListener);wp = null;isInited = false;}//申请权限private void initPermission(Context context) {String permissions[] = {Manifest.permission.RECORD_AUDIO,Manifest.permission.ACCESS_NETWORK_STATE,Manifest.permission.INTERNET,Manifest.permission.WRITE_EXTERNAL_STORAGE};PackageManager pm = getActivityByContext(context).getPackageManager();boolean permission_readStorage = (PackageManager.PERMISSION_GRANTED ==pm.checkPermission("android.permission.RECORD_AUDIO", "com.cientx.tianguo"));boolean permission_network_state = (PackageManager.PERMISSION_GRANTED ==pm.checkPermission("android.permission.ACCESS_NETWORK_STATE", "com.cientx.tianguo"));boolean permission_internet = (PackageManager.PERMISSION_GRANTED ==pm.checkPermission("android.permission.INTERNET", "com.cientx.tianguo"));boolean permission_writeStorage = (PackageManager.PERMISSION_GRANTED ==pm.checkPermission("android.permission.WRITE_EXTERNAL_STORAGE", "com.cientx.tianguo"));if (!(permission_readStorage && permission_writeStorage && permission_network_state && permission_internet)) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {getActivityByContext(context).requestPermissions(permissions, 0x01);}}}}

7、在语音技术主类CientBaiDuVoiceMainActivity中调用语音识别、语音唤醒接口

//语音识别RecognHandler mRecognHandler;//语音唤醒WakeupHandler mWakeup;//语音合成SpeechSynthesizerHandler mSynthesizerHandler;//语音识别初始化public void InitRecogn(Context context) {RecognListener listener=new RecognListener();mRecognHandler=new RecognHandler(context,listener);}//开始语音识别public void StartRecogn() {mRecognHandler.Start();}//停止语音识别public void StopRecogn() {mRecognHandler.Stop();}//释放语音识别实例public void ReleaseRecogn() {mRecognHandler.Release();mRecognHandler=null;}//唤醒初始化public void InitWakeUp(Context context){WakeupListener listener=new WakeupListener();mWakeup = new WakeupHandler(context,listener);}//开始唤醒public void StartWakeUp(){mWakeup.Start();}//停止唤醒public void StopWakeUp(){mWakeup.Stop();}//释放唤醒实例public void ReleaseWakeUp(){mWakeup.Release();mWakeup=null;}

六、编写AndroidManifest.cml文件

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="/apk/res/android"xmlns:tools="/tools"package="com.xxx.xxx"> <!-- 填写自己的包名 --><!-- 通用权限 --><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!-- 语音识别权限 --><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><!-- 语音合成权限 --><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.WRITE_SETTINGS"tools:ignore="ProtectedPermissions" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /><application android:allowBackup="true"><activity android:name=".Wakeup.WakeUpResult"></activity><activity android:name=".Wakeup.WakeupHandler" /><activityandroid:name=".CientBaiDuVoiceMainActivity"android:launchMode="singleTask" /><!-- 请填写真实的APP_ID API_KEY SECRET_KEY --><meta-dataandroid:name="com.baidu.speech.APP_ID"android:value="xxxxx" /><meta-dataandroid:name="com.baidu.speech.API_KEY"android:value="xxxxx" /><meta-dataandroid:name="com.baidu.speech.SECRET_KEY"android:value="xxxxx" /><serviceandroid:name="com.baidu.speech.VoiceRecognitionService"android:exported="false" /></application></manifest>

因为语音唤醒是离线的,需要从百度语音技术官网中导出.bin文件

网址

自定义唤醒词在/tech/speech/wake

最后导出并下载.bin文件,将文件放到我们的项目下的assets目录下

如何创建assets目录?

七、设置签名

请查看我的另一篇博文中的设置签名

/weixin_43271060/article/details/90318254

八、导出arr包

在我们新建的Module中的build.gradle中设置

task copyPlugin(type: Copy) {dependsOn assemblefrom('build/outputs/aar')into('../../Assets/Plugins/Android')include(project.name + '-release.aar')}

然后在右上角的Gradle中的wxplugins->Task->other中选择copyPlugin即可导出指定的并且已经存在的目录中

九、Unity中调用

void Start(){AndroidJavaClass _androidJC = new AndroidJavaClass("com.unity3d.player.UnityPlayer");if (_androidJC == null){Debug.Log("JNI initialization failure.");return;}m_AndroidPluginObj = _androidJC.GetStatic<AndroidJavaObject>("currentActivity");}public void InitAsr(){AndroidJavaClass jc = new AndroidJavaClass("com.xxx.xxx.CientBaiDuVoiceMainActivity");//包名加类名AndroidJavaObject m_Android = jc.CallStatic<AndroidJavaObject>("getInstance");if (m_Android != null){m_Android.Call("InitRecogn", m_AndroidPluginObj);}elseDebug.Log("AndroidPlugin is Null");}public void StartRecogn(){AndroidJavaClass jc = new AndroidJavaClass("com.xxx.xxx.CientBaiDuVoiceMainActivity");AndroidJavaObject m_Android = jc.CallStatic<AndroidJavaObject>("getInstance");if (m_Android != null){m_Android.Call("StartRecogn");}elseDebug.Log("AndroidPlugin is Null");}public void StopRecogn(){AndroidJavaClass jc = new AndroidJavaClass("com.xxx.xxx.CientBaiDuVoiceMainActivity");AndroidJavaObject m_Android = jc.CallStatic<AndroidJavaObject>("getInstance");if (m_Android != null){m_Android.Call("StopRecogn");}elseDebug.Log("AndroidPlugin is Null");}public void InitWakeUp(){AndroidJavaClass jc = new AndroidJavaClass("com.xxx.xxx.CientBaiDuVoiceMainActivity");AndroidJavaObject m_Android = jc.CallStatic<AndroidJavaObject>("getInstance");if (m_Android != null){m_Android.Call("InitWakeUp", m_AndroidPluginObj);}elseDebug.Log("AndroidPlugin is Null");}public void StartWakeUp(){AndroidJavaClass jc = new AndroidJavaClass("com.xxx.xxx.CientBaiDuVoiceMainActivity");AndroidJavaObject m_Android = jc.CallStatic<AndroidJavaObject>("getInstance");if (m_Android != null){m_Android.Call("StartWakeUp");}elseDebug.Log("AndroidPlugin is Null");}public void StopWakeUp(){AndroidJavaClass jc = new AndroidJavaClass("com.xxx.xxx.CientBaiDuVoiceMainActivity");AndroidJavaObject m_Android = jc.CallStatic<AndroidJavaObject>("getInstance");if (m_Android != null){m_Android.Call("StopWakeUp");}elseDebug.Log("AndroidPlugin is Null");}public Text mRecognRes;/// <summary>/// 百度语音唤醒结果反馈/// </summary>/// <param name="res"></param>void WakeupResult(string res){string[] ress = res.Split('&');JsonData jsonData = JsonMapper.ToObject(ress[1]);if (ress[0] == "wp.data"){if (jsonData["errorCode"].ToString() == "0"){mRecognRes.text = "唤醒成功:" + jsonData["word"].ToString();}}}/// <summary>/// 百度语音识别结果反馈/// </summary>/// <param name="res"></param>void RecognResult(string res){string[] ress = res.Split('&');JsonData jsonData = JsonMapper.ToObject(ress[1]);string resStr = "";if (jsonData["result_type"].ToString() == "partial_result"){resStr = "临时识别结果:";}else{resStr = "最终识别结果:";}resStr += jsonData["best_result"].ToString();mRecognRes.text = resStr;}

十、发布arr包遇到的问题,请查看我的另一边博客

/weixin_43271060/article/details/108383451

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。