Unity3d在Window上使用SAPI進行語音識別

前言

        在以前《Unity利用Sapi進行windows語音開發》中,本計劃不許備繼續作語音識別。由於在unity3d中已經提供了語音識別的相關方法,詳見unity3d的官方文檔:https://docs.unity3d.com/ScriptReference/Windows.Speech.KeywordRecognizer.html。可是有一點是這個只支持win10。對於win7用戶來講,若是不使用百度語音或者科大訊飛語音的話,那麼使用SAPI就是最好的方式了。一樣的,因爲Unity中沒法直接使用SAPI,因此只能按照原來的思路,把它寫到一個exe工具中,而後再由unity3d來調用。html

工程變動和重構

        仍是繼續以前的工程,可是爲了規範一些,我把工程名稱從SpeechTest改成了Speech。而且重構了Socket通訊結構,將本來的SocketExtra分爲了SocketBase,SocketServer和SocketClient。這樣作的目的就是簡單化,而且增長SocketServer發送信息到SocketClient的功能。git

        這是工程的最終結構圖github

clip_image002

通訊數據結構

        因爲speech加入了語音識別功能,因此爲了區別以前的通訊信息,從新整理定義了新的通訊數據結構。通訊數據結構定爲二進制數據,前4位是一個int32型的命令碼,這些命令碼有不一樣的含義和內容:windows

  • 1:表示初始化,
  • 2:表示文字轉語音,後面緊跟着一個string
  • 3:表示語音識別,後面是一個int32型,0表示結束識別,1表示開始識別

        當speech收到1時,進行初始化。收到2的信息時,讀取以後的文本數據,而後交由Speecher來發音。收到3時,讀取後面的數據,若是是1,則開始進行錄音識別,若是是0則中止錄音識別。api

        Speech代碼NetServer.cs數據結構

        public bool NetReciveMsg(byte[] recivebuffer, int netID)
        {
            var arg = new ByteOutArg(recivebuffer);
            var cmd = arg.ReadInt32();
            switch ((EmCmd)cmd)
            {
                case EmCmd.Init:
                    Init();
                    break;
                case EmCmd.Speak:
                    var str = arg.ReadString();
                    Console.WriteLine(str);
                    m_speecher.Speak(str);
                    return true;
                case EmCmd.Recognize:
                    var scmd = arg.ReadInt32();
                    if (scmd == 1)
                        m_recognizer.BeginRec();
                    if (scmd == 0)
                        m_recognizer.EndRec();
                    return true;
                default:
                    throw new ArgumentOutOfRangeException();
            }
            return false;
        }

        在unity發送的代碼。(ByteInArg是一個簡單地寫如byte[]數據的類)socket

/***測試代碼,可刪除Start***/

    public void OnGUI()
    {
        if (GUILayout.Button("Connect"))
        {
            StartCoroutine(Connect());
        }
        if (GUILayout.Button("InitServer"))
        {
            StartCoroutine(InitServer());
        }

        if (GUILayout.Button("Speak"))
        {
            Speak("hello world");
        }

        if (GUILayout.Button("Recognize Start"))
        {
            Recognize(true);
        }
        if (GUILayout.Button("Recognize End"))

        {
            Recognize(false);
        }
    }

    /***測試代碼,可刪除End***/

    private void Recognize(bool tf)
    {
        var arg = new ByteInArg();
        arg.Write(3);
        arg.Write(tf ? 1 : 0);
        NetSendMsg(arg.GetBuffer());
    }

    public IEnumerator Connect()
    {
        m_socket = new SocketClient(this);
        m_socket.Connect("127.0.0.1", 9903);
        while (!m_socket.Connected)
        {
            yield return 1;
        }
    }

    public IEnumerator InitServer()
    {
        var arg = new ByteInArg();
        arg.Write(1);
        NetSendMsg(arg.GetBuffer());
        yield return 1;
    }

    public void Speech(string str)
    {
        if (m_socket.Connected)
        {
            var arg = new ByteInArg();
            arg.Write(2);
            arg.Write(str);
            //var bytes = Encoding.Default.GetBytes(str);
            NetSendMsg(arg.GetBuffer());
        }
    }

封裝SAPI語音識別模塊

        封裝SAPI的語音識別模塊這方面的代碼不少,也比較簡單。這裏建立的Recognizer類,代碼更改自http://kevin19900306.iteye.com/blog/1206534,其中的含義能夠查閱SAPI的相關文檔。Recognizer類有構造函數,兩個接口,一個回調向外提供。這兩個接口爲開始識別BeginRec和中止識別EndRec,當識別完成時,使用回調,將識別的文字傳出。函數

        在speech的NetServer.cs中,回調相關的代碼以下工具

        public void Init()
        {
            m_speecher = new Speecher();
            m_recognizer = new Recognizer
            {
                OnRecognized = OnRecognized
            };
            Console.WriteLine("初始化完成");
        }

        private void OnRecognized(string text)
        {
            var arg = new ByteInArg();
            arg.Write(text);
            NetSendMsg(arg.GetBuffer());
        }

 

測試

        運行unity3d,畫面中出現5個按鈕,分別爲Connect,InitServer,Speak,Recognize Start,Recognize End。依次點擊Connect,InitServer。而後點擊Speak,聽到「hello world」語音。點擊Recognize Start,對麥克風說任何中文,能夠看到debug輸出對應的文字。點擊Recognize End中止識別。測試

Github源代碼

        源代碼下載https://github.com/CodeGize/UnitySapi/

轉載聲明

        轉載請保留

        www.codegize.com,

        www.cnblogs.com/CodeGize/

相關文章
相關標籤/搜索