iOS-Speech Framework

Speech Framework 是Apple公司在2016年WWDC上介紹的一個語音識別的API。它是Siri用來做語音識別的框架。在你的應(yīng)用里面可以使用 Speech APIs 來拓展和提高語音識別功能,而不僅僅是單純的使用鍵盤。

Speech APIs的執(zhí)行需要使用一個設(shè)備內(nèi)置的語音識別器和連接到蘋果的服務(wù)器。如果發(fā)現(xiàn)語音識別器是用于一個特定的語言,例如英文、國語等,可以采用 SFSpeechRecognizerDelegate 協(xié)議。

因?yàn)槟愕膽?yīng)用可能需要連接到服務(wù)器進(jìn)行識別,而這涉及到尊重用戶的隱私問題,出于這個原因,我們在啟動語音識別功能之前必須得到用戶的明確許可。

做了一個demo,使用Speech Framework 實(shí)現(xiàn)語音轉(zhuǎn)文字的功能。

Speech_DemoPic.png

上面這個效果圖中的文字是識別我的話轉(zhuǎn)出來的,接下來我們來實(shí)現(xiàn)一下。

1.我們要寫個句子告訴用戶在應(yīng)用中可以如何使用這個語音功能。
例如,在這個例子中寫了這么一句提示的話"Lets you mark an item as finished by saying Done."。

2.在 Info.plist里面添加兩個鍵值對,分別是Privacy - Speech Recognition Usage Description (用于請求語音識別) 以及 Privacy - Microphone Usage Description(用于請求麥克風(fēng)語音輸入授權(quán))。

3.創(chuàng)建 SFSpeechRecognizer 對象,使用 requestAuthorization: 去申請用戶語音識別權(quán)限 。

@property (nonatomic,strong)SFSpeechRecognizer *speechRecognizer;

viewDidLoad:中初始化 speechRecognizer對象,并設(shè)置代理。

// zh-CN 代表是簡體中文
 NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh-CN"];
    _speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:locale];

    //把語音識別的代理設(shè)置為 self
    _speechRecognizer.delegate = self;

申請用戶語音識別權(quán)限

[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
       
        BOOL isButtonEnable = NO;

        //檢查驗(yàn)證的狀態(tài)。如果被授權(quán)了,讓microphone按鈕有效。如果沒有,打印錯誤信息然后讓microphone按鈕失效。
        switch (status) {
            case SFSpeechRecognizerAuthorizationStatusAuthorized:
            {
                isButtonEnable = YES;
                NSLog(@"用戶授權(quán)語音識別");
            }
                break;
            
            case SFSpeechRecognizerAuthorizationStatusDenied:
            {
                isButtonEnable = NO;
                NSLog(@"用戶拒絕授權(quán)語音識別");
            }
                break;
            case SFSpeechRecognizerAuthorizationStatusRestricted:
            {
                isButtonEnable = NO;
                NSLog(@"設(shè)備不支持語音識別功能");
            }
                break;
            case SFSpeechRecognizerAuthorizationStatusNotDetermined:
            {
                isButtonEnable = NO;
                NSLog(@"結(jié)果未知 用戶尚未進(jìn)行選擇");
            }
                break;
        }

運(yùn)行后我們會發(fā)現(xiàn)授權(quán)請示如下:


語音識別授權(quán).png
麥克風(fēng)授權(quán).png

4.在用戶允許通過語音識別和麥克風(fēng)授權(quán)之后,寫一個方發(fā)startRecording用于語音識別請求。

//實(shí)例化recognitionRequest。在這里我們創(chuàng)建了SFSpeechAudioBufferRecognitionRequest對象。稍后我們利用它把語音數(shù)據(jù)傳到蘋果后臺
    _recognitionRequest = [SFSpeechAudioBufferRecognitionRequest new];
    
    //當(dāng)用戶說話的時候讓recognitionRequest報告語音識別的部分結(jié)果
    _recognitionRequest.shouldReportPartialResults = YES;
    
    //調(diào)用 speechRecognizer的recognitionTask 方法來開啟語音識別。這個方法有一個completion handler回調(diào)。這個回調(diào)每次都會在識別引擎收到輸入的時候,完善了當(dāng)前識別的信息時候,或者被刪除或者停止的時候被調(diào)用,最后會返回一個最終的文本      (進(jìn)行請求)
    _recognitionTask = [_speechRecognizer recognitionTaskWithRequest:_recognitionRequest resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
       
        //定義一個布爾值決定識別是否已經(jīng)結(jié)束
        BOOL isFinal = NO;
        
        //如果結(jié)果 result 不是nil, 把 textView.text 的值設(shè)置為我們的最優(yōu)文本。如果結(jié)果是最終結(jié)果,設(shè)置 isFinal為true
        if (result != nil) {
            
            self.textView.text = result.bestTranscription.formattedString;
            isFinal = result.isFinal;
        }
        
        //如果沒有錯誤或者結(jié)果是最終結(jié)果,停止 audioEngine(語音輸入)并且停止 recognitionRequest 和 recognitionTask.同時,使Start Recording按鈕有效
        if (error != nil || isFinal) {
            
            [self.audioEngine stop];
            [inputNode removeTapOnBus:0];
            
            self.recognitionRequest = nil;
            self.recognitionTask = nil;
            
            self.microphoneButton.enabled = YES;
        }
    }];

在開始了recognitionTask之后向 recognitionRequest增加一個語音輸入。Speech Framework 會在語音輸入被加入的同時就開始進(jìn)行解析識別

AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    
    [audioSession setCategory:AVAudioSessionCategoryRecord error:nil];
    [audioSession setMode:AVAudioSessionModeMeasurement error:nil];
    [audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];

    //檢查 audioEngine(你的設(shè)備)是否有做錄音功能作為語音輸入
    AVAudioInputNode *inputNode = [_audioEngine inputNode];
    if (!inputNode) {
        NSLog(@"Audio engine has no input node");
    }

AVAudioFormat *recordingFormat = [inputNode outputFormatForBus:0];
    [inputNode installTapOnBus:0 bufferSize:1024 format:recordingFormat block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
       
        [self.recognitionRequest appendAudioPCMBuffer:buffer];
    }];

準(zhǔn)備并且開始audioEngine,并讓textView的文本為 "Say something, I'm listening!"。

    [_audioEngine prepare];
    [_audioEngine startAndReturnError:nil];
    _textView.text = @"Say something, I'm listening!";

我們讓當(dāng)前視圖控制器作為speechRecognizer 的代理,在SFSpeechRecognizerDelegate中有可選的speechRecognizer:availabilityDidChange:方法,實(shí)現(xiàn)一下。

//當(dāng)語音識別操作可用性發(fā)生改變時會被調(diào)用
- (void)speechRecognizer:(SFSpeechRecognizer *)speechRecognizer availabilityDidChange:(BOOL)available{

    if (available) {
        _microphoneButton.enabled = YES;
    }
    else{
        _microphoneButton.enabled = NO;
    }
}

下面是一些LocaleIdentifier,可以參考一下需要的語言。

LocaleIdentifier.png

到此,使用Speech Framework實(shí)現(xiàn)了語音轉(zhuǎn)文字功能實(shí)現(xiàn)了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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