unity3d 讯飞语音识别

2018-05-22 11:30:44 qq_31298129 阅读数 2155
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

这个是语音识别的转自:https://blog.csdn.net/zzjinjiazz/article/details/54862237

语音识别:

eclipse这边推荐下载一个ADT_bundle对应自己的系统版本(里面有自带的android sdk),不然自己下载的eclipse可能会没有 android application project 让你创建,我的就是刚开始没有

adt_bundle_win_64下载地址https://pan.baidu.com/s/1sZr7ubk3E86uaeSs312eJw 密码:o6ew

安装eclipse之前应该先安装JDK并配置好环境
JDK下载和配置:https://pan.baidu.com/s/1DmJwfsvM8qzg8WofEcs3-Q
密码:wbii

完了之后就照作者的步骤去写吧

讯飞这个语音是需要联网的

我自己配置所遇到的问题:

UnityPlayer.UnitySendMessage(“Main Camera”, “xxx”, “初始化完成”);
这三个参数,第一个Main Camera为unity中脚本对象所挂在的Gameobject的名 字;第二个参数xxx为你unity脚本所需要接收这个返回参数(也就是eclipse中的voiceResult这个参数)的方法名字,第三个为显示状态

至于打包出来的那个jar这个包的名字可以自己随意写一个

我第一次没成功的主要原因是脚本没有挂载到Main Camera上面,引以为戒

unity测试工程和打包出来的APK链接地址:
https://pan.baidu.com/s/1nBZcKvBVK516L8gzUfJmgA 密码:6l1o

这个是语音合成(文字转语音):

语音识别和语音合成的SDK没必要下两遍,直接使用语音识别的那个SDK就行,就按照之前导进去的那个,然后开始改写你的 MainActivity.java这个脚本就行
我是把语音识别和语音合成写到一块了,可以参照代码,懒人可以直接复制粘贴

package com.zhimin.mysoundshibie;

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

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.SpeechSynthesizer; 
import com.iflytek.cloud.SynthesizerListener;
import com.iflytek.cloud.ErrorCode;
import com.unity3d.player.UnityPlayer; 
import com.unity3d.player.UnityPlayerActivity;



public class MainActivity extends UnityPlayerActivity {

    SpeechRecognizer mIat; 
    String voiceResult = "";

    // 语音合成对象
    private SpeechSynthesizer speechSynthesizer;

    // 默认发言人
    private String voicer = "xiaoyan";

    // 引擎类型
    private String mEngineType = SpeechConstant.TYPE_CLOUD;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SpeechUtility.createUtility(this, "appid=xxxxx");   
    }

    //unity中调用进行语音识别
    public void Yuyin_shibie() {

        mIat = SpeechRecognizer.createRecognizer(this, mInitListener);

        mIat.setParameter(SpeechConstant.DOMAIN, "iat");

        mIat.setParameter(SpeechConstant.ACCENT, "mandarin");

        mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");

        mIat.setParameter(SpeechConstant.KEY_SPEECH_TIMEOUT, "4000");

        mIat.setParameter(SpeechConstant.VAD_EOS, "2000");

        mIat.setParameter(SpeechConstant.ASR_PTT, "0");

        mIat.startListening(recognizerListener);
        mIat.setParameter(SpeechConstant.ENGINE_TYPE,"");
        mIat.setParameter(SpeechConstant.ENGINE_MODE,"");

        UnityPlayer.UnitySendMessage("Main Camera", "zhimin", "初始化完成");

        if (voiceResult != null || voiceResult != "") {

            voiceResult = "";

        }

    }

    //unity中调用进行语音合成
    public void kaishi_bofang_yuyin(String str)
    {
        speechSynthesizer = SpeechSynthesizer.createSynthesizer(this, mTtsInitListener);
         // 设置参数
        setParam();
        // 开始播放
        int code = speechSynthesizer.startSpeaking(str, mTtsListener);

        if (code != ErrorCode.SUCCESS) {
            showToast("语音合成失败,错误码: " + code);
        } else {
            showToast("语音合成成功啦");
        }
    }

    private RecognizerListener recognizerListener = new RecognizerListener() {

        // 说话音量

        @Override
        public void onVolumeChanged(int arg0, byte[] arg1) {

            // TODO Auto-generated method stub

        }

     // 得到返回的语音结果

        @Override
        public void onResult(RecognizerResult arg0, boolean arg1) {

            // TODO Auto-generated method stub

            voiceResult = voiceResult
                    + JsonParser.parseIatResult(arg0.getResultString());

            if (arg1) {

                UnityPlayer.UnitySendMessage("Main Camera","zhimin",
                        voiceResult);

            }

        }

     // 扩展接口

        @Override
        public void onEvent(int arg0, int arg1, int arg2, Bundle arg3) {

            // TODO Auto-generated method stub

        }

        // 发生错误回调

        @Override
        public void onError(SpeechError arg0) {

            // TODO Auto-generated method stub

            UnityPlayer.UnitySendMessage("Main Camera", "zhimin", "发生错误啦");

        }

        // 结束录音

        @Override
        public void onEndOfSpeech() {

            // TODO Auto-generated method stub

            UnityPlayer.UnitySendMessage("Main Camera", "zhimin", "结束录音啦");

        }

        // 开始录音

        @Override
        public void onBeginOfSpeech() {

            // TODO Auto-generated method stub

            UnityPlayer.UnitySendMessage("Main Camera", "zhimin", "开始录音啦");

        }
    };

        private InitListener mInitListener = new InitListener() {

            @Override
            public void onInit(int arg0) {

                // TODO Auto-generated method stub

                UnityPlayer.UnitySendMessage("Main Camera", "zhimin",
                        "mInitListener");

                if (arg0 == 0) {

                    Toast.makeText(MainActivity.this, "语音可以用", Toast.LENGTH_SHORT)
                            .show();

                } else {

                    Toast.makeText(MainActivity.this, "语音不可以用", Toast.LENGTH_SHORT)
                            .show();

                }

            }
        };

        // 设置参数
        private void setParam() {
            // 清空参数
            speechSynthesizer.setParameter(SpeechConstant.PARAMS, null);
            // 根据合成引擎设置相应参数
            if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) {
                speechSynthesizer.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
                // 设置在线合成发音人
                speechSynthesizer.setParameter(SpeechConstant.VOICE_NAME, voicer);
                //设置合成语速
                speechSynthesizer.setParameter(SpeechConstant.SPEED, "50");
                //设置合成音调
                speechSynthesizer.setParameter(SpeechConstant.PITCH, "50");
                //设置合成音量
                speechSynthesizer.setParameter(SpeechConstant.VOLUME, "50");
            } else {
                speechSynthesizer.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
                // 设置本地合成发音人 voicer为空,默认通过语记界面指定发音人。
                speechSynthesizer.setParameter(SpeechConstant.VOICE_NAME, "");
                /**
                 * TODO 本地合成不设置语速、音调、音量,默认使用语记设置
                 * 开发者如需自定义参数,请参考在线合成参数设置
                 */
            }
            //设置播放器音频流类型
            speechSynthesizer.setParameter(SpeechConstant.STREAM_TYPE, "5");
            // 设置播放合成音频打断音乐播放,默认为true
            speechSynthesizer.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");

            // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
            // 注:AUDIO_FORMAT参数语记需要更新版本才能生效
            speechSynthesizer.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
            //speechSynthesizer.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/tts.wav");
        }
        // 播放回调
        private SynthesizerListener mTtsListener = new SynthesizerListener() {
            @Override
            public void onSpeakBegin() {
            }

            @Override
            public void onSpeakPaused() {
            }

            @Override
            public void onSpeakResumed() {
            }

            @Override
            public void onBufferProgress(int percent, int beginPos, int endPos,
                                         String info) {
                // 合成进度
            }

            @Override
            public void onSpeakProgress(int percent, int beginPos, int endPos) {
                // 播放进度
            }

            @Override
            public void onCompleted(SpeechError error) {
                if (error == null) {
                    showToast("播放完成");
                } else if (error != null) {
                    showToast(error.getPlainDescription(true));
                }
            }

            @Override
            public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
                // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
                // 若使用本地能力,会话id为null
                //  if (SpeechEvent.EVENT_SESSION_ID == eventType) {
                //      String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
                //      Log.d(TAG, "session id =" + sid);
                //  }
            }
        };

        /**
         * 初始化监听。
         */
        private InitListener mTtsInitListener = new InitListener() {
            @Override
            public void onInit(int code) {
                //Log.d(TAG, "InitListener init() code = " + code);
                if (code != ErrorCode.SUCCESS) {
                    showToast("初始化失败,错误码:" + code);
                } else {
                    // 初始化成功,之后可以调用startSpeaking方法
                    // 注:有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成,
                    // 正确的做法是将onCreate中的startSpeaking调用移至这里
                    showToast("初始化成功");
                }
            }
        };

        // 传入 meg,弹出一个 Toast 操作
        public void showToast(final String meg)
        {
            Toast.makeText(MainActivity.this, meg, Toast.LENGTH_LONG).show();
        }



    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

此处的xxxx为你的讯飞appID

接下来是AndRoidMainfest.xml的改写

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.zhimin.mysoundshibie"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="19"
        android:targetSdkVersion="19" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.zhimin.mysoundshibie.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<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" /> 
</manifest>


注意标红的地方要和MainActivity.java里第一行那一致,比MainActivity.java里第一行后面多一个.MainActivity

然后ctrl+s后,点File(在左上角),然后点里面的Export,再点JAVA下面的JARfile,然后next

点击finish,自己选择你的打包路径

unity里面的格式


这个haha是我自己的打的jar包,该拖的和该创建的文件夹以及名字不能出错
libs和res自己在java的那个安卓过程拖过来即可

然后我的脚本代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
using UnityEngine.UI;

public class NewBehaviourScript1 : MonoBehaviour {

    public Text tx1;
    public Text tx2;

    AndroidJavaClass jc;
    AndroidJavaObject jo;
    void Start () {
        jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
    }


    void Update () {

    }

    public void kaishi_yuyin_shibie()
    {
        jo.Call("Yuyin_shibie");
    }

    public void kaishi_bofang_yuyin()
    {
        jo.Set<string>("voicer", "xiaoyu");//改变java中的播放者   (可以百度查询科大讯飞里面的语音人物名称)
        jo.Call("Yuyin_bofang","小猪佩琪身上纹,掌声送给社会人"); //第二个参数为需要播放的语音文字,可以随意定义
    }

    void zhimin(string str)
    {
        tx1.text = str;

    }



}

看不懂的同学不要着急,这里贴上我的安卓工程和unity工程以及打包好的apk包

注意:unity打包APK的PackageName必须和安卓工程中com.zhimin.mysoundshibie一致

安卓工程:https://pan.baidu.com/s/1nSJDieWCKKtFLIxwXwwkLQ 密码:7duu
unity工程: https://pan.baidu.com/s/1-rH83WMzeaCdSnjsY0jDpQ 密码: 4xac
APK包:https://pan.baidu.com/s/1Pzi5lRa4Ia9sm6BZE6SF8w 密码:32mh

2015-11-05 13:03:17 xiaomuzi0802 阅读数 0
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

这次说说Unity上的语音识别,使用的是讯飞语音识别的SDK,目标平台是安卓客户端

在写文章之前,参考了讯飞官方论坛给出的Unity结合讯飞语音识别的案例,参照案例可以很方便的进行语音识别,

文章链接就不贴出来了,想看的移步讯飞官方论坛,搜索unity相关。

既然官方有,为什么我还写呢,我不想做搬运工的(可能吧)。。。

因为在开发过程中,使用论坛帖子的方式,必须要将androidMainfast.xml放到工程里面,这样我就不开心了,因为我原先工程里面就已经用了Mainfast了,并且是个复杂系统,不好改。能不能我将讯飞语音制作成一个Jar包,用的时候调用一下就可以了。

当然是可以的!!!

废话不多说,下面开始来做

第一步:创建安卓工程都是没问题的吧,工程创建好之后,将讯飞给出的Demo中的libs文件夹拷贝到我们新建工程的libs文件夹中

第二步:开始写代码

package com.petit.voice_voice;

import java.util.HashMap;
import java.util.LinkedHashMap;
import org.json.JSONException;
import org.json.JSONObject;
import com.iflytek.cloud.InitListener;
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.RecognizerListener;
import com.unity3d.player.UnityPlayer;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public class MainActivity {
	
	public SpeechRecognizer mSpeech;	
	static MainActivity instance=null;	
	// 用HashMap存储听写结果
	private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();
	//用来存放由Unity传送过来的Activity,这里换成Context也是可行的
	private  Activity activity = null;
	  
	public MainActivity(){
	
		instance=this;	
	
	}
	public static MainActivity instance(){
		if(instance==null){
			instance=new MainActivity();
		}
		return instance;
	}
	public void setContext(Activity act){
		this.activity=act;
		if(this.activity!=null){
			try{
//这里在获取到Unity里面的activity之后,注册你在讯飞申请的appId
		SpeechUtility.createUtility(activity, "appid=XXXXXXX");
//初始化
		mSpeech=SpeechRecognizer.createRecognizer(activity, mInitListener);
			}
		catch(Exception e){
//使用UnityPlayer将消息发送回Unity,具体用法找度娘耍耍
			UnityPlayer.UnitySendMessage("Manager", "Init", "StartActivity0"+e.getMessage());
		}
		}else{
			
			UnityPlayer.UnitySendMessage("Manager", "Init", "setContext is null");
		}	
	}
	
	public void StartActivity1(){
		//进行语音识别
		mSpeech.setParameter(SpeechConstant.DOMAIN,"iat");
		mSpeech.setParameter(SpeechConstant.SAMPLE_RATE, "16000");
		mSpeech.setParameter(SpeechConstant.LANGUAGE,"zh_cn");
		int ret=mSpeech.startListening(recognizerListener);
		Toast.makeText(activity, "startListening ret:"+ret, Toast.LENGTH_SHORT).show();
		UnityPlayer.UnitySendMessage("Manager", "Init", "startListening ret:"+ret);
		
	}
	
	public RecognizerListener recognizerListener=new RecognizerListener(){

		@Override
		public void onBeginOfSpeech() {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void onEndOfSpeech() {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void onError(SpeechError arg0) {
			// TODO Auto-generated method stub
			Log.d("ss", "error"+arg0.getErrorCode());
		}

		@Override
		public void onEvent(int arg0, int arg1, int arg2, Bundle arg3) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void onResult(RecognizerResult arg0, boolean arg1) {
			// TODO Auto-generated method stub
			 Log.d("ss", "result:"+arg0.getResultString());
             Toast.makeText(activity, "result:"+arg0.getResultString(), Toast.LENGTH_SHORT).show();
         //	UnityPlayer.UnitySendMessage("Manager", "Result", "result:"+arg0.getResultString());
         	printResult(arg0);
		}

		@Override
		public void onVolumeChanged(int arg0, byte[] arg1) {
			// TODO Auto-generated method stub
			
		}
		
	};
	private void printResult(RecognizerResult results) {
		String text = JsonParser.parseIatResult(results.getResultString());

		String sn = null;
		// 读取json结果中的sn字段,这里需要一个Java文件JsonParser.java这个在讯飞歌的Demo中可以找到
		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的Result函数中
		UnityPlayer.UnitySendMessage("Manager", "Result", "result:"+resultBuffer.toString());
	}
	private InitListener mInitListener=new InitListener(){

		@Override
		public void onInit(int arg0) {
			// TODO Auto-generated method stub
			if(arg0==0){
				
				Log.d("ss", "loin");
				Toast.makeText(activity, "login", Toast.LENGTH_SHORT).show();
			}else{
				Log.d("ss","login error"+arg0);
				Toast.makeText(activity, "login error"+arg0, Toast.LENGTH_SHORT).show();
			}
		
		}
		
	
	};

}


Java这边其实就这么点东西

第三步:将文件导出Jar包:实际上我们只需要将需要的文件进行打包就可以了,其他的res啊、lib啊什么的不需要管他们


下一步,设置好导出路径,直接finish就OK了


第四步:将Jar包放到Unity里面,同时需要将讯飞的我们需要的包也要放到里面,实际上是把Libs文件夹拷贝到unity里面就可以了。不过在Unity中,插件是要放到指定位置的,目录如下,这其中的Voice.jar就是我们刚才导出来的Jar包哦

第五步:编写Unity端的调用代码

</pre>第六步:你以为到上一步就完了么,那就错咯,道出了一运行但是没有结果,如果你想办法打印出错误日志,会发现,是缺少权限,因为unity导出android会自动生成Mainfest的,而这个MainFest里面不包含语音识别所需要的权限,所以你懂得<p></p><p><span style="font-size:18px">D:\Program Files (x86)\Unity\Editor\Data\PlaybackEngines\androidplayer我的unity安装目录,在这里面找到</span></p><p><span style="font-size:18px">AndroidManifest.xml这是隔膜板,把你需要的权限加进去就好了</span></p><p><span style="font-size:18px"><img src="http://img.blog.csdn.net/20151105125053323?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /></span></p><p></p><pre code_snippet_id="1840336" snippet_file_name="blog_20160819_3_8233424" name="code" class="csharp">using UnityEngine;
using UnityEngine.UI;
using System.Collections;


public class TestInstance : MonoBehaviour {

    private string show = "sss";
    private string showResult = "";
    private AndroidJavaObject testobj = null;
    private AndroidJavaObject playerActivityContext = null;

    void Start()
    {
       
    }
    void OnGUI()
    {
        if (GUILayout.Button("login", GUILayout.Height(100)))
        {
            if (testobj == null)
            {
                // First, obtain the current activity context借用外国友人的代码
                using (var actClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
                {//获取当前的activity并保存下来
                    playerActivityContext = actClass.GetStatic<AndroidJavaObject>("currentActivity");
                }

                // Pass the context to a newly instantiated TestUnityProxy object调用我们写的类
                using (var pluginClass = new AndroidJavaClass("com.petit.voice_voice.MainActivity"))
                {
                    if (pluginClass != null && playerActivityContext!=null)
                    {//调用Java中函数,并将activity传进去
                        testobj = pluginClass.CallStatic<AndroidJavaObject>("instance");
                        testobj.Call("setContext", playerActivityContext);
                     
                    }
                }
            }
        }
        if (GUILayout.Button("startRecognizer", GUILayout.Height(100)))
        {
   //调用识别函数
            testobj.Call("StartActivity1");
            show += "StartActivity1";
        }

       GUILayout.TextArea(show + showResult, GUILayout.Width(200));


    }
//这两个函数是不是挺熟悉,这就是接受UnityPlayer发送过来消息的函数,Manager是要创建一个空物体,将这个脚本挂在到上面,才能正常接收消息
    public void Init(string hh)
    {
        show = hh;

    }
    public void Result(string hh)
    {
        showResult = hh;

    }
}

下面就可以导出来了,build,看看运行效果

OK,到此为止咯

附上下载链接

点我点我


有朋友说测试有问题。我按照自己写的又做了一遍,在Unity5.4.3,64位版本上,是不能够运行的,在unity4.6.3,32位上正常运行,因为电脑上只有两个版本,可能是因为讯飞没有针对Unity的64位开发包造成的,所以建议使用32位的Unity进行编辑

点击打开链接


2019-06-27 14:10:49 sinat_39291423 阅读数 5030
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

现在语音识别已经被广泛的应用到各个领域中,在Unity开发中,语音识别也非常受欢迎。大部分人都会选择科大讯飞的语音识别功能,但是在一些小的项目中,使用科大讯飞的就有点大材小用了。今天就介绍一下Unity自带的语音识别功能。说是语音识别,其实unity本身还是做不到的,Unity自带的语音识别功能其实是关键字识别。比如我在Unity中设定好一句话汇总的几个关键词。当我再说这句话的时候就会和识别到。经过测试发现当一句话中有八个关键字,这句话就会非常好的被识别出来。
接下来就一起来实现一下:
首先贴一张效果图:
在这里插入图片描述
场景我们沿用的是音频可视化那篇文章里用到的场景。这里就不多做介绍了。Unity自带的语音识别功能官方有API供参考,地址在这里(戳这里
在这里插入图片描述
这里大家可以自行去看一下。下面开始介绍一下我们要实现的功能:
想要识别语音识别功能我们首先由先引用个命名空间

using UnityEngine.Windows.Speech;//引入命名空间

然后定义一个string类型数组,这个数组就是存放那些我们要识别关键字。

	 // 关键字
    public string[] keywords = { "你好", "开始","停止" };

紧接着我们要在start方法中先创建一个语音识别器,这样才能够进行语音识别

	//创建一个识别器
	m_PhraseRecognizer = new KeywordRecognizer(keywords, m_confidenceLevel);
	//通过注册监听的方法
	m_PhraseRecognizer.OnPhraseRecognized += M_PhraseRecognizer_OnPhraseRecognized;
	//开启识别器
	m_PhraseRecognizer.Start();

接着是一个方法,这个方法主要就是用于识别到关键字后要做的事情

	 /// <summary>
    ///  当识别到关键字时,会调用这个方法
    /// </summary>
    /// <param name="args"></param>
    private void M_PhraseRecognizer_OnPhraseRecognized(PhraseRecognizedEventArgs args)
    {
        print(args.text);
    }

这样基本上重要的部分就完成。下面是全部的代码,在底部还有一个小Demo,感兴趣的可以下载下来自行体验一下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Windows.Speech;//引入命名空间  利用

/// <summary>
/// 语音识别(主要是别关键字)
/// </summary>
public class speechKey : MonoBehaviour
{
    // 短语识别器
    private PhraseRecognizer m_PhraseRecognizer;
    // 关键字
    public string[] keywords = { "你好", "开始","停止" };
    // 可信度
    public ConfidenceLevel m_confidenceLevel = ConfidenceLevel.Medium;

    // Use this for initialization
    void Start()
    {
        if (m_PhraseRecognizer == null)
        {
            //创建一个识别器
            m_PhraseRecognizer = new KeywordRecognizer(keywords, m_confidenceLevel);
            //通过注册监听的方法
            m_PhraseRecognizer.OnPhraseRecognized += M_PhraseRecognizer_OnPhraseRecognized;
            //开启识别器
            m_PhraseRecognizer.Start();
          
            Debug.Log("创建识别器成功");
        }
    }

    /// <summary>
    ///  当识别到关键字时,会调用这个方法
    /// </summary>
    /// <param name="args"></param>
    private void M_PhraseRecognizer_OnPhraseRecognized(PhraseRecognizedEventArgs args)
    {
        SpeechRecognition();
        print(args.text);
    }
    private void OnDestroy()
    {
        //判断场景中是否存在语音识别器,如果有,释放
        if (m_PhraseRecognizer != null)
        {
            //用完应该释放,否则会带来额外的开销
            m_PhraseRecognizer.Dispose();
        }

    }
    // Update is called once per frame
    void Update()
    {

    }
    /// <summary>
    /// 识别到语音的操作
    /// </summary>
    void SpeechRecognition()
    {
       
    }  
}

Demo下载地址:https://github.com/ShuxinWen/AutomaticSpeechRecognition-ASR-

2018-07-20 18:57:12 hyy_sui_yuan 阅读数 5700
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

上一篇只是shi'实现C#接讯飞语音识别SDK,这一篇在unity中实现语音识别

1、在unitygong工yin'音频资源

2、导入SDK中的msc:

3、创建脚本,封装dll,步骤就不重复了

4、做一个处理音频的接口,传入appid,会话信息、音频路径

5、负责初始化appid ,会话信息,音频路经,最后调用接口(appid传入自己的,msc导入自己的)

6、识别英文的结果:

识别中文的结果:

注意事项(我在做项目时遇到的问题):

首先:SDK不是线程安全的,不支持多路并发调用,即上一会话没有结束,就开启了下一会话,我因为同时开了多个VS,测试不同的语音识别项目,结果就导致其中一个项目运行时登陆失败,问了讯飞的开发人员才找出了原因

语言如果选错,最后会识别不出来,中文语音会话信息就选中文模式,英文音频就选英文模式,不然会识别出乱码,输出不了。

程序中使用msc_x64,如果用msc会报错,可能是因为电脑是64位的吧,这只是我的猜测

有开始就要有结束:

比如登陆后,最后使用完毕一定要退出

开启会话,最后也要关闭会话

今天就写到这,下一篇是关于在线录制音频之后把音频转成文字

demo地址;https://download.csdn.net/download/hyy_sui_yuan/10554682

有不理解的地方可以问,我也是刚研究没多长时间,知道刚接触是有些困难

2017-04-17 14:11:17 morning_bird 阅读数 4286
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

在上班时间一边接sdk ,一边总结接入语音sdk中出现的一些问题。拿来和大家分享一下, 不会写得很详细。

官方的sdk例子值得了解,并可以解决很多问题。 

我在这里例举出几个自己犯下的错误 跟大家一起分享。 

1.报单例创建失败的问题,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688

2.AndoridJavaException: android.view.ViewRootImpl$CalledFromWrongThreadException :only the original thread that created a view hiearchy can touch its views.错误,

主要是在非UI层调用,如何解决。将内容写在 runOnUiThread 里可以解决问题,实际上的问题 :http://blog.csdn.net/vivianyouyi/article/details/51781141 ,我的问题是将Toast在Unity 调用的方法里直接调用。

3.导入jar包到Unity 里面的, build 之后运行发现报错说找不到引用,  要去看一下 讯飞的libs库是否导入到了Unity 的lib 库中(不能连文件夹一起拷,会有问题),讯飞Demo下有一个JsonParser 需要导入到Eclipse工程目录下,

4. 压缩问题, 因为讯飞支持的语音格式为wav 和pcm ,要支持语音发送的话得先压缩 ,我这里将pcm 格式转换为amr格式,你会发现还需要引用一个文件AmrInputStream,但是找不到这个文件,其实是有的,去sdk 目录全局搜索, 然后把文件找到了放到工程中 ,不能修改AmrInputStream的包名。

public byte[] pcm2amr()
		throws IOException
   {
	
		InputStream inStream = new FileInputStream("/msc/mAudio.pcm");
	    AmrInputStream aStream = new AmrInputStream(inStream);
	    File file = new File("/msc/mAudio1"  + ".amr");
	    file.createNewFile();
	    OutputStream out = new FileOutputStream(file);
	 
	    byte[] x = new byte[1024];
	 
	    out.write(35);
		out.write(33);
		out.write(65);
		out.write(77);
		out.write(82);
		out.write(10);
	    int len;
	    while ((len = aStream.read(x)) > 0)
	    {
	    	out.write(x, 0, len);
	    }
	    out.close();
	    aStream.close();
	    
	    /*读取字节流*/
	    FileInputStream fis = new FileInputStream(file);
	    ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
	    byte[] b = new byte[1024];
	    int n;
	    while((n = fis.read(b))!= -1){
	    	bos.write(b,0,n);
	    }
	    fis.close();
	    bos.close();
	    
	    byte[] buffer = bos.toByteArray();
	    
	    return buffer;
   }


Android向Unity发送信息: UnityPlayer.UnitySendMessage("场景中的物体名", "场景中的物体名上挂在的任意名称Script里面的方法名", "传递内容”);

Unity向Android发送消息:

private AndroidJavaObject _ajo;

#if UNITY_ANDROID && !UNITY_EDITOR
            AndroidJavaClass ajc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            if (ajc != null)
            {
                _ajo = ajc.GetStatic<AndroidJavaObject>("currentActivity");
            }
#endif

_ajo.Call<返回值>("方法名",params);

本文没有仔细检查或许还有很多问题, 大致犯的错误就这么多,仅供参考。后面再完善吧 。