YOUPAILZRecordAudioView.m 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. //
  2. // YOUPAILZRecordAudioView.m
  3. // VQU
  4. //
  5. // Created by CY on 2021/4/26.
  6. // Copyright © 2021 leo. All rights reserved.
  7. //
  8. #import "YOUPAILZRecordAudioView.h"
  9. #import "NSURL+TransferFileFormat.h"
  10. #import "YOUPAILZGameModel.h"
  11. @interface YOUPAILZRecordAudioView() <AVAudioPlayerDelegate,AVAudioRecorderDelegate>
  12. @property (nonatomic, weak)UILabel *youpaiptimeL;
  13. @property (nonatomic, weak)UIButton *youpaipleftBtn;
  14. @property (nonatomic, weak)UIButton *youpaipcenterBtn;
  15. @property (nonatomic, weak)UIButton *youpaiprightBtn;
  16. /// 录制
  17. @property (nonatomic, strong)AVAudioRecorder *youpaiprecorder;
  18. @property (nonatomic, strong)NSURL *youpaiprecordAudioUrl;
  19. /// 播放
  20. @property (nonatomic, strong)AVAudioPlayer *youpaipaudioPlayer;
  21. @property (nonatomic, weak)UILabel *youpaipdescL;
  22. @property (nonatomic,strong)NSTimer *youpaiptimer;
  23. @property (nonatomic,assign)NSInteger youpaipaudioTime;
  24. @property (nonatomic,assign)NSInteger youpaipplayTime;
  25. @property (nonatomic,strong)YOUPAILZGameModel *youpaipgameModel;
  26. @end
  27. @implementation YOUPAILZRecordAudioView
  28. - (instancetype)initWithFrame:(CGRect)frame model:(YOUPAILZGameModel *)model{
  29. if (self = [super initWithFrame:frame]) {
  30. self.youpaipgameModel = model;
  31. [self youpaifsetupUI];
  32. self.youpaipstate = LZCaptrueAudioStateNone;
  33. }
  34. return self;
  35. }
  36. - (void)youpaifsetupUI{
  37. UIButton *centerBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  38. [centerBtn addTarget:self action:@selector(youpaifcenterBtnClick) forControlEvents:UIControlEventTouchUpInside];
  39. [self addSubview:centerBtn];
  40. self.youpaipcenterBtn = centerBtn;
  41. [centerBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  42. make.center.equalTo(self);
  43. make.size.mas_offset(CGSizeMake(65.0f, 65.0f));
  44. }];
  45. UILabel *timeL = [[UILabel alloc] init];
  46. timeL.font = LCFont15;
  47. timeL.textColor = HexColorFromRGB(0x999999);
  48. timeL.text = @"00:00";
  49. [self addSubview:timeL];
  50. self.youpaiptimeL = timeL;
  51. [timeL mas_makeConstraints:^(MASConstraintMaker *make) {
  52. make.centerX.equalTo(centerBtn.mas_centerX);
  53. make.bottom.equalTo(centerBtn.mas_top).offset(-15.0f);
  54. }];
  55. UILabel *descL = [[UILabel alloc] init];
  56. descL.font = LCFont15;
  57. descL.textColor = HexColorFromRGB(0x999999);
  58. descL.text = @"点击录音";
  59. [self addSubview:descL];
  60. self.youpaipdescL = descL;
  61. [descL mas_makeConstraints:^(MASConstraintMaker *make) {
  62. make.centerX.equalTo(centerBtn.mas_centerX);
  63. make.top.equalTo(centerBtn.mas_bottom).offset(15.0f);
  64. }];
  65. UIButton *leftBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  66. [leftBtn addTarget:self action:@selector(youpaifleftBtnClick) forControlEvents:UIControlEventTouchUpInside];
  67. [self addSubview:leftBtn];
  68. self.youpaipleftBtn = leftBtn;
  69. [leftBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  70. make.centerY.equalTo(centerBtn.mas_centerY);
  71. make.size.mas_offset(CGSizeMake(50.0f, 50.0f));
  72. make.right.equalTo(centerBtn.mas_left).offset(-44.0f);
  73. }];
  74. UIButton *rightBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  75. [rightBtn addTarget:self action:@selector(youpaifrightBtnClick) forControlEvents:UIControlEventTouchUpInside];
  76. [self addSubview:rightBtn];
  77. self.youpaiprightBtn = rightBtn;
  78. [rightBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  79. make.centerY.equalTo(centerBtn.mas_centerY);
  80. make.size.mas_offset(CGSizeMake(50.0f, 50.0f));
  81. make.left.equalTo(centerBtn.mas_right).offset(44.0f);
  82. }];
  83. }
  84. - (void)youpaifleftBtnClick{
  85. [self youpaifstopTimer];
  86. self.youpaipstate = LZCaptrueAudioStateNone;
  87. self.youpaiprecordAudioUrl = nil;
  88. self.youpaiprecorder = nil;
  89. // 停止播放
  90. [self.youpaipaudioPlayer stop];
  91. self.youpaipaudioPlayer = nil;
  92. }
  93. - (void)youpaifcenterBtnClick{
  94. if(self.youpaipstate == LZCaptrueAudioStateNone){
  95. self.youpaipstate = LZCaptrueAudioStateStart;
  96. //创建录音通道
  97. [self setAudioSession];
  98. // 开始录音
  99. [self.youpaiprecorder record];
  100. // 检查权限
  101. [self youpaifsetupAuthority];
  102. self.youpaipaudioTime = 0;
  103. [self youpaifstartTimer];
  104. }else if(self.youpaipstate == LZCaptrueAudioStateFinish){
  105. self.youpaipstate = LZCaptrueAudioStatePlay;
  106. // UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
  107. // AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory);
  108. UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
  109. AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
  110. AVAudioSession * session = [AVAudioSession sharedInstance];
  111. [session setActive:YES error:nil];
  112. [session setCategory:AVAudioSessionCategoryPlayback error:nil];
  113. NSError *error;
  114. self.youpaipaudioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:self.youpaiprecordAudioUrl error:&error];
  115. if (error) {
  116. NSLog(@"%@",error);
  117. }
  118. self.youpaipaudioPlayer.delegate = self;
  119. // 播放
  120. [self.youpaipaudioPlayer play];
  121. self.youpaipplayTime = self.youpaipaudioTime;
  122. [self youpaifstartTimer];
  123. }else if (self.youpaipstate == LZCaptrueAudioStatePlay){
  124. self.youpaipstate = LZCaptrueAudioStateFinish;
  125. // 停止播放
  126. [self.youpaipaudioPlayer stop];
  127. self.youpaipaudioPlayer = nil;
  128. [self youpaifstopTimer];
  129. }else if (self.youpaipstate == LZCaptrueAudioStateStart){
  130. self.youpaipstate = LZCaptrueAudioStateFinish;
  131. // 停止录制
  132. [self.youpaiprecorder stop];
  133. self.youpaiprecorder = nil;
  134. [self youpaifstopTimer];
  135. }
  136. }
  137. - (void)youpaifrightBtnClick{
  138. self.youpaipstate = LZCaptrueAudioStateSubmit;
  139. [self youpaifstopTimer];
  140. // 停止播放
  141. [self.youpaipaudioPlayer stop];
  142. self.youpaipaudioPlayer = nil;
  143. self.youpaipgameModel.youpaipaudioUrl = [self.youpaiprecordAudioUrl transformCAFToMP3];
  144. self.youpaipgameModel.youpaipaudioDuration = self.youpaipaudioTime;
  145. self.youpaiprecorder = nil;
  146. self.youpaiprecordAudioUrl = nil;
  147. }
  148. - (void)setYoupaipstate:(LZCaptrueAudioState)state{
  149. _youpaipstate = state;
  150. NSString *time = @"";
  151. NSString *desc = @"";
  152. self.youpaipleftBtn.hidden = YES;
  153. self.youpaiprightBtn.hidden = YES;
  154. UIImage *centerImg = nil;
  155. UIImage *leftImg = nil;
  156. UIImage *rightImg = nil;
  157. switch (state) {
  158. case LZCaptrueAudioStateNone:{
  159. time = @"00:00";
  160. desc = @"点击录音";
  161. centerImg = [UIImage imageNamed:@"vqu_images_H_game_audio_none1"];
  162. }
  163. break;
  164. case LZCaptrueAudioStateStart:{
  165. time = @"00:00";
  166. desc = @"点击结束录音";
  167. centerImg = [UIImage imageNamed:@"vqu_images_game_audio_start"];
  168. }
  169. break;
  170. case LZCaptrueAudioStateFinish:{
  171. time = [self youpaiftimeFormatted:self.youpaipaudioTime];
  172. desc = @"点击试听";
  173. centerImg = [UIImage imageNamed:@"vqu_images_game_audio_finish"];
  174. leftImg = [UIImage imageNamed:@"vqu_images_game_audio_re_record"];
  175. rightImg = [UIImage imageNamed:@"vqu_images_game_audio_submit"];
  176. self.youpaipleftBtn.hidden = NO;
  177. self.youpaiprightBtn.hidden = NO;
  178. }
  179. break;
  180. case LZCaptrueAudioStatePlay:{
  181. time = [self youpaiftimeFormatted:self.youpaipaudioTime];
  182. desc = @"播放中";
  183. centerImg = [UIImage imageNamed:@"vqu_images_H_game_audio_play1"];
  184. leftImg = [UIImage imageNamed:@"vqu_images_game_audio_re_record"];
  185. rightImg = [UIImage imageNamed:@"vqu_images_game_audio_submit"];
  186. self.youpaipleftBtn.hidden = NO;
  187. self.youpaiprightBtn.hidden = NO;
  188. }
  189. break;
  190. case LZCaptrueAudioStateSubmit:{
  191. time = [self youpaiftimeFormatted:self.youpaipaudioTime];
  192. desc = @"已录制";
  193. centerImg = [UIImage imageNamed:@"vqu_images_game_audio_success"];
  194. }
  195. break;
  196. default:
  197. break;
  198. }
  199. self.youpaiptimeL.text = time;
  200. self.youpaipdescL.text = desc;
  201. [self.youpaipleftBtn setBackgroundImage:leftImg forState:UIControlStateNormal];
  202. [self.youpaiprightBtn setBackgroundImage:rightImg forState:UIControlStateNormal];
  203. [self.youpaipcenterBtn setBackgroundImage:centerImg forState:UIControlStateNormal];
  204. }
  205. #pragma mark - AVAudioPlayerDelegate
  206. - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
  207. self.youpaipstate = LZCaptrueAudioStateFinish;
  208. // 停止播放
  209. [self.youpaipaudioPlayer stop];
  210. self.youpaipaudioPlayer = nil;
  211. [self youpaifstopTimer];
  212. }
  213. - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error{
  214. self.youpaipstate = LZCaptrueAudioStateFinish;
  215. // 停止播放
  216. [self.youpaipaudioPlayer stop];
  217. self.youpaipaudioPlayer = nil;
  218. [self youpaifstopTimer];
  219. }
  220. - (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player{
  221. self.youpaipstate = LZCaptrueAudioStateFinish;
  222. // 停止播放
  223. [self.youpaipaudioPlayer stop];
  224. self.youpaipaudioPlayer = nil;
  225. [self youpaifstopTimer];
  226. }
  227. #pragma mark - AVAudioRecorderDelegate
  228. - (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError * _Nullable)error{
  229. self.youpaipstate = LZCaptrueAudioStateFinish;
  230. // 停止录制
  231. [self.youpaiprecorder stop];
  232. self.youpaiprecorder = nil;
  233. [self youpaifstopTimer];
  234. }
  235. - (void)audioRecorderBeginInterruption:(AVAudioRecorder *)recorder{
  236. self.youpaipstate = LZCaptrueAudioStateFinish;
  237. // 停止录制
  238. [self.youpaiprecorder stop];
  239. self.youpaiprecorder = nil;
  240. [self youpaifstopTimer];
  241. }
  242. // 开始计时
  243. - (void)youpaifstartTimer{
  244. self.youpaiptimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(youpaiftimerAction) userInfo:nil repeats:YES];
  245. [[NSRunLoop currentRunLoop] addTimer:self.youpaiptimer forMode:NSRunLoopCommonModes];
  246. }
  247. // 结束计时
  248. - (void)youpaifstopTimer{
  249. [self.youpaiptimer invalidate];
  250. self.youpaiptimer = nil;
  251. self.youpaiptimeL.text = [self youpaiftimeFormatted:self.youpaipaudioTime];
  252. }
  253. - (void)youpaiftimerAction{
  254. if (self.youpaipstate == LZCaptrueAudioStateStart) {
  255. self.youpaipaudioTime ++;
  256. self.youpaiptimeL.text = [self youpaiftimeFormatted:self.youpaipaudioTime];
  257. if (self.youpaipaudioTime >= kAudioMaxDuration) {
  258. self.youpaipstate = LZCaptrueAudioStateFinish;
  259. // 停止录制
  260. [self.youpaiprecorder stop];
  261. self.youpaiprecorder = nil;
  262. [self youpaifstopTimer];
  263. }
  264. }else if (self.youpaipstate == LZCaptrueAudioStatePlay){
  265. self.youpaipplayTime --;
  266. self.youpaiptimeL.text = [self youpaiftimeFormatted:self.youpaipplayTime];
  267. }
  268. }
  269. - (NSString *)youpaiftimeFormatted:(NSInteger)totalSeconds{
  270. NSInteger seconds = totalSeconds % 60;
  271. NSInteger minutes = (totalSeconds / 60);
  272. return [NSString stringWithFormat:@"%02ld:%02ld", minutes, seconds];
  273. }
  274. /// 视频本地url路径
  275. - (NSURL *)youpaiprecordAudioUrl{
  276. if (!_youpaiprecordAudioUrl) {
  277. NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) lastObject];
  278. NSString *fileName = @"audioVerify.caf";
  279. _youpaiprecordAudioUrl = [NSURL fileURLWithPath:[path stringByAppendingPathComponent:fileName]];
  280. if ([[NSFileManager defaultManager] fileExistsAtPath:_youpaiprecordAudioUrl.resourceSpecifier]){
  281. [[NSFileManager defaultManager] removeItemAtPath:_youpaiprecordAudioUrl.resourceSpecifier error:nil];
  282. }
  283. }
  284. return _youpaiprecordAudioUrl;
  285. }
  286. - (AVAudioRecorder *)youpaiprecorder{
  287. if (_youpaiprecorder == nil) {
  288. //创建录音机
  289. NSError *error=nil;
  290. _youpaiprecorder = [[AVAudioRecorder alloc] initWithURL:self.youpaiprecordAudioUrl settings:[self getAudioSetting] error:&error];
  291. _youpaiprecorder.delegate = self;
  292. if (error) {
  293. NSLog(@"创建录音机对象时发生错误,错误信息:%@",error.localizedDescription);
  294. return nil;
  295. }
  296. }
  297. return _youpaiprecorder;
  298. }
  299. /**
  300. * 取得录音文件设置
  301. *
  302. * @return 录音设置
  303. */
  304. -(NSDictionary *)getAudioSetting{
  305. NSDictionary *recordSetting = @{
  306. AVFormatIDKey : @(kAudioFormatLinearPCM),
  307. AVSampleRateKey : @(44100),
  308. AVNumberOfChannelsKey : @(2),
  309. AVLinearPCMBitDepthKey : @(16),
  310. AVLinearPCMIsNonInterleaved : @NO,
  311. AVLinearPCMIsFloatKey : @NO,
  312. AVLinearPCMIsBigEndianKey : @NO,
  313. };
  314. return recordSetting;
  315. }
  316. /// 权限
  317. - (void)youpaifsetupAuthority{
  318. [UCAuthorityManager microPhoneAuthority:^{
  319. } denied:^{
  320. [self youpaifshowAlertVCWithTitle:@"请在iphone的“设置-隐私-麦克风”选项中,允许APP访问您的麦克风。"];
  321. }];
  322. }
  323. - (void)youpaifshowAlertVCWithTitle:(NSString *)title{
  324. UIAlertController *systemAlert = [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleAlert];
  325. UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"现在去设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action){
  326. if ([[UIDevice currentDevice].systemVersion floatValue] < 10.0)
  327. {
  328. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
  329. }
  330. else
  331. {
  332. // 去系统设置页面
  333. if (@available(iOS 10.0, *)) {
  334. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
  335. } else {
  336. // Fallback on earlier versions
  337. }
  338. }
  339. }];
  340. UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
  341. [systemAlert addAction:cancelAction];
  342. [systemAlert addAction:action];
  343. dispatch_async(dispatch_get_main_queue(), ^{
  344. [[LCTools getCurrentVC] presentViewController: systemAlert animated: YES completion: nil];
  345. });
  346. }
  347. - (void)setAudioSession{
  348. AVAudioSession *session = [AVAudioSession sharedInstance];
  349. NSError *sessionError;
  350. [session setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];
  351. if(session == nil){
  352. NSLog(@"Error creating session: %@", [sessionError description]);
  353. }
  354. else{
  355. [session setActive:YES error:nil];
  356. }
  357. }
  358. - (void)dealloc{
  359. [self youpaifstopTimer];
  360. self.youpaiprecordAudioUrl = nil;
  361. self.youpaiprecorder = nil;
  362. // 停止播放
  363. [self.youpaipaudioPlayer stop];
  364. self.youpaipaudioPlayer = nil;
  365. }
  366. @end