iOS 讯飞语音之语音听写 录音的实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012490014/article/details/80798327

引入库

第一步 获取appid

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。

设置bitcode

在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中需要用到的权限主要包括麦克风权限、联系人权限和地理位置权限:

<key>NSMicrophoneUsageDescription</key>
<string></string>
<key>NSLocationUsageDescription</key>
<string></string>
<key>NSLocationAlwaysUsageDescription</key>
<string></string>
<key>NSContactsUsageDescription</key>
<string></string>

即在Info.plist 中增加下图设置

第三步初始化

//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;

/*!
 *  识别结果回调
 *
 *  在识别过程中可能会多次回调此函数,你最好不要在此回调函数中进行界面的更改等操作,只需要将回调的结果保存起来。<br>
 *  使用results的示例如下:
 *  <pre><code>
 *  - (void) onResults:(NSArray *) results{
 *     NSMutableString *result = [[NSMutableString alloc] init];
 *     NSDictionary *dic = [results objectAtIndex:0];
 *     for (NSString *key in dic){
 *        [result appendFormat:@"%@",key];//合并结果
 *     }
 *   }
 *  </code></pre>
 *
 *  @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 <Foundation/Foundation.h>

@interface RecordHelper : NSObject

- (void)startRecord:(NSString *)path;
- (void)stopRecord;

@end
m文件的实现
#import "RecordHelper.h"
#import <AVFoundation/AVFoundation.h>
@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

注意:需要自己建立文件夹,该类不会根据路径自己建立文件夹,路径里面包含文件格式例如.wav, .pcm





猜你喜欢

转载自blog.csdn.net/u012490014/article/details/80798327