// // PBRecordingView.m // IphoneBIMe // // Created by zjf on 2019/1/3. // Copyright © 2019 ProBIM. All rights reserved. // #import "PBRecordingView.h" #import #import "ConvertAudioFile.h" #define ETRECORD_RATE 11025.0 @interface PBRecordingView() //时间记录 @property (nonatomic, strong) UILabel *timeL; //录音机 @property (nonatomic, strong) AVAudioRecorder *recorder; //每秒60次 @property (nonatomic, strong) CADisplayLink *displayLink; //录音计数 @property (nonatomic, assign) NSInteger recordingTimer; @property (nonatomic, assign) NSInteger totalTime; //录音路径 @property (nonatomic, copy) NSString *recordingCafPath; //记录右侧按钮状态 @property (nonatomic, assign) BOOL isComplete; @end @implementation PBRecordingView - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { [self setupUI]; } return self; } - (void)setupUI { self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.3]; UIView *toolsView = [[UIView alloc] init]; toolsView.backgroundColor = [UIColor whiteColor]; toolsView.layer.cornerRadius = 10.0f; [toolsView.layer setMasksToBounds:YES]; [self addSubview:toolsView]; [toolsView mas_makeConstraints:^(MASConstraintMaker *make) { make.center.equalTo(self); make.size.mas_equalTo(CGSizeMake(317, 166)); }]; UILabel *promptL = [UILabel z_labelWithText:@"提示:仅可上传一条语音,最多60秒" Color:TitleColor isBold:NO Font:14]; [self addSubview:promptL]; [promptL mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(toolsView).offset(20); make.centerX.equalTo(toolsView); make.height.equalTo(@20); }]; UILabel *countdownL = [UILabel z_labelWithText:@"倒计时" Color:TitleColor isBold:NO Font:16]; [self addSubview:countdownL]; [countdownL mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(toolsView).offset(98); make.top.equalTo(toolsView).offset(72); make.size.mas_equalTo(CGSizeMake(57, 22)); }]; self.timeL = [UILabel z_labelWithText:@"60 S" Color:TitleColor isBold:YES Font:20]; [self addSubview:self.timeL]; [self.timeL mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(countdownL); make.left.equalTo(countdownL.mas_right).offset(20); make.height.equalTo(@28); }]; UIView *linView = [[UIView alloc] init]; linView.backgroundColor = PBColor(208, 211, 218); [self addSubview:linView]; [linView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(toolsView).offset(115); make.left.right.equalTo(toolsView); make.height.equalTo(@1); }]; UIView *lin2View = [[UIView alloc] init]; lin2View.backgroundColor = PBColor(208, 211, 218); [self addSubview:lin2View]; [lin2View mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(linView.mas_bottom); make.bottom.equalTo(toolsView); make.centerX.equalTo(toolsView); make.width.equalTo(@1); }]; UIButton *cancelBtn = [UIButton z_textButton:@"取消" fontSize:20 normalColor:IndicatedColor]; [cancelBtn addTarget:self action:@selector(cancelInterAction) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:cancelBtn]; [cancelBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(linView.mas_bottom); make.left.bottom.equalTo(toolsView); make.right.equalTo(lin2View.mas_left); }]; UIButton *endBtn = [UIButton z_textButton:@"开始" fontSize:20 normalColor:IndicatedColor]; [endBtn addTarget:self action:@selector(endAction:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:endBtn]; [endBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(linView.mas_bottom); make.right.bottom.equalTo(toolsView); make.left.equalTo(lin2View.mas_right); }]; } //定时器 - (void)updateMeters{ self.recordingTimer ++; NSInteger seconds = self.recordingTimer / 60; NSInteger countdown = self.totalTime - seconds; if (countdown == 0) { [self.recorder stop]; [self.displayLink invalidate]; [self cleanCafFile]; if (self.endRecordingBlock) { NSString *mp3Path = [_recordingCafPath stringByReplacingOccurrencesOfString:@"caf" withString:@"mp3"]; self.endRecordingBlock([mp3Path lastPathComponent]); } [self removeFromSuperview]; } self.timeL.text = [NSString stringWithFormat:@"%zd S",countdown]; } - (void)cleanCafFile { NSFileManager *fileManager=[NSFileManager defaultManager]; BOOL isDir = FALSE; BOOL isDirExist = [fileManager fileExistsAtPath:_recordingCafPath isDirectory:&isDir]; if (isDirExist) { [fileManager removeItemAtPath:_recordingCafPath error:nil]; } } - (void)cleanMp3File { NSString *recordingMp3Path = [_recordingCafPath stringByReplacingOccurrencesOfString:@"caf" withString:@"mp3"]; NSFileManager *fileManager=[NSFileManager defaultManager]; BOOL isDir = FALSE; BOOL isDirExist = [fileManager fileExistsAtPath:recordingMp3Path isDirectory:&isDir]; if (isDirExist) { [fileManager removeItemAtPath:recordingMp3Path error:nil]; } } //取消录音 - (void)cancelInterAction { if (self.isComplete) { [self.recorder stop]; [self.displayLink invalidate]; [self cleanCafFile]; [self cleanMp3File]; } [self removeFromSuperview]; } // 开始/完成录音 - (void)endAction:(UIButton *)button { if (self.isComplete) { [self.recorder stop]; [[ConvertAudioFile sharedInstance] sendEndRecord]; [self.displayLink invalidate]; [self cleanCafFile]; if (self.endRecordingBlock) { NSString *mp3Path = [_recordingCafPath stringByReplacingOccurrencesOfString:@"caf" withString:@"mp3"]; self.endRecordingBlock([mp3Path lastPathComponent]); } [self removeFromSuperview]; }else { [button setTitle:@"完成" forState:UIControlStateNormal]; self.totalTime = 60; AVAudioSession *audioSession = [AVAudioSession sharedInstance]; [audioSession setCategory:AVAudioSessionCategoryRecord error:nil]; [self.recorder record]; //转换MP3格式 [[ConvertAudioFile sharedInstance] conventToMp3WithCafFilePath:_recordingCafPath mp3FilePath:[_recordingCafPath stringByReplacingOccurrencesOfString:@"caf" withString:@"mp3"] sampleRate:ETRECORD_RATE]; self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateMeters)]; [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; self.isComplete = YES; } } #pragma mark - 懒加载 - (AVAudioRecorder *)recorder { if (_recorder == nil) { NSDateFormatter * formatter = [[NSDateFormatter alloc ] init]; [formatter setDateFormat:@"YYYYMMddHHmmssSSS"]; NSString *date = [formatter stringFromDate:[NSDate date]]; NSString *recordingName = [NSString stringWithFormat:@"%@.caf",date]; AVAudioSession *session = [AVAudioSession sharedInstance]; NSError *sessionError; [session setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError]; if(session == nil) { NSLog(@"Error creating session: %@", [sessionError description]); } else { [session setActive:YES error:nil]; } //设置录音输出路径 _recordingCafPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject stringByAppendingPathComponent:recordingName]; NSLog(@"=======%@", _recordingCafPath); // 2.录音参数设置 NSMutableDictionary *settingDictM = [NSMutableDictionary dictionary]; [settingDictM setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey]; [settingDictM setObject:@(ETRECORD_RATE) forKey:AVSampleRateKey]; [settingDictM setObject:@(2) forKey:AVNumberOfChannelsKey]; [settingDictM setObject:@(16) forKey:AVLinearPCMBitDepthKey]; [settingDictM setObject:[NSNumber numberWithInt:AVAudioQualityMin] forKey:AVEncoderAudioQualityKey]; //创建录音机 NSError *error=nil; _recorder = [[AVAudioRecorder alloc]initWithURL:[NSURL fileURLWithPath:_recordingCafPath] settings:settingDictM error:&error]; // _recorder.delegate = self; _recorder.meteringEnabled = YES;//如果要监控声波则必须设置为YES [_recorder prepareToRecord]; if (error) { NSLog(@"创建录音机对象时发生错误,错误信息:%@",error.localizedDescription); return nil; } } return _recorder; } /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } */ @end