appid是第三方应用集成讯飞开放平台SDK的身份标识,SDK静态库和appid是绑定的,每款应用必须保持唯一,否则会出现10407错误码。appid在开放平台申请应用时可以获得,下载SDK后可从SDK中sample文件夹的Demo工程里找到(例如: /sample/MSCDemo/MSCDemo/Definition.h 的APPID_VALUE)
将开发工具包中lib目录下的iflyMSC.framework添加到工程中,同时请将Demo中依赖的其他库也添加到工程中。 按下图示例添加 SDK 所需要的 iOS系统库:
注意:
1 .添加iflyMSC.framework时,请检查工程BuildSetting中的framwork path的设置,如果出现找不到framework的情况,可以将path清空,在Xcode中删除framework,然后重新添加。
2 .iflyMSC.framework最低支持iOS 8.0。
3 .如果使用aiui,需要添加libicucord.tbd。
在Xcode 7,8默认开启了Bitcode,而Bitcode 需要工程依赖的所有类库同时支持。MSC SDK暂时还不支持Bitcode,可以先临时关闭。后续MSC SDK支持Bitcode 时,会在讯飞开放平台上进行SDK版本更新,QQ支持群中同时会有相关提醒,请关注。关闭此设置,只需在Targets - Build Settings 中搜索Bitcode 即可,找到相应选项,设置为NO。
iOS 10发布以来,苹果为了用户信息安全,加入隐私权限设置机制,让用户来选择是否允许。 隐私权限配置可在info.plist 新增相关privacy字段,MSC SDK中需要用到的权限主要包括麦克风权限、联系人权限和地理位置权限:
NSMicrophoneUsageDescription
NSLocationUsageDescription
NSLocationAlwaysUsageDescription
NSContactsUsageDescription
//Appid是应用的身份信息,具有唯一性,初始化时必须要传入Appid。
NSString *initString = [[NSString alloc] initWithFormat:@"appid=%@", @"YourAppid"];
[IFlySpeechUtility createUtility:initString];
_iFlySpeechRecognizer = [IFlySpeechRecognizer sharedInstance];
_iFlySpeechRecognizer.delegate = self;
//设置识别参数
//设置为听写模式
[_iFlySpeechRecognizer setParameter: @"iat" forKey: [IFlySpeechConstant IFLY_DOMAIN]];
//asr_audio_path 是录音文件名,设置value为nil或者为空取消保存,默认保存目录在Library/cache下。
[_iFlySpeechRecognizer setParameter:nil forKey:[IFlySpeechConstant ASR_AUDIO_PATH]];
[_iFlySpeechRecognizer setParameter:@"20000" forKey:[IFlySpeechConstant NET_TIMEOUT]];
//设置是否返回标点符号
[_iFlySpeechRecognizer setParameter:@"0" forKey:[IFlySpeechConstant ASR_PTT]];
// //设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音
// [_iFlySpeechRecognizer setParameter:@"10000" forKey:[IFlySpeechConstant VAD_EOS]];
//设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理
[_iFlySpeechRecognizer setParameter:@"10000" forKey:[IFlySpeechConstant VAD_BOS]];
控制器遵循IFlySpeechRecognizerDelegate协议,
实现协议方法
/*!
* 识别结果回调
*
* 在进行语音识别过程中的任何时刻都有可能回调此函数,你可以根据errorCode进行相应的处理,当errorCode没有错误时,表示此次会话正常结束;否则,表示此次会话有错误发生。特别的当调用`cancel`函数时,引擎不会自动结束,需要等到回调此函数,才表示此次会话结束。在没有回调此函数之前如果重新调用了`startListenging`函数则会报错误。
*
* @param errorCode 错误描述
*/
- (void) onCompleted:(IFlySpeechError *) errorCode;
/*!
* 识别结果回调
*
* 在识别过程中可能会多次回调此函数,你最好不要在此回调函数中进行界面的更改等操作,只需要将回调的结果保存起来。
* 使用results的示例如下:
*
* - (void) onResults:(NSArray *) results{
* NSMutableString *result = [[NSMutableString alloc] init];
* NSDictionary *dic = [results objectAtIndex:0];
* for (NSString *key in dic){
* [result appendFormat:@"%@",key];//合并结果
* }
* }
*
*
* @param results -[out] 识别结果,NSArray的第一个元素为NSDictionary,NSDictionary的key为识别结果,sc为识别结果的置信度。
* @param isLast -[out] 是否最后一个结果
*/
- (void) onResults:(NSArray *) results isLast:(BOOL)isLast;
开始识别:
[_iFlySpeechRecognizer startListening];
结束识别:
[self.iFlySpeechRecognizer stopListening];
因为语音识别返回的格式都是下边的样式:
{"sn":1,"ls":true,"bg":0,"ed":0,"ws":[{"bg":0,"cw":[{"w":"呵呵","sc":0}]},{"bg":0,"cw":[{"w":"哈哈","sc":0}]},{"bg":0,"cw":[{"w":"。","sc":0}]}]}
所以要解析数据:
- (NSString *)stringFromJson:(NSString*)params
{
if (params == NULL) {
return nil;
}
NSMutableString *tempStr = [[NSMutableString alloc] init];
NSDictionary *resultDic = [NSJSONSerialization JSONObjectWithData: //返回的格式必须为utf8的,否则发生未知错误
[params dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
if (resultDic!= nil) {
NSArray *wordArray = [resultDic objectForKey:@"ws"];
for (int i = 0; i < [wordArray count]; i++) {
NSDictionary *wsDic = [wordArray objectAtIndex: i];
NSArray *cwArray = [wsDic objectForKey:@"cw"];
for (int j = 0; j < [cwArray count]; j++) {
NSDictionary *wDic = [cwArray objectAtIndex:j];
NSString *str = [wDic objectForKey:@"w"];
[tempStr appendString: str];
}
}
}
return tempStr;
}
注意设置等待时间,默认_iFlySpeechRecognizer等待时间是5s,也就是5s之内检测不到说话的声音,就会自动关闭
[self.iFlySpeechRecognizer startListening];
[self.iFlySpeechRecognizer writeAudio:[NSData dataWithContentsOfURL:[NSURL fileURLWithPath:pat]]];
[self.iFlySpeechRecognizer stopListening];
pat是指语音文件的路径,也是在上边提到的协议的基础上,数据会通过协议返回,但是需要注意的是,不能连续不间隔的实现多个语音文件,需要间隔1s或者其他的时间,连续不间隔的实现识别多个语音会出问题
因为讯飞只有在线的情况才可以录音,并且录音的路径是固定的无法改变,所以自己写一个录音控制器,最好自己写一个专门的Record管理文件,因为录音路径需要记下来
h文件
#import
@interface RecordHelper : NSObject
- (void)startRecord:(NSString *)path;
- (void)stopRecord;
@end
m文件的实现
#import "RecordHelper.h"
#import
@interface RecordHelper()
@property (nonatomic , strong) AVAudioSession *session;
@property (nonatomic , strong) AVAudioRecorder *recorder;
@property (nonatomic , strong) NSURL *recordFileUrl;
@end
@implementation RecordHelper
- (void)startRecord:(NSString *)path{
[self session];
//获取文件路径
self.recordFileUrl = [NSURL fileURLWithPath:path];
//设置参数
NSDictionary *recordSetting = [[NSDictionary alloc] initWithObjectsAndKeys:
//采样率 8000/11025/22050/44100/96000(影响音频的质量)
[NSNumber numberWithFloat: 8000.0],AVSampleRateKey,
// 音频格式
[NSNumber numberWithInt: kAudioFormatLinearPCM],AVFormatIDKey,
//采样位数 8、16、24、32 默认为16
[NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
// 音频通道数 1 或 2
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
//录音质量
[NSNumber numberWithInt:AVAudioQualityHigh],AVEncoderAudioQualityKey,
nil];
_recorder = [[AVAudioRecorder alloc] initWithURL:self.recordFileUrl settings:recordSetting error:nil];
if (_recorder) {
_recorder.meteringEnabled = YES;
[_recorder prepareToRecord];
[_recorder record];
}else{
NSLog(@"音频格式和文件存储格式不匹配,无法初始化Recorder");
}
}
- (void)stopRecord{
if ([self.recorder isRecording]) {
[self.recorder stop];
_recorder = nil;
}
NSFileManager *manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:[self.recordFileUrl path]]){
NSLog(@"录音成功");
}else{
NSLog(@"录音失败");
}
}
- (AVAudioSession *)session{
if(!_session){
_session = [AVAudioSession sharedInstance];
NSError *sessionError;
[_session setCategory:AVAudioSessionCategoryRecord error:&sessionError];
if (_session == nil) {
NSLog(@"Error creating session: %@",[sessionError description]);
}else{
[_session setActive:YES error:nil];
}
}
return _session;
}
@end