iOS錄音實踐
在AVFoundation架構中AVAudioRecorder類專門處理錄音操作,支援多種音頻格式。下面是常用的屬性和方法:
屬性 |
說明 |
@property(readonly, getter=isRecording) BOOL recording; |
是否正在錄音,唯讀 |
@property(readonly) NSURL *url |
錄音檔案地址,唯讀 |
@property(readonly) NSDictionary *settings |
錄音檔案設定,唯讀 |
@property(readonly) NSTimeInterval currentTime |
錄音時間長度,唯讀,注意僅僅在錄音狀態可用 |
@property(readonly) NSTimeInterval deviceCurrentTime |
輸入設定的時間長度,唯讀,注意此屬性一直可訪問 |
@property(getter=isMeteringEnabled) BOOL meteringEnabled; |
是否啟用錄音測量,如果啟用錄音測量可以獲得錄音分貝等資料資訊 |
@property(nonatomic, copy) NSArray *channelAssignments |
當前錄音的通道 |
對象方法 |
說明 |
- (instancetype)initWithURL:(NSURL *)url settings:(NSDictionary *)settings error:(NSError **)outError |
錄音機對象初始化方法,注意其中的url必須是本地檔案url,settings是錄音格式、編碼等設定 |
- (BOOL)prepareToRecord |
準備錄音,主要用於建立緩衝區,如果不手動調用,在調用record錄音時也會自動調用 |
- (BOOL)record |
開始錄音 |
- (BOOL)recordAtTime:(NSTimeInterval)time |
在指定的時間開始錄音,一般用於錄音暫停再恢複錄音 |
- (BOOL)recordForDuration:(NSTimeInterval) duration |
按指定的時間長度開始錄音 |
- (BOOL)recordAtTime:(NSTimeInterval)time forDuration:(NSTimeInterval) duration |
在指定的時間開始錄音,並指定錄音時間長度 |
- (void)pause; |
暫停錄音 |
- (void)stop; |
停止錄音 |
- (BOOL)deleteRecording; |
刪除錄音,注意要刪除錄音此時錄音機必須處於停止狀態 |
- (void)updateMeters; |
更新測量資料,注意只有meteringEnabled為YES此方法才可用 |
- (float)peakPowerForChannel:(NSUInteger)channelNumber; |
指定通道的測量峰值,注意只有調用完updateMeters才有值 |
- (float)averagePowerForChannel:(NSUInteger)channelNumber |
指定通道的測量平均值,注意只有調用完updateMeters才有值 |
代理方法 |
說明 |
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag |
完成錄音 |
- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error |
錄音編碼發生錯誤 |
AVAudioRecorder建立錄音機時除了指定路徑外還必須指定錄音設定資訊,因為錄音機必須知道錄音檔案的格式、採樣率、通道數、每個採樣點的位元等資訊,通常只需要幾個常用設定。關於錄音設定詳見協助文檔中的“AV Foundation Audio Settings Constants”。
以下代碼實現錄音,暫停,繼續,取消,停止,播放功能。
#import ViewController.h#import #define kAudioFileName @test.caf@interface ViewController ()@property (nonatomic,strong) AVAudioRecorder *audioRecorder; //音頻錄音機@property (nonatomic,strong) AVAudioPlayer *audioPlayer; //音頻播放器@property (nonatomic,strong) NSTimer *timer; //錄音監控@property (weak, nonatomic) IBOutlet UIProgressView *audioPower;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; [self setAudioSession];}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}/** * 設定音頻會話 */-(void)setAudioSession{ AVAudioSession *audioSession=[AVAudioSession sharedInstance]; //設定為播放和錄音狀態,以便可以在錄製完之後播放錄音 [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; [audioSession setActive:YES error:nil];}/** * 錄音檔案設定 * * @return 返回錄音設定 */- (NSDictionary *)getAudioSetting{ NSMutableDictionary *dic = [NSMutableDictionary dictionary]; [dic setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey]; //設定錄音格式 [dic setObject:@(8000) forKey:AVSampleRateKey]; //設定採樣率 [dic setObject:@(1) forKey:AVNumberOfChannelsKey]; //設定通道,這裡採用單聲道 [dic setObject:@(8) forKey:AVLinearPCMBitDepthKey]; //每個採樣點位元,分為8,16,24,32 [dic setObject:@(YES) forKey:AVLinearPCMIsFloatKey]; //是否使用浮點數採樣 return dic;}/** * 錄音儲存路徑 * * @return 返回儲存路徑 */- (NSURL *)getSavePath{ NSString *url = [NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask,YES) lastObject]; url = [url stringByAppendingPathComponent:kAudioFileName]; return [NSURL URLWithString:url];}- (NSTimer *)timer{ if (!_timer) { _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(audioPowerChange) userInfo:nil repeats:YES]; } return _timer;}- (AVAudioRecorder *)audioRecorder{ if (!_audioRecorder) { NSError *error = nil; _audioRecorder = [[AVAudioRecorder alloc] initWithURL:[self getSavePath] settings:[self getAudioSetting] error:&error]; _audioRecorder.delegate = self; _audioRecorder.meteringEnabled = YES; //是否啟用錄音測量,如果啟用錄音測量可以獲得錄音分貝等資料資訊 if (error) { NSLog(@建立錄音機對象發生錯誤:%@,error.localizedDescription); return nil; } } return _audioRecorder;}- (AVAudioPlayer *)audioPlayer{ if (!_audioPlayer) { NSError *error = nil; _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[self getSavePath] error:&error]; if (error) { NSLog(@建立音頻播放器對象發生錯誤:%@,error.localizedDescription); return nil; } } return _audioPlayer;}#pragma mark - #pragma mark - AVAudioRecorderDelegate//錄音成功- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{ if (![self.audioPlayer isPlaying]) { [self.audioPlayer play]; }}//錄音失敗- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error{ }#pragma mark - #pragma mark - Action- (void)audioPowerChange{ [self.audioRecorder updateMeters]; //更新測量值 float power = [self.audioRecorder averagePowerForChannel:1]; //取得第一個通道的音頻,注意音頻強度範圍時-160到0 self.audioPower.progress = (1.0/160)*(power+160);}/** * 點擊錄音按鈕 * * @param sender 錄音按鈕 */- (IBAction)startRecord:(id)sender { if (![self.audioRecorder isRecording]) { [self.audioRecorder record]; self.timer.fireDate = [NSDate distantPast]; }}/** * 點擊取消錄音按鈕 * * @param sender 取消錄音按鈕 */- (IBAction)cancelRecord:(id)sender { self.audioRecorder.delegate = nil; if ([self.audioRecorder isRecording]) { [self.audioRecorder stop]; } self.audioRecorder = nil;}/** * 點擊暫訂按鈕 * * @param sender 暫停按鈕 */- (IBAction)pause:(id)sender { if ([self.audioRecorder isRecording]) { [self.audioRecorder pause]; self.timer.fireDate = [NSDate distantFuture]; }}/** * 點擊恢複按鈕 * 恢複錄音只需要再次調用record,AVAudioSession會協助你記錄上次錄音位置並追加錄音 * * @param sender 恢複按鈕 */- (IBAction)goon:(id)sender { [self startRecord:nil];}/** * 點擊停止按鈕 * * @param sender 停止按鈕 */- (IBAction)stop:(id)sender { if ([self.audioRecorder isRecording]) { [self.audioRecorder stop]; self.timer = [NSDate distantFuture]; }}/** * 點擊播放按鈕 * * @param sender 播放按鈕 */- (IBAction)play:(id)sender { if (![self.audioPlayer isPlaying]) { [self.audioPlayer play]; }}