https://ai.baidu.com/sdk#tts
本教程使用AndroidStudio3.6.3版本
由于是第三方插件,并且项目中已经有了一个第三方的插件,众所周知,Unity与安卓交互时,安卓端只能有一个Activity继承自UnityPlayerActivity,所以为了不与其他人的sdk冲突,我们便使用不继承UnityPlayerActivity的Java类
并且创建安卓版语音技术应用
jar包位于core/libs/目录下
在我们创建好的项目中导入该sdk,
如何创建项目请参考我的另一篇博文
https://blog.csdn.net/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 {
@Override
public 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 params = new LinkedHashMap();
// 基于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; // 可以替换成自己的json
json = new JSONObject(params).toString(); // 这里可以替换成你需要测试的json
asr.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 {
@Override
public 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();
//将结果发送给Unity
UnityPlayer.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 params = new HashMap();
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;
}
因为语音唤醒是离线的,需要从百度语音技术官网中导出.bin文件
网址
自定义唤醒词 在 http://ai.baidu.com/tech/speech/wake
最后导出并下载.bin文件,将文件放到我们的项目下的assets目录下
如何创建assets目录?
请查看我的另一篇博文中的设置签名
https://blog.csdn.net/weixin_43271060/article/details/90318254
在我们新建的Module中的build.gradle中设置
task copyPlugin(type: Copy) {
dependsOn assemble
from('build/outputs/aar')
into('../../Assets/Plugins/Android')
include(project.name + '-release.aar')
}
然后在右上角的Gradle中的wxplugins->Task->other中选择copyPlugin即可导出指定的并且已经存在的目录中
void Start()
{
AndroidJavaClass _androidJC = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
if (_androidJC == null)
{
Debug.Log("JNI initialization failure.");
return;
}
m_AndroidPluginObj = _androidJC.GetStatic("currentActivity");
}
public void InitAsr()
{
AndroidJavaClass jc = new AndroidJavaClass("com.xxx.xxx.CientBaiDuVoiceMainActivity");//包名加类名
AndroidJavaObject m_Android = jc.CallStatic("getInstance");
if (m_Android != null)
{
m_Android.Call("InitRecogn", m_AndroidPluginObj);
}
else
Debug.Log("AndroidPlugin is Null");
}
public void StartRecogn()
{
AndroidJavaClass jc = new AndroidJavaClass("com.xxx.xxx.CientBaiDuVoiceMainActivity");
AndroidJavaObject m_Android = jc.CallStatic("getInstance");
if (m_Android != null)
{
m_Android.Call("StartRecogn");
}
else
Debug.Log("AndroidPlugin is Null");
}
public void StopRecogn()
{
AndroidJavaClass jc = new AndroidJavaClass("com.xxx.xxx.CientBaiDuVoiceMainActivity");
AndroidJavaObject m_Android = jc.CallStatic("getInstance");
if (m_Android != null)
{
m_Android.Call("StopRecogn");
}
else
Debug.Log("AndroidPlugin is Null");
}
public void InitWakeUp()
{
AndroidJavaClass jc = new AndroidJavaClass("com.xxx.xxx.CientBaiDuVoiceMainActivity");
AndroidJavaObject m_Android = jc.CallStatic("getInstance");
if (m_Android != null)
{
m_Android.Call("InitWakeUp", m_AndroidPluginObj);
}
else
Debug.Log("AndroidPlugin is Null");
}
public void StartWakeUp()
{
AndroidJavaClass jc = new AndroidJavaClass("com.xxx.xxx.CientBaiDuVoiceMainActivity");
AndroidJavaObject m_Android = jc.CallStatic("getInstance");
if (m_Android != null)
{
m_Android.Call("StartWakeUp");
}
else
Debug.Log("AndroidPlugin is Null");
}
public void StopWakeUp()
{
AndroidJavaClass jc = new AndroidJavaClass("com.xxx.xxx.CientBaiDuVoiceMainActivity");
AndroidJavaObject m_Android = jc.CallStatic("getInstance");
if (m_Android != null)
{
m_Android.Call("StopWakeUp");
}
else
Debug.Log("AndroidPlugin is Null");
}
public Text mRecognRes;
///
/// 百度语音唤醒结果反馈
///
///
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();
}
}
}
///
/// 百度语音识别结果反馈
///
///
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;
}
https://blog.csdn.net/weixin_43271060/article/details/108383451