欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Unity - 演示 ✨ 访问 "KDDI "语音识别 SDK(完成)

最编程 2024-04-17 16:43:53
...



文章目录


  • ​Unity接入讯飞的SDK使用​

  • ​一.Android Studio操作​

      • ​1.工程开始​
      • ​2.建立相应文件夹​
      • ​3.接入Unity的ckasses.jar包​
      • ​4.接入讯飞语音的classess.jar包​
      • ​5.关联两个classes.jar包​
      • ​6.添加libmsc.so​
      • ​7.修改AndroidManifest文件​
      • ​8.写SDK的接口​
      • ​9.打包aar​
      • ​10.修改aar与AndroidManifest​

  • ​二.Unity端的操作​

      • ​1.导入aar包​
      • ​2.搭建一个简易UI​
      • ​3.挂在iFlytekASRController物体上的脚本​
      • ​4.调用方法​
      • ​5.修改Unity中 PlayerSetting​
      • ​6.打包apk到真机测试即可​




Unity接入讯飞的SDK使用

准备工具:

1.​​语音识别的基本知识​

2.​​讯飞的官网注册信息并创建一个应用用于使用SDK​


正文


一.Android Studio操作

1.工程开始

在AS新建一个工程,名字随便。然后新建一个module,起一个名字

File-new-new Module(下图)

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_android

2.建立相应文件夹

然后在java文件夹下新建两个文件夹便于管理语音识别跟语音唤醒,再新建一个MainActivity.class(下图)

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_语音识别_02

3.接入Unity的ckasses.jar包

把Unity的class接入,路径在安装Unity客户端的路径下

Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_json_03

4.接入讯飞语音的classess.jar包

将下载的讯飞SDK文件夹libs下的所有文件也复制到AS工程的libs下,与Unity的classes.jar一样,与下图一样即可

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_unity_04

5.关联两个classes.jar包

右键libs文件夹下两个.jar文件,Add As Libray…

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_unity_05

也可以右键iflytevoice,Open Module Settings

将.jar文件手动添加,添加完了记得点apply应用一下

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_android_06

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_android_07

6.添加libmsc.so

在main文件夹下新建一个Jnilibs文件夹,然后将libmsc.so添加进去。libmsc.so在讯飞SDK文件夹里的libs\armeabi-v7a下,最好连armeabi-v7a文件夹一起复制进去。效果如下

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_语音识别_08

7.修改AndroidManifest文件

将app下的AndroidManifest的以下蓝色内容复制到我们module的AndroidManifest中,如下

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_unity_09

改成这样就行了,这里注意一下,将这个的name改成自己之前建立的类名,我的是asr.asrPort

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_语音识别_10

然后将以下代码添加到AndroidManifest中,这些代码是获取相应的权限,比如存取、录音机等权限

​<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BROADCAST_STICKY" />​

AndroidManifest算是配置完了

8.写SDK的接口

到了这一步,讯飞的SDK算是配置差不多了,接下来就是写方法使用了

先写语音识别的代码,在之前建立的asrPort类中写

package com.example.iflytekvoice.asr;
import android.os.Bundle;
import com.example.iflytekvoice.JsonParser;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SpeechUtility;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.LinkedHashMap;
public class asrPort extends UnityPlayerActivity{
private SpeechRecognizer mIat;
private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//初始化
SpeechUtility.createUtility(this, SpeechConstant.APPID + "=60307482");
mIat = SpeechRecognizer.createRecognizer(this, null);
//设置mIat的参数
//表示是什么服务
mIat.setParameter(SpeechConstant.DOMAIN, "iat");
//设置语言
mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
//接受语言的类型
mIat.setParameter(SpeechConstant.ACCENT, "mandarin");
//使用什么样引擎
mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
}
RecognizerListener mRecognizerLis=new RecognizerListener() {
@Override
public void onVolumeChanged(int i, byte[] bytes) {
}
@Override
public void onBeginOfSpeech() {
}
@Override
public void onEndOfSpeech() {
}
@Override
public void onResult(RecognizerResult recognizerResult, boolean b) {
printResult(recognizerResult);
}
@Override
public void onError(SpeechError speechError) {
}
@Override
public void onEvent(int i, int i1, int i2, Bundle bundle) {
}
};
//解析Json的方法
//方法来自speechDemo->java->voicedemo->IatDemo中的printResult方法
private void printResult(RecognizerResult results) {
String text = JsonParser.parseIatResult(results.getResultString());
String sn = null;
// 读取json结果中的sn字段
try {
JSONObject resultJson = new JSONObject(results.getResultString());
sn = resultJson.optString("sn");
} catch (JSONException e) {
e.printStackTrace();
}
mIatResults.put(sn, text);
StringBuffer resultBuffer = new StringBuffer();
for (String key : mIatResults.keySet()) {
resultBuffer.append(mIatResults.get(key));
}
//把消息发送给Unity场景中iFlytekASRController物体上的OnResult方法
UnityPlayer.UnitySendMessage("iFlytekASRController", "OnResult", resultBuffer.toString());
}
public void beginListen(){
//开始识别
mIat.startListening(mRecognizerLis);
}
public void connected(){
UnityPlayer.UnitySendMessage("iFlytekASRController","tryConnected","连通成功了");
}
public int beginTest(int a, int b){
//交互测试
return a+b;
}
}

其中还加了一个解析Json的类,直接新建在java文件夹下就行。JsonParser如下

package com.example.iflytekvoice;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
/**
* Json结果解析类
*/
public class JsonParser {
public static String parseIatResult(String json) {
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener);
JSONArray words = joResult.getJSONArray("ws");
for (int i = 0; i < words.length(); i++) {
// 转写结果词,默认使用第一个结果
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
JSONObject obj = items.getJSONObject(0);
ret.append(obj.getString("w"));
// 如果需要多候选结果,解析数组其他字段
// for(int j = 0; j < items.length(); j++)
// {
// JSONObject obj = items.getJSONObject(j);
// ret.append(obj.getString("w"));
// }
}
} catch (Exception e) {
e.printStackTrace();
}
return ret.toString();
}

public static String parseGrammarResult(String json) {
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener);
JSONArray words = joResult.getJSONArray("ws");
for (int i = 0; i < words.length(); i++) {
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
for(int j = 0; j < items.length(); j++)
{
JSONObject obj = items.getJSONObject(j);
if(obj.getString("w").contains("nomatch"))
{
ret.append("没有匹配结果.");
return ret.toString();
}
ret.append("【结果】" + obj.getString("w"));
ret.append("【置信度】" + obj.getInt("sc"));
ret.append("\n");
}
}
} catch (Exception e) {
e.printStackTrace();
ret.append("没有匹配结果.");
}
return ret.toString();
}

public static String parseLocalGrammarResult(String json) {
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener);
JSONArray words = joResult.getJSONArray("ws");
for (int i = 0; i < words.length(); i++) {
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
for(int j = 0; j < items.length(); j++)
{
JSONObject obj = items.getJSONObject(j);
if(obj.getString("w").contains("nomatch"))
{
ret.append("没有匹配结果.");
return ret.toString();
}
ret.append("【结果】" + obj.getString("w"));
ret.append("\n");
}
}
ret.append("【置信度】" + joResult.optInt("sc"));
} catch (Exception e) {
e.printStackTrace();
ret.append("没有匹配结果.");
}
return ret.toString();
}
public static String parseTransResult(String json,String key) {
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener);
String errorCode = joResult.optString("ret");
if(!errorCode.equals("0")) {
return joResult.optString("errmsg");
}
JSONObject transResult = joResult.optJSONObject("trans_result");
ret.append(transResult.optString(key));
/*JSONArray words = joResult.getJSONArray("results");
for (int i = 0; i < words.length(); i++) {
JSONObject obj = words.getJSONObject(i);
ret.append(obj.getString(key));
}*/
} catch (Exception e) {
e.printStackTrace();
}
return ret.toString();
}
}

在asrPort后面加入的几个方法是用于后边与unity交互使用的,暂时写上即可,后边会用到。

到此为止,在asrPort中写完了语音识别的方法类,打包aar包给Unity导入用即可。

9.打包aar

上面在AS写的工程给Unity使用,选中module,右键选择"Make Module ‘iflytekvoice’"等待片刻

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_语音识别_11

将aar包与AndroidManifest复制到自己一个文件夹中(如下)

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_json_12

10.修改aar与AndroidManifest

1.aar包中的文件如下,进入libs文件夹,将里面的classes.jar删掉,换成根目录下的这个classes.jar

将下图中的"假"删掉,"真"的剪切进去,只能留"真"的那一个,两个Unity打包时会报错

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_语音识别_13Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_json_14

然后修改aar包中的AndroidManifest,将 “android:label="这行删掉,这里是设置打包出来的apk名字,这里不删会与aar包外的那个AndroidManifest冲突(跟着做就对了,我都是摸爬滚打一堆bug改过来的…)

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_json_15

修改aar包外的AndroidManifest,只需要改package即可,这里改成与包内的不一样即可,但是在Unity playerSetting中的PackageName一定要与这里设置的一样,要不然unity掉不到AS中写的方法。如下图

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_unity_16

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_json_17

到这里,在AS的操作就结束了,aar包也打出来了,在Unity中用即可,下面写在Unity中的操作步骤


二.Unity端的操作

1.导入aar包

在Unity的Assets内新建Plugins/Android文件夹,将aar于AndroidManifest文件放入进去即可。如下所示

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_unity_18

2.搭建一个简易UI

示例如下。一个Text组件用于显示语音识别出来的内容,一个Button组件用于点击就开始进行语音识别

下面的Try是为了确认aar包在Unity中正常连通了,之前在AS里写了方法就是为了留给点击这个按钮后调用的

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_json_19

3.挂在iFlytekASRController物体上的脚本

代码如下,只有简单两个点击事件,和调用aar包内的方法

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SpeechManager : MonoBehaviour
{
public Text ASRmsg;
public Text tryTex;
public Text aad;
private Button TryBtn;
private Button ASR_Btn;
private AndroidJavaObject jo;

private void Awake()
{
ASR_Btn = GameObject.Find("Speech/ASR_Btn").GetComponent<Button>();
TryBtn = GameObject.Find("Test/TryBtn").GetComponent<Button>();
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
}
void Start()
{
ASR_Btn.onClick.AddListener(()=> {
jo.Call("beginListen");
});
TryBtn.onClick.AddListener(tryConnect);
}
public void OnResult(string msg)
{
ASRmsg.text = msg;
}
/// <summary>
/// 点击Try按钮
/// </summary>
public void tryConnect()
{
int aaa;
aaa=jo.Call<int>("beginTest",2,3);
aad.text = aaa.ToString();
jo.Call("connected");
}
public void tryConnected(string tryMsg)
{
tryTex.text = tryMsg;
Color ramColor = ColorRandom();
tryTex.color = ramColor;
}
public Color ColorRandom()
{
float r = Random.Range(0f,1f);
float g = Random.Range(0f, 1f);
float b = Random.Range(0f, 1f);
Color color = new Color(r, g, b);
return color;
}
}

要记得将脚本挂到这个物体上,因为也是在AS中写好的,也可以在AS那边改

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_语音识别_20

4.调用方法

其中下图是固定写法,大家Unity这部分自己随意发挥,只要方法名与在AndroidStudio中写的一样即可,要不然调不到

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_json_21

①Unity内调用Android Studio内的方法

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_android_22

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_android_23


②Android Studio内调用Unity中的方法

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_json_24

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_语音识别_25

5.修改Unity中 PlayerSetting

这里一定要与aar外的AndroidManifest中的pakeage名字一样才能调用aar包中写的方法

Unity -Demo 之 ✨ 接入“科大讯飞”语音识别SDK(完整)_json_26

6.打包apk到真机测试即可



总结:到此为止,一个简单的科大讯飞语音识别的SDK就接入Unity可以使用了,至于怎么使用就随意发挥了。
文章不算短,但是真正的核心部分不多。看起来挺复杂,其实仔细一想也没干什么事。从Android方面不是很懂,连Android
Studio都不是很熟练,自己在网上摸索了一周左右,才学会打包aar,安卓与Unity简单交互,接入科大讯飞SDK等。
此文章主要写了在Unity接科大讯飞语音识别SDK的全过程,核心不多,但是每个细节都不能出错,因为我就是从bug堆里摸索出来的,毕竟安卓这方面实在差的太远了。


本来是想一篇文章写语音识别+语音唤醒的,一看太多了,就只写了语音识别,下篇文章写语音唤醒(只写语音唤醒的接口)。如果哪个地方没搞出来,或者我这哪里写的不太对都可以评论区告诉我哦,看到有时间就会回复的。