iOS-語音識別

前言

語音識別現(xiàn)在已經(jīng)在開發(fā)中越來越常見了余蟹,科大訊飛卷胯、百度等第三方庫層出不窮,在這里簡單的介紹一下iOS原生的語音識別該怎么做威酒。其原理就是錄音窑睁,然后把錄音數(shù)據(jù)傳給iOS內(nèi)部的語音識別庫,然后再導(dǎo)出來(原生語音識別所支持的版本為10.0及以上)葵孤。

實(shí)現(xiàn)

添加配置文件

在info.plist的文件中添加語音識別和麥克風(fēng)使用的配置Privacy - Speech Recognition Usage DescriptionPrivacy - Microphone Usage Description担钮,如下圖:

導(dǎo)入類庫
#import <Speech/Speech.h>
#import <AVFoundation/AVFoundation.h>
定義相應(yīng)的控件
@property (strong, nonatomic) SFSpeechRecognizer *speechRecognizer;
@property (strong, nonatomic) SFSpeechRecognitionTask *recognitionTask;
@property (strong, nonatomic) SFSpeechAudioBufferRecognitionRequest *recognitionRequest;

@property (strong, nonatomic) AVAudioEngine *audioEngine;
@property (strong, nonatomic) AVAudioSession *audioSession;

上面的三個是iOS的語音識別的類,下面兩個是音頻的類箫津,對AVAudioEngine有興趣的小伙伴可以去看一下說明1說明2宰啦,對AVAudioSession有興趣的小伙伴可以去看一下這里
然后懶加載初始化相應(yīng)的類田炭,如下:

- (SFSpeechRecognizer *)speechRecognizer {
    if (!_speechRecognizer) {
        NSLocale *local = [[NSLocale alloc]initWithLocaleIdentifier:@"zh_CN"];
        
        _speechRecognizer = [[SFSpeechRecognizer alloc]initWithLocale:local];
        _speechRecognizer.delegate = self;
    }
    return _speechRecognizer;
}

- (AVAudioEngine *)audioEngine {
    if (!_audioEngine) {
        _audioEngine = [[AVAudioEngine alloc]init];
    }
    return _audioEngine;
}

- (AVAudioSession *)audioSession {
    if (!_audioSession) {
        _audioSession = [AVAudioSession sharedInstance];
        NSError *error;
        [_audioSession setCategory:AVAudioSessionCategoryRecord error:&error];
        [_audioSession setMode:AVAudioSessionModeMeasurement error:&error];
        [_audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error];
    }
    return _audioSession;
}

小編在初始化語音識別類的時候使用的是zh_CN,這個的意思是語音識別的類型是中文,可以根據(jù)需要替換成其他類型欺缘。可以通過下列代碼獲得所支持的類型:

for (NSLocale *temp in SFSpeechRecognizer.supportedLocales) {
        NSLog(@"國家代碼:%@,語言代碼:%@,輸入方式:%@_%@", temp.countryCode, temp.languageCode, temp.languageCode, temp.countryCode);
    }

可以使用的類型為輸入方式后面的輸出丧鸯。

獲取相應(yīng)的授權(quán)
- (void)viewDidLoad {
    [super viewDidLoad];
   
    [self accessPermissions];
}

- (void)accessPermissions {
//    語音識別授權(quán)
    [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
        
        BOOL isEnabled = NO;
        NSString *str;
        switch (status) {
            case SFSpeechRecognizerAuthorizationStatusNotDetermined:
                isEnabled = NO;
                str = @"不支持錄音";
                NSLog(@"結(jié)果未知 用戶尚未進(jìn)行選擇");
                break;
            case SFSpeechRecognizerAuthorizationStatusDenied:
                isEnabled = NO;
                str = @"不支持錄音";
                NSLog(@"用戶未授權(quán)使用語音識別");
                break;
            case SFSpeechRecognizerAuthorizationStatusRestricted:
                isEnabled = NO;
                str = @"不支持錄音";
                NSLog(@"設(shè)備不支持語音識別功能");
                break;
            case SFSpeechRecognizerAuthorizationStatusAuthorized:
                isEnabled = YES;
                str = @"開始錄音";
                NSLog(@"用戶授權(quán)語音識別");
                break;
            default:
                break;
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            self.recordButton.enabled = isEnabled;
            if (isEnabled) {
                [self.recordButton setTitle:str forState:UIControlStateNormal];
            }else {
                [self.recordButton setTitle:str forState:UIControlStateDisabled];
            }
        });
    }];
    
//    麥克風(fēng)使用授權(quán)
    if ([self.audioSession respondsToSelector:@selector(requestRecordPermission:)]) {
        [self.audioSession performSelector:@selector(requestRecordPermission:) withObject:^(BOOL granted) {
            dispatch_async(dispatch_get_main_queue(), ^{
                self.recordButton.enabled = granted;
                if (granted) {
                    NSLog(@"麥克風(fēng)授權(quán)");
                    [self.recordButton setTitle:@"開始錄音" forState:UIControlStateNormal];
                }else {
                    NSLog(@"麥克風(fēng)未授權(quán)");
                    [self.recordButton setTitle:@"麥克風(fēng)未授權(quán)" forState:UIControlStateDisabled];
                }
            });
        }];
    }
}
語音識別
開始錄音
- (void)startRecording {
    if (_recognitionTask) {
        [_recognitionTask cancel];
        _recognitionTask = nil;
    }
    
    _recognitionRequest = [[SFSpeechAudioBufferRecognitionRequest alloc]init];
    AVAudioInputNode *inputNode = self.audioEngine.inputNode;
    _recognitionRequest.shouldReportPartialResults = YES;
    _recognitionTask = [self.speechRecognizer recognitionTaskWithRequest:_recognitionRequest resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
        BOOL isFinal = NO;
        if (result) {
            self.displayLabel.text = result.bestTranscription.formattedString;
            isFinal = result.isFinal;
        }
        
        if (error || isFinal) {
            [self.audioEngine stop];
            [inputNode removeTapOnBus:0];
            self.recognitionTask = nil;
            self.recognitionRequest = nil;
            self.recordButton.enabled = YES;
            [self.recordButton setTitle:@"開始錄音" forState:UIControlStateNormal];
        }
    }];
    
    AVAudioFormat *recordingFormat = [inputNode outputFormatForBus:0];
    [inputNode removeTapOnBus:0];
    [inputNode installTapOnBus:0 bufferSize:1024 format:recordingFormat block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
        if (self.recognitionRequest) {
            [self.recognitionRequest appendAudioPCMBuffer:buffer];
        }
    }];
    
    NSError *error;
    [self.audioEngine prepare];
    [self.audioEngine startAndReturnError:&error];
    self.displayLabel.text = @"正在錄音蜂怎。。氢伟。";
}
結(jié)束錄音
- (void)endRecording {
    [self.audioEngine stop];
    if (_recognitionRequest) {
        [_recognitionRequest endAudio];
    }
    
    if (_recognitionTask) {
        [_recognitionTask cancel];
        _recognitionTask = nil;
    }
    
    self.recordButton.enabled = NO;
    
    self.displayLabel.text = @"";
}
綁定的語音識別代理
#pragma mark - SFSpeechRecognizerDelegate
- (void)speechRecognizer:(SFSpeechRecognizer *)speechRecognizer availabilityDidChange:(BOOL)available {
    
    if (available) {
        NSLog(@"開始錄音");
        [self.recordButton setTitle:@"開始錄音" forState:UIControlStateNormal];
    }else {
        NSLog(@"語音識別不可用");
        [self.recordButton setTitle:@"語音識別不可用" forState:UIControlStateDisabled];
    }
    self.recordButton.enabled = available;
}

希望這篇文章對各位小伙伴有所幫助朵锣,想要Demo的小伙伴點(diǎn)擊這里(注意:語音識別只能進(jìn)行真機(jī)調(diào)試)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诚些,一起剝皮案震驚了整個濱河市诬烹,隨后出現(xiàn)的幾起案子犀被,更是在濱河造成了極大的恐慌外冀,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異脑沿,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)注服,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門溶弟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辜御,“玉大人屈张,你說我怎么就攤上這事袱巨∮淅希” “怎么了剖效?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵贱鄙,是天一觀的道長逗宁。 經(jīng)常有香客問我,道長件甥,這世上最難降的妖魔是什么哼拔? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任倦逐,我火速辦了婚禮,結(jié)果婚禮上曾我,老公的妹妹穿的比我還像新娘健民。我一直安慰自己,他們只是感情好蛉谜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布型诚。 她就那樣靜靜地躺著俺驶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪还绘。 梳的紋絲不亂的頭發(fā)上栖袋,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天塘幅,我揣著相機(jī)與錄音,去河邊找鬼踏揣。 笑死捞稿,一個胖子當(dāng)著我的面吹牛拼缝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播衰齐,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼耻涛,長吁一口氣:“原來是場噩夢啊……” “哼穴翩!你這毒婦竟也來了锦积?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤背蟆,失蹤者是張志新(化名)和其女友劉穎带膀,沒想到半個月后橙垢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柜某,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年淤翔,在試婚紗的時候發(fā)現(xiàn)自己被綠了佩谷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡抡谐,死狀恐怖童叠,靈堂內(nèi)的尸體忽然破棺而出课幕,到底是詐尸還是另有隱情,我是刑警寧澤乍惊,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布润绎,位于F島的核電站,受9級特大地震影響呢蛤,放射性物質(zhì)發(fā)生泄漏棍郎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一励翼、第九天 我趴在偏房一處隱蔽的房頂上張望辜荠。 院中可真熱鬧,春花似錦伯病、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至持偏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鸿秆,已是汗流浹背怎囚。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工恳守, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人催烘。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓伊群,卻偏偏與公主長得像,于是被迫代替她去往敵國和親崇棠。 傳聞我的和親對象是個殘疾皇子丸卷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

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

  • 前言 最近在做一個翻譯工具及老,由于項目需要兼容 iOS 8.0,所以語音識別、合成都是用的科大訊飛的匕垫。使用過程中發(fā)現(xiàn)...
    OnlyFunny閱讀 2,529評論 2 4
  • 前言 最近在做一個翻譯工具,由于項目需要兼容 iOS 8.0寞秃,所以語音識別、合成都是用的科大訊飛的朗涩。使用過程中發(fā)現(xiàn)...
    分貝丶閱讀 1,800評論 2 2
  • 因?yàn)橐Y(jié)局swift3.0中引用snapKit的問題,看到一篇介紹Xcode8,swift3變化的文章,覺得很詳細(xì)...
    uniapp閱讀 4,418評論 0 12
  • 現(xiàn)在市面上的即時通訊app都有語音轉(zhuǎn)文本的功能, 那么語音轉(zhuǎn)文本如何實(shí)現(xiàn)呢? 自己寫是不現(xiàn)實(shí)的, 因?yàn)檫@涉及到模式...
    小冰山口閱讀 6,958評論 10 17
  • 隨著AI、大數(shù)據(jù)越來越火识腿,各大互聯(lián)網(wǎng)公司對AR造壮、VR等各種技術(shù)越來越重視,google耳璧、apple、訊飛都推出...
    huangjun0閱讀 890評論 0 0