一次嘗試使用cmu sphinx做語音識別的失敗記錄

好好的C++不去寫,爲啥想起來搞什麼語音識別?事情是這樣的,我經常躺在牀上聽歌,使用電腦連音響播放,因爲我比較懶,切歌啥的都直接召喚小娜幫我做,可以節省體力。然而小娜笨啊,除了能切歌啥也幹不了,我要是聽到一首好聽的,還得爬起來去收藏,這多麼麻煩是不是?小娜也沒開放啥接口可以自定義命令,就想自己寫一個程序,識別到我的指令後,按照播放器的快捷鍵虛擬鍵盤按鍵事件。
網上一搜“開源語音識別引擎”,好,就是你了:cmu sphinx。然而結果是慘淡的,週末兩天的工作成果並沒能使我輕鬆一點。我的“小小紅”雖然能聽懂更多我需要的指令,然而只有在我不播放音樂時才聽得懂,環境噪聲稍大就不聽話了。相比之下小娜就可靠多了,即使開着音樂也能聽懂我的指令。雖然失敗了,但也做個記錄吧,當然是以一個語音識別門外漢的視角做的記錄,是自己的理解,不見得準確。

  1. 因爲是在windows下播放音樂,所以直接下載了cmu sphinx的win32版源碼,自帶VS工程文件。
  2. 要想在win10上正常運行自帶的continuous樣例,需要把sphinxbase和pocketsphinx都編譯成release版,同時把運行庫編譯參數指定爲:多線程DLL(/MD)。
  3. 要注意中文編碼問題,語言模型文件和字典文件編碼要相同,我都設置成了GB2312,可以避免終端輸出亂碼。
  4. 需要使用3種模型文件,具體可見https://cmusphinx.github.io/wiki/tutorialconcepts/,聲音模型用來把聲音輸入映射到定義好的音素,語言模型定義了所有可能的輸出(即詞的組合),字典用來把語言模型中的詞映射到音素,字典不影響識別準確率(這一點見https://cmusphinx.github.io/wiki/tutorialdict/)。
  5. 使用cmu sphinx提供的默認普通話聲音模型和語言模型,識別準確率相當感人,完全用不了。
  6. 將語言模型限定爲我定義的指令,識別準確率就上來了(當然是安靜情況下),這一度令我很高興,然而後來發現“下一首”在90%以上情況被識別爲“上一首”
  7. 按照https://cmusphinx.github.io/wiki/tutorialadapt/的方法,使用我的語音做適配後,“上一首”和“下一首”就分得清了,這裏是一個腳本:
sphinx_fe -argfile .\zh_broadcastnews_ptm256_8000\feat.params -samprate 16000 -c .\arctic20.fileids -di . -do . -ei wav -eo mfc -mswav yes
bw -hmmdir .\zh_broadcastnews_ptm256_8000 -moddeffn .\zh_broadcastnews_ptm256_8000\mdef -ts2cbfn .ptm. -feat s2_4x -cmn current -agc none -dictfn self.dic -ctlfn .\arctic20.fileids -lsnfn .\arctic20.transcription -accumdir .
mllr_solve.exe -meanfn .\zh_broadcastnews_ptm256_8000\means -varfn .\zh_broadcastnews_ptm256_8000\variances -outmllrfn mllr_matrix -accumdir .
map_adapt.exe -moddeffn .\zh_broadcastnews_ptm256_8000\mdef -ts2cbfn .ptm. -meanfn .\zh_broadcastnews_ptm256_8000\means -varfn .\zh_broadcastnews_ptm256_8000\variances -mixwfn .\zh_broadcastnews_ptm256_8000\mixture_weights -tmatfn .\zh_broadcastnews_ptm256_8000\transition_matrices -accumdir . -mapmeanfn .\zh_ptm_adapt\means -mapvarfn .\zh_ptm_adapt\variances -mapmixwfn .\zh_ptm_adapt\mixture_weights -maptmatfn .\zh_ptm_adapt\transition_matrices
  1. 識別時很容易受到噪聲影響,該開始識別時不開始,該結束識別時不結束(在recognize_from_microphone函數中的utt_started in_speech記錄一段語音識別的開始和結束。
  2. 通過設置vad_threshold能一定程度改善問題8,尤其是在安靜情況下,能讓識別率上升到90%以上,打開音樂時也有一定改善。
  3. 一旦打開音樂,問題8再次出現,使用9中的方法很難把握閾值,最終沒有很大的改善。
  4. 剛打開程序時,或者一段時間沒說指令時,初次說出的兩三個指令幾乎沒被識別對過,後面的才能識別,原因未知。這個讓我想不通,使用in_speech標識的每次識別過程難道不是獨立的嗎?
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章