2.2AVAudioRecord 錄制音頻
創(chuàng)建AVAudioRecord實(shí)例時(shí)需要具備一些必要信息,
1、音頻流寫入文件的本地文件url
2、包含用于配置錄音會(huì)話的NSDictionary對(duì)象
3、捕捉各種錯(cuò)誤信息的NSError指針
上述設(shè)置代碼如下:
NSString *directory = @"path";
NSString *filePath = [directory stringByAppendingPathComponent:@"voice.m4a"];
NSURL *url = [NSURL fileURLWithPath:filePath];
NSDictionary *settings = @{
AVFormatIDKey:@(kAudioFormatMPEG4AAC),//文件格式
AVSampleRateKey:@22050.0f, //采樣率 一般用44100
// AVLinearPCMBitDepthKey:@(16), //比特率。 一般設(shè)置 16,32
AVNumberOfChannelsKey:@(1), //通道數(shù)
// AVEncoderAudioQualityKey:@(AVAudioQualityMin), // 錄音質(zhì)量
// AVEncoderBitRateKey:@(12800) //比特采樣率 一般是12800
};
NSError *error;
self.recoder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
if (self.recoder) {
[self.recoder prepareToRecord];
}else{
//處理錯(cuò)誤
}
prepareToRecord 和prepareToPlay方法類似,這個(gè)方法執(zhí)行底層Audio Queue初始化的必要過(guò)程。該方法還在url參數(shù)指定的位置創(chuàng)建一個(gè)文件,將錄制啟動(dòng)時(shí)的延遲降到最小。
對(duì)于配置一些錄制信息的字典,可配置的信息都在<AVFoundation/AVAudioSettings.h>文件中可以看到。下面是一下通用配置信息
1.音頻格式
AVFormatIDKey定義了寫入內(nèi)如的音頻格式,所支持的值有:
kAudioFormatLinearPCM
kAudioFormatMPEG4AAC
kAudioFormatAppleLossless
kAudioFormatAppleIMA4
kAudioFormatiLBC
kAudioFormatULaw
kAudioFormatLinearPCM會(huì)將未壓縮的音頻流寫入文件中,這種格式的保真度最高,響應(yīng)的文件也最大。一般上選擇ACC或者AppleIMA4的壓縮格式會(huì)顯著縮小文件,還能保證高質(zhì)量的音頻內(nèi)容。
還有一點(diǎn)就是你的音頻格式要和你定義的URL的文件類型兼容性。
2.采樣率
AVSampleRateKey用于定義錄音器的采樣率。會(huì)影響錄音的質(zhì)量和文件大小,一般上標(biāo)準(zhǔn)的的采樣率是44100,也有使用8000,1600和22050
3.通道數(shù)
AVNumberOfChannelsKey是定義記錄音頻內(nèi)容的通道數(shù)。為默認(rèn)值1,也就是使用單聲道錄制,設(shè)置2為立體聲錄制,一般為單聲道錄音。
下面是具體實(shí)現(xiàn),首先要注意的是需要設(shè)置一下隱私設(shè)置,允許用戶使用麥克風(fēng)。
typedef void (^ LKRecordingStopCompletionHandler)(BOOL); //錄音結(jié)束block
typedef void (^ LKRecordingSaveCompletionHandler)(BOOL,id);//錄音保存完畢block
@class LKAudioRecordModel;
@interface LKAudioRecordManager : NSObject
@property (nonatomic, copy, readonly) NSString *formattedCurrentTime; //當(dāng)前錄音的時(shí)間
//開(kāi)始記錄
- (BOOL)record;
//暫停
- (void)pause;
//刪除
- (void)deleteCurrentRecord;
//停止錄音
- (void)stopWithCompletionHandler:(LKRecordingStopCompletionHandler)handler;
//保存到本地
- (void)saveRecordingWithName:(NSString *)name
completionHandler:(LKRecordingSaveCompletionHandler)handler;
//播放
- (BOOL)playbackSound:(LKAudioRecordModel *)sound;
@end
設(shè)置一個(gè)Manager來(lái)控制錄制周期
LKAudioRecordManager init方法主要是對(duì)錄音器進(jìn)行配置,
- (instancetype)init {
if (self = [super init]) {
// NSString *directory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
NSString *directory = NSTemporaryDirectory();
NSString *filePath = [directory stringByAppendingPathComponent:@"voice.caf"];
NSURL *url = [NSURL fileURLWithPath:filePath];
/*
kAudioFormatLinearPCM
kAudioFormatMPEG4AAC
kAudioFormatAppleLossless
kAudioFormatAppleIMA4
kAudioFormatiLBC
kAudioFormatULaw
*/
NSDictionary *settings = @{
AVFormatIDKey:@(kAudioFormatAppleIMA4),//文件格式
AVSampleRateKey:@(44100.0f), //采樣率 一般用44100
AVEncoderBitDepthHintKey:@(16),
AVNumberOfChannelsKey:@(1), //通道數(shù)
AVEncoderAudioQualityKey:@(AVAudioQualityMedium), // 錄音質(zhì)量
// AVEncoderBitRateKey:@(12800) //比特采樣率 一般是12800
};
NSError *error;
self.recoder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
if (self.recoder) {
self.recoder.delegate = self;
[self.recoder prepareToRecord];
}else{
//處理錯(cuò)誤
NSLog(@"創(chuàng)建錄音對(duì)象失敗:%@",[error localizedDescription]);
}
}
return self;
}
下面是錄音器的錄音,暫停,停止,和完成的操作
//錄音
- (BOOL)record {
[self.player stop];
return [self.recoder record];
}
//暫停
- (void)pause {
[self.recoder pause];
}
//刪除當(dāng)前錄音
- (void)deleteCurrentRecord {
if([self.recoder deleteRecording]) {
NSLog(@"刪除錄音成功");
}
}
//停止
- (void)stopWithCompletionHandler:(LKRecordingStopCompletionHandler)handler {
self.completionhandler = handler;
[self.recoder stop];
}
//錄音完成
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag {
if (self.completionhandler) {
self.completionhandler(flag);
}
}
這些方法的實(shí)現(xiàn)很直接,當(dāng)調(diào)用stop方法的時(shí)候,需要彈出一個(gè)alert讓用戶去輸入保存的名稱,或者刪除錄音,這個(gè)具體情況具體操作吧,下面是保存的操作。
//保存錄音文件
- (void)saveRecordingWithName:(NSString *)name completionHandler:(LKRecordingSaveCompletionHandler)handler {
NSTimeInterval timestamp = [NSDate timeIntervalSinceReferenceDate];
NSString *filename = [NSString stringWithFormat:@"%@-%f.caf",name,timestamp];
NSString *docsDir = [self documentsDirectory];
NSString *destPath = [docsDir stringByAppendingString:filename];
NSURL *scrURL = self.recoder.url;
NSURL *destURL = [NSURL fileURLWithPath:destPath];
NSError *saveError;
BOOL success = [[NSFileManager defaultManager] copyItemAtURL:scrURL
toURL:destURL
error:&saveError];
if (success) {
handler(YES,[LKAudioRecordModel modelWithTitle:name url:destURL]);
} else {
handler(NO,saveError);
}
}
- (NSString *)documentsDirectory {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [paths.firstObject stringByAppendingString:@"/"];
}
然后根據(jù)完成路徑使用AVAudioPlayer播放音頻文件就行了。這樣一個(gè)基本的錄音器就完成了。如果現(xiàn)在有一個(gè)需求,要求實(shí)現(xiàn)類似于微信的錄音,可以根據(jù)你錄音時(shí)的聲音大小做出相應(yīng)的改變,或者作出一個(gè)錄音的波動(dòng)圖。
AVAudioRecorder 和AVAudioPlayer中最實(shí)用的功能就是對(duì)音頻進(jìn)行測(cè)量AudioMetering可以讓開(kāi)發(fā)者讀取音頻的平均分貝和峰值分貝數(shù)據(jù)。這里AVAudioRecord并沒(méi)有給出具體的實(shí)時(shí)監(jiān)聽(tīng)的代理方法,但是提供了兩個(gè)方法[self.recoder peakPowerForChannel:0];和 [self.recoder averagePowerForChannel:0];
前面一個(gè)代表的是峰值,后面一個(gè)代表的是平均值。兩個(gè)方法都會(huì)返回一個(gè)浮點(diǎn)值表示分貝等級(jí)。這個(gè)值的范圍從表示最大分貝的0Db到表示最小或靜音的-160dB。我們可以通過(guò)調(diào)用一個(gè)定時(shí)器來(lái)實(shí)時(shí)監(jiān)聽(tīng)錄音時(shí)的波動(dòng)值。 首先需要設(shè)置AVAudioRecord的meteringEnabled屬性,開(kāi)啟測(cè)量。
如果你要實(shí)時(shí)監(jiān)聽(tīng)計(jì)量值的變化并且展示到UI上的話,建議使用CADisplayLink,它和NSTimer類似,不過(guò)它可以和顯示刷新率自動(dòng)同步,保持動(dòng)畫效果平滑性。當(dāng)然這也只針對(duì)短時(shí)間的錄音,如果是長(zhǎng)時(shí)間的錄音,則考慮使用OpenGL ES,更高效的繪制方法。