iOS-Speech Framework

Speech Framework 是Apple公司在2016年WWDC上介绍的一个语音识别的API。它是Siri用来做语音识别的框架。在你的应用里面可以使用 Speech APIs 来拓展和提高语音识别功能,而不仅仅是单纯的使用键盘。

Speech APIs的执行需要使用一个设备内置的语音识别器和连接到苹果的服务器。如果发现语音识别器是用于一个特定的语言,例如英文、国语等,可以采用 SFSpeechRecognizerDelegate 协议。

因为你的应用可能需要连接到服务器进行识别,而这涉及到尊重用户的隐私问题,出于这个原因,我们在启动语音识别功能之前必须得到用户的明确许可。

做了一个demo,使用Speech Framework 实现语音转文字的功能。

Speech_DemoPic.png

上面这个效果图中的文字是识别我的话转出来的,接下来我们来实现一下。

1.我们要写个句子告诉用户在应用中可以如何使用这个语音功能。
例如,在这个例子中写了这么一句提示的话"Lets you mark an item as finished by saying Done."。

2.在 Info.plist里面添加两个键值对,分别是Privacy - Speech Recognition Usage Description (用于请求语音识别) 以及 Privacy - Microphone Usage Description(用于请求麦克风语音输入授权)。

3.创建 SFSpeechRecognizer 对象,使用 requestAuthorization: 去申请用户语音识别权限 。

@property (nonatomic,strong)SFSpeechRecognizer *speechRecognizer;

viewDidLoad:中初始化 speechRecognizer对象,并设置代理。

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

    //把语音识别的代理设置为 self
    _speechRecognizer.delegate = self;

申请用户语音识别权限

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

        //检查验证的状态。如果被授权了,让microphone按钮有效。如果没有,打印错误信息然后让microphone按钮失效。
        switch (status) {
            case SFSpeechRecognizerAuthorizationStatusAuthorized:
            {
                isButtonEnable = YES;
                NSLog(@"用户授权语音识别");
            }
                break;
            
            case SFSpeechRecognizerAuthorizationStatusDenied:
            {
                isButtonEnable = NO;
                NSLog(@"用户拒绝授权语音识别");
            }
                break;
            case SFSpeechRecognizerAuthorizationStatusRestricted:
            {
                isButtonEnable = NO;
                NSLog(@"设备不支持语音识别功能");
            }
                break;
            case SFSpeechRecognizerAuthorizationStatusNotDetermined:
            {
                isButtonEnable = NO;
                NSLog(@"结果未知 用户尚未进行选择");
            }
                break;
        }

运行后我们会发现授权请示如下:


语音识别授权.png
麦克风授权.png

4.在用户允许通过语音识别和麦克风授权之后,写一个方发startRecording用于语音识别请求。

//实例化recognitionRequest。在这里我们创建了SFSpeechAudioBufferRecognitionRequest对象。稍后我们利用它把语音数据传到苹果后台
    _recognitionRequest = [SFSpeechAudioBufferRecognitionRequest new];
    
    //当用户说话的时候让recognitionRequest报告语音识别的部分结果
    _recognitionRequest.shouldReportPartialResults = YES;
    
    //调用 speechRecognizer的recognitionTask 方法来开启语音识别。这个方法有一个completion handler回调。这个回调每次都会在识别引擎收到输入的时候,完善了当前识别的信息时候,或者被删除或者停止的时候被调用,最后会返回一个最终的文本      (进行请求)
    _recognitionTask = [_speechRecognizer recognitionTaskWithRequest:_recognitionRequest resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
       
        //定义一个布尔值决定识别是否已经结束
        BOOL isFinal = NO;
        
        //如果结果 result 不是nil, 把 textView.text 的值设置为我们的最优文本。如果结果是最终结果,设置 isFinal为true
        if (result != nil) {
            
            self.textView.text = result.bestTranscription.formattedString;
            isFinal = result.isFinal;
        }
        
        //如果没有错误或者结果是最终结果,停止 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 会在语音输入被加入的同时就开始进行解析识别

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

    //检查 audioEngine(你的设备)是否有做录音功能作为语音输入
    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];
    }];

准备并且开始audioEngine,并让textView的文本为 "Say something, I'm listening!"。

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

我们让当前视图控制器作为speechRecognizer 的代理,在SFSpeechRecognizerDelegate中有可选的speechRecognizer:availabilityDidChange:方法,实现一下。

//当语音识别操作可用性发生改变时会被调用
- (void)speechRecognizer:(SFSpeechRecognizer *)speechRecognizer availabilityDidChange:(BOOL)available{

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

下面是一些LocaleIdentifier,可以参考一下需要的语言。

LocaleIdentifier.png

到此,使用Speech Framework实现了语音转文字功能实现了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容