本文系原創,禁止轉載。
分享如何使用c#對接科大訊飛語音聽寫服務,簡單高效地實現語音聽寫。
實現語音聽寫主要分為錄音和語音識別兩部分;錄音是指獲取設備聲卡端口的音頻數據並將之保存為音頻文件,語音識別就是將剛才所述的音頻文件通過調用訊飛的語音聽寫服務轉換為文字。
相關的類庫文件
1. 開源錄音庫 NAudio.dll
http://pan.baidu.com/s/1dFth2nv
2.語音聽寫庫 msc.dll
去訊飛開放平台申請相關的SDK
錄音部分可以使用開源的.net音頻處理類庫NAudio.dll,它是托管的類庫,使用起來比較方便,當然你也可以自己去讀聲卡錄音,微軟有相關的系統API,這里不詳述。
錄音部分核心代碼:
1 //初始化 2 String FilePath = AppDomain.CurrentDomain.BaseDirectory + "Temp.wav"; 3 WaveIn m_waveSource = new WaveIn(); 4 m_waveSource.WaveFormat = new NAudio.Wave.WaveFormat(16000, 16, 1);// 16bit,16KHz,Mono的錄音格式 5 m_waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable); 6 m_waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped); 7 WaveFileWriter m_waveFile = new WaveFileWriter(m_fileName, m_waveSource.WaveFormat); 8 9 //開始錄音 10 m_waveSource.StartRecording(); 11 12 //保存到截獲到的聲音 13 private void waveSource_DataAvailable(object sender, WaveInEventArgs e) 14 { 15 if (m_waveFile != null) 16 { 17 m_waveFile.Write(e.Buffer, 0, e.BytesRecorded); 18 m_waveFile.Flush(); 19 } 20 } 21 22 //停止錄音 23 m_waveSource.StopRecording();
錄音完成后就可以進行語音聽寫了,訊飛提供的語音聽寫服務SDK中的類庫msc.dll是原生的類庫,在c#中沒有辦法像托管類庫那樣使用,需要通過使用Import的方式來引用,也可以包裝成托管的類庫來使用,這里只介紹第一種方法。
上述類庫是msc.dll使用C語言封裝的,在聲明接口的時候需注意C語言的變量類型的表達方式與C#有很多不同之處;比如,在SDK中有很多針對內存地址操作的,所以涉及到很多的指針類型變量,而C#中指針概念相對較弱。提供兩個解決思路,一是在C#中聲明UnSafe代碼,這樣就可以像C/C++一樣使用指針,二是使用IntPtr、ref 變量的表達方式,來實現“兼容”。
相關接口聲明:
1 [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] 2 public static extern int MSPLogin(string usr, string pwd, string @params); 3 4 [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] 5 public static extern IntPtr QISRSessionBegin(string grammarList, string _params, ref int errorCode); 6 7 [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] 8 public static extern int QISRGrammarActivate(string sessionID, string grammar, string type, int weight); 9 10 [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] 11 public static extern int QISRAudioWrite(string sessionID, IntPtr waveData, uint waveLen, int audioStatus, ref int epStatus, ref int recogStatus); 12 13 [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] 14 public static extern IntPtr QISRGetResult(string sessionID, ref int rsltStatus, int waitTime, ref int errorCode); 15 16 [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] 17 public static extern int QISRSessionEnd(string sessionID, string hints); 18 19 [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] 20 public static extern int QISRGetParam(string sessionID, string paramName, string paramValue, ref uint valueLen); 21 22 [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)] 23 public static extern int MSPLogout();
業務流程:
1.調用 MSPLogin(...)接口登入,可以只登入一次,但是必須保證在調用其他接口前先登入;
2.調用 QISRSessionBegin(...)開始一次語音聽寫;
3.調用 QISRAudioWrite(...) 分塊寫入音頻數據
4.循環調用 QISRGetResult(...) 接口返回聽寫結果
5.調用 QISRSessionEnd(...) 主動結束本次聽寫
6.不再使用服務的時候 調用MSPLogout()登出,避免不必要的麻煩。
核心代碼:
public string AudioToString(string inFile) { int ret = 0; string text = String.Empty; FileStream fileStream = new FileStream(inFile, FileMode.OpenOrCreate); byte[] array = new byte[this.BUFFER_NUM]; IntPtr intPtr = Marshal.AllocHGlobal(this.BUFFER_NUM); int audioStatus = 2; int epStatus = -1; int recogStatus = -1; int rsltStatus = -1; while (fileStream.Position != fileStream.Length) { int waveLen = fileStream.Read(array, 0, this.BUFFER_NUM); Marshal.Copy(array, 0, intPtr, array.Length); ret = iFlyASR.QISRAudioWrite(this.m_sessionID, intPtr, (uint)waveLen, audioStatus, ref epStatus, ref recogStatus); if (ret != 0) { fileStream.Close(); throw new Exception("QISRAudioWrite err,errCode=" + ret); } if (recogStatus == 0) { IntPtr intPtr2 = iFlyASR.QISRGetResult(this.m_sessionID, ref rsltStatus, 0, ref ret); if (intPtr2 != IntPtr.Zero) { text += this.Ptr2Str(intPtr2); } } Thread.Sleep(500); } fileStream.Close(); audioStatus = 4; ret = iFlyASR.QISRAudioWrite(this.m_sessionID, intPtr, 1u, audioStatus, ref epStatus, ref recogStatus); if (ret != 0) { throw new Exception("QISRAudioWrite write last audio err,errCode=" + ret); } int timesCount = 0; while (true) { IntPtr intPtr2 = iFlyASR.QISRGetResult(this.m_sessionID, ref rsltStatus, 0, ref ret); if (intPtr2 != IntPtr.Zero) { text += this.Ptr2Str(intPtr2); } if (ret != 0) { break; } Thread.Sleep(200); if (rsltStatus == 5 || timesCount++ >= 50) { break; } } return text; }
自己設計以下UI交互,或者和你的應用程序結合一下,就可以讓你的應用程序長一雙會聽的耳朵了!
結果: