zjf
2023-03-06 392b76515f40376b6d36f40a114850ef63650384
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
//
//  PBRecordingView.m
//  IphoneBIMe
//
//  Created by zjf on 2019/1/3.
//  Copyright © 2019 ProBIM. All rights reserved.
//
 
#import "PBRecordingView.h"
#import <AVFoundation/AVFoundation.h>
#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