摘要: iOS10語音辨識架構SpeechFramework應用
一、引言
iOS10系統是一個較有突破性的系統,其在Message,Notification等方面都開放了很多實用性的開發介面。本篇部落格將主要探討iOS10中新引入的SpeechFramework架構。有個這個架構,開發人員可以十分容易的為自己的App添加語音辨識功能,不需要再依賴於其他第三方的語音辨識服務,並且,Apple的Siri應用的強大也證明了Apple的Voice Messaging Service是足夠強大的,不通過第三方,也大大增強了使用者的安全性。
二、SpeechFramework架構中的重要類
SpeechFramework架構比較輕量級,其中的類並不十分冗雜,在學習SpeechFramework架構前,我們需要對其中類與類與類之間的關係有個大致的熟悉瞭解。
SFSpeechRecognizer:這個類是語音辨識的操作類,用於語音辨識使用者權限的申請,語言環境的設定,語音模式的設定以及向Apple服務發送語音辨識的請求。
SFSpeechRecognitionTask:這個類是語音辨識服務要求任務類,每一個語音辨識請求都可以抽象為一個SFSpeechRecognitionTask執行個體,其中SFSpeechRecognitionTaskDelegate協議中約定了許多請求任務過程中的監聽方法。
SFSpeechRecognitionRequest:語音辨識請求類,需要通過其子類來進行執行個體化。
SFSpeechURLRecognitionRequest:通過音頻URL來建立語音辨識請求。
SFSpeechAudioBufferRecognitionRequest:通過音頻流來建立語音辨識請求。
SFSpeechRecognitionResult:語音辨識請求結果類。
SFTranscription:語音轉換後的資訊類。
SFTranscriptionSegment:語音轉換中的音頻節點類。
瞭解了上述類的作用於其之間的聯絡,使用SpeechFramework架構將十分容易。
三、申請使用者語音辨識許可權與進行語音辨識請求
開發人員若要在自己的App中使用語音辨識功能,需要擷取使用者的同意。首先需要在工程的Info.plist檔案中添加一個Privacy-Speech Recognition Usage Description鍵,其實需要對應一個String類型的值,這個值將會在系統擷取許可權的警告框中顯示,Info.plist檔案如下圖所示:
使用SFSpeechRecognize類的requestAuthorization方法來進行使用者權限的申請,使用者的反饋結果會在這個方法的回調block中傳入,如下:
//申請使用者語音辨識許可權 [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) { }];
SFSpeechRecognizerAuthorzationStatus枚舉中定義了使用者的反饋結果,如下:
typedef NS_ENUM(NSInteger, SFSpeechRecognizerAuthorizationStatus) { //結果未知 使用者尚未進行選擇 SFSpeechRecognizerAuthorizationStatusNotDetermined, //使用者拒絕授權語音辨識 SFSpeechRecognizerAuthorizationStatusDenied, //裝置不支援語音辨識功能 SFSpeechRecognizerAuthorizationStatusRestricted, //使用者授權語音辨識 SFSpeechRecognizerAuthorizationStatusAuthorized,};
如果申請使用者語音辨識許可權成功,開發人員可以通過SFSpeechRecognizer操作類來進行語音辨識請求,樣本如下:
//建立語音辨識操作類對象 SFSpeechRecognizer * rec = [[SFSpeechRecognizer alloc]init]; //通過一個音頻路徑建立音頻識別請求 SFSpeechRecognitionRequest * request = [[SFSpeechURLRecognitionRequest alloc]initWithURL:[[NSBundle mainBundle] URLForResource:@"7011" withExtension:@"m4a"]]; //進行請求 [rec recognitionTaskWithRequest:request resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) { //列印語音辨識的結果字串 NSLog(@"%@",result.bestTranscription.formattedString); }];
四、深入SFSpeechRecognizer類
SFSpeechRecognizer類的主要作用是申請許可權,配置參數與進行語音辨識請求。其中比較重要的屬性與方法如下:
//擷取目前使用者許可權狀態+ (SFSpeechRecognizerAuthorizationStatus)authorizationStatus;//申請語音辨識使用者權限+ (void)requestAuthorization:(void(^)(SFSpeechRecognizerAuthorizationStatus status))handler;//擷取所支援的所有語言環境+ (NSSet<NSLocale *> *)supportedLocales;//初始化方法 需要注意 這個初始化方法將預設以裝置當前的語言環境作為語音辨識的語言環境- (nullable instancetype)init;//初始化方法 設定一個特定的語言環境- (nullable instancetype)initWithLocale:(NSLocale *)locale NS_DESIGNATED_INITIALIZER;//語音辨識是否可用@property (nonatomic, readonly, getter=isAvailable) BOOL available;//語音辨識操作類協議代理@property (nonatomic, weak) id<SFSpeechRecognizerDelegate> delegate;//設定語音辨識的配置參數 需要注意 在每個語音辨識請求中也有這樣一個屬性 這裡設定將作為預設值//如果SFSpeechRecognitionRequest對象中也進行了設定 則會覆蓋這裡的值/*typedef NS_ENUM(NSInteger, SFSpeechRecognitionTaskHint) { SFSpeechRecognitionTaskHintUnspecified = 0, // 無定義 SFSpeechRecognitionTaskHintDictation = 1, // 正常的聽寫風格 SFSpeechRecognitionTaskHintSearch = 2, // 搜尋風格 SFSpeechRecognitionTaskHintConfirmation = 3, // 短語風格};*/@property (nonatomic) SFSpeechRecognitionTaskHint defaultTaskHint;//使用回調Block的方式進行語音辨識請求 請求結果會在Block中傳入- (SFSpeechRecognitionTask *)recognitionTaskWithRequest:(SFSpeechRecognitionRequest *)request resultHandler:(void (^)(SFSpeechRecognitionResult * __nullable result, NSError * __nullable error))resultHandler;//使用代理回調的方式進行語音辨識請求- (SFSpeechRecognitionTask *)recognitionTaskWithRequest:(SFSpeechRecognitionRequest *)request delegate:(id <SFSpeechRecognitionTaskDelegate>)delegate;//佈建要求所佔用的任務隊列@property (nonatomic, strong) NSOperationQueue *queue;
SFSpeechRecognizerDelegate協議中只約定了一個方法,如下:
//當語音辨識操作可用性發生改變時會被調用- (void)speechRecognizer:(SFSpeechRecognizer *)speechRecognizer availabilityDidChange:(BOOL)available;
通過Block回調的方式進行語音辨識請求十分簡單,如果使用代理回調的方式,開發人員需要實現SFSpeechRecognitionTaskDelegate協議中的相關方法,如下:
//當開始檢測音頻源中的語音時首先調用此方法- (void)speechRecognitionDidDetectSpeech:(SFSpeechRecognitionTask *)task;//當識別出一條可用的資訊後 會調用/*需要注意,apple的語音辨識服務會根據提供的音頻源識別出多個可能的結果 每有一條結果可用 都會調用此方法*/- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didHypothesizeTranscription:(SFTranscription *)transcription;//當識別完成所有可用的結果後調用- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didFinishRecognition:(SFSpeechRecognitionResult *)recognitionResult;//當不再接受音頻輸入時調用 即開始處理語音辨識任務時調用- (void)speechRecognitionTaskFinishedReadingAudio:(SFSpeechRecognitionTask *)task;//當語音辨識任務被取消時調用- (void)speechRecognitionTaskWasCancelled:(SFSpeechRecognitionTask *)task;//語音辨識任務完成時被調用- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didFinishSuccessfully:(BOOL)successfully;
SFSpeechRecognitionTask類中封裝了屬性和方法如下:
//此任務的目前狀態/*typedef NS_ENUM(NSInteger, SFSpeechRecognitionTaskState) { SFSpeechRecognitionTaskStateStarting = 0, // 任務開始 SFSpeechRecognitionTaskStateRunning = 1, // 任務正在運行 SFSpeechRecognitionTaskStateFinishing = 2, // 不在進行音頻讀入 即將返回識別結果 SFSpeechRecognitionTaskStateCanceling = 3, // 任務取消 SFSpeechRecognitionTaskStateCompleted = 4, // 所有結果返回完成};*/@property (nonatomic, readonly) SFSpeechRecognitionTaskState state;//音頻輸入是否完成@property (nonatomic, readonly, getter=isFinishing) BOOL finishing;//手動完成音頻輸入 不再接收音頻- (void)finish;//任務是否被取消@property (nonatomic, readonly, getter=isCancelled) BOOL cancelled;//手動取消任務- (void)cancel;
關於音頻識別請求類,除了可以使用SFSpeechURLRecognitionRequest類來進行建立外,還可以使用SFSpeechAudioBufferRecognitionRequest類來進行建立:
@interface SFSpeechAudioBufferRecognitionRequest : SFSpeechRecognitionRequest@property (nonatomic, readonly) AVAudioFormat *nativeAudioFormat;//拼接音頻流- (void)appendAudioPCMBuffer:(AVAudioPCMBuffer *)audioPCMBuffer;- (void)appendAudioSampleBuffer:(CMSampleBufferRef)sampleBuffer;//完成輸入- (void)endAudio;@end
五、語音辨識結果類SFSpeechRecognitionResult
SFSpeechRecognitionResult類是語音辨識結果的封裝,其中包含了許多套平行的識別資訊,其每一份識別資訊都有可信度屬性來描述其準確程度。SFSpeechRecognitionResult類中屬性如下:
//識別到的多套語音轉換資訊數組 其會按照準確度進行排序@property (nonatomic, readonly, copy) NSArray<SFTranscription *> *transcriptions;//準確性最高的識別執行個體@property (nonatomic, readonly, copy) SFTranscription *bestTranscription;//是否已經完成 如果YES 則所有所有識別資訊都已經擷取完成@property (nonatomic, readonly, getter=isFinal) BOOL final;
SFSpeechRecognitionResult類只是語音辨識結果的一個封裝,真正的識別資訊定義在SFTranscription類中,SFTranscription類中屬性如下:
//完整的語音辨識准換後的文本資訊字串@property (nonatomic, readonly, copy) NSString *formattedString;//語音辨識節點數組@property (nonatomic, readonly, copy) NSArray<SFTranscriptionSegment *> *segments;
當對一句完整的話進行識別時,Apple的語音辨識服務實際上會把這句語音拆分成若干個音頻節點,每個節點可能為一個單詞,SFTranscription類中的segments屬性就存放這些節點。SFTranscriptionSegment類中定義的屬性如下:
//當前節點識別後的文本資訊@property (nonatomic, readonly, copy) NSString *substring;//當前節點識別後的文本資訊在整體識別語句中的位置@property (nonatomic, readonly) NSRange substringRange;//當前節點的音頻時間戳記@property (nonatomic, readonly) NSTimeInterval timestamp;//當前節點音訊期間@property (nonatomic, readonly) NSTimeInterval duration;//可信度/準確度 0-1之間@property (nonatomic, readonly) float confidence;//關於此節點的其他可能的識別結果 @property (nonatomic, readonly) NSArray<NSString *> *alternativeSubstrings;
溫馨提示:SpeechFramework架構在模擬器上運行會出現異常情況,無法進行語音辨識請求。會報出kAFAssistantErrorDomain的錯誤,還望有知道解決方案的朋友,給些建議,Thanks。
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。