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


前言

        在之前《Unity利用Sapi進行windows語音開發》中,本計划不准備繼續做語音識別。因為在unity3d中已經提供了語音識別的相關方法,詳見unity3d的官方文檔:https://docs.unity3d.com/ScriptReference/Windows.Speech.KeywordRecognizer.html。但是有一點是這個只支持win10。對於win7用戶來說,如果不使用百度語音或者科大訊飛語音的話,那么使用SAPI就是最好的方式了。同樣的,由於Unity中無法直接使用SAPI,所以只能按照原來的思路,把它寫到一個exe工具中,然后再由unity3d來調用。

工程變更和重構

        還是繼續之前的工程,但是為了規范一些,我把工程名稱從SpeechTest改為了Speech。並且重構了Socket通信結構,將原本的SocketExtra分為了SocketBase,SocketServer和SocketClient。這樣做的目的就是簡單化,並且增加SocketServer發送信息到SocketClient的功能。

        這是工程的最終結構圖

clip_image002

通信數據結構

        由於speech加入了語音識別功能,所以為了區別之前的通信信息,重新整理定義了新的通信數據結構。通信數據結構定為二進制數據,前4位是一個int32型的命令碼,這些命令碼有不同的含義和內容:

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

        當speech收到1時,進行初始化。收到2的信息時,讀取之后的文本數據,然后交由Speecher來發音。收到3時,讀取后面的數據,如果是1,則開始進行錄音識別,如果是0則停止錄音識別。

        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[]數據的類)

/***測試代碼,可刪除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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM