iOS小记IOSiOS学习开发

iOS语音识别功能实现

2016-12-02  本文已影响2192人  小冰山口

现在市面上的即时通讯app都有语音转文本的功能, 那么语音转文本如何实现呢? 自己写是不现实的, 因为这涉及到模式识别的算法, 所以只能用到第三方SDK了, 我在项目中用到的是百度语音SDK, 自己也是刚刚实现功能, 很多地方都还需要优化, 就简单介绍一下如何实现吧

一 注册应用
查看Key
二 配置环境
官方SDK文件目录 添加依赖库1
添加依赖库2

关于添加依赖库, 百度官方是这样解释的:

BDVRClient 使用了录音和播放功能,因此需要在 Xcode 工程中引入 AudioToolbox.framework和 AVFoundation.framework;BDVRClient 还使用到了网络状态检测功能,因此还需要引入SystemConfiguration.framework;为了生成设备 UDID,需要引入 Security.framework;为了支持 gzip压缩,需要引入 libz.1.dylib; 网络模块需要引入 CFNetwork.framework;某些场景需要获取设备地理位置以 高识别准确度,需引入 CoreLocation.framework。为了支持识别控件,需要引入 OpenGLES.framework,QuartzCore.framework,GLKit.framework,CoreGraphics.framework 和 CoreText.framework。

添加方式:右键点击 Xcode 中的工程文件,在出现的界面中,选中 TARGETS 中应用,在出现的界面中选中 Build Phase->Link Binary With Libraries,点击界面中的“+”图标,在弹出的界面中选择此 7 个 Framework 即可,添加完成效果图如图 8 所示(libBDVoiceRecognitionClient.a 将在随后添加

三 开始写代码
创建音频识别管理类

**Note: 需要注意的是, 静态库采用Objective C++实现, 因此, 需要保证工程中引用静态库头文件的实现文件的扩展名必须为.mm **

+ (instancetype)sharedRecognizer {
   static ZHLVoiceRecognizer *recognizer = nil;
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
       recognizer = [[ZHLVoiceRecognizer alloc] init];
   });
   return recognizer;
}
/**
 语音识别代理
 */
@property (nonatomic,strong)BDVoiceRecognitionClient *client;
- (BDVoiceRecognitionClient *)client {
    if (!_client) {
        _client = [BDVoiceRecognitionClient sharedInstance];
        [_client setPropertyList:@[@(EVoiceRecognitionPropertyMusic),                  // 音乐
                                   @(EVoiceRecognitionPropertyVideo),                  // 视频
                                   @(EVoiceRecognitionPropertyApp),                    // 应用
                                   @(EVoiceRecognitionPropertyWeb),                    // web
                                   @(EVoiceRecognitionPropertySearch),                 // 热词
                                   @(EVoiceRecognitionPropertyEShopping),              // 电商&购物
                                   @(EVoiceRecognitionPropertyHealth),                 // 健康&母婴
                                   @(EVoiceRecognitionPropertyCall),                   // 打电话
                                   @(EVoiceRecognitionPropertyMedicalCare) ,           // 医疗
                                   @(EVoiceRecognitionPropertyCar),                    // 汽车
                                   @(EVoiceRecognitionPropertyCatering),               // 娱乐餐饮
                                   @(EVoiceRecognitionPropertyFinanceAndEconomics),    // 财经
                                   @(EVoiceRecognitionPropertyGame),                   // 游戏
                                   @(EVoiceRecognitionPropertyCookbook),               // 菜谱
                                   @(EVoiceRecognitionPropertyAssistant),              // 助手
                                   @(EVoiceRecognitionPropertyRecharge),               // 话费充值
                                   /* 离线垂类 */
                                   @(EVoiceRecognitionPropertyContacts) ,              // 联系人指令
                                   @(EVoiceRecognitionPropertySetting),                // 手机设置
                                   @(EVoiceRecognitionPropertyTVInstruction),          // 电视指令
                                   @(EVoiceRecognitionPropertyPlayerInstruction),      // 播放器指令
                                   @(EVoiceRecognitionPropertyRadio)]];
        /* 设置识别语言为中文 */
        [_client setLanguage:EVoiceRecognitionLanguageChinese];
        /* 设置不禁用标点符号 */
        [_client disablePuncs:NO];
        /* 设置对语音进行端点检测 */
        [_client setNeedVadFlag:YES];
        /* 设置对上传的语音进行压缩 */
        [_client setNeedCompressFlag:YES];
        /* 设置在线识别的响应等待时间,如果超时,触发同步离线识别 */
        [_client setOnlineWaitTime:5];
        [_client setPlayTone:EVoiceRecognitionPlayTonesRecStart isPlay:YES];
        [_client setPlayTone:EVoiceRecognitionPlayTonesRecEnd isPlay:YES];
        /* 在开始识别前,需要加载离线识别引擎, 需要传入授权信息、语言模型文件信息及语法槽信息 */
        /* 识别垂类语法槽信息 */
        
        NSDictionary* recogGrammSlot = @{@"$name_CORE" : @"张三\n 李四\n",
                                         @"$song_CORE" : @"小苹果\n 我的滑板鞋\n", @"$app_CORE" : @"百度\n 百度地图\n",
                                         @"$artist_CORE" : @"刘德华\n 周华健\n"};
        NSString *licensePath = [[NSBundle mainBundle] pathForResource:@"bdasr_temp_license" ofType:@"dat"];
        NSString *datFilePath = [[NSBundle mainBundle] pathForResource:@"s_1" ofType:nil];
        int result = [_client loadOfflineEngine:@"8979326" license:licensePath  datFile:datFilePath LMDatFile:nil grammSlot:recogGrammSlot];
        if (result == 0) {
            NSLog(@"加载离线识别引擎成功");
        }else {
            NSLog(@"加载离线识别引擎失败");
        }
        [_client setApiKey:@"UsLZWXdC45BHo1YXMni2M4Ga" withSecretKey:@"ebb161770a7c78d2df8e46ddc4badf25"];
        
    }
    return _client;
}

其实懒加载中我们做了很多事情, 而我们进行语音识别主要也是靠BDVoiceRecognitionClient这个类的对象,
1.设置属性列表

 EVoiceRecognitionPropertyMap = 10060,  // 地图
 EVoiceRecognitionPropertyInput = 20000, // 输入

以上两个要单独使用, 不能添加到数组中,否则就会出现这个错误

EVoiceRecognitionStartWorkPropertyInvalid

2.进行各种设置

        /* 设置识别语言为中文 */
        [_client setLanguage:EVoiceRecognitionLanguageChinese];
        /* 设置不禁用标点符号 */
        [_client disablePuncs:NO];
        /* 设置对语音进行端点检测 */
        [_client setNeedVadFlag:YES];
        /* 设置对上传的语音进行压缩 */
        [_client setNeedCompressFlag:YES];
        /* 设置在线识别的响应等待时间,如果超时,触发同步离线识别 */
        [_client setOnlineWaitTime:5];
        [_client setPlayTone:EVoiceRecognitionPlayTonesRecStart isPlay:YES];
        [_client setPlayTone:EVoiceRecognitionPlayTonesRecEnd isPlay:YES];```

3.在开始识别前,需要加载离线识别引擎, 需要传入授权信息、语言模型文件信息及语法槽信息

    /* 在开始识别前,需要加载离线识别引擎, 需要传入授权信息、语言模型文件信息及语法槽信息 */
    /* 识别垂类语法槽信息 */
    
    NSDictionary* recogGrammSlot = @{@"$name_CORE" : @"张三\n 李四\n",
                                     @"$song_CORE" : @"小苹果\n 我的滑板鞋\n", @"$app_CORE" : @"百度\n 百度地图\n",
                                     @"$artist_CORE" : @"刘德华\n 周华健\n"};
    NSString *licensePath = [[NSBundle mainBundle] pathForResource:@"bdasr_temp_license" ofType:@"dat"];
    NSString *datFilePath = [[NSBundle mainBundle] pathForResource:@"s_1" ofType:nil];
    int result = [_client loadOfflineEngine:@"8979326" license:licensePath  datFile:datFilePath LMDatFile:nil grammSlot:recogGrammSlot];
    if (result == 0) {
        NSLog(@"加载离线识别引擎成功");
    }else {
        NSLog(@"加载离线识别引擎失败");
    }
**Note: 其中, 在方法``` - (int)loadOfflineEngine: (NSString*)appCode
                 license: (NSString*)licenseFile
                 datFile: (NSString*)datFilePath
               LMDatFile: (NSString*)LMDatFilePath
               grammSlot: (NSDictionary*)dictSlot;```中的第一个参数appCode, 就是之前在百度语音官网上注册的你的AppID**


![查看key](http:https://img.haomeiwen.com/i2868984/8bed501e49e1b6fa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

然后再设置API key 和 Secret Key 

[_client setApiKey:@"你的ApiKey" withSecretKey:@"你的SecretKey"];


4.接着, 就要写一个开始语音识别的代码了, 其实也是一句代码的事情, 剩下的都是错误处理
然后把这个方法暴露给外界使用

5.遵守代理

<MVoiceRecognitionClientDelegate>


6.实现代理回调方法

在上面这个方法实现中, 我将语音识别的结果传给我本类的代理方法

@class ZHLVoiceRecognizer;
@protocol ZHLVoiceRecognizerDelegate <NSObject>
@optional

@end


7.这样,我在其他类中遵守```ZHLVoiceRecognizerDelegate```这个代理, 实现代理方法时, 就能拿到语音识别的结果, 就是那个字符串啦

比如,在我们公司的项目中, 我就将其赋值给textView.text,这样就用户就可以看到语音识别的结果了


#####给大家看看实现效果, 我觉得语音识别的准确率是很高的,请原谅我不是很标准的普通话
![实现效果](http:https://img.haomeiwen.com/i2868984/ea8bd94681f05432.gif?imageMogr2/auto-orient/strip)
上一篇 下一篇

猜你喜欢

热点阅读