zoukankan      html  css  js  c++  java
  • 【Unity】讯飞语音识别SDK

    1、进入讯飞官网,注册帐号,进入控制台,创建新应用UnityXunfeiDemo,平台选Android。在当前应用这点下载SDK,添加AI能力(添加新服务),选择语音听写,即可下载安卓SDK(下称讯飞安卓SDK)。

    2、打开Android Studio,新建一个项目(选Empty Activity即可),打开该项目,点击菜单【File—New—Import Module】,导入的模块路径是刚才下载的安卓SDK包/sample/speechDemo>

    3、导入AS后会看到报错如下,该模块需要android-23的SDK,而我现在没下(我有Android-26的SDK)。

    4、AS切到Project视图下,打开speechDemo/build.gradle文件,修改compileSdkVersion为26,去掉buildToolsVersion这一行,最低平台16,目标平台26,最下面dependencies中的v4:23也改为v4:26。改完后点Gradle提示栏的Try Again重新同步一次即可。

    5、AS切换回Android视图,选中speechDemo模块,点击菜单【Run—Run speechDemo】。选择一个安卓真机,即可在手机上看到该Demo效果(即将要在Unity上实现的功能)。注意,用安卓模拟器(AVD)将无法运行该Demo,会报错INSTALL_FAILED_NO_MATCHING_ABIS,原因是模拟器与真机的架构不同,该Demo需要一些本地库是模拟器上没有的,即该项目必须用真机运行。https://stackoverflow.com/questions/24572052/install-failed-no-matching-abis-when-install-apk

    6、 AS切换到Project视图,新建模块Android Library取名xunfeilibrary。复制讯飞安卓SDK/libs/Msc.jar到xunfeilibrary/libs/下,复制Unity的classes.jar(路径形如D:Unity 2017.3.0f3EditorDataPlaybackEnginesAndroidPlayerVariationsmonoReleaseClassesclasses.jar)到xunfeilibrary/libs/下。右键Add as Library—Add to Module xunfeilibrary。为确保jar包已导入到模块中,在Project Structure中查看引用,如下图。

    7、在xunfeilibrary/src/main/下新建文件夹jniLibs,复制讯飞安卓SDK/libs/armeabi-v7a文件夹到该jniLibs下。(如果之后这个不行,就换复制别的arm开头的文件夹进来)

    8、AS切换到Android视图,在xunfeilibrary/java/包名/下新建一个Empty Activity。删除随之生成的布局文件xunfeilibrary/res/layout/activity_main.xml,修改MainActivity.java如下。

    9、复制app/manifests/AndroidManifest.xml清单中的< application >节点,替换掉xunfeilibrary//manifests/AndroidManifest.xml中的< application >节点内容,删除报错的行。修改android:label="XunfeiDemo"。加上meta-data。再把speech/manifests/AndroidManifest.xml清单最下面的所有权限拷贝过来。最后xunfeilibrary//manifests/AndroidManifest.xml清单的内容如下。

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="me.guxin.xunfeilibrary">
    
        <application
            android:allowBackup="true"
            android:label="XunfeiDemo"
            android:supportsRtl="true">
            <activity android:name=".MainActivity">
                <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>
    
        <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.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    </manifest>

    10、参考speechDemo/java/com.iflytek/voicedemo/IatDemo.java,来编写我们的MainActivity,内容如下。

    package me.guxin.xunfeilibrary;
    
    import android.os.Bundle;
    
    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 MainActivity extends UnityPlayerActivity {
        private SpeechRecognizer mIat;
        // 用HashMap存储听写结果
        private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // setContentView(R.layout.activity_main);
    
            // 初始化引擎,APPID在讯飞控制台的应用那。
            SpeechUtility.createUtility(this, SpeechConstant.APPID + "=5adca626");
            // 创建语音识别对象(cloud包下的),Iat是讯飞语音听写的简写。第二参数是成功或失败的监听器,这里简单传空。
            mIat = SpeechRecognizer.createRecognizer(this, null);
            // 设置参数
            mIat.setParameter(SpeechConstant.DOMAIN, "iat");      // 服务类型,语音听写
            mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");  // 语言是中文
            mIat.setParameter(SpeechConstant.ACCENT, "mandarin"); // 口音是普通话
            mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); // 引擎类型,云端引擎
        }
    
        // 监听器
        private RecognizerListener mRecognizer = 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) {
    
            }
        };
    
        /**
         * 给Unity调用的,开始监听。
         */
        public void startListen(){
            mIat.startListening(mRecognizer);
        }
    
        /**
         * 打印输出结果。该方法从latDemo中复制的。
         * JsonParser工具类从speechDemo/java/com.iflytek/speech/util/JsonParser.java复制到xunfeilibrary/java/包名/下。
         * @param results
         */
        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展示。安卓调用Unity
             * 参数一:Unity场景中的GameObject名。
             * 参数二:物体身上任一脚本中的指定方法。
             * 参数三:调用该方法的传参。
             */
            UnityPlayer.UnitySendMessage("XunfeiManager", "OnResult", resultBuffer.toString());
        }
    }

    11、AS切换Project视图,选中xunfeilibrary,菜单项Build—Make Modelu "xunfeilibrary",把xunfeilibrary/build/outputs/arr/xunfeilibrary-debug.arr包复制到桌面。从桌面打开aar包,把aar/classes.jar移动并同名替换aar/libs/classes.jar(被替换掉的是Unity导入的)。打开aar/AndroidManifest.xml清单,去掉android:label。再把xunfeilibrary/build/intermediates/manifests/full/debug/AndroidManifest.xml清单复制到桌面(这是项目的总的清单)。桌面打开清单,修改包名如package="me.guxin.xunfeidemo"(必须全部小写)。这样就准备好了给Unity用的aar包和清单文件。

    12、打开Unity,新建项目UnityXunfeiDemo,新建文件夹Plugins/Android,把上一步得到的aar包和安卓清单复制到该文件夹下。新建一个Text用于显示语音输入结果(取消Text的射线检测Raycast Target),新建一个Button点击开始语音输入。新建一个GameObject取名XunfeiManager(名字要与安卓Java代码中规定的一致),新建C#脚本XunfeiManager挂到物体XunfeiManager身上。项目结构如下图。

    13、编写XunfeiManager脚本如下。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class XunfeiManager : MonoBehaviour
    {
        public Text resultText;
        private AndroidJavaObject currentActivity;
    
        private void Start()
        {
            currentActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity");
        }
    
        /// <summary>
        /// 点击按钮,开始语音输入
        /// </summary>
        public void OnClick()
        {
            currentActivity.Call("startListen");
        }
    
        /// <summary>
        /// 方法名要与安卓Java代码中规定的一致
        /// </summary>
        public void OnResult(string s)
        {
            resultText.text = s;
        }
    }

     14、打开Unity的Build Settings,切换平台为Android。打开Player Settings设置包名如me.guxin.xunfeidemo(跟桌面的安卓清单中的一致),设置自己的签名密钥。发布项目到桌面UnityXunfeiDemo.apk,安装到真机上即可。


    学习资料:

  • 相关阅读:
    团体程序设计天梯赛-练习集-L1-039. 古风排版
    团体程序设计天梯赛-练习集-L1-038. 新世界
    团体程序设计天梯赛-练习集-L1-037. A除以B
    团体程序设计天梯赛-练习集-L1-036. A乘以B
    团体程序设计天梯赛-练习集-L1-035. 情人节
    团体程序设计天梯赛-练习集-L1-034. 点赞
    团体程序设计天梯赛-练习集-L1-033. 出生年
    团体程序设计天梯赛-练习集-L1-032. Left-pad
    团体程序设计天梯赛-练习集-L1-031. 到底是不是太胖了
    团体程序设计天梯赛-练习集-L1-030. 一帮一
  • 原文地址:https://www.cnblogs.com/guxin/p/unity-speech-recognition-by-iflytek-iat-sdk.html
Copyright © 2011-2022 走看看