雲狐語音識別軟件視頻演示及代碼簡明解析

一、雲狐簡介

雲狐語音識別軟件是基於百度智能雲,由進擊的狐狸進行開發的一款軟件。注意,因爲核心類代碼是2017年就已經寫好的了,所以使用的C# SDK包不是最新的。雲狐目前支持的平臺是Windows系統平臺,使用時需要安裝微軟最新的.net framework 。雲狐的主要功能是長時間的語音識別,支持時長超過一分鐘的各種類型的語音文件識別,缺點就是速度較慢一些。

雲狐視頻演示及代碼解析的視頻鏈接:

https://v.qq.com/x/page/j3023vgs9yz.html

雲狐語音識別軟件下載:

https://blog.csdn.net/ciel_arc/article/details/103172138

另外,雲狐和雲貓實際上是姐妹軟件,因爲他們都是基於百度智能雲,用C#進行開發的,使用的是百度最新的人工智能技術。而且他們目前都是免費的。這裏聯動一下,對雲貓OCR和雲狐語音感興趣的同學,可以百度搜索“雲貓OCR”或“雲狐語音” 進行了解。

二、雲狐的簡單評測

雲狐軟件自帶有計時功能,我們可以簡單做一下評測。從上文視頻演示的結果可以看出,1分鐘左右的語音文件,雲狐可以在10秒以內識別完畢,而30分鐘左右的語音文件,雲狐需要120秒即2分鐘左右,才能識別完畢。從中推算出識別速度大概是4秒/分鐘。

三、雲狐軟件的代碼原理

    百度智能雲給出的長語音識別接口只支持一分鐘以內的語音文件的識別。而對於超過一分鐘的語音文件識別,我們需要怎麼做呢?

   雲狐軟件的原理就是:把超過一分鐘的文件進行切片,切成若干個小於或者等於一分鐘時長的語音文件。對每個切片文件調用百度雲語音識別接口進行識別,再把結果串聯起來即可。

四、雲狐的代碼簡明解析

(一)核心類foxSpeechDemo

namespace foxAudio2Word

{

    class foxSpeechDemo

    {

        private readonly Asr _asrClient;

        public foxSpeechDemo(string myAPIKey,string mySecretKey)

        {

            _asrClient = new Asr(myAPIKey,mySecretKey);

        }

        // 識別本地文件

        public string AsrData(string pcmFilePath)

        {

            var data = File.ReadAllBytes(pcmFilePath);

            var result = _asrClient.Recognize(data, "pcm", 16000);

            return result.ToString();

        }

}

}

   上面的代碼是根據百度SDK包文檔,進行少量改動實現的。注意爲了簡便,這裏貼出的代碼段可能跟具體的雲狐實現代碼有一些出入。

   不是任何一個語音文件都可以交給百度智能雲直接識別。文件需要預處理,不然識別效果會很差。具體來說,作者用FFmpeg對語音文件進行預處理,然後再用百度接口識別。FFmpeg的命令行預處理類似下面的形式:

ffmpeg -y  -i 003_16k.wav  -acodec pcm_s16le -f s16le -ac 1 -ar 16000 16k.pcm

(二)預處理的輔助函數

   共有大概4個關於預處理的輔助函數,代碼如下:

1.此函數的主要功能是用C#程序自動執行命令行語句,它可執行任何語句的命令行,string cmdStr是形參,可以將命令行語句賦值給cmdStr進行執行。

 private string myCmdFun(string cmdStr)

        {

            try

            {

                Process CmdProcess = new Process();

                CmdProcess.StartInfo.FileName = "cmd.exe";

                CmdProcess.StartInfo.CreateNoWindow = true;         // 不創建新窗口    

                CmdProcess.StartInfo.UseShellExecute = false;       //不啓用shell啓動進程  

                CmdProcess.StartInfo.RedirectStandardInput = true;  // 重定向輸入    

                CmdProcess.StartInfo.RedirectStandardOutput = true; // 重定向標準輸出    

                CmdProcess.StartInfo.RedirectStandardError = true;  // 重定向錯誤輸出  

                //CmdProcess.StartInfo.Arguments = "/c " + "=====cmd命令======";//“/C”表示執行完命令後馬上退出

                //string cmdStr = "ffmpeg -y  -i 003_16k.wav  -acodec pcm_s16le -f s16le -ac 1 -ar 16000 16k.pcm";

                CmdProcess.StartInfo.Arguments = "/c " + cmdStr;//“/C”表示執行完命令後馬上退出  

                CmdProcess.Start();//執行  

                string temp = CmdProcess.StandardOutput.ReadToEnd();//輸出  

                CmdProcess.WaitForExit();//等待程序執行完退出進程  

                CmdProcess.Close();//結束

                return temp;

            }

            catch (Exception ex)

            {

                return ex.ToString();

            }

        }

2.此函數表示利用ffprobe命令行獲取語音文件的時長信息,以便對語音文件進行分割,注意返回值是整形變量。比如語音時長有1.5分鐘,這個函數就會返回2 ,以此類推。

/// 

 

        /// 獲取音頻文件的持續時間信息

        /// 

 

        /// 

        /// 

        private int foxGetAudioDuration(string filename)

        {

            //使用命令行要非常小心對空格的處理

            string tempCmdStr = "ffprobe -v quiet -print_format json -show_streams "

                + filename;

            string result = myCmdFun(tempCmdStr);

            //結果使用json格式解析

            JObject jo = (JObject)JsonConvert.DeserializeObject(result);

            string audioDuration = jo["streams"][0]["duration"].ToString();

            //直接返回整形數據,單位是秒

            int durationSecond = (int)Math.Ceiling(System.Convert.ToDouble(audioDuration));

            //轉成分鐘表示

            int durationMinute = (durationSecond / 60) + 1;

            return durationMinute;

        }

3.此函數主要功能是對語音文件進行分割,時間單位是秒。比如我有一個2分鐘的語音文件,程序就把這個文件分成2塊,每塊60秒即1分鐘,以此類推。

///分割的時間單位應該是秒

        ///分割音頻文件

        private void foxAudioCut(string filename,int timePos,int duration,int fileIndex)

        {

            //string tempCmdStr = "ffmpeg -i 003_16k.wav -ss 10 -t 10 003_1.wav";

            string tempCmdStr = "ffmpeg -y -i "+filename+

                " -ss "+timePos.ToString()

                +" -t "+duration.ToString()

                +" "+ "temp\\" + fileIndex.ToString()+".wav";

 

            myCmdFun(tempCmdStr);

        }

4.此函數的主要功能是把切片文件轉換成百度雲能夠進行正常識別的文件格式。

/// 

 

        /// 把目標音頻文件轉換爲百度語音能夠識別的文件

        /// 

 

        /// 

        private string foxAudioConvert(string filename,int fileIndex)

        {

            //臨時工作夾目錄設置爲“temp”

            string resultFileName = "Convert_" + fileIndex.ToString() + ".wav";

            //注意這句含有兩個“temp\\”

            string tempCmdStr = "ffmpeg -y  -i "+ "temp\\" + filename

                +"  -acodec pcm_s16le -ac 1 -ar 16000 " 

                + "temp\\" +resultFileName;

            myCmdFun(tempCmdStr);

 

            return resultFileName;

        }

(三)主函數的代碼邏輯

//注意:文件路徑裏面不能含有空格

                    string tempFilePath = Path.GetFullPath(openFileDialog1.FileName);

                    //獲取音頻文件持續時間信息

                    int duration = foxGetAudioDuration(tempFilePath);

                    //主要的長語音識別邏輯

                    //將音頻文件分成塊,每塊的長度默認爲1分鐘

                    for (int i = 0; i < duration; i++)

                    {

                        //首先分割文件

                        foxAudioCut(tempFilePath, i * 60, 60, i);

                        //然後轉換格式

                        string tempConvertFileName = foxAudioConvert(i.ToString() + ".wav", i);

                        //最後進行識別

                        //tempResult += fd.AsrData("temp\\" + tempConvertFileName);

                        //解析json

                        string tempStr = fd.AsrData("temp\\" + tempConvertFileName);

                        JObject jo = (JObject)JsonConvert.DeserializeObject(tempStr);

                        if (jo["err_no"].ToString().Equals("0"))

                        {

                            string result = jo["result"][0].ToString();

                            tempResult += result;

                        }

                    }

                    richTextBox1.Text = tempResult;

    上面是主函數裏面的核心代碼段,裏面有很多的註釋,大家可以仔細看看。主要功能就是整合預處理輔助函數的作用,把文件切片並轉換格式,最後提交給百度智能雲進行識別,並對識別結果進行解析,把json轉換成對人類友好的文本格式。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章