iOS录音及播放全解

丁德义
2023-12-01

iOS录音及播放全解

//
//  ViewController.m
//  录音与播放
//
//  Created by 张璟冰 on 2020/3/29.
//  Copyright © 2020 张璟冰. All rights reserved.
//

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController ()<AVAudioRecorderDelegate>{
    UILabel *timeLabel;
        float time;//保存我们录音录了多久
}
@property(nonatomic,strong)AVAudioRecorder *audioRecorder;//录音器
@property (nonatomic,strong) NSString *mp3Path;
@property (nonatomic,strong) NSString *cafPath;
@property (nonatomic, strong) NSTimer *timer;//定时器
@property (nonatomic, strong) AVAudioPlayer *player; //播放器
@end

@implementation ViewController
#pragma mark  第三步 录音器的懒加载
- (AVAudioRecorder *)audioRecorder
{
    if (!_audioRecorder)
    {
        //7.0第一次运行会提示,是否允许使用麦克风
        AVAudioSession *session = [AVAudioSession sharedInstance];
        NSError *sessionError;
        //AVAudioSessionCategoryPlayAndRecord用于录音和播放
        [session setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];
        if(session == nil)
            NSLog(@"Error creating session: %@", [sessionError description]);
        else
            [session setActive:YES error:nil];
        
        //创建录音文件保存路径
        NSURL *url = [self getSavePath];
        //创建录音格式设置
        NSDictionary *setting = [self getAudioSetting];
        //创建录音机
        NSError *error=nil;
        _audioRecorder = [[AVAudioRecorder alloc]initWithURL:url settings:setting error:&error];
        _audioRecorder.delegate=self;
        _audioRecorder.meteringEnabled=YES;//如果要监控声波则必须设置为YES
        [_audioRecorder prepareToRecord];
        if (error)
        {
            NSLog(@"创建录音机对象时发生错误,错误信息:%@",error.localizedDescription);
            return nil;
        }
    }
    return _audioRecorder;
}
/**
 *  取得录音文件保存路径
 *
 *  @return 录音文件路径
 */
-(NSURL *)getSavePath
{
    //iPhone会为每一个应用程序生成一个私有目录,这个目录位于/user/.../Application下
    //并会随机生成一个数字字母串作为目录名
    //通常使用Documents目录进行数据持久化的保存
    //  在Documents目录下创建一个名为AudioData的文件夹、
    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:@"AudioData"];
    NSLog(@"%@",path);
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL isDir = FALSE;
    BOOL isDirExist = [fileManager fileExistsAtPath:path isDirectory:&isDir];
    if(!(isDirExist && isDir))
        
    {
        BOOL bCreateDir = [fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
        if(!bCreateDir){
            NSLog(@"创建文件夹失败!");
        }
        NSLog(@"创建文件夹成功,文件路径%@",path);
    }
    NSString *fileName = @"record";
    NSString *cafFileName = [NSString stringWithFormat:@"%@.caf", fileName];
    NSString *mp3FileName = [NSString stringWithFormat:@"%@.mp3", fileName];
    //拼接路径
    NSString *cafPath = [path stringByAppendingPathComponent:cafFileName];
    NSString *mp3Path = [path stringByAppendingPathComponent:mp3FileName];
    
    self.mp3Path = mp3Path;
    self.cafPath = cafPath;
    
    NSLog(@"file path:%@",cafPath);
    
    NSURL *url=[NSURL fileURLWithPath:cafPath];
    return url;
}
/**
 *  取得录音文件设置
 *
 *  @return 录音设置
 */
- (NSDictionary *)getAudioSetting
{
    NSMutableDictionary *dicM = [NSMutableDictionary dictionary];
    [dicM setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey];
//    [dicM setObject:@(ETRECORD_RATE) forKey:AVSampleRateKey];
    [dicM setObject:@(2) forKey:AVNumberOfChannelsKey];
    [dicM setObject:@(16) forKey:AVLinearPCMBitDepthKey];
    [dicM setObject:[NSNumber numberWithInt:AVAudioQualityMin] forKey:AVEncoderAudioQualityKey];
    return dicM;
}
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
    btn.tag = 10000;
    [btn setTitle:@"开始录音" forState:UIControlStateNormal];
    [btn setTitle:@"停止录音" forState:UIControlStateSelected];
    [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    btn.backgroundColor = [UIColor whiteColor];
    [btn addTarget:self action:@selector(recordClick:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
    
    UIButton *btn2 = [[UIButton alloc]initWithFrame:CGRectMake(120, 0, 100, 100)];
    btn2.tag = 10001;
       [btn2 setTitle:@"播放录音" forState:UIControlStateNormal];
       [btn2 setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
       btn2.backgroundColor = [UIColor whiteColor];
    [btn2 addTarget:self action:@selector(play:) forControlEvents:UIControlEventTouchUpInside];
       [self.view addSubview:btn2];
    
    //时间
    timeLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 200, 100, 30)];
    timeLabel.text = @"录音时长";
    timeLabel.font = [UIFont systemFontOfSize:16];
    timeLabel.textColor = [UIColor blackColor];
    [self.view addSubview:timeLabel];
}
#pragma mark 播放录音
-(void)play:(UIButton *)sender
{
    if ([self.player isPlaying])
        return;
    
    self.player = [[AVAudioPlayer alloc]initWithData:[NSData dataWithContentsOfFile:self.cafPath] error:nil];
    
    [self.player play];
}
#pragma mark 第四步 开始/结束录音点击、播放点击
-(void)recordClick:(UIButton *)sender
{
    sender.selected = !sender.selected;
    if (sender.selected)
    {
        //开始录音
        [self startRecord];
    }
    else
    {
        //结束录音
        [self finishRecorded];
    }
}
//结束录音
- (void)finishRecorded
{
    //使用系统自带录音机
    if ([self.audioRecorder isRecording])
    {
        NSLog(@"完成");
        [self destoryTimer];
        [self.audioRecorder stop];//停止工作
    }
    
    
    if (time < 1)
    {
        NSLog(@"录音时间过短!");//清空录音内容
        return;
    }
    
    //进行录音格式的转码成mp3格式、提交网络上传
    //Lame
    
    time = 0;
    timeLabel.text = @"点击录音";

}
//开始录音
- (void)startRecord
{
    // 重置录音机
    if (self.audioRecorder)
    {
        self.audioRecorder = nil;
        time = 0;
        [self destoryTimer];
    }
    
    if (![self.audioRecorder isRecording])
    {
        AVAudioSession *session = [AVAudioSession sharedInstance];
        NSError *sessionError;
        //AVAudioSessionCategoryPlayAndRecord用于录音和播放
        [session setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];
        if(session == nil)
            NSLog(@"Error creating session: %@", [sessionError description]);
        else
            [session setActive:YES error:nil];
        
        
        //创建定时器方法,实时计算录音了几秒钟
        self.timer = [NSTimer scheduledTimerWithTimeInterval:1
                                                      target:self
                                                    selector:@selector(record)
                                                    userInfo:nil
                                                     repeats:YES];
        timeLabel.text = @"00:00";
        [self.audioRecorder record];//开始工作
        
        NSLog(@"录音开始");
        

        
    }
    else
    {
        NSLog(@"is  recording now  ....");
    }
    
}
//   定时器方法--录音时间计算
- (void)record
{
    time = time+1;
    timeLabel.text = [self timeFormatted:(float)time];
    
    //假如一次性只能录180s,一般写倒计时提示
    if (time == 180)
    {
        NSLog(@"%@",@"最多仅能录取180s");
        
        //结束录音
        UIButton *btn = [self.view viewWithTag:10000];
        btn.selected = !btn.selected;
//        [self finishRecorded];//调用录音结束
        [self.timer invalidate];
        self.timer = nil;
//        _recordGIFImg.hidden = YES;//关闭GIF图,这个图是一个光播图标)))
//        [_recordGIFImg stopAnimating];
    }
}
- (NSString *)timeFormatted:(NSInteger)totalSeconds
{
    NSInteger seconds = totalSeconds % 60;
    NSInteger minutes = (totalSeconds / 60) % 60;
    NSInteger hours = totalSeconds / 3600;
    if (hours <= 0)
    {
        return [NSString stringWithFormat:@"%02ld:%02ld",(long)minutes, (long)seconds];
    }
    return [NSString stringWithFormat:@"%02ld:%02ld:%02ld",(long)hours, (long)minutes, (long)seconds];
}

//销毁定时器
- (void)destoryTimer
{
    if (self.timer)
    {
        [self.timer invalidate];//使其无效
        self.timer = nil;//置空
        NSLog(@"----- timer destory");
    }
}
@end
 类似资料: