iOS10語音識(shí)別框架SpeechFramework應(yīng)用詳解

一铭若、引言

??????? iOS10系統(tǒng)是一個(gè)較有突破性的系統(tǒng),其在Message递览,Notification等方面都開放了很多實(shí)用性的開發(fā)接口奥喻。本篇博客將主要探討iOS10中新引入的SpeechFramework框架。有個(gè)這個(gè)框架非迹,開發(fā)者可以十分容易的為自己的App添加語音識(shí)別功能环鲤,不需要再依賴于其他第三方的語音識(shí)別服務(wù),并且憎兽,Apple的Siri應(yīng)用的強(qiáng)大也證明了Apple的語音服務(wù)是足夠強(qiáng)大的冷离,不通過第三方,也大大增強(qiáng)了用戶的安全性纯命。

二西剥、SpeechFramework框架中的重要類

??????? SpeechFramework框架比較輕量級(jí),其中的類并不十分冗雜亿汞,在學(xué)習(xí)SpeechFramework框架前瞭空,我們需要對(duì)其中類與類與類之間的關(guān)系有個(gè)大致的熟悉了解。

SFSpeechRecognizer:這個(gè)類是語音識(shí)別的操作類疗我,用于語音識(shí)別用戶權(quán)限的申請(qǐng)咆畏,語言環(huán)境的設(shè)置,語音模式的設(shè)置以及向Apple服務(wù)發(fā)送語音識(shí)別的請(qǐng)求吴裤。

SFSpeechRecognitionTask:這個(gè)類是語音識(shí)別服務(wù)請(qǐng)求任務(wù)類旧找,每一個(gè)語音識(shí)別請(qǐng)求都可以抽象為一個(gè)SFSpeechRecognitionTask實(shí)例,其中SFSpeechRecognitionTaskDelegate協(xié)議中約定了許多請(qǐng)求任務(wù)過程中的監(jiān)聽方法麦牺。

SFSpeechRecognitionRequest:語音識(shí)別請(qǐng)求類钮蛛,需要通過其子類來進(jìn)行實(shí)例化。

SFSpeechURLRecognitionRequest:通過音頻URL來創(chuàng)建語音識(shí)別請(qǐng)求剖膳。

SFSpeechAudioBufferRecognitionRequest:通過音頻流來創(chuàng)建語音識(shí)別請(qǐng)求魏颓。

SFSpeechRecognitionResult:語音識(shí)別請(qǐng)求結(jié)果類。

SFTranscription:語音轉(zhuǎn)換后的信息類吱晒。

SFTranscriptionSegment:語音轉(zhuǎn)換中的音頻節(jié)點(diǎn)類甸饱。

??????? 了解了上述類的作用于其之間的聯(lián)系,使用SpeechFramework框架將十分容易枕荞。

三柜候、申請(qǐng)用戶語音識(shí)別權(quán)限與進(jìn)行語音識(shí)別請(qǐng)求

??????? 開發(fā)者若要在自己的App中使用語音識(shí)別功能搞动,需要獲取用戶的同意。首先需要在工程的Info.plist文件中添加一個(gè)Privacy-Speech Recognition Usage Description鍵渣刷,其實(shí)需要對(duì)應(yīng)一個(gè)String類型的值鹦肿,這個(gè)值將會(huì)在系統(tǒng)獲取權(quán)限的警告框中顯示,Info.plist文件如下圖所示:

使用SFSpeechRecognize類的requestAuthorization方法來進(jìn)行用戶權(quán)限的申請(qǐng)辅柴,用戶的反饋結(jié)果會(huì)在這個(gè)方法的回調(diào)block中傳入箩溃,如下:

//申請(qǐng)用戶語音識(shí)別權(quán)限

[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {

}];

SFSpeechRecognizerAuthorzationStatus枚舉中定義了用戶的反饋結(jié)果,如下:

typedefNS_ENUM(NSInteger, SFSpeechRecognizerAuthorizationStatus) {

?//結(jié)果未知 用戶尚未進(jìn)行選擇

?SFSpeechRecognizerAuthorizationStatusNotDetermined,

?//用戶拒絕授權(quán)語音識(shí)別

?SFSpeechRecognizerAuthorizationStatusDenied,

?//設(shè)備不支持語音識(shí)別功能

?SFSpeechRecognizerAuthorizationStatusRestricted,

?//用戶授權(quán)語音識(shí)別

?SFSpeechRecognizerAuthorizationStatusAuthorized,

};

??????? 如果申請(qǐng)用戶語音識(shí)別權(quán)限成功碌嘀,開發(fā)者可以通過SFSpeechRecognizer操作類來進(jìn)行語音識(shí)別請(qǐng)求涣旨,示例如下:

//創(chuàng)建語音識(shí)別操作類對(duì)象

SFSpeechRecognizer * rec = [[SFSpeechRecognizer alloc]init];

//通過一個(gè)音頻路徑創(chuàng)建音頻識(shí)別請(qǐng)求

SFSpeechRecognitionRequest * request = [[SFSpeechURLRecognitionRequest alloc]initWithURL:[[NSBundle mainBundle] URLForResource:@"7011"withExtension:@"m4a"]];

//進(jìn)行請(qǐng)求

[rec recognitionTaskWithRequest:request resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {

?//打印語音識(shí)別的結(jié)果字符串

?NSLog(@"%@",result.bestTranscription.formattedString);

}];

四、深入SFSpeechRecognizer類

??????? SFSpeechRecognizer類的主要作用是申請(qǐng)權(quán)限股冗,配置參數(shù)與進(jìn)行語音識(shí)別請(qǐng)求霹陡。其中比較重要的屬性與方法如下:

//獲取當(dāng)前用戶權(quán)限狀態(tài)

+ (SFSpeechRecognizerAuthorizationStatus)authorizationStatus;

//申請(qǐng)語音識(shí)別用戶權(quán)限

+ (void)requestAuthorization:(void(^)(SFSpeechRecognizerAuthorizationStatus status))handler;

//獲取所支持的所有語言環(huán)境

+ (NSSet *)supportedLocales;

//初始化方法 需要注意 這個(gè)初始化方法將默認(rèn)以設(shè)備當(dāng)前的語言環(huán)境作為語音識(shí)別的語言環(huán)境

- (nullable instancetype)init;

//初始化方法 設(shè)置一個(gè)特定的語言環(huán)境

- (nullable instancetype)initWithLocale:(NSLocale *)locale NS_DESIGNATED_INITIALIZER;

//語音識(shí)別是否可用

@property (nonatomic, readonly, getter=isAvailable) BOOLavailable;

//語音識(shí)別操作類協(xié)議代理

@property (nonatomic, weak) id delegate;

//設(shè)置語音識(shí)別的配置參數(shù) 需要注意 在每個(gè)語音識(shí)別請(qǐng)求中也有這樣一個(gè)屬性 這里設(shè)置將作為默認(rèn)值

//如果SFSpeechRecognitionRequest對(duì)象中也進(jìn)行了設(shè)置 則會(huì)覆蓋這里的值

/*

typedef NS_ENUM(NSInteger, SFSpeechRecognitionTaskHint) {

?SFSpeechRecognitionTaskHintUnspecified = 0,? // 無定義

?SFSpeechRecognitionTaskHintDictation = 1,? // 正常的聽寫風(fēng)格

?SFSpeechRecognitionTaskHintSearch = 2,?? // 搜索風(fēng)格

?SFSpeechRecognitionTaskHintConfirmation = 3, // 短語風(fēng)格

};

*/

@property (nonatomic) SFSpeechRecognitionTaskHint defaultTaskHint;

//使用回調(diào)Block的方式進(jìn)行語音識(shí)別請(qǐng)求 請(qǐng)求結(jié)果會(huì)在Block中傳入

- (SFSpeechRecognitionTask *)recognitionTaskWithRequest:(SFSpeechRecognitionRequest *)request

???????????resultHandler:(void(^)(SFSpeechRecognitionResult * __nullable result, NSError * __nullable error))resultHandler;

//使用代理回調(diào)的方式進(jìn)行語音識(shí)別請(qǐng)求

- (SFSpeechRecognitionTask *)recognitionTaskWithRequest:(SFSpeechRecognitionRequest *)request

????????????delegate:(id )delegate;

//設(shè)置請(qǐng)求所占用的任務(wù)隊(duì)列

@property (nonatomic, strong) NSOperationQueue *queue;

SFSpeechRecognizerDelegate協(xié)議中只約定了一個(gè)方法,如下:

//當(dāng)語音識(shí)別操作可用性發(fā)生改變時(shí)會(huì)被調(diào)用

- (void)speechRecognizer:(SFSpeechRecognizer *)speechRecognizer availabilityDidChange:(BOOL)available;

??????? 通過Block回調(diào)的方式進(jìn)行語音識(shí)別請(qǐng)求十分簡(jiǎn)單止状,如果使用代理回調(diào)的方式烹棉,開發(fā)者需要實(shí)現(xiàn)SFSpeechRecognitionTaskDelegate協(xié)議中的相關(guān)方法,如下:

//當(dāng)開始檢測(cè)音頻源中的語音時(shí)首先調(diào)用此方法

- (void)speechRecognitionDidDetectSpeech:(SFSpeechRecognitionTask *)task;

//當(dāng)識(shí)別出一條可用的信息后 會(huì)調(diào)用

/*

需要注意怯疤,apple的語音識(shí)別服務(wù)會(huì)根據(jù)提供的音頻源識(shí)別出多個(gè)可能的結(jié)果 每有一條結(jié)果可用 都會(huì)調(diào)用此方法

*/

- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didHypothesizeTranscription:(SFTranscription *)transcription;

//當(dāng)識(shí)別完成所有可用的結(jié)果后調(diào)用

- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didFinishRecognition:(SFSpeechRecognitionResult *)recognitionResult;

//當(dāng)不再接受音頻輸入時(shí)調(diào)用 即開始處理語音識(shí)別任務(wù)時(shí)調(diào)用

- (void)speechRecognitionTaskFinishedReadingAudio:(SFSpeechRecognitionTask *)task;

//當(dāng)語音識(shí)別任務(wù)被取消時(shí)調(diào)用

- (void)speechRecognitionTaskWasCancelled:(SFSpeechRecognitionTask *)task;

//語音識(shí)別任務(wù)完成時(shí)被調(diào)用

- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didFinishSuccessfully:(BOOL)successfully;

SFSpeechRecognitionTask類中封裝了屬性和方法如下:

//此任務(wù)的當(dāng)前狀態(tài)

/*

typedef NS_ENUM(NSInteger, SFSpeechRecognitionTaskState) {

?SFSpeechRecognitionTaskStateStarting = 0,? // 任務(wù)開始

?SFSpeechRecognitionTaskStateRunning = 1,? // 任務(wù)正在運(yùn)行

?SFSpeechRecognitionTaskStateFinishing = 2,? // 不在進(jìn)行音頻讀入 即將返回識(shí)別結(jié)果

?SFSpeechRecognitionTaskStateCanceling = 3,? // 任務(wù)取消

?SFSpeechRecognitionTaskStateCompleted = 4,? // 所有結(jié)果返回完成

};

*/

@property (nonatomic, readonly) SFSpeechRecognitionTaskState state;

//音頻輸入是否完成

@property (nonatomic, readonly, getter=isFinishing) BOOLfinishing;

//手動(dòng)完成音頻輸入 不再接收音頻

- (void)finish;

//任務(wù)是否被取消

@property (nonatomic, readonly, getter=isCancelled) BOOLcancelled;

//手動(dòng)取消任務(wù)

- (void)cancel;

關(guān)于音頻識(shí)別請(qǐng)求類浆洗,除了可以使用SFSpeechURLRecognitionRequest類來進(jìn)行創(chuàng)建外,還可以使用SFSpeechAudioBufferRecognitionRequest類來進(jìn)行創(chuàng)建:

@interface SFSpeechAudioBufferRecognitionRequest : SFSpeechRecognitionRequest


@property (nonatomic, readonly) AVAudioFormat *nativeAudioFormat;

//拼接音頻流

- (void)appendAudioPCMBuffer:(AVAudioPCMBuffer *)audioPCMBuffer;

- (void)appendAudioSampleBuffer:(CMSampleBufferRef)sampleBuffer;

//完成輸入

- (void)endAudio;


@end

五集峦、語音識(shí)別結(jié)果類SFSpeechRecognitionResult

SFSpeechRecognitionResult類是語音識(shí)別結(jié)果的封裝伏社,其中包含了許多套平行的識(shí)別信息,其每一份識(shí)別信息都有可信度屬性來描述其準(zhǔn)確程度塔淤。SFSpeechRecognitionResult類中屬性如下:

//識(shí)別到的多套語音轉(zhuǎn)換信息數(shù)組 其會(huì)按照準(zhǔn)確度進(jìn)行排序

@property (nonatomic, readonly, copy) NSArray *transcriptions;

//準(zhǔn)確性最高的識(shí)別實(shí)例

@property (nonatomic, readonly, copy) SFTranscription *bestTranscription;

//是否已經(jīng)完成 如果YES 則所有所有識(shí)別信息都已經(jīng)獲取完成

@property (nonatomic, readonly, getter=isFinal) BOOLfinal;

SFSpeechRecognitionResult類只是語音識(shí)別結(jié)果的一個(gè)封裝摘昌,真正的識(shí)別信息定義在SFTranscription類中,SFTranscription類中屬性如下:

//完整的語音識(shí)別準(zhǔn)換后的文本信息字符串

@property (nonatomic, readonly, copy) NSString *formattedString;

//語音識(shí)別節(jié)點(diǎn)數(shù)組

@property (nonatomic, readonly, copy) NSArray *segments;

當(dāng)對(duì)一句完整的話進(jìn)行識(shí)別時(shí)凯沪,Apple的語音識(shí)別服務(wù)實(shí)際上會(huì)把這句語音拆分成若干個(gè)音頻節(jié)點(diǎn)第焰,每個(gè)節(jié)點(diǎn)可能為一個(gè)單詞买优,SFTranscription類中的segments屬性就存放這些節(jié)點(diǎn)妨马。SFTranscriptionSegment類中定義的屬性如下:

//當(dāng)前節(jié)點(diǎn)識(shí)別后的文本信息

@property (nonatomic, readonly, copy) NSString *substring;

//當(dāng)前節(jié)點(diǎn)識(shí)別后的文本信息在整體識(shí)別語句中的位置

@property (nonatomic, readonly) NSRange substringRange;

//當(dāng)前節(jié)點(diǎn)的音頻時(shí)間戳

@property (nonatomic, readonly) NSTimeInterval timestamp;

//當(dāng)前節(jié)點(diǎn)音頻的持續(xù)時(shí)間

@property (nonatomic, readonly) NSTimeInterval duration;

//可信度/準(zhǔn)確度 0-1之間

@property (nonatomic, readonly) floatconfidence;

//關(guān)于此節(jié)點(diǎn)的其他可能的識(shí)別結(jié)果

@property (nonatomic, readonly) NSArray *alternativeSubstrings;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市杀赢,隨后出現(xiàn)的幾起案子烘跺,更是在濱河造成了極大的恐慌,老刑警劉巖脂崔,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滤淳,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡砌左,警方通過查閱死者的電腦和手機(jī)脖咐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門铺敌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人屁擅,你說我怎么就攤上這事偿凭。” “怎么了派歌?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵弯囊,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我胶果,道長(zhǎng)匾嘱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任早抠,我火速辦了婚禮霎烙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蕊连。我一直安慰自己吼过,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布咪奖。 她就那樣靜靜地躺著盗忱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪羊赵。 梳的紋絲不亂的頭發(fā)上趟佃,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音昧捷,去河邊找鬼闲昭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛靡挥,可吹牛的內(nèi)容都是我干的序矩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼跋破,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼簸淀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起毒返,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤租幕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后拧簸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體劲绪,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了贾富。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歉眷。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖颤枪,靈堂內(nèi)的尸體忽然破棺而出姥芥,到底是詐尸還是另有隱情,我是刑警寧澤汇鞭,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布凉唐,位于F島的核電站,受9級(jí)特大地震影響霍骄,放射性物質(zhì)發(fā)生泄漏台囱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一读整、第九天 我趴在偏房一處隱蔽的房頂上張望簿训。 院中可真熱鬧,春花似錦米间、人聲如沸强品。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽的榛。三九已至,卻和暖如春逻锐,著一層夾襖步出監(jiān)牢的瞬間夫晌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工昧诱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晓淀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓盏档,卻偏偏與公主長(zhǎng)得像凶掰,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蜈亩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容