iOS中 语音识别功能/语音转文字教程具体解释 韩俊强的博客
原文地址:http://blog.csdn.net/qq_31810357/article/details/51111702
前言:近期研究了一下语音识别,从百度语音识别到讯飞语音识别;首先说一下个人针对两者的看法,讯飞毫无疑问比較专业。识别率也非常高真对语音识别是比較精准的,可是非常多开发人员和我一样期望离线识别,而讯飞离线是收费的;请求次数来讲。两者都能够申请高配额,针对用户较多的差点儿都一样。
基于免费而且支持离线我选择了百度离线语音识别。比較简单,UI设计多一点,以下写一下教程:
1.首先:须要的库
2.我是自己定义的UI所以以功能实现为主(头文件)
// 头文件
#import "BDVRCustomRecognitonViewController.h"
#import "BDVRClientUIManager.h"
#import "WBVoiceRecordHUD.h"
#import "BDVRViewController.h"
#import "MyViewController.h"
#import "BDVRSConfig.h"
3.须要知道的功能:能用到的例如以下:
//-------------------类方法------------------------
// 创建语音识别客户对像,该对像是个单例
+ (BDVoiceRecognitionClient *)sharedInstance; // 释放语音识别客户端对像
+ (void)releaseInstance; //-------------------识别方法-----------------------
// 推断能否够录音
- (BOOL)isCanRecorder; // 開始语音识别,须要实现MVoiceRecognitionClientDelegate代理方法。并传入实现对像监听事件
// 返回值參考 TVoiceRecognitionStartWorkResult
- (int)startVoiceRecognition:(id<MVoiceRecognitionClientDelegate>)aDelegate; // 说完了,用户主动完毕录音时调用
- (void)speakFinish; // 结束本次语音识别
- (void)stopVoiceRecognition; /**
* @brief 获取当前识别的採样率
*
* @return 採样率(16000/8000)
*/
- (int)getCurrentSampleRate; /**
* @brief 得到当前识别模式(deprecated)
*
* @return 当前识别模式
*/
- (int)getCurrentVoiceRecognitionMode __attribute__((deprecated)); /**
* @brief 设置当前识别模式(deprecated)。请使用-(void)setProperty:(TBDVoiceRecognitionProperty)property;
*
* @param 识别模式
*
* @return 是否设置成功
*/
- (void)setCurrentVoiceRecognitionMode:(int)aMode __attribute__((deprecated)); // 设置识别类型
- (void)setProperty:(TBDVoiceRecognitionProperty)property __attribute__((deprecated)); // 获取当前识别类型
- (int)getRecognitionProperty __attribute__((deprecated)); // 设置识别类型列表, 除EVoiceRecognitionPropertyInput和EVoiceRecognitionPropertySong外
// 能够识别类型复合
- (void)setPropertyList: (NSArray*)prop_list; // cityID仅对EVoiceRecognitionPropertyMap识别类型有效
- (void)setCityID: (NSInteger)cityID; // 获取当前识别类型列表
- (NSArray*)getRecognitionPropertyList; //-------------------提示音-----------------------
// 播放提示音。默觉得播放,录音開始,录音结束提示音
// BDVoiceRecognitionClientResources/Tone
// record_start.caf 录音開始声音文件
// record_end.caf 录音结束声音文件
// 声音资源须要加到项目project里。用户可替换资源文件,文件名称不能够变,建音提示音不宜过长,0。5秒左右。
// aTone 取值參考 TVoiceRecognitionPlayTones,如没有找到文件。则返回NO
- (BOOL)setPlayTone:(int)aTone isPlay:(BOOL)aIsPlay;
4.录音button相关动画(我自己定义的,大家能够借鉴)
// 录音button相关
@property (nonatomic, weak, readonly) UIButton *holdDownButton;// 说话button
/**
* 是否取消錄音
*/
@property (nonatomic, assign, readwrite) BOOL isCancelled; /**
* 是否正在錄音
*/
@property (nonatomic, assign, readwrite) BOOL isRecording;
/**
* 当录音button被按下所触发的事件,这时候是開始录音
*/
- (void)holdDownButtonTouchDown; /**
* 当手指在录音button范围之外离开屏幕所触发的事件。这时候是取消录音
*/
- (void)holdDownButtonTouchUpOutside; /**
* 当手指在录音button范围之内离开屏幕所触发的事件,这时候是完毕录音
*/
- (void)holdDownButtonTouchUpInside; /**
* 当手指滑动到录音button的范围之外所触发的事件
*/
- (void)holdDownDragOutside;
5.初始化系统UI
#pragma mark - layout subViews UI /**
* 依据正常显示和高亮状态创建一个button对象
*
* @param image 正常显示图
* @param hlImage 高亮显示图
*
* @return 返回button对象
*/
- (UIButton *)createButtonWithImage:(UIImage *)image HLImage:(UIImage *)hlImage ;
- (void)holdDownDragInside;
- (void)createInitView; // 创建初始化界面。播放提示音时会用到
- (void)createRecordView; // 创建录音界面
- (void)createRecognitionView; // 创建识别界面
- (void)createErrorViewWithErrorType:(int)aStatus; // 在识别view中显示具体错误信息
- (void)createRunLogWithStatus:(int)aStatus; // 在状态view中显示具体状态信息 - (void)finishRecord:(id)sender; // 用户点击完毕动作
- (void)cancel:(id)sender; // 用户点击取消动作 - (void)startVoiceLevelMeterTimer;
- (void)freeVoiceLevelMeterTimerTimer;
6.最重要的部分
// 录音完毕
[[BDVoiceRecognitionClient sharedInstance] speakFinish];
// 取消录音
[[BDVoiceRecognitionClient sharedInstance] stopVoiceRecognition];
7.两个代理方法
- (void)VoiceRecognitionClientWorkStatus:(int)aStatus obj:(id)aObj
{
switch (aStatus)
{
case EVoiceRecognitionClientWorkStatusFlushData: // 连续上屏中间结果
{
NSString *text = [aObj objectAtIndex:0]; if ([text length] > 0)
{
// [clientSampleViewController logOutToContinusManualResut:text]; UILabel *clientWorkStatusFlushLabel = [[UILabel alloc]initWithFrame:CGRectMake(kScreenWidth/2 - 100,64,200,60)];
clientWorkStatusFlushLabel.text = text;
clientWorkStatusFlushLabel.textAlignment = NSTextAlignmentCenter;
clientWorkStatusFlushLabel.font = [UIFont systemFontOfSize:18.0f];
clientWorkStatusFlushLabel.numberOfLines = 0;
clientWorkStatusFlushLabel.backgroundColor = [UIColor whiteColor];
[self.view addSubview:clientWorkStatusFlushLabel]; } break;
}
case EVoiceRecognitionClientWorkStatusFinish: // 识别正常完毕并获得结果
{
[self createRunLogWithStatus:aStatus]; if ([[BDVoiceRecognitionClient sharedInstance] getRecognitionProperty] != EVoiceRecognitionPropertyInput)
{
// 搜索模式下的结果为数组,演示样例为
// ["公园", "公元"]
NSMutableArray *audioResultData = (NSMutableArray *)aObj;
NSMutableString *tmpString = [[NSMutableString alloc] initWithString:@""]; for (int i=0; i < [audioResultData count]; i++)
{
[tmpString appendFormat:@"%@\r\n",[audioResultData objectAtIndex:i]];
} clientSampleViewController.resultView.text = nil;
[clientSampleViewController logOutToManualResut:tmpString]; }
else
{
NSString *tmpString = [[BDVRSConfig sharedInstance] composeInputModeResult:aObj];
[clientSampleViewController logOutToContinusManualResut:tmpString]; } if (self.view.superview)
{
[self.view removeFromSuperview];
} break;
}
case EVoiceRecognitionClientWorkStatusReceiveData:
{
// 此状态仅仅有在输入模式下使用
// 输入模式下的结果为带置信度的结果,示比例如以下:
// [
// [
// {
// "百度" = "0.6055192947387695";
// },
// {
// "摆渡" = "0.3625582158565521";
// },
// ]
// [
// {
// "一下" = "0.7665404081344604";
// }
// ],
// ]
//临时关掉 -- 否则影响跳转结果
// NSString *tmpString = [[BDVRSConfig sharedInstance] composeInputModeResult:aObj];
// [clientSampleViewController logOutToContinusManualResut:tmpString]; break;
}
case EVoiceRecognitionClientWorkStatusEnd: // 用户说话完毕,等待server返回识别结果
{
[self createRunLogWithStatus:aStatus];
if ([BDVRSConfig sharedInstance].voiceLevelMeter)
{
[self freeVoiceLevelMeterTimerTimer];
} [self createRecognitionView]; break;
}
case EVoiceRecognitionClientWorkStatusCancel:
{
if ([BDVRSConfig sharedInstance].voiceLevelMeter)
{
[self freeVoiceLevelMeterTimerTimer];
} [self createRunLogWithStatus:aStatus]; if (self.view.superview)
{
[self.view removeFromSuperview];
}
break;
}
case EVoiceRecognitionClientWorkStatusStartWorkIng: // 识别库開始识别工作,用户能够说话
{
if ([BDVRSConfig sharedInstance].playStartMusicSwitch) // 假设播放了提示音。此时再给用户提示能够说话
{
[self createRecordView];
} if ([BDVRSConfig sharedInstance].voiceLevelMeter) // 开启语音音量监听
{
[self startVoiceLevelMeterTimer];
} [self createRunLogWithStatus:aStatus]; break;
}
case EVoiceRecognitionClientWorkStatusNone:
case EVoiceRecognitionClientWorkPlayStartTone:
case EVoiceRecognitionClientWorkPlayStartToneFinish:
case EVoiceRecognitionClientWorkStatusStart:
case EVoiceRecognitionClientWorkPlayEndToneFinish:
case EVoiceRecognitionClientWorkPlayEndTone:
{
[self createRunLogWithStatus:aStatus];
break;
}
case EVoiceRecognitionClientWorkStatusNewRecordData:
{
break;
}
default:
{
[self createRunLogWithStatus:aStatus];
if ([BDVRSConfig sharedInstance].voiceLevelMeter)
{
[self freeVoiceLevelMeterTimerTimer];
}
if (self.view.superview)
{
[self.view removeFromSuperview];
} break;
}
}
}
- (void)VoiceRecognitionClientNetWorkStatus:(int) aStatus
{
switch (aStatus)
{
case EVoiceRecognitionClientNetWorkStatusStart:
{
[self createRunLogWithStatus:aStatus];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
break;
}
case EVoiceRecognitionClientNetWorkStatusEnd:
{
[self createRunLogWithStatus:aStatus];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
break;
}
}
}
8.录音button的一些操作
#pragma mark ------ 关于button操作的一些事情-------
- (void)holdDownButtonTouchDown {
// 開始动画
_disPlayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(delayAnimation)];
_disPlayLink.frameInterval = 40;
[_disPlayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; self.isCancelled = NO;
self.isRecording = NO; // 開始语音识别功能,之前必须实现MVoiceRecognitionClientDelegate协议中的VoiceRecognitionClientWorkStatus:obj方法
int startStatus = -1;
startStatus = [[BDVoiceRecognitionClient sharedInstance] startVoiceRecognition:self];
if (startStatus != EVoiceRecognitionStartWorking) // 创建失败则报告错误
{
NSString *statusString = [NSString stringWithFormat:@"%d",startStatus];
[self performSelector:@selector(firstStartError:) withObject:statusString afterDelay:0.3]; // 延迟0.3秒。以便能在出错时正常删除view
return;
}
// "按住说话-松开搜索"提示
[voiceImageStr removeFromSuperview];
voiceImageStr = [[UIImageView alloc]initWithFrame:CGRectMake(kScreenWidth/2 - 40, kScreenHeight - 153, 80, 33)];
voiceImageStr.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"searchVoice"]];
[self.view addSubview:voiceImageStr]; } - (void)holdDownButtonTouchUpOutside {
// 结束动画
[self.view.layer removeAllAnimations];
[_disPlayLink invalidate];
_disPlayLink = nil; // 取消录音
[[BDVoiceRecognitionClient sharedInstance] stopVoiceRecognition]; if (self.view.superview)
{
[self.view removeFromSuperview];
}
} - (void)holdDownButtonTouchUpInside {
// 结束动画
[self.view.layer removeAllAnimations];
[_disPlayLink invalidate];
_disPlayLink = nil; [[BDVoiceRecognitionClient sharedInstance] speakFinish];
} - (void)holdDownDragOutside { //假设已經開始錄音了, 才须要做拖曳出去的動作, 否則仅仅要切換 isCancelled, 不讓錄音開始.
if (self.isRecording) {
// if ([self.delegate respondsToSelector:@selector(didDragOutsideAction)]) {
// [self.delegate didDragOutsideAction];
// }
} else {
self.isCancelled = YES;
}
} #pragma mark - layout subViews UI - (UIButton *)createButtonWithImage:(UIImage *)image HLImage:(UIImage *)hlImage {
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(kScreenWidth/2 -36, kScreenHeight - 120, 72, 72)]; if (image)
[button setBackgroundImage:image forState:UIControlStateNormal];
if (hlImage)
[button setBackgroundImage:hlImage forState:UIControlStateHighlighted]; return button;
} #pragma mark ----------- 动画部分 -----------
- (void)startAnimation
{
CALayer *layer = [[CALayer alloc] init];
layer.cornerRadius = [UIScreen mainScreen].bounds.size.width/2;
layer.frame = CGRectMake(0, 0, layer.cornerRadius * 2, layer.cornerRadius * 2);
layer.position = CGPointMake([UIScreen mainScreen].bounds.size.width/2,[UIScreen mainScreen].bounds.size.height - 84);
// self.view.layer.position;
UIColor *color = [UIColor colorWithRed:arc4random()%10*0.1 green:arc4random()%10*0.1 blue:arc4random()%10*0.1 alpha:1];
layer.backgroundColor = color.CGColor;
[self.view.layer addSublayer:layer]; CAMediaTimingFunction *defaultCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]; _animaTionGroup = [CAAnimationGroup animation];
_animaTionGroup.delegate = self;
_animaTionGroup.duration = 2;
_animaTionGroup.removedOnCompletion = YES;
_animaTionGroup.timingFunction = defaultCurve; CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale.xy"];
scaleAnimation.fromValue = @0.0;
scaleAnimation.toValue = @1.0;
scaleAnimation.duration = 2; CAKeyframeAnimation *opencityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
opencityAnimation.duration = 2;
opencityAnimation.values = @[@0.8,@0.4,@0];
opencityAnimation.keyTimes = @[@0,@0.5,@1];
opencityAnimation.removedOnCompletion = YES; NSArray *animations = @[scaleAnimation,opencityAnimation];
_animaTionGroup.animations = animations;
[layer addAnimation:_animaTionGroup forKey:nil]; [self performSelector:@selector(removeLayer:) withObject:layer afterDelay:1.5];
} - (void)removeLayer:(CALayer *)layer
{
[layer removeFromSuperlayer];
} - (void)delayAnimation
{
[self startAnimation];
}
完毕以上操作,就大功告成了!
温馨提示:
1.因为是语音识别,须要用到麦克风相关权限。模拟器会爆12个错误。使用真机能够解决;
2.涉及到授权文件相关并不复杂,projectBundle Identifier仅仅须要设置百度的离线授权一致就可以。例如以下图:
终于效果例如以下:
有不懂或不明确的地方能够微博联系我:
iOS开发人员交流群:446310206
iOS中 语音识别功能/语音转文字教程具体解释 韩俊强的博客的更多相关文章
- iOS中 语音识别功能/语音转文字教程详解 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博 原文地址:http://blog.csdn.net/qq_31810357/article/details/5111 ...
- iOS中 最新微信支付/最全的微信支付教程具体解释 韩俊强的博客
亲们, 首先让我们来看一下微信支付的流程吧. 1. 注冊微信开放平台,创建应用获取appid,appSecret,申请支付功能,申请成功之后会返回一些參数. 2. 下载微信支付sdk 3. clien ...
- iOS中 扫描二维码/生成二维码具体解释 韩俊强的博客
近期大家总是问我有没有关于二维码的demo,为了满足大家的需求,特此研究了一番,希望能帮到大家! 每日更新关注:http://weibo.com/hanjunqiang 新浪微博 指示根视图: se ...
- iOS中 HTTP/Socket/TCP/IP通信协议具体解释 韩俊强的博客
简介: // OSI(开放式系统互联), 由ISO(国际化标准组织)制定 // 1. 应用层 // 2. 表示层 // 3. 会话层 // 4. 传输层 // 5. 网络层 // 6. 数据链接层 / ...
- iOS中 最新微信支付/最全的微信支付教程详解 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博! 亲们, 首先让我们来看一下微信支付的流程吧. 1. 注册微信开放平台,创建应用获取appid,appSecret, ...
- iOS中 扫描二维码/生成二维码详解 韩俊强的博客
最近大家总是问我有没有关于二维码的demo,为了满足大家的需求,特此研究了一番,希望能帮到大家! 每日更新关注:http://weibo.com/hanjunqiang 新浪微博 指示根视图: se ...
- iOS中 按钮和标题完美各种排列/完美教程 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博! 前言:最近常常用到按钮和相应标题的组合,当按钮设置图片加标题时,触发范围较小,不易触发,最重要的是还要调试偏移量, ...
- iOS中 Realm的学习与使用 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博! 有问题或技术交流可以咨询!欢迎加入! 这篇直接搬了一份官方文档过来看的 由于之前没用markdown搞的乱七八糟的 ...
- iOS中 流媒体播放和下载 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博 iOS中关于流媒体的简介:介于下载本地播放与实时流媒体之间的一种播放形式,下载本地播放必须全部将文件下载完成后才能播 ...
随机推荐
- SQL中获取排序分组后数据的脚本
废话不多说了,先上一段代码,如下所示: select distinct b.OrgID,b.CompanyID,b.AreaID,b.CustChannelID,b.CustID,b.SaleTo ...
- Linux高速缓冲区原理
文件系统-高速缓冲区: 首先我们为什么需要高速缓冲区而不是直接访问块设备中的数据.这是因为,IO设备和内存之间的读写速度不匹配而且有一点数据需要写入或者读出磁盘就访问磁盘,磁盘很快就会损坏,而高速缓冲 ...
- SharePoint 2013创建WCF REST Service
SharePoint 2013为开发者提供了丰富的REST API,方便了我们在客户端操作List中的数据.当然我们也可以在SharePoint 2013中创建自定义的REST Service,比如通 ...
- 使用layui 和 jquery 问题小结
问题 1 在使用 layui 2.2.5 之前,可以引入最新版的 jquery ,使用更好的性能.也可以使用layui 的jquery内部版本.如果引入要在引入layui.js 之前引入 2 使用 s ...
- django session入门详解
概括性的讲: 1.django默认是打开对session的支持的 2.默认情况下session相关的数据会保存在数据库中.浏览器端只保存了session id session 的科普: 1.动态网站中 ...
- MySql(九):MySQL性能调优——Schema设计的性能优化
一.高效的模型设计 先了解下数据库设计的三大范式 第一范式:要求有主键,并且要求每一个字段原子性不可再分 第二范式:要求所有非主键字段完全依赖主键,不能产生部分依赖 第三范式:所有非主键字段和主键字段 ...
- Unity创建一个简易的弹簧(弹动)效果
参考文章:http://www.cnblogs.com/SkyD/archive/2008/09/05/1284778.html 主要依据胡克公式F=-k·x.这里k是倔度系数,可以理解为k值越大弹性 ...
- iOS 应用程序目录结构
iOS应用程序采用的是沙盒原理设计,普及一下知识:沙盒是在受限的安全环境中运行应用程序的一种做法,这种做法是要限制授予应用程序的代码访问权限. 具体的特点有三点:1.每个应用程序都有自己的存储空间: ...
- [svc][dhcp]关于无线ap自动发现选项dhcp option43配置
有人问到option43的问题,查了点资料.总结了下win和linux的option43的配置: windows2003 http://www.h3c.com.cn/Service/Channel_S ...
- [100]linux常用命令参数小结
1.mkdir 2.ls -l -d 显示目录 -F 给文件夹结尾加/标识 -a 以.开头的都是隐藏文件 -rt 按照修改时间倒序排列(最新修改的在最下) ls -lhrt #最新的在下面 3.cd ...