手机录音 AVAudioRecorder,并转成mp3格式

苹果提供了AVAudioRecorder类来让我们进行音频录制,是录音变的非常的便捷!
在使用AVAudioRecorder进行录音之前要做几样准备工作,
① 、在iOS10及以上,调用系统功能需要在info.plist文件里添加相应的key,如图,在info.plist文件下添加Key: Privacy - Microphone Usage Description, Value值可以自己随便写哦!


Key

② 、进行权限验证,如下代码:

AVAudioSession *session = [AVAudioSession sharedInstance];
 if ([session respondsToSelector:@selector(requestRecordPermission:)]) {
        
        [session performSelector:@selector(requestRecordPermission:) withObject:^(BOOL granted) {
            if (granted) {
                
                // 用户同意获取麦克风,一定要在主线程中执行UI操作!!!
                dispatch_queue_t queueOne = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
                dispatch_async(queueOne, ^{
                    
                    dispatch_async(dispatch_get_main_queue(), ^{
                        
                        //在主线程中执行UI,这里主要是执行录音和计时的UI操作
                        [self record];
                    });
                });
            } else {
                
                // 用户不同意获取麦克风
                UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"麦克风不可用" message:@"请在“设置 - 隐私 - 麦克风”中允许XXX访问你的麦克风" preferredStyle:UIAlertControllerStyleAlert];
                UIAlertAction *openAction = [UIAlertAction actionWithTitle:@"前往开启" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                    
                    //如果要让用户直接跳转到设置界面,则可以进行下面的操作,如不需要,就忽略下面的代码
                    /*
                     *iOS10 开始苹果禁止应用直接跳转到系统单个设置页面,只能跳转到应用所有设置页面
                     *iOS10以下可以添加单个设置的系统路径,并在info里添加URL Type,将URL schemes 设置路径为prefs即可。
                     *@"prefs:root=Sounds"
                     */
                    NSURL * url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                    
                    if([[UIApplication sharedApplication] canOpenURL:url]) {
                        
                        [[UIApplication sharedApplication] openURL:url];
                    }
                }];
                
                [alertController addAction:openAction];
                [self presentViewController:alertController animated:YES completion:nil];
            }
        }];
    }

3️⃣ 、为了知道你正在录音,肯定得搞个录音的计时器吧!
首先搞个label显示时间

- (void)addTimerLabel {
    
    //这个是自己封装的创建label的方法!
    _timerLabel = [CommonLib createLabelFrame:CGRectMake(20, 120, kScreenWidth - 40, TimerLabelH) text:@"00:00:00" alignment:NSTextAlignmentCenter textColor:[UIColor greenColor] font:TimerLabelH];
    [self.view addSubview:_timerLabel];
}

//要计时当然少不了计时器了,这里计时器设置成每秒更新,因为这里设定的最小时间单位是秒,若最小时间单位是毫秒,就把1.0,改成0.01!这个方法在你点击录音的时候调用
- (void)startTimer {
    
    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateSecond:) userInfo:nil repeats:YES];
}

//执行更新UI的操作,每秒执行
- (void)updateSecond:(NSTimer *)timer {
    
    _second ++;
    if (_second == 1) {
        
        [self enbleBtn];
    }
    //这个方法是把时间显示成时分秒的形式显示在label上
    NSString *timerStr = [self convertTimeToString:_second];
    _timerLabel.text = timerStr;
}

 //规范时间格式
- (NSString *)convertTimeToString:(NSInteger)second {
   
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"HH:mm:ss"];
    NSDate *date = [formatter dateFromString:@"00:00:00"];
    date = [date dateByAddingTimeInterval:second];
    NSString *timeString = [formatter stringFromDate:date];
    return timeString;
}

好了,以上步骤走完,就可以开始录音的操作了!

//设置后台播放,下面这段是录音和播放录音的设置
_session = [AVAudioSession sharedInstance];
NSError *sessionError;
[_session setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];
//判断后台有没有播放
if (_session == nil) {
            
        SIMEILog(@"Error creating sessing:%@", [sessionError description]);
} else {
//关闭其他音频播放,把自己设为活跃状态
        [_session setActive:YES error:nil];
}
        
if (![_timer isValid]) {
            
            [self startTimer];
} else {
            
            //这个方法是写了一个NSTimer的拓展类 Category,具体方法在下面附上代码
            [_timer continueTimer];
}

//设置AVAudioRecorder
if (!self.recorder) {
            
            NSDictionary *settings = @{AVFormatIDKey  :  @(kAudioFormatLinearPCM), AVSampleRateKey : @(11025.0), AVNumberOfChannelsKey :@2, AVEncoderBitDepthHintKey : @16, AVEncoderAudioQualityKey : @(AVAudioQualityHigh)};

            //开始录音,将所获取到得录音存到文件里 _recordUrl
是存放录音的文件路径,在下面附上
            self.recorder = [[AVAudioRecorder alloc] initWithURL:_recordUrl settings:settings error:nil];
            
            /*
             * settings 参数
             1.AVNumberOfChannelsKey 通道数 通常为双声道 值2
             2.AVSampleRateKey 采样率 单位HZ 通常设置成44100 也就是44.1k,采样率必须要设为11025才能使转化成mp3格式后不会失真
             3.AVLinearPCMBitDepthKey 比特率 8 16 24 32
             4.AVEncoderAudioQualityKey 声音质量
             ① AVAudioQualityMin  = 0, 最小的质量
             ② AVAudioQualityLow  = 0x20, 比较低的质量
             ③ AVAudioQualityMedium = 0x40, 中间的质量
             ④ AVAudioQualityHigh  = 0x60,高的质量
             ⑤ AVAudioQualityMax  = 0x7F 最好的质量
             5.AVEncoderBitRateKey 音频编码的比特率 单位Kbps 传输的速率 一般设置128000 也就是128kbps
             
             */
        }
        
        //准备记录录音
        [_recorder prepareToRecord];
        
        //开启仪表计数功能,必须开启这个功能,才能检测音频值
        [_recorder setMeteringEnabled:YES];
        //启动或者恢复记录的录音文件
        [_recorder record];

下面附上NSTimer的Category,怎么创建Category呢,右击New Files -> ObjectC - Files -> File Type选择Category, Class 选择NSTimer ,File文件名自己随便取

在.h文件中添加两个方法

//暂停计时
- (void)pauseTimer;

//继续计时
- (void)continueTimer;

在.m文件中实现两个方法

- (void)pauseTimer {
    
    //如果已被释放则return!isValid对应invalidate
    if (![self isValid]) return;
    //启动时间为很久以后
    [self setFireDate:[NSDate distantFuture]];
}

- (void)continueTimer {
    
    if (![self isValid]) return;
    //启动时间为现在
    [self setFireDate:[NSDate date]];
}

附上_recordUrl的路径创建

//因为录音文件比较大,所以我们把它存在Temp文件里,Temp文件里的文件在app重启的时候会自动删除
_recordFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent: @"record.caf"];
    //创建临时文件来存放录音文件
_recordUrl = [NSURL fileURLWithPath:self.recordFilePath];

下面我们就要把录音文件转成mp3格式了,在网上查了很多方法,发现大部分人都推荐使用lame来转换mp3!
所以下面附上lame转换mp3的方法,lame的github下载链接https://github.com/rbrito/lame

下载完成后倒入过程中,在Build Phases 下的Link Binary With Library 下添加lame


lame

一般导入后Library Search Paths 就会自动添加上lame文件在工程中的路径,若没有添加上,就自己手动添加上,否则会报错!!!

导入成功后,就开始使用lame转换mp3了,一大段的C代码,C语言好的同学看着就比较得心应手了

首先#import "lame.h"

//然后开始写转换的代码
    //如果要保存下来自己听,就讲mp3保存到到Document中,如下代码,如果不的话,就保存到Temp文件中
    NSString *fileName = [NSString stringWithFormat:@"/%@.mp3", nowTime];
    NSString *filePath = [[NSHomeDirectory() stringByAppendingFormat:@"/Documents/"] stringByAppendingPathComponent:fileName];
    _mp3Url = [NSURL URLWithString:filePath];
    
    @try {
        int read, write;
        
        FILE *pcm = fopen([_recordFilePath cStringUsingEncoding:1], "rb");   //source 被转换的音频文件位置
        fseek(pcm, 4 * 1024, SEEK_CUR);//删除头,否则在前一秒钟会有杂音
        FILE *mp3 = fopen([filePath cStringUsingEncoding:1], "wb"); //output 输出生成的Mp3文件位置
        
        const int PCM_SIZE = 8192;
        const int MP3_SIZE = 8192;
        short int pcm_buffer[PCM_SIZE * 2];
        unsigned char mp3_buffer[MP3_SIZE];
        //这里要注意,lame的配置要跟AVAudioRecorder的配置一致,否则会造成转换不成功
        lame_t lame = lame_init();
        lame_set_in_samplerate(lame, 11025.0);//采样率
        lame_set_VBR(lame, vbr_default);
        lame_init_params(lame);
        
        do {
            read = (int)fread(pcm_buffer, 2 * sizeof(short int), PCM_SIZE, pcm);
            if (read == 0)
                write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
            else
                write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
            
            fwrite(mp3_buffer, write, 1, mp3);
            
        } while (read != 0);
        
        lame_close(lame);
        fclose(mp3);
        fclose(pcm);
    }
    @catch (NSException *exception) {
        NSLog(@"%@",[exception description]);
    }
    @finally {
        NSLog(@"MP3生成成功!!!");
}

好了以上就是录音和转mp3的主要代码了,最后说一下,这个demo上传github的时候出了点问题,所以如果要demo的同学把邮箱留一下哈!若是对你有帮助的话,随手点个赞哦👍!!!

附上lame编译:
先到官网下载lame文件
再到github上下载外国网友上传的编译脚本文件
将编译脚本文件build-lame.sh 复制到lame文件夹下
修改脚本文件
打开终端
chmod 777 build-lame.sh //chmod 777 是修改权限的指令
./build-lame.sh 开始编译
大概需要一分钟左右
编译完成后lame文件下会生成fat-lame和thin-lame两个文件夹
将fat-lame中的lame.h 和 libmp3lame.a导入工程即可

ps: 如果我没有及时回复,可以先下载swift版的哦!
https://github.com/jieming123/RecordToMP3

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容