有一些人喜歡用第三方,我還是比較喜歡用自己封裝的,每次更改內(nèi)部什么的都熟悉!
55225BC9-A8C8-40B2-A01C-E20E396874B8.png
共包含兩個(gè)文件
JPRecordTool
和RecorderView
,前者是個(gè)工具類,為后者服務(wù),如果有其他需求只用前者來(lái)完成自己的特殊需求,如果只是簡(jiǎn)單的需求,只用控制后者即可,代碼如下:
JPRecordTool.h
@class JPRecordTool;
@protocol JPRecordToolDelegate
@optional
- (void) recordTool:(JPRecordTool *)recordTool didstartRecoring:(int)no;
@end
@interface JPRecordTool : NSObject
/** 錄音工具單例 */
+ (instancetype) sharedRecordTool;
+ (instancetype)allocWithZone:(struct _NSZone *)zone;
/** 開始錄音 */
- (void) startRecording;
/** 停止錄音*/
- (void) stopRecording;
/** 播放錄音文件 */
- (void) playRecordingFile;
/** 停止播放錄音文件 *
/- (void) stopPlaying;
/** 銷毀錄音文件*/
- (void)destructionRecordingFile;
/** 錄音對(duì)象 */
@property (nonatomic, strong) AVAudioRecorder *recorder;
/** 更新圖片的代理 */
@property (nonatomic, assign) iddelegate;
@end
JPRecordTool.m
#import "JPRecordTool.h"
#define LVRecordFielName @"JPVRecord.caf"
@interface JPRecordTool ()
/** 播放器對(duì)象 */
@property (nonatomic, retain) AVAudioPlayer *player;
/** 錄音文件地址 */
@property (nonatomic, copy) NSURL *recordFileUrl;
/** 定時(shí)器 */
@property (nonatomic, retain) NSTimer *timer;
@property (nonatomic, retain) AVAudioSession *session;
@end
@implementation JPRecordTool
- (void)startRecording {
// 錄音時(shí)停止播放 刪除曾經(jīng)生成的文件
[self stopPlaying];
[self destructionRecordingFile];
[self setUp];
[self.recorder record];
NSTimer *timer = [NSTimer timerWithTimeInterval:0.5 target:self selector:@selector(updateImage) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
[timer fire];
self.timer = timer;
}
- (void)updateImage {
[self.recorder updateMeters];
double lowPassResults = pow(10, (0.05 * [self.recorder peakPowerForChannel:0]));
float result = 10 * (float)lowPassResults;
NSLog(@"%f", result);
int no = 0;
if (result > 0 && result <= 1.3) {
no = 1;
} else if (result > 1.3 && result <= 2) {
no = 2;
} else if (result > 2 && result <= 3.0) {
no = 3;
} else if (result > 3.0 && result <= 5.0) {
no = 4;
} else if (result > 5.0 && result <= 10) {
no = 5;
} else if (result > 10 && result <= 40) {
no = 6;
} else if (result > 40) {
no = 7;
}
if ([self.delegate respondsToSelector:@selector(recordTool:didstartRecoring:)]) {
[self.delegate recordTool:self didstartRecoring: no];
}
}
- (void)stopRecording {
[self.recorder stop];
[self.timer invalidate];
}
- (void)playRecordingFile {
// 播放時(shí)停止錄音
[self.recorder stop];
// 正在播放就返回
if ([self.player isPlaying]) return;
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:self.recordFileUrl error:NULL];
[self.player play];
}
- (void)stopPlaying {
[self.player stop];
}
static id instance;
#pragma mark - 單例
+ (instancetype)sharedRecordTool {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (instance == nil) {
instance = [[self alloc] init];
}
});
return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (instance == nil) {
instance = [super allocWithZone:zone];
}
});
return instance;
}
- (void)creatRecorder:(NSMutableDictionary*)dic
{
AVAudioRecorder *recorder = [[AVAudioRecorder alloc] initWithURL:self.recordFileUrl settings:dic error:NULL];
recorder.delegate = self;
recorder.meteringEnabled = YES;
[recorder prepareToRecord];
self.recorder = recorder;
}
- (void) setUp
{
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];
self.session = session;
// 1.獲取沙盒地址
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [path stringByAppendingPathComponent:LVRecordFielName];
self.recordFileUrl = [NSURL fileURLWithPath:filePath];
NSLog(@"%@", filePath);
// 3.設(shè)置錄音的一些參數(shù)
NSMutableDictionary *setting = [NSMutableDictionary dictionary];
// 音頻格式
setting[AVFormatIDKey] = @(kAudioFormatAppleIMA4);
// 錄音采樣率(Hz) 如:AVSampleRateKey==8000/44100/96000(影響音頻的質(zhì)量)
setting[AVSampleRateKey] = @(44100);
// 音頻通道數(shù) 1 或 2
setting[AVNumberOfChannelsKey] = @(1);
// 線性音頻的位深度 8、16、24徐伐、32
setting[AVLinearPCMBitDepthKey] = @(8);
//錄音的質(zhì)量
setting[AVEncoderAudioQualityKey] = [NSNumber numberWithInt:AVAudioQualityHigh];
[self creatRecorder:setting];
}
- (void)destructionRecordingFile {
NSFileManager *fileManager = [NSFileManager defaultManager];
if (self.recordFileUrl) {
[fileManager removeItemAtURL:self.recordFileUrl error:NULL];
}
}
#pragma mark - AVAudioRecorderDelegate
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag {
if (flag) {
NSLog(@"錄音成功");
NSError *sessionError;
[self.session setCategory:AVAudioSessionCategoryPlayback error:&sessionError];
}
}
@end
RecorderView.h
@interface RecorderView : UIView
+ (instancetype)recordView;
@end
RecorderView.m
#import "RecorderView.h"
#import "JPRecordTool.h"
@interface RecorderView ()@property (weak, nonatomic) IBOutlet UIButton *imageView;//添加播放麥克風(fēng)圖片(點(diǎn)擊后依然可以錄音)
@property (weak, nonatomic) IBOutlet UIButton *recorderButton;//錄音按鈕
@property (weak, nonatomic) IBOutlet UIButton *playButton;//播放按鈕
@property (strong, nonatomic) JPRecordTool *recordTool;
@end
@implementation RecorderView
+ (instancetype)recordView {
RecorderView *recordView = [[[NSBundle mainBundle] loadNibNamed:@"RecorderView" owner:nil options:nil] lastObject];//此xib中可以完成自己的特殊需求,那三個(gè)按鈕的擺放位置什么的都是自己定義的,筆者不說(shuō)
recordView.recordTool = [JPRecordTool sharedRecordTool];
// 初始化監(jiān)聽事件
[recordView setup];
return recordView;
}
- (void)setup {
self.recorderButton.layer.cornerRadius = 10;
self.playButton.layer.cornerRadius = 10;
[self.recorderButton setTitle:@"按住 說(shuō)話" forState:UIControlStateNormal];
[self.recorderButton setTitle:@"松開 結(jié)束" forState:UIControlStateHighlighted];
self.recordTool.delegate = self;
// 錄音按鈕
[self.recorderButton addTarget:self action:@selector(recordBtnDidTouchDown:) forControlEvents:UIControlEventTouchDown];
[self.recorderButton addTarget:self action:@selector(recordBtnDidTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
[self.recorderButton addTarget:self action:@selector(recordBtnDidTouchDragExit:) forControlEvents:UIControlEventTouchDragExit];
[self.imageView addTarget:self action:@selector(recordBtnDidTouchDown:) forControlEvents:UIControlEventTouchDown];
[self.imageView addTarget:self action:@selector(recordBtnDidTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
[self.imageView addTarget:self action:@selector(recordBtnDidTouchDragExit:) forControlEvents:UIControlEventTouchDragExit];
// 播放按鈕
[self.playButton addTarget:self action:@selector(play) forControlEvents:UIControlEventTouchUpInside];
}
#pragma mark - 錄音按鈕事件
// 按下
- (void)recordBtnDidTouchDown:(UIButton *)recordBtn {
[self.recordTool startRecording];
}
// 點(diǎn)擊
- (void)recordBtnDidTouchUpInside:(UIButton *)recordBtn {
double currentTime = self.recordTool.recorder.currentTime;
if (currentTime < 1) {
[self.imageView setImage:[UIImage imageNamed:@"mic_0"] forState:UIControlStateNormal];
[self alertWithMessage:@"說(shuō)話時(shí)間太短"];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self.recordTool stopRecording];
[self.recordTool destructionRecordingFile];
});
} else {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self.recordTool stopRecording];
dispatch_async(dispatch_get_main_queue(), ^{
[self.imageView setImage:[UIImage imageNamed:@"mic_0"] forState:UIControlStateNormal]; });
});
// 已成功錄音
NSLog(@"已成功錄音");
}
}
// 手指從按鈕上移除
- (void)recordBtnDidTouchDragExit:(UIButton *)recordBtn {
[self.imageView setImage:[UIImage imageNamed:@"mic_0"] forState:UIControlStateNormal]; dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self.recordTool stopRecording];
[self.recordTool destructionRecordingFile];
dispatch_async(dispatch_get_main_queue(), ^{
[self alertWithMessage:@"已取消錄音"];
});
});
}
#pragma mark - 彈窗提示
- (void)alertWithMessage:(NSString *)message {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"確定" otherButtonTitles: nil];
[alert show];
}
#pragma mark - 播放錄音
- (void)play {
[self.recordTool playRecordingFile];
}
#pragma mark - JPRecordToolDelegate
- (void)recordTool:(JPRecordTool *)recordTool didstartRecoring:(int)no {
NSString *imageName = [NSString stringWithFormat:@"mic_%d", no];
[self.imageView setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
}
@end
之所以封裝成一個(gè)View,原因有很多,畢竟這只是個(gè)簡(jiǎn)單的錄音,太分散不利于與App協(xié)調(diào),最主要解決了模擬器可以錄音播放通過(guò)真機(jī)不行的問(wèn)題!希望對(duì)大家有用吧!