123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- //
- // YOUPAILZSoundRecordView.m
- // MSYOUPAI
- //
- // Created by CY on 2022/3/16.
- // Copyright © 2022 MS. All rights reserved.
- //
- #import "YOUPAILZSoundRecordView.h"
- #import "NSURL+TransferFileFormat.h"
- #import "LZCircleView.h"
- @interface YOUPAILZSoundRecordView ()<AVAudioPlayerDelegate,AVAudioRecorderDelegate>
- @property (nonatomic, weak)UILabel *youpaiptimeL;
- @property (nonatomic, weak)LZCircleView *youpaipcircleView;
- /// 录制
- @property (nonatomic, strong)AVAudioRecorder *youpaiprecorder;
- @property (nonatomic, strong)NSURL *youpaiprecordAudioUrl;
- /// 播放
- @property (nonatomic, strong)AVAudioPlayer *youpaipaudioPlayer;
- @property (nonatomic,strong)NSTimer *youpaiptimer;
- @property (nonatomic,assign)NSInteger youpaipplayTime;
- @property (nonatomic,assign) LZSoundRecordState youpaipstate;
- @end
- @implementation YOUPAILZSoundRecordView
- - (instancetype)initWithFrame:(CGRect)frame{
- if (self = [super initWithFrame:frame]) {
- [self youpaifinitValue];
- [self youpaifsetupUI];
- self.youpaipstate = LZSoundRecordStateNone;
- }
- return self;
- }
- - (void)youpaifinitValue{
- self.youpaipminTimer = 2;
- self.youpaipmaxTimer = 8;
- self.youpaiptype = LZAudioTypeWithPM3;
- }
- - (void)youpaifsetupUI{
-
- UILabel *timeL = [[UILabel alloc] init];
- timeL.font = LCFont12;
- timeL.textColor = LZ273145Color;
- timeL.text = @"0s";
- [self addSubview:timeL];
- self.youpaiptimeL = timeL;
- [timeL mas_makeConstraints:^(MASConstraintMaker *make) {
- make.centerX.equalTo(self);
- make.top.offset(-10.0f);
- }];
-
- LZCircleView *circleView = [[LZCircleView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 74.0f, 74.0f)];
- circleView.progress = 0.0f;
- circleView.progerssColor = HexColorFromRGB(0xFDD45E);
- circleView.progerssBackgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.13f];
- circleView.progerWidth = 2.5f;
- circleView.backgroundProgerWidth = 1.0f;
- circleView.hidden = YES;
- [self addSubview:circleView];
- self.youpaipcircleView = circleView;
- [circleView mas_makeConstraints:^(MASConstraintMaker *make) {
- make.centerX.equalTo(self);
- make.top.equalTo(timeL.mas_bottom).offset(14.0f);
- make.size.mas_offset(CGSizeMake(74.0f, 74.0f));
- }];
-
- UIButton *centerBtn = [UIButton buttonWithType:UIButtonTypeCustom];
- [centerBtn addTarget:self action:@selector(youpaifcenterBtnClick) forControlEvents:UIControlEventTouchUpInside];
- [self addSubview:centerBtn];
- self.youpaiprecordBtn = centerBtn;
- [centerBtn mas_makeConstraints:^(MASConstraintMaker *make) {
- make.center.equalTo(circleView);
- make.size.mas_offset(CGSizeMake(65.0f, 65.0f));
- }];
-
-
-
- UILabel *descL = [[UILabel alloc] init];
- descL.font = LCFont12;
- descL.textColor = LZA3AABEColor;
- descL.text = [NSString stringWithFormat:@"录制一段%@~%@秒的语音",@(self.youpaipminTimer),@(self.youpaipmaxTimer)];
- [self addSubview:descL];
- self.youpaipdescL = descL;
- [descL mas_makeConstraints:^(MASConstraintMaker *make) {
- make.centerX.equalTo(self);
- make.top.equalTo(centerBtn.mas_bottom).offset(15.0f);
- }];
-
- UIButton *leftBtn = [UIButton buttonWithType:UIButtonTypeCustom];
- [leftBtn addTarget:self action:@selector(youpaifleftBtnClick) forControlEvents:UIControlEventTouchUpInside];
- leftBtn.titleLabel.font = LCFont16;
- leftBtn.backgroundColor = LZF5F4F7Color;
- leftBtn.layer.cornerRadius = 24.0f;
- leftBtn.clipsToBounds = YES;
- [leftBtn setTitleColor:LZ273145Color forState:UIControlStateNormal];
- [leftBtn setTitle:@"重录" forState:UIControlStateNormal];
- leftBtn.hidden = YES;
- [self addSubview:leftBtn];
- self.youpaipreRecordBtn = leftBtn;
- [leftBtn mas_makeConstraints:^(MASConstraintMaker *make) {
- make.top.equalTo(descL.mas_bottom).offset(20.0f);
- make.size.mas_offset(CGSizeMake(135.0f, 48.0f));
- make.centerX.equalTo(self);
- }];
-
-
- }
- - (void)youpaifleftBtnClick{
- [self youpaifstopTimer];
- self.youpaipstate = LZSoundRecordStateNone;
-
- self.youpaiprecordAudioUrl = nil;
- self.youpaiprecorder = nil;
- // 停止播放
- [self.youpaipaudioPlayer stop];
- self.youpaipaudioPlayer = nil;
- }
- - (void)youpaifcenterBtnClick{
- if(self.youpaipstate == LZSoundRecordStateNone){
- self.youpaipstate = LZSoundRecordStateStart;
-
- //创建录音通道
- [self setAudioSession];
- // 开始录音
- [self.youpaiprecorder record];
- // 检查权限
- [self youpaifsetupAuthority];
- self.youpaipaudioTime = 0;
- [self youpaifstartTimer];
-
- }else if(self.youpaipstate == LZSoundRecordStateFinish){
- self.youpaipstate = LZSoundRecordStatePlay;
-
- // UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
- // AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);
- UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
- AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
-
- AVAudioSession * session = [AVAudioSession sharedInstance];
- [session setActive:YES error:nil];
- [session setCategory:AVAudioSessionCategoryPlayback error:nil];
-
- NSError *error;
- self.youpaipaudioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:self.youpaiprecordAudioUrl error:&error];
- if (error) {
- NSLog(@"%@",error);
- }
- self.youpaipaudioPlayer.delegate = self;
- // 播放
- [self.youpaipaudioPlayer play];
- self.youpaipplayTime = self.youpaipaudioTime;
- [self youpaifstartTimer];
- }else if (self.youpaipstate == LZSoundRecordStatePlay){
- self.youpaipstate = LZSoundRecordStateFinish;
- // 停止播放
- [self.youpaipaudioPlayer stop];
- self.youpaipaudioPlayer = nil;
- [self youpaifstopTimer];
- }else if (self.youpaipstate == LZSoundRecordStateStart){
- self.youpaipstate = LZSoundRecordStateFinish;
- // 停止录制
- [self.youpaiprecorder stop];
- self.youpaiprecorder = nil;
- [self youpaifstopTimer];
- if (self.youpaipaudioTime < self.youpaipminTimer) {
- [ZCHUDHelper showTitle:[NSString stringWithFormat:@"录音不可少于%@秒",@(self.youpaipminTimer)]];
- [self youpaifleftBtnClick];
- }
- }
- }
- - (NSURL*)getSubmitSound{
-
- [self youpaifstopTimer];
- // 停止播放
- [self.youpaipaudioPlayer stop];
- if (_youpaipstate < LZSoundRecordStateFinish){
- return nil;
- }
- NSURL *returnurl = nil;
- switch (self.youpaiptype) {
- case LZAudioTypeWithPM3:
- returnurl = [self.youpaiprecordAudioUrl transformCAFToMP3];
- break;
- case LZAudioTypeWithAAC:{
- returnurl = self.youpaiprecordAudioUrl;
- }
- break;
- default:
- break;
- }
-
- return returnurl;
- }
- - (void)setYoupaipstate:(LZSoundRecordState)state{
- _youpaipstate = state;
-
- NSString *time = @"";
- NSString *desc = @"";
- self.youpaipreRecordBtn.hidden = YES;
- // self.youpaiprightBtn.hidden = YES;
- self.youpaipcircleView.hidden = YES;
- self.youpaipcircleView.progress = 0.0f;
- UIImage *centerImg = nil;
- // UIImage *leftImg = nil;
- // UIImage *rightImg = nil;
-
- switch (state) {
- case LZSoundRecordStateNone:{
- time = @"0s";
- desc = [NSString stringWithFormat:@"录制一段%@~%@秒的语音",@(self.youpaipminTimer),@(self.youpaipmaxTimer)];
- centerImg = [UIImage imageNamed:@"vqu_images_big_cast_audio_none"];
- }
- break;
- case LZSoundRecordStateStart:{
- time = @"0s";
- desc = @"点击结束录音";
- centerImg = [UIImage imageNamed:@"vqu_images_big_cast_audio_start"];
- self.youpaipcircleView.hidden = NO;
- [self youpaifprogressAnimation];
- }
- break;
- case LZSoundRecordStateFinish:{
- time = [NSString stringWithFormat:@"%@s",@(self.youpaipaudioTime)];
- desc = @"点击试听";
- centerImg = [UIImage imageNamed:@"vqu_images_big_cast_audio_finish"];
- self.youpaipreRecordBtn.hidden = NO;
- // leftImg = [UIImage imageNamed:@"vqu_images_big_case_audio_re_record"];
- // rightImg = [UIImage imageNamed:@"vqu_images_big_cast_audio_submit"];
-
- // self.youpaipleftBtn.hidden = NO;
- // self.youpaiprightBtn.hidden = NO;
- // [self.youpaipleftBtn setTitle:@"重录" forState:UIControlStateNormal];
- // [self.youpaiprightBtn setTitle:@"确定" forState:UIControlStateNormal];
- }
- break;
- case LZSoundRecordStatePlay:{
- time = [NSString stringWithFormat:@"%@s",@(self.youpaipaudioTime)];
- desc = @"播放中";
- centerImg = [UIImage imageNamed:@"vqu_images_big_cast_audio_play1"];
- self.youpaipreRecordBtn.hidden = NO;
- }
- break;
- case LZSoundRecordStateSubmit:{
- // time = [self timeFormatted:self.audioTime];
- // desc = @"已录制";
- // centerImg = [UIImage imageNamed:@"vqu_images_game_audio_success"];
- }
- break;
- default:
- break;
- }
- self.youpaiptimeL.text = time;
- self.youpaipdescL.text = desc;
- // [self.youpaipleftBtn setImage:leftImg forState:UIControlStateNormal];
- // [self.youpaiprightBtn setImage:rightImg forState:UIControlStateNormal];
- [self.youpaiprecordBtn setBackgroundImage:centerImg forState:UIControlStateNormal];
- // [self youpaifinitButton:self.youpaipleftBtn];
- // [self youpaifinitButton:self.youpaiprightBtn];
- }
- #pragma mark - AVAudioPlayerDelegate
- - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
- self.youpaipstate = LZSoundRecordStateFinish;
- // 停止播放
- [self.youpaipaudioPlayer stop];
- self.youpaipaudioPlayer = nil;
- [self youpaifstopTimer];
- }
- - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error{
- self.youpaipstate = LZSoundRecordStateFinish;
- // 停止播放
- [self.youpaipaudioPlayer stop];
- self.youpaipaudioPlayer = nil;
- [self youpaifstopTimer];
- }
- - (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player{
- self.youpaipstate = LZSoundRecordStateFinish;
- // 停止播放
- [self.youpaipaudioPlayer stop];
- self.youpaipaudioPlayer = nil;
- [self youpaifstopTimer];
- }
- #pragma mark - AVAudioRecorderDelegate
- - (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError * _Nullable)error{
- self.youpaipstate = LZSoundRecordStateFinish;
- // 停止录制
- [self.youpaiprecorder stop];
- self.youpaiprecorder = nil;
- [self youpaifstopTimer];
- }
- - (void)audioRecorderBeginInterruption:(AVAudioRecorder *)recorder{
- self.youpaipstate = LZSoundRecordStateFinish;
- // 停止录制
- [self.youpaiprecorder stop];
- self.youpaiprecorder = nil;
- [self youpaifstopTimer];
- }
- // 开始计时
- - (void)youpaifstartTimer{
- self.youpaiptimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(youpaiftimerAction) userInfo:nil repeats:YES];
- [[NSRunLoop currentRunLoop] addTimer:self.youpaiptimer forMode:NSRunLoopCommonModes];
- }
- // 结束计时
- - (void)youpaifstopTimer{
- [self.youpaiptimer invalidate];
- self.youpaiptimer = nil;
- self.youpaiptimeL.text = [NSString stringWithFormat:@"%@s",@(self.youpaipaudioTime)];
- }
- - (void)youpaifprogressAnimation{
- __block CGFloat timeout = 0.0f;
- dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
- dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
- dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, 0.025f * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
- //3.设置定时器要执行的任务
- dispatch_source_set_event_handler(_timer, ^{
- if(timeout >= 1.0f){
- dispatch_source_cancel(_timer);
- dispatch_async(dispatch_get_main_queue(), ^{
-
- });
- }else{
- timeout += 0.025f;
- CGFloat currentTime = (CGFloat)self.youpaipaudioTime + timeout;
- dispatch_async(dispatch_get_main_queue(), ^{
- self.youpaipcircleView.progress = currentTime / (CGFloat)self.youpaipmaxTimer;
- });
- }
- });
- dispatch_resume(_timer);
- }
- - (void)youpaiftimerAction{
- if (self.youpaipstate == LZSoundRecordStateStart) {
- self.youpaipaudioTime ++;
- self.youpaiptimeL.text = [NSString stringWithFormat:@"%@s",@(self.youpaipaudioTime)];
- [self youpaifprogressAnimation];
- if (self.youpaipaudioTime >= self.youpaipmaxTimer) {
- self.youpaipstate = LZSoundRecordStateFinish;
- // 停止录制
- [self.youpaiprecorder stop];
- self.youpaiprecorder = nil;
- [self youpaifstopTimer];
- }
- }else if (self.youpaipstate == LZSoundRecordStatePlay){
- self.youpaipplayTime --;
- self.youpaiptimeL.text = [NSString stringWithFormat:@"%@s",@(self.youpaipplayTime)];
- }
-
-
- }
- //- (NSString *)timeFormatted:(NSInteger)totalSeconds{
- // NSInteger seconds = totalSeconds % 60;
- // NSInteger minutes = (totalSeconds / 60);
- // return [NSString stringWithFormat:@"%02ld:%02ld", minutes, seconds];
- //}
- /// 视频本地url路径
- - (NSURL *)youpaiprecordAudioUrl{
- if (!_youpaiprecordAudioUrl) {
- NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) lastObject];
- NSString *fileName;
- if (self.youpaiptype == LZAudioTypeWithAAC) {
- fileName = @"audioVerify.aac";
- }else{
- fileName = @"audioVerify.caf";
- }
- _youpaiprecordAudioUrl = [NSURL fileURLWithPath:[path stringByAppendingPathComponent:fileName]];
- if ([[NSFileManager defaultManager] fileExistsAtPath:_youpaiprecordAudioUrl.resourceSpecifier]){
- [[NSFileManager defaultManager] removeItemAtPath:_youpaiprecordAudioUrl.resourceSpecifier error:nil];
- }
- }
- return _youpaiprecordAudioUrl;
- }
- - (AVAudioRecorder *)youpaiprecorder{
- if (_youpaiprecorder == nil) {
- //创建录音机
- NSError *error=nil;
- _youpaiprecorder = [[AVAudioRecorder alloc] initWithURL:self.youpaiprecordAudioUrl settings:[self getAudioSetting] error:&error];
- _youpaiprecorder.delegate = self;
- if (error) {
- NSLog(@"创建录音机对象时发生错误,错误信息:%@",error.localizedDescription);
- return nil;
- }
- }
- return _youpaiprecorder;
- }
- /**
- * 取得录音文件设置
- *
- * @return 录音设置
- */
- -(NSDictionary *)getAudioSetting{
- if (self.youpaiptype == LZAudioTypeWithAAC) {
- NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc]init] ;
- //设置录音格式 AVFormatIDKey==kAudioFormatLinearPCM
- [recordSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
- //设置录音采样率(Hz) 如:AVSampleRateKey==8000/44100/96000(影响音频的质量)
- [recordSetting setValue:[NSNumber numberWithFloat:44100] forKey:AVSampleRateKey];
- //录音通道数 1 或 2
- [recordSetting setValue:[NSNumber numberWithInt:1] forKey:AVNumberOfChannelsKey];
- //线性采样位数 8、16、24、32
- [recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
- //录音的质量
- [recordSetting setValue:[NSNumber numberWithInt:AVAudioQualityMedium] forKey:AVEncoderAudioQualityKey];
- return recordSetting.copy;
- }else{
- NSDictionary *recordSetting = @{
- AVFormatIDKey : @(kAudioFormatLinearPCM),
- AVSampleRateKey : @(44100),
- AVNumberOfChannelsKey : @(2),
- AVLinearPCMBitDepthKey : @(16),
- AVLinearPCMIsNonInterleaved : @NO,
- AVLinearPCMIsFloatKey : @NO,
- AVLinearPCMIsBigEndianKey : @NO,
- };
-
- return recordSetting;
- }
-
- }
- /// 权限
- - (void)youpaifsetupAuthority{
- [UCAuthorityManager microPhoneAuthority:^{
-
- } denied:^{
- [self youpaifshowAlertVCWithTitle:@"请在iphone的“设置-隐私-麦克风”选项中,允许APP访问您的麦克风。"];
- }];
- }
- - (void)youpaifshowAlertVCWithTitle:(NSString *)title{
- UIAlertController *systemAlert = [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleAlert];
- UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"现在去设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action){
- if ([[UIDevice currentDevice].systemVersion floatValue] < 10.0)
- {
- [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
-
- }
- else
- {
- // 去系统设置页面
- if (@available(iOS 10.0, *)) {
- [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
- } else {
- // Fallback on earlier versions
- }
- }
- }];
- UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
- [systemAlert addAction:cancelAction];
- [systemAlert addAction:action];
- dispatch_async(dispatch_get_main_queue(), ^{
- [[LCTools getCurrentVC] presentViewController: systemAlert animated: YES completion: nil];
- });
- }
- - (void)setAudioSession{
- 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];
- }
- }
- - (void)youpaifstopSoundRecord{
- [self youpaifstopTimer];
- self.youpaiprecordAudioUrl = nil;
- self.youpaiprecorder = nil;
- // 停止播放
- [self.youpaipaudioPlayer stop];
- self.youpaipaudioPlayer = nil;
- }
- - (void)dealloc{
- [self youpaifstopSoundRecord];
- }
- @end
|