如何使用AVAudioRecorder在iPhone上录制audio?
现在iPhone 3.0 sdk是公开的,我想我可以问你那些已经玩过3.0 sdk的人的这个问题。 我想在我的应用程序中录制audio,但是我想使用AVAudioRecorder,而不是像SpeakHere所示的那样使用旧的录制方式。 iPhone开发中心没有任何如何做到这一点的例子,只能参考类。 我是一个iPhone开发新手,所以我正在寻找一个简单的例子,让我开始。 提前致谢。
其实根本没有例子。 这是我的工作代码。 录制是由用户按下导航栏上的button触发的。 录音使用cd质量(44100个采样),立体声(2个通道)线性pcm。 注意:如果你想使用不同的格式,尤其是编码格式,请确保你完全理解如何设置AVAudioRecorder设置(仔细阅读audiotypes文档),否则你将永远无法正确初始化它。 还有一件事。 在代码中,我没有展示如何处理计量数据,但是你可以很容易地弄清楚。 最后,请注意,截止到本文撰写的AVAudioRecorder方法deleteRecording崩溃了您的应用程序。 这就是为什么我通过文件pipe理器删除logging的文件。 录制完成后,我使用KVC将录制的audio保存为当前编辑的对象中的NSData。
#define DOCUMENTS_FOLDER [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] - (void) startRecording{ UIBarButtonItem *stopButton = [[UIBarButtonItem alloc] initWithTitle:@"Stop" style:UIBarButtonItemStyleBordered target:self action:@selector(stopRecording)]; self.navigationItem.rightBarButtonItem = stopButton; [stopButton release]; AVAudioSession *audioSession = [AVAudioSession sharedInstance]; NSError *err = nil; [audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err]; if(err){ NSLog(@"audioSession: %@ %d %@", [err domain], [err code], [[err userInfo] description]); return; } [audioSession setActive:YES error:&err]; err = nil; if(err){ NSLog(@"audioSession: %@ %d %@", [err domain], [err code], [[err userInfo] description]); return; } recordSetting = [[NSMutableDictionary alloc] init]; [recordSetting setValue :[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey]; [recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey]; [recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey]; [recordSetting setValue :[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey]; [recordSetting setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey]; [recordSetting setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey]; // Create a new dated file NSDate *now = [NSDate dateWithTimeIntervalSinceNow:0]; NSString *caldate = [now description]; recorderFilePath = [[NSString stringWithFormat:@"%@/%@.caf", DOCUMENTS_FOLDER, caldate] retain]; NSURL *url = [NSURL fileURLWithPath:recorderFilePath]; err = nil; recorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recordSetting error:&err]; if(!recorder){ NSLog(@"recorder: %@ %d %@", [err domain], [err code], [[err userInfo] description]); UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @"Warning" message: [err localizedDescription] delegate: nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; [alert release]; return; } //prepare to record [recorder setDelegate:self]; [recorder prepareToRecord]; recorder.meteringEnabled = YES; BOOL audioHWAvailable = audioSession.inputIsAvailable; if (! audioHWAvailable) { UIAlertView *cantRecordAlert = [[UIAlertView alloc] initWithTitle: @"Warning" message: @"Audio input hardware not available" delegate: nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [cantRecordAlert show]; [cantRecordAlert release]; return; } // start recording [recorder recordForDuration:(NSTimeInterval) 10]; } - (void) stopRecording{ [recorder stop]; NSURL *url = [NSURL fileURLWithPath: recorderFilePath]; NSError *err = nil; NSData *audioData = [NSData dataWithContentsOfFile:[url path] options: 0 error:&err]; if(!audioData) NSLog(@"audio data: %@ %d %@", [err domain], [err code], [[err userInfo] description]); [editedObject setValue:[NSData dataWithContentsOfURL:url] forKey:editedFieldKey]; //[recorder deleteRecording]; NSFileManager *fm = [NSFileManager defaultManager]; err = nil; [fm removeItemAtPath:[url path] error:&err]; if(err) NSLog(@"File Manager: %@ %d %@", [err domain], [err code], [[err userInfo] description]); UIBarButtonItem *startButton = [[UIBarButtonItem alloc] initWithTitle:@"Record" style:UIBarButtonItemStyleBordered target:self action:@selector(startRecording)]; self.navigationItem.rightBarButtonItem = startButton; [startButton release]; } - (void)audioRecorderDidFinishRecording:(AVAudioRecorder *) aRecorder successfully:(BOOL)flag { NSLog (@"audioRecorderDidFinishRecording:successfully:"); // your actions here }
虽然这是一个回答的问题(和老式的),我决定发布我的完整的工作代码,发现很难find很好的工作(开箱即用)播放和录音的例子 – 包括编码,PCM,播放通过扬声器,在这里写入文件是:
AudioPlayerViewController.h:
#import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> @interface AudioPlayerViewController : UIViewController { AVAudioPlayer *audioPlayer; AVAudioRecorder *audioRecorder; int recordEncoding; enum { ENC_AAC = 1, ENC_ALAC = 2, ENC_IMA4 = 3, ENC_ILBC = 4, ENC_ULAW = 5, ENC_PCM = 6, } encodingTypes; } -(IBAction) startRecording; -(IBAction) stopRecording; -(IBAction) playRecording; -(IBAction) stopPlaying; @end
AudioPlayerViewController.m:
#import "AudioPlayerViewController.h" @implementation AudioPlayerViewController - (void)viewDidLoad { [super viewDidLoad]; recordEncoding = ENC_AAC; } -(IBAction) startRecording { NSLog(@"startRecording"); [audioRecorder release]; audioRecorder = nil; // Init audio with record capability AVAudioSession *audioSession = [AVAudioSession sharedInstance]; [audioSession setCategory:AVAudioSessionCategoryRecord error:nil]; NSMutableDictionary *recordSettings = [[NSMutableDictionary alloc] initWithCapacity:10]; if(recordEncoding == ENC_PCM) { [recordSettings setObject:[NSNumber numberWithInt: kAudioFormatLinearPCM] forKey: AVFormatIDKey]; [recordSettings setObject:[NSNumber numberWithFloat:44100.0] forKey: AVSampleRateKey]; [recordSettings setObject:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey]; [recordSettings setObject:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey]; [recordSettings setObject:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey]; [recordSettings setObject:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey]; } else { NSNumber *formatObject; switch (recordEncoding) { case (ENC_AAC): formatObject = [NSNumber numberWithInt: kAudioFormatMPEG4AAC]; break; case (ENC_ALAC): formatObject = [NSNumber numberWithInt: kAudioFormatAppleLossless]; break; case (ENC_IMA4): formatObject = [NSNumber numberWithInt: kAudioFormatAppleIMA4]; break; case (ENC_ILBC): formatObject = [NSNumber numberWithInt: kAudioFormatiLBC]; break; case (ENC_ULAW): formatObject = [NSNumber numberWithInt: kAudioFormatULaw]; break; default: formatObject = [NSNumber numberWithInt: kAudioFormatAppleIMA4]; } [recordSettings setObject:formatObject forKey: AVFormatIDKey]; [recordSettings setObject:[NSNumber numberWithFloat:44100.0] forKey: AVSampleRateKey]; [recordSettings setObject:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey]; [recordSettings setObject:[NSNumber numberWithInt:12800] forKey:AVEncoderBitRateKey]; [recordSettings setObject:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey]; [recordSettings setObject:[NSNumber numberWithInt: AVAudioQualityHigh] forKey: AVEncoderAudioQualityKey]; } NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/recordTest.caf", [[NSBundle mainBundle] resourcePath]]]; NSError *error = nil; audioRecorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recordSettings error:&error]; if ([audioRecorder prepareToRecord] == YES){ [audioRecorder record]; }else { int errorCode = CFSwapInt32HostToBig ([error code]); NSLog(@"Error: %@ [%4.4s])" , [error localizedDescription], (char*)&errorCode); } NSLog(@"recording"); } -(IBAction) stopRecording { NSLog(@"stopRecording"); [audioRecorder stop]; NSLog(@"stopped"); } -(IBAction) playRecording { NSLog(@"playRecording"); // Init audio with playback capability AVAudioSession *audioSession = [AVAudioSession sharedInstance]; [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/recordTest.caf", [[NSBundle mainBundle] resourcePath]]]; NSError *error; audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error]; audioPlayer.numberOfLoops = 0; [audioPlayer play]; NSLog(@"playing"); } -(IBAction) stopPlaying { NSLog(@"stopPlaying"); [audioPlayer stop]; NSLog(@"stopped"); } - (void)dealloc { [audioPlayer release]; [audioRecorder release]; [super dealloc]; } @end
希望这会帮助你们中的一些人。
我已经上传了一个示例项目。 你可以看看。
录音机
它真的很有帮助。 我唯一的问题是logging后创build的声音文件的大小。 我需要减less文件大小,所以我做了一些设置的改变。
NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init]; [recordSetting setValue :[NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey]; [recordSetting setValue:[NSNumber numberWithFloat:16000.0] forKey:AVSampleRateKey]; [recordSetting setValue:[NSNumber numberWithInt: 1] forKey:AVNumberOfChannelsKey];
文件大小从360kb减less到25kb(2秒logging)。
我一直试图让这个代码在过去的2个小时内工作,虽然在模拟器上没有显示任何错误,但是在设备上却有一个错误。
原来,至less在我的情况下,错误来自目录使用(包):
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/recordTest.caf", [[NSBundle mainBundle] resourcePath]]];
这是不可写的或类似的东西…除了事实prepareToRecord失败没有错误…
因此,我将其replace为:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *recDir = [paths objectAtIndex:0]; NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/recordTest.caf", recDir]]
它现在像一个魅力。
希望这可以帮助别人。
非常感谢@Massimo Cafaro和Shaybc,我能够完成以下任务
在iOS 8中:
录制audio和保存
播放保存的录音
1.将“AVFoundation.framework”添加到您的项目中
在.h文件中
2.添加下面的导入语句“AVFoundation / AVFoundation.h”。
3.定义“AVAudioRecorderDelegate”
4.用Record,Playbutton及其动作方法创build一个布局
5.定义logging器和播放器等
这里是完整的示例代码,可以帮助你。
ViewController.h
#import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> @interface ViewController : UIViewController <AVAudioRecorderDelegate> @property(nonatomic,strong) AVAudioRecorder *recorder; @property(nonatomic,strong) NSMutableDictionary *recorderSettings; @property(nonatomic,strong) NSString *recorderFilePath; @property(nonatomic,strong) AVAudioPlayer *audioPlayer; @property(nonatomic,strong) NSString *audioFileName; - (IBAction)startRecording:(id)sender; - (IBAction)stopRecording:(id)sender; - (IBAction)startPlaying:(id)sender; - (IBAction)stopPlaying:(id)sender; @end
然后做这个工作
ViewController.m
#import "ViewController.h" #define DOCUMENTS_FOLDER [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] @interface ViewController () @end @implementation ViewController @synthesize recorder,recorderSettings,recorderFilePath; @synthesize audioPlayer,audioFileName; #pragma mark - View Controller Life cycle methods - (void)viewDidLoad { [super viewDidLoad]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } #pragma mark - Audio Recording - (IBAction)startRecording:(id)sender { AVAudioSession *audioSession = [AVAudioSession sharedInstance]; NSError *err = nil; [audioSession setCategory :AVAudioSessionCategoryPlayAndRecord error:&err]; if(err) { NSLog(@"audioSession: %@ %ld %@", [err domain], (long)[err code], [[err userInfo] description]); return; } [audioSession setActive:YES error:&err]; err = nil; if(err) { NSLog(@"audioSession: %@ %ld %@", [err domain], (long)[err code], [[err userInfo] description]); return; } recorderSettings = [[NSMutableDictionary alloc] init]; [recorderSettings setValue :[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey]; [recorderSettings setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey]; [recorderSettings setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey]; [recorderSettings setValue :[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey]; [recorderSettings setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey]; [recorderSettings setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey]; // Create a new audio file audioFileName = @"recordingTestFile"; recorderFilePath = [NSString stringWithFormat:@"%@/%@.caf", DOCUMENTS_FOLDER, audioFileName] ; NSURL *url = [NSURL fileURLWithPath:recorderFilePath]; err = nil; recorder = [[ AVAudioRecorder alloc] initWithURL:url settings:recorderSettings error:&err]; if(!recorder){ NSLog(@"recorder: %@ %ld %@", [err domain], (long)[err code], [[err userInfo] description]); UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @"Warning" message: [err localizedDescription] delegate: nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; return; } //prepare to record [recorder setDelegate:self]; [recorder prepareToRecord]; recorder.meteringEnabled = YES; BOOL audioHWAvailable = audioSession.inputIsAvailable; if (! audioHWAvailable) { UIAlertView *cantRecordAlert = [[UIAlertView alloc] initWithTitle: @"Warning"message: @"Audio input hardware not available" delegate: nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [cantRecordAlert show]; return; } // start recording [recorder recordForDuration:(NSTimeInterval) 60];//Maximum recording time : 60 seconds default NSLog(@"Recroding Started"); } - (IBAction)stopRecording:(id)sender { [recorder stop]; NSLog(@"Recording Stopped"); } - (void)audioRecorderDidFinishRecording:(AVAudioRecorder *) aRecorder successfully:(BOOL)flag { NSLog (@"audioRecorderDidFinishRecording:successfully:"); } #pragma mark - Audio Playing - (IBAction)startPlaying:(id)sender { NSLog(@"playRecording"); AVAudioSession *audioSession = [AVAudioSession sharedInstance]; [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil]; NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@.caf", DOCUMENTS_FOLDER, audioFileName]]; NSError *error; audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error]; audioPlayer.numberOfLoops = 0; [audioPlayer play]; NSLog(@"playing"); } - (IBAction)stopPlaying:(id)sender { [audioPlayer stop]; NSLog(@"stopped"); } @end
This is from Multimedia programming guide... - (IBAction) recordOrStop: (id) sender { if (recording) { [soundRecorder stop]; recording = NO; self.soundRecorder = nil; [recordOrStopButton setTitle: @"Record" forState: UIControlStateNormal]; [recordOrStopButton setTitle: @"Record" forState: UIControlStateHighlighted]; [[AVAudioSession sharedInstance] setActive: NO error:nil]; } else { [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryRecord error: nil]; NSDictionary *recordSettings = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithFloat: 44100.0], AVSampleRateKey, [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey, [NSNumber numberWithInt: 1], AVNumberOfChannelsKey, [NSNumber numberWithInt: AVAudioQualityMax], AVEncoderAudioQualityKey, nil]; AVAudioRecorder *newRecorder = [[AVAudioRecorder alloc] initWithURL: soundFileURL settings: recordSettings error: nil]; [recordSettings release]; self.soundRecorder = newRecorder; [newRecorder release]; soundRecorder.delegate = self; [soundRecorder prepareToRecord]; [soundRecorder record]; [recordOrStopButton setTitle: @"Stop" forState: UIControlStateNormal]; [recordOrStopButton setTitle: @"Stop" forState: UIControlStateHighlighted]; recording = YES; } }
在以下链接中,您可以find有关使用AVAudioRecording进行录制的有用信息。 在第一部分“使用audio”的链接中,有一个名为“使用AVAudioRecorder类录制”的锚点,可以引导您进行示例。
AudioVideo概念多媒体
好的,所以我得到的答案帮助了我正确的方向,我非常感激。 它帮助我弄清楚如何在iPhone上实际logging,但是我想我还会包含一些我从iPhone Reference Library得到的有用的代码:
AudioandVideoTechnologies
我使用这个代码,并相当容易地将其添加到avTouch示例。 通过上面的代码示例和参考库中的示例,我能够得到这个工作非常好。
对于audio设置下的wav格式
NSDictionary *audioSetting = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithFloat:44100.0],AVSampleRateKey, [NSNumber numberWithInt:2],AVNumberOfChannelsKey, [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey, [NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey, [NSNumber numberWithBool:NO], AVLinearPCMIsFloatKey, [NSNumber numberWithBool:0], AVLinearPCMIsBigEndianKey, [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved, [NSData data], AVChannelLayoutKey, nil];
ref: http : //objective-audio.jp/2010/09/avassetreaderavassetwriter.html
开始
NSError *sessionError = nil; [[AVAudioSession sharedInstance] setDelegate:self]; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError]; [[AVAudioSession sharedInstance] setActive: YES error: nil]; UInt32 doChangeDefaultRoute = 1; AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof(doChangeDefaultRoute), &doChangeDefaultRoute); NSError *error = nil; NSString *filename = [NSString stringWithFormat:@"%@.caf",FILENAME]; NSString *path = [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingPathComponent:filename]; NSURL *soundFileURL = [NSURL fileURLWithPath:path]; NSDictionary *recordSettings = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey, [NSNumber numberWithInt:AVAudioQualityMedium],AVEncoderAudioQualityKey, [NSNumber numberWithInt:AVAudioQualityMedium], AVSampleRateConverterAudioQualityKey, [NSNumber numberWithInt: 1], AVNumberOfChannelsKey, [NSNumber numberWithFloat:22050.0],AVSampleRateKey, nil]; AVAudioRecorder *audioRecorder = [[AVAudioRecorder alloc] initWithURL:soundFileURL settings:recordSettings error:&error]; if (!error && [audioRecorder prepareToRecord]) { [audioRecorder record]; }
停
[audioRecorder stop]; [audioRecorder release]; audioRecorder = nil;
-(void)viewDidLoad { // Setup audio session AVAudioSession *session = [AVAudioSession sharedInstance]; [session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; // Define the recorder setting NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init]; [recordSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey]; [recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey]; [recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey]; // Initiate and prepare the recorder recorder = [[AVAudioRecorder alloc] initWithURL:outputFileURL settings:recordSetting error:NULL]; recorder.delegate = self; recorder.meteringEnabled = YES; [recorder prepareToRecord]; } - (IBAction)btnRecordDidClicked:(UIButton *)sender { if (player1.playing) { [player1 stop]; } if (!recorder.recording) { AVAudioSession *session = [AVAudioSession sharedInstance]; [session setActive:YES error:nil]; // Start recording [recorder record]; [_recordTapped setTitle:@"Pause" forState:UIControlStateNormal]; } else { // Pause recording [recorder pause]; [_recordTapped setTitle:@"Record" forState:UIControlStateNormal]; } [_stopTapped setEnabled:YES]; [_playTapped setEnabled:NO]; } - (IBAction)btnPlayDidClicked:(UIButton *)sender { if (!recorder.recording){ player1 = [[AVAudioPlayer alloc] initWithContentsOfURL:recorder.url error:nil]; [player1 setDelegate:self]; [player1 play]; } } - (IBAction)btnStopDidClicked:(UIButton *)sender { [recorder stop]; AVAudioSession *audioSession = [AVAudioSession sharedInstance]; [audioSession setActive:NO error:nil]; } - (void) audioRecorderDidFinishRecording:(AVAudioRecorder *)avrecorder successfully:(BOOL)flag{ [_recordTapped setTitle:@"play" forState:UIControlStateNormal]; [_stopTapped setEnabled:NO]; [_playTapped setEnabled:YES]; }