美文网首页
iOS录音和音频播放

iOS录音和音频播放

作者: iOS弗森科 | 来源:发表于2019-10-23 22:58 被阅读0次


    简介

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

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

    AVAudioRecorder录音

    AVAudioRecorder录音的主要步骤:

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

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

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

    //导入头文件

    #import <AVFoundation/AVFoundation.h>

    #import "GTMBase64.h"

    @interface ViewController ()<AVAudioRecorderDelegate,AVAudioPlayerDelegate>{

        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 <AVFoundation/AVFoundation.h>

    #import "GTMBase64.h"

    @interface ViewController ()<AVAudioRecorderDelegate,AVAudioPlayerDelegate>{

        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录音和音频播放

          本文链接:https://www.haomeiwen.com/subject/omylvctx.html