iOS录音和音频播放


简介

最近公司研发了一个语音识别的框架,但这个框架是后端识别,所以需要手机端录音,录音后将音频文件通转成NSData类型,然后通过bsae64转码传给后台进行语音识别,识别的文字再传回给前端,虽然我认为这样做体验并不好,毕竟请求是耗时的,并且iOS10以后,自带语音识别框架,但毕竟是公司研发的框架,所以就配合做了一下测试。

iOS录音和音频播放用到时AVFoundation.h框架中的,AVAudioRecorder类和AVAudioPlayer,其中AVAudioPlayer播放器只能播放本地音频文件,如果要在线播放需要用AVPlayer,其配合AVPlayerLayer类还可实现视频播放。另外支持播放进度监听。

AVAudioRecorder录音

AVAudioRecorder录音的主要步骤:

创建录音文件保存路径,并设置相关属性(是一个字典),然后实例化AVAudioRecorder录音对象,该对象必须是全局变量。

使用AVAudioSession的单例对象(音频会话对象)来设置当前音频会话状态和会话类别。

录音对象设置开始录音,录音结束后会调用录音完成的代理方法。

//导入头文件

#import

#import "GTMBase64.h"

@interface ViewController (){

    NSURL * recordUrl;

    AVAudioRecorder * audioRecorder;//必须为全局变量

    AVAudioPlayer * player;//必须为全局变量

    }

//开始录音

- (void)startRecord

{

    //删除上次生成的文件,保留最新文件

    NSFileManager *fileManager = [NSFileManager defaultManager];

    //默认就是wav格式,是无损的

    if ([fileManager fileExistsAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"recordAudio.wav"]]) {

        [fileManager removeItemAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"recordAudio.wav"] error:nil];

    }

    //录音设置

    NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];

    //设置录音格式 AVFormatIDKey==kAudioFormatLinearPCM

    [recordSetting setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];

    //设置录音采样率(Hz) 如:AVSampleRateKey==8000/44100/96000(影响音频的质量), 采样率必须要设为11025才能使转化成mp3格式后不会失真

    [recordSetting setValue:[NSNumber numberWithFloat:16000] forKey:AVSampleRateKey];

    //录音通道数 1 或 2 ,要转换成mp3格式必须为双通道

    [recordSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];

    //线性采样位数 8、16、24、32

    [recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];

    //录音的质量

    [recordSetting setValue:[NSNumber numberWithInt:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey];

    // 设置录制音频采用高位优先的记录格式

    [recordSetting setValue:[NSNumber numberWithBool:YES] forKey:AVLinearPCMIsBigEndianKey];

    // 设置采样信号采用浮点数

    [recordSetting setValue:[NSNumber numberWithBool:YES] forKey:AVLinearPCMIsFloatKey];

    //存储录音文件

    NSURL * recordUrl = [NSURL URLWithString:[NSTemporaryDirectory()stringByAppendingPathComponent:@"recordAudio.wav"]];

    //初始化录音对象

    NSError * error;

    audioRecorder = [[AVAudioRecorder alloc] initWithURL:recordUrl settings:recordSetting error:&error];

    if (error) {

        NSLog(@"%@",error.description);

        return;

    }

    audioRecorder.delegate = self;

    //开启音量检测

    audioRecorder.meteringEnabled = YES;

    AVAudioSession * audioSession = [AVAudioSession sharedInstance];//得到音频会话单例对象

    //如果不是正在录音

    if (![audioRecorder isRecording]) {

        [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];//设置类别,表示该应用同时支持播放和录音

        [audioSession setActive:YES error:nil];//激活当前应用的音频会话,此时会阻断后台音乐的播放.

        [audioRecorder prepareToRecord];//准备录音

        [audioRecorder record];//开始录音

        //暂停录音

//        [audioRecorder pause];

    }

}

//结束录音

- (void)endRecord

{

    [audioRecorder stop];            //录音停止

}

//录音结束后代理

-(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{

    [[AVAudioSession sharedInstance] setActive:NO error:nil];//一定要在录音停止以后再关闭音频会话管理(否则会报错),此时会延续后台音乐播放

    if (!flag) return;

    //请求接口传给后台

    [self postwavdata];

}

注意:

录音时音频文件类型后缀必须为.caf、.aif、.wav中的一种,不能是.mp3,但播放是可以播放.mp3文件,可以导入githu上的一个C语言框架lame转成mp3音频文件。

将音频文件转成NSData然后用bsae64加密传给服务器,用系统自带的base64EncodedStringWithOptions编码方法后台可能解析有问题,主要是有空格和换行,可以多encode一次转义去掉这些特殊符号,也可以用第三方框架GTMBase64,请求数据时候request的Content-Type要设置为application/json,否则后台可能结束不到音频转码后端参数。


//设置request的Content-Type为application/json

[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

//转成base64编码格式上传服务器

-(NSString *)wavToBASE64{

NSData * wavData = [NSData dataWithContentsOfFile:[NSTemporaryDirectory() stringByAppendingPathComponent:@"recordAudio.wav"]];

NSString * encodedImageStr = [GTMBase64 encodeBase64Data:wavData];

}

AVAudioPlayer播放音频文件。

AVAudioPlayer播放音频文件主要步骤:

获取音频文件URL或者音频文件数据;

初始化AVAudioPlayer音频播放器全局对象;

设置相关属性,并播放文件。

相关代码

————————————————


//导入头文件

#import

#import "GTMBase64.h"

@interface ViewController (){

    NSURL * recordUrl;

    AVAudioRecorder * audioRecorder;//必须为全局变量

    AVAudioPlayer * player;//必须为全局变量

    }

//开始录音

- (void)startRecord

{

    //删除上次生成的文件,保留最新文件

    NSFileManager *fileManager = [NSFileManager defaultManager];

    //默认就是wav格式,是无损的

    if ([fileManager fileExistsAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"recordAudio.wav"]]) {

        [fileManager removeItemAtPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"recordAudio.wav"] error:nil];

    }

    //录音设置

    NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];

    //设置录音格式 AVFormatIDKey==kAudioFormatLinearPCM

    [recordSetting setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];

    //设置录音采样率(Hz) 如:AVSampleRateKey==8000/44100/96000(影响音频的质量), 采样率必须要设为11025才能使转化成mp3格式后不会失真

    [recordSetting setValue:[NSNumber numberWithFloat:16000] forKey:AVSampleRateKey];

    //录音通道数 1 或 2 ,要转换成mp3格式必须为双通道

    [recordSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];

    //线性采样位数 8、16、24、32

    [recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];

    //录音的质量

    [recordSetting setValue:[NSNumber numberWithInt:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey];

    // 设置录制音频采用高位优先的记录格式

    [recordSetting setValue:[NSNumber numberWithBool:YES] forKey:AVLinearPCMIsBigEndianKey];

    // 设置采样信号采用浮点数

    [recordSetting setValue:[NSNumber numberWithBool:YES] forKey:AVLinearPCMIsFloatKey];

    //存储录音文件

    NSURL * recordUrl = [NSURL URLWithString:[NSTemporaryDirectory()stringByAppendingPathComponent:@"recordAudio.wav"]];

    //初始化录音对象

    NSError * error;

    audioRecorder = [[AVAudioRecorder alloc] initWithURL:recordUrl settings:recordSetting error:&error];

    if (error) {

        NSLog(@"%@",error.description);

        return;

    }

    audioRecorder.delegate = self;

    //开启音量检测

    audioRecorder.meteringEnabled = YES;

    AVAudioSession * audioSession = [AVAudioSession sharedInstance];//得到音频会话单例对象

    //如果不是正在录音

    if (![audioRecorder isRecording]) {

        [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];//设置类别,表示该应用同时支持播放和录音

        [audioSession setActive:YES error:nil];//激活当前应用的音频会话,此时会阻断后台音乐的播放.

        [audioRecorder prepareToRecord];//准备录音

        [audioRecorder record];//开始录音

        //暂停录音

//        [audioRecorder pause];

    }

}

//结束录音

- (void)endRecord

{

    [audioRecorder stop];            //录音停止

}

//录音结束后代理

-(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{

    [[AVAudioSession sharedInstance] setActive:NO error:nil];//一定要在录音停止以后再关闭音频会话管理(否则会报错),此时会延续后台音乐播放

    if (!flag) return;

    //请求接口传给后台

    [self postwavdata];

}

注意:

录音时音频文件类型后缀必须为.caf、.aif、.wav中的一种,不能是.mp3,但播放是可以播放.mp3文件,可以导入githu上的一个C语言框架lame转成mp3音频文件。

将音频文件转成NSData然后用bsae64加密传给服务器,用系统自带的base64EncodedStringWithOptions编码方法后台可能解析有问题,主要是有空格和换行,可以多encode一次转义去掉这些特殊符号,也可以用第三方框架GTMBase64,请求数据时候request的Content-Type要设置为application/json,否则后台可能结束不到音频转码后端参数。

————————————————

//设置request的Content-Type为application/json

[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

//转成base64编码格式上传服务器

-(NSString *)wavToBASE64{

NSData * wavData = [NSData dataWithContentsOfFile:[NSTemporaryDirectory() stringByAppendingPathComponent:@"recordAudio.wav"]];

NSString * encodedImageStr = [GTMBase64 encodeBase64Data:wavData];

}


AVAudioPlayer播放音频文件。

AVAudioPlayer播放音频文件主要步骤:

获取音频文件URL或者音频文件数据;

初始化AVAudioPlayer音频播放器全局对象;

设置相关属性,并播放文件。

相关代码


//开始播放音频文件

- (void)playWav{

//获取音频文件url

//  NSURL * url = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"recordAudio.wav"]];

//获取录音数据

NSData * wavData = [NSData dataWithContentsOfFile:[NSTemporaryDirectory() stringByAppendingPathComponent:@"recordAudio.wav"]];

NSError * error;

//    AVAudioPlayer * player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];

  player = [[AVAudioPlayer alloc]initWithData:wavData error:&error];

  player.delegate = self;

  if (error) {

      NSLog(@"语音播放失败,%@",error);

      return;

  }

    //播放器的声音会自动切到receiver,所以听起来特别小,如果需要从speaker出声,需要自己设置。

  [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];

  // 单独设置音乐的音量(默认1.0,可设置范围为0.0至1.0,两个极端为静音、系统音量):

  player.volume = 1.0;

//    修改左右声道的平衡(默认0.0,可设置范围为-1.0至1.0,两个极端分别为只有左声道、只有右声道):

  player.pan = -1;

//    设置播放速度(默认1.0,可设置范围为0.5至2.0,两个极端分别为一半速度、两倍速度):

  player.rate = 2.0;

//    设置循环播放(默认1,若设置值大于0,则为相应的循环次数,设置为-1可以实现无限循环):

  player.numberOfLoops = 0;

//    player.currentTime = 0;

  //调用prepareToPlay方法,这样可以提前获取需要的硬件支持,并加载音频到缓冲区。在调用play方法时,减少开始播放的延迟。

  [player prepareToPlay];

//    开始播放音乐:

  [player play];


  }

//播放完成代理

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{

  if (flag) {

      NSLog(@"停止播放");

      //调用pause或stop来暂停播放,这里的stop方法的效果也只是暂停播放,不同之处是stop会撤销prepareToPlay方法所做的准备。

      [player stop];

      player = nil;

  }

}


最后


给大家推荐一个优秀的iOS交流平台,平台里的伙伴们都是非常优秀的iOS开发人员,我们专注于技术的分享与技巧的交流,大家可以在平台上讨论技术,交流学习。欢迎大家的加入(想要进入的可加小编微信1367798518)


iOS录音和音频播放_第1张图片

你可能感兴趣的:(iOS录音和音频播放)