说明:讯飞离线语音听写目前只有Android平台,当前时间是2020年03月06号,本博客介绍使用Unity来搭建这个demo作为测试
Unity导出离线语音听写apk
描述:采用讯飞的离线语音SDK在unity上进行导出
条件:需要注册讯飞开放平台账号,Android Studio,Unity
原理:使用Android Studio导出AAR包给Unity,在Unity上进行操作控制
第一步:你得注册一个账号用来下载SDK
默认你已经注册好了,你需要注意免费试用是有时间限制的。
现在看看它下载下来的样子:
第二步:在Android Studio上的处理
1. 建立一个工程
下面不使用布局文件,Generate Layout File 不勾选
很好,接下来调成Project模式,你的结构如下
2. 新增一个模块
填写库名,模块名,这里也有一个包名,记住它,接下来所有的操作都将在这个模块里完成
3. 添加第三方资源
找到从讯飞下载下来的文件夹,找到libs,选择这两项,添加到模块iatlibrary/libs
里面
在Unity安装目录下找到这个jar包,同样的添加到模块iatlibrary/libs.
然后再去sample里找到JsonParse这个文件,添加到iatlibrary/src/main/java/你的包名 下面
现在你的项目里是这样的
接下来把classes.jar和Msc.jar以库文件的形式进行添加
这是完成后的样子
AndroidStudio要添加的东西完成了,接下来是写东西和导出AAR包
4. 写代码(活动)
代码如下:
package com.zy.iatlibrary;
import android.os.Bundle;
import android.widget.Toast;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
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.iflytek.cloud.util.ResourceUtil;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
/**
* Created by zy on 2020/3/6.
*/
public class Iat extends UnityPlayerActivity{
private SpeechRecognizer mIat;
private String result= "";
private String mEngineType = SpeechConstant.TYPE_LOCAL;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
SpeechUtility.createUtility(this, SpeechConstant.APPID + "=9y35h930h");
mIat = SpeechRecognizer.createRecognizer(this, mTtsInitListener);
if(mIat==null)
{
Toast.makeText(Iat.this,"对象为空,检查是否有jet资源",Toast.LENGTH_LONG).show();
return;
}
else
{
mIat.setParameter(SpeechConstant.PARAMS,null);
mIat.setParameter(SpeechConstant.ENGINE_TYPE,mEngineType);
if (mEngineType.equals(SpeechConstant.TYPE_LOCAL))
{
mIat.setParameter(ResourceUtil.ASR_RES_PATH,getResourcePath());
}
mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
mIat.setParameter(SpeechConstant.KEY_SPEECH_TIMEOUT, "20000"); //语音输入超时时间 设置录取音频的最长时间
mIat.setParameter(SpeechConstant.VAD_BOS,"3000"); //开始录入音频后,音频前面部分最长静音时长
mIat.setParameter(SpeechConstant.VAD_EOS, "2000"); //开始录入音频后,音频后面部分最长静音时长
}
}
//Unity调用这个方法
public void StartListening(String str)
{
Toast.makeText(Iat.this,str,Toast.LENGTH_LONG).show();
int ret = mIat.startListening(mRecognizerListener);
UnityPlayer.UnitySendMessage("GameObject","OnStartListening",String.valueOf(ret));
}
/**初始化监听**/
private InitListener mTtsInitListener = new InitListener()
{
@Override
public void onInit(int i)
{
if (i!= ErrorCode.SUCCESS)
{
Toast.makeText(Iat.this,"初始化失败,错误码:" + i+",请点击网址https://www.xfyun.cn/document/error-code查询解决方案",Toast.LENGTH_LONG).show();
}
UnityPlayer.UnitySendMessage("GameObject","OnStartListening",String.valueOf(i));
}
};
private RecognizerListener mRecognizerListener =new RecognizerListener() {
@Override
public void onVolumeChanged(int i, byte[] bytes) {
}
@Override
public void onBeginOfSpeech()
{
UnityPlayer.UnitySendMessage("GameObject","OnBeginOfSpeech","");
}
@Override
public void onEndOfSpeech()
{
UnityPlayer.UnitySendMessage("GameObject","OnEndOfSpeech","");
}
@Override
public void onResult(RecognizerResult recognizerResult, boolean b)
{
result+= JsonParser.parseIatResult(recognizerResult.getResultString());
if(b)
{
UnityPlayer.UnitySendMessage("GameObject","OnResult",result);
result = "";
mIat.stopListening();
}
}
@Override
public void onError(SpeechError speechError)
{
UnityPlayer.UnitySendMessage("GameObject","OnError",speechError.getErrorCode()+"");
}
@Override
public void onEvent(int i, int i1, int i2, Bundle bundle) {
}
};
private String getResourcePath()
{
StringBuffer tempBuffer = new StringBuffer();
tempBuffer.append(ResourceUtil.generateResourcePath(this,ResourceUtil.RESOURCE_TYPE.assets,"iat/common.jet"));
tempBuffer.append(";");
tempBuffer.append(ResourceUtil.generateResourcePath(this,ResourceUtil.RESOURCE_TYPE.assets,"iat/sms_16k.jet"));
return tempBuffer.toString();
}
}
不懂的查API:http://mscdoc.xfyun.cn/android/api/
如果之后报了出错码到这里查:https://www.xfyun.cn/document/error-code
代码很简单,有面向对象语言基础的都能看懂,说明一下:
这一条后面的9y35h930h是指你的appid,第一部分就圈了,你的换成自己的。
SpeechUtility.createUtility(this, SpeechConstant.APPID + "=9y35h930h");
UnityPlayer.UnitySendMessage(unity中对象名称,挂在对象上面脚本的方法,要传递的参数,没有就不写);
还有一点,JsonParse里的包名记得换成你的模块里的包名:
5. 修改AndroidManifest.xml
懂的自然懂,不懂的以后会懂
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zy.iatlibrary"
android:versionCode="1"
android:versionName="1.0" >
<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-sdk
android:minSdkVersion="19"
android:targetSdkVersion="24" />
<application android:allowBackup="true"
android:supportsRtl="true">
<activity
android:name=".Iat">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true"/>
</activity>
</application>
</manifest>
6.导出AAR
等待重构完成,再点击这个
我们看到建立的aar包已经完成了
在文件夹中打开
libs里面有classes.jar包,删除它,把外面这个classes.jar放进去,你发现libs里面没有armeabi-v7a,在你项目里找到它拷贝进去完成后进行下一步
留下这四个文件,待会要拷贝到Unity里面。
第三步:Unity中要做的事
1. 搭界面
建立工程搭建界面:
2. 放资源
建立一个文件夹Plugins/Android,刚刚的文件放进去
在之前下载的讯飞包里找到这两个文件然后放入Unity Assets/Android/Plugins/assets/iat里
补充一下:
打开Unity里刚刚导入的AndroidMainfest.xml,添加这两行,不然待会你在Unity里设置的名称和图标会无用
3.敲代码
新建一个脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Iatdemo : MonoBehaviour
{
private AndroidJavaClass ajc;
private AndroidJavaObject ajo;
public Button startBtn;
public Button exitBtn;
public Text resultText;
private void Awake()
{
startBtn = GameObject.Find("Canvas/Button").GetComponent<Button>();
exitBtn = GameObject.Find("Canvas/Button_2").GetComponent<Button>();
resultText = GameObject.Find("Canvas/Text").GetComponent<Text>();
}
// Use this for initialization
void Start ()
{
ajc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
ajo = ajc.GetStatic<AndroidJavaObject>("currentActivity");
if (startBtn)
{
startBtn.onClick.AddListener(()=> { StartListening(); } );
}
if (exitBtn)
{
exitBtn.onClick.AddListener(()=> { Quit(); });
}
}
public void StartListening()
{
ajo.Call("StartListening", "点击了监听");
}
public void OnStartListening(string ret)
{
int result = int.Parse(ret);
startBtn.interactable = result == 0;
}
public void OnResult(string result)
{
resultText.text = result;
}
public void OnError(string errorMessage)
{
resultText.text = errorMessage;
}
public void OnEndOfSpeech()
{
startBtn.GetComponentInChildren<Text>().text = "点击倾听";
startBtn.interactable = true;
}
public void OnBeginOfSpeech()
{
startBtn.GetComponentInChildren<Text>().text = "倾听中";
startBtn.interactable = false;
}
public void Quit()
{
Application.Quit();
}
}
将这个脚本挂载在GameObject上
4.导出apk
这里的包名记得和之前AS里面的模块里的包名是一致的,这里的应用名称和应用图标也填一下,之前在xml里如果没有新增那两条的话,这里填了也没有用
接下来点击Build然后把apk安装在android上