1.什麼是OpenEars
OpenEars是面向iOS平臺的一個離線的語音識別和text-to-speech(文字語音轉換)開發工具包。因爲是離線的,它無需象Siri那樣需要和服務器進行網絡連接。當然,還要強調一點的是,OpenEars主要是針對英語的。最重要的是,它是免費的。除了基本的免費功能,它還提供了可以用來擴展基本功能的付費插件,也即Politepix OpenEars插件。
使用OpenEars,可以在iPhone和iPad應用中輕鬆實現英語的語音識別和TTS(語音合成)功能,並可使用開源的CMU Pocketsphinx,CMU Flite,CMUCLMTK類庫。
OpenEars 平臺也是一個完整的開發平臺,其中包含了免費的OpenEArs SDK,以及一些拓展的功能插件(付費)。
考慮到我朝開發人員多數是屌絲出身,這裏先介紹免費的SDK,等大家熟悉了之後再自行探索付費功能插件。
對於iPhone本地應用來說,要實現高精確度的大容量詞彙識別目前來說是非常困難的,即便是Siri也需要利用強大的服務器數據庫來完成這一任務。不過Pocketsphinx(OpenEars所使用的開源語音識別引擎)能夠做到在iPhone本地應用中根據環境和其它因素來識別英語詞彙。
當前OpenEars的最新版本是1.2.5,下載地址:http://www.politepix.com/wp-content/uploads/OpenEarsDistribution.tar.bz2
2.OpenEars的功能特性
OpenEars目前有以下的功能特性:
1. 在後臺線程中連續監聽,並根據需要暫停或繼續語言處理,而這些操作在iPhone4中僅佔用4%的CPU(包括語言解碼,語音合成)。
2. 支持9種語音類型,包括男性和女性,速度和質量在一定的範圍內,並可在使用的過程中更改。
3. 可以更改語音合成的音高,音速和變化。
4. 判斷當前耳機是否在插孔中,然後僅當耳機在插孔中時才繼續語言識別。
5. 支持藍牙語音設備(實驗中)。
6. 語音識別和語音合成的結果可以被當前應用的任一類所共享
7. 支持JSGF語法
8. 根據NSArray或NSString中的輸入來動態生成新的ARPA語言模型
9. 動態切換ARPA語言模型或JSGF語法
10. 測試已有的錄音
11. 可以通過標準的Objective-C方法進行交互
12. 所有的語音識別和語音合成功能均在內存中完成,無需寫入到音頻文件中再讀取。
13. 包裝在一個Cocoa標準風格的框架中
注意:
在使用OpenEars的時候,儘量直接在設備上測試應用,在模擬器上的識別精度會有所下降。
此外,在Xcode4.5中蘋果已經刪除armv6架構編譯。如果需要爲armv6設備編譯,可以使用OpenEars之前的舊版本,但該版本不會繼續更新,也無法用於編譯armv7s設備。http://www.politepix.com/wp-content/uploads/OpenEarsDistributionLegacy.tar.bz2
3.OpenEars的安裝和使用
(1)首先下載框架:
http://www.politepix.com/wp-content/uploads/OpenEarsDistribution.tar.bz2
(2)在Xcode中創建自己的應用,並添加AudioToolbox和AVFoundation框架。
(3)將所下載壓縮包中的Frameworks文件夾拖到項目中
接下來呢?~現在就已經可以開始使用OpenEars了。
爲了熟悉它的基本功能,可以先嚐試運行示例項目。因爲示例項目支持ARC,所以最好使用最新的Xcode版本。
4. OpenEars示例項目簡介
在我第一次使用OpenEars的示例項目時,因爲受了Siri的影響,於是嘗試說了一大堆,結果發現這個簡單示例項目支持的是詞彙識別,而不是句子的識別。還是頗有些失望的。
不過最起碼它還是可以識別出你所說的單詞,精確度還很高。
在Xcode中打開OpenEarsSampleApp,項目的結果非常簡單,首先是OpenEars的特有框架,然後是AudioToolbox和AVFoundation這兩個標準框架,當然還有其它幾個幾乎每個項目都會用到的框架。
隨便打開一個.xib文件,會看到項目的佈局。
兩個文本框,兩個標籤,還有四個按鈕。
打開ViewController.h,會看到它遵循OpenEarsEventsObserverDelegatex協議。在頭文件裏面定義了多個方法,其中四個IBAction方法是我們重點要了解的。
切換到ViewControlller.m,來看看幾個方法的實現代碼。
最重要的當然是startListening方法,只有一行代碼,startListeningWithLanguageModelAtPath:dictionaryAtPath:languageModelIsJSGF方法需要知道所使用的語法文件,詞典文件,以及該語法是否是JSGF。在單個語音識別循環中,只能使用JSGF或ARPA語法文件中的一種,而不能在兩種類型中切換。
ARPA語法通常是.languagemodel或.DMP後綴的文件,而JSGF語法則是.gram後綴的文件。
如果你只是想識別某個單獨的語音wav文件,可以使用以下方式:
NSString *wavPath = [NSString stringWithFormat:@"%@/%@",[[NSBundle mainBundle] resourcePath], @"test.wav"];
[self.pocketsphinxController runRecognitionOnWavFileAtPath:wavPath usingLanguageModelAtPath:self.pathToGrammarToStartAppWith dictionaryAtPath:self.pathToDictionaryToStartAppWith languageModelIsJSGF:FALSE]; // Starts the recognition loop.
示例中的方法適用於進行連續語音識別。
在viewDidLoad方法中主要是指定了startListening 方法中所使用的參數,然後調用了startListening方法和startDisplayingLevels方法。
這裏使用的默認詞典和語法是OpenEars1.dic和OpenEras1.languagemodel(在Frameworks文件中自帶的)。
需要注意的是startDisplayingLevels方法是這個示例項目中特有的方法,這裏就不詳細介紹了。
此外就是OpenEarsEventsObserver的協議實現方法,稍作修改就可以在其它項目中使用。
當用戶說出change model後,就會將詞典和語法切換到動態生成的詞典,也就是languageArray中的幾個單詞。
在設備上運行項目後,首先看到如下界面:默認的詞典裏面只支持Backward,change,forward,go,left,model,right,turn幾個單詞。當你說change model後,就切換到由程序數組動態生成的詞典,就可以支持change,model,Monday,Tuesday,…Sunday, QUIDNUNC。
爲了進一步測試,我嘗試把viewDidLoad裏面的詞組更換爲:
NSArray *languageArray = [[NSArray alloc] initWithArray:[NSArray arrayWithObjects: // All capital letters.
@"APPLE",
@"Steve Jobs",
@"Tim Cook",
@"MICROSOFT",
@"FOOD",
@"MONEY",
@"GAME",
@"IPHONE",
@"SIRI",
nil]];
再次運行測試,當說出change model的指令後,程序對於新的詞組都可以識別並輸出,如圖:
說明這個識別是與大小寫無關的。
然後來測試對句子的識別,將viewDidLoad中的詞組修改爲如下:
NSArray *languageArray = [[NSArray alloc] initWithArray:[NSArray arrayWithObjects: // All capital letters.
@"APPLE",
@"Steve Jobs",
@"Tim Cook",
@"I love Apple",
@"I am hungry",
@"I really really need money",
@"I'm not a baby",
@"IPHONE",
@"SIRI",
nil]];
再次測試,基本上識別精度仍然很高,但連續識別的時候容易跟之前的句子弄混,不過這個體驗問題不難解決。
這樣的話,示例項目的目的已經基本上達到。我們對示例項目做一些修改就可以爲自己所用。