我的iPhone应用程序使用“AVAudioRecorder”进行录音。它还使用“UIImagePickerController”来录制电影,使用“MPMoviePlayerController”来播放电影。
一切正常,直到我连续做三件事:
当我在步骤3中调用AVAudioRecorder的“记录”方法时,它返回NO表示失败,但没有提示原因(来自Apple!)AVAudioRecorder的audioRecorderEncodeErrorDidOccur委托方法永远不会被调用,我在设置时没有收到任何其他错误录音机。
我的第一个猜测是电影录制/播放正在修改“AVAudioSession”的共享实例,以防止录音机工作。但是,我手动将AVAudioSession的类别属性设置为“AVAudioSessionCategoryRecord”,并且在尝试录制之前使音频会话处于活动状态。
这是我创建录音机的方法:
- (void)createAudioRecorder
{
NSError *error = nil;
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryRecord error:&error];
if (error)
...
[audioSession setActive:YES error:&error];
if (error)
...
NSMutableDictionary *settings = [[NSMutableDictionary alloc] init];
// General Audio Format Settings
[settings setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey];
[settings setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[settings setValue:[NSNumber numberWithInt:1] forKey:AVNumberOfChannelsKey];
// Encoder Settings
[settings setValue:[NSNumber numberWithInt:AVAudioQualityMin] forKey:AVEncoderAudioQualityKey];
[settings setValue:[NSNumber numberWithInt:96] forKey:AVEncoderBitRateKey];
[settings setValue:[NSNumber numberWithInt:16] forKey:AVEncoderBitDepthHintKey];
// Write the audio to a temporary file
NSURL *tempURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"Recording.m4a"]];
audioRecorder = [[AVAudioRecorder alloc] initWithURL:tempURL settings:settings error:&error];
if (error)
...
audioRecorder.delegate = self;
if ([audioRecorder prepareToRecord] == NO)
NSLog(@"Recorder fails to prepare!");
[settings release];
}
这是我开始录制的方法:
- (void)startRecording
{
if (!audioRecorder)
[self createAudioRecorder];
NSError *error = nil;
[[AVAudioSession sharedInstance] setActive:YES error:&error];
if (error)
...
BOOL recording = [audioRecorder record];
if (!recording)
NSLog(@"Recording won't start!");
}
之前有没有人遇到过这个问题?
答案 0 :(得分:14)
我遇到了同样的问题。在我解决问题之前,我的录制/播放代码是这样的:
开始录制功能
- (BOOL) startRecording {
@try {
NSDictionary *recordSetting = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey, [NSNumber numberWithFloat: 44100.0], AVSampleRateKey, [NSNumber numberWithInt: 1], AVNumberOfChannelsKey, [NSNumber numberWithInt: AVAudioQualityMax], AVEncoderAudioQualityKey, nil];
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *soundFilePath = [documentsPath stringByAppendingPathComponent:@"recording.caf"];
if(audioRecorder != nil) {
[audioRecorder stop];
[audioRecorder release];
audioRecorder = nil;
}
NSError *err = nil;
audioRecorder = [[AVAudioRecorder alloc] initWithURL:soundFileURL settings:recordSetting error:&err];
[soundFileURL release];
[recordSetting release];
if(!audioRecorder || err){
NSLog(@"recorder initWithURL: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
return NO;
}
[audioRecorder peakPowerForChannel:8];
[audioRecorder updateMeters];
audioRecorder.meteringEnabled = YES;
[audioRecorder record];
}
@catch (NSException * e) {
return NO;
}
recording = YES;
return YES;
}
停止录制功能
- (BOOL) stopRecording {
@try {
[audioRecorder stop];
[audioRecorder release];
audioRecorder = nil;
recording = NO;
}
@catch (NSException * e) {
return NO;
}
return YES;
}
开始播放功能
- (BOOL) startPlaying {
@try {
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *soundFilePath = [documentsPath stringByAppendingPathComponent:@"recording.caf"]; NSURL * soundFileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
NSError *err = nil;
if (audioPlayer) {
[audioPlayer release];
audioPlayer = nil;
}
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error: &err];
[soundFileURL release];
if (!audioPlayer || err) {
NSLog(@"recorder: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
return NO;
}
[audioPlayer prepareToPlay];
[audioPlayer setDelegate: self];
[audioPlayer play];
playing = YES;
}
@catch (NSException * e) {
return NO;
}
return YES;
}
停止播放功能
- (BOOL) stopPlaying {
@try {
[audioPlayer stop];
[audioPlayer release];
audioPlayer = nil;
playing = NO;
}
@catch (NSException * e) {
return NO;
}
return YES;
}
我在播放拍摄的视频后修正了录制问题,代码如下:
- (BOOL) startRecording {
@try {
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryRecord error:nil];
// rest of the recording code is the same .
}
- (BOOL) stopRecording {
@try {
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
// rest of the code is the same
}
- (BOOL) startPlaying {
@try {
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
// rest of the code is the same.
}
- (BOOL) stopPlaying {
// There is no change in this function
}
答案 1 :(得分:2)
有同样的问题。我的解决方案是在开始录制会话之前停止播放电影。我的代码类似于rmomin的代码。
答案 2 :(得分:1)
我一直有同样的问题。我使用AVPlayer播放作曲(以前的录音我用过AVAudioRecord)。但是,我发现一旦我使用了AVPlayer,我就再也无法使用AVAudioRecorder了。经过一些搜索,我发现只要AVPlayer在内存中实例化并且至少播放过一次(通常是在实例化之后立即执行),AVAudioRecorder将不会记录。但是,一旦AVPlayer被释放,AVAudioRecorder就可以再次自由录制。似乎AVPlayer坚持AVAudioRecorder需要的某种连接,而且它很贪婪......直到你从冷酷无情的手中撬开它才会让它消失。
这是我找到的解决方案。有些人声称实例化AVPlayer需要花费太多时间来保持分解和重新设置。但是,事实并非如此。实例化AVPlayer实际上非常简单。所以也是实例化AVPlayerItem。什么不是微不足道的是加载AVAsset(或其任何子类)。你真的只想做一次。他们的关键是使用这个序列:
**请注意,销毁AVPlayer可能需要的不仅仅是释放它并将其var设置为nil。最有可能的是,您还添加了一个定期时间观察器来跟踪播放进度。执行此操作时,您将收到一个您应该保留的不透明对象。如果您没有从播放器中删除此项并将其释放/设置为nil,则AVPlayer将不会取消激活。 Apple似乎创建了一个有意保留的循环,您必须手动中断。所以在你破坏AVPlayer之前你需要(例子):
[_player removeTimeObserver:_playerObserver];
[_playerObserver release]; //Only if you're not using ARC
_playerObserver = nil;
作为附注,您可能还设置了NSNotifications(我用一个确定播放器何时完成播放)...不要忘记删除它们。
答案 3 :(得分:0)
我在Monotouch遇到了同样的问题,并调整了Monotouch的rmomins答案。
已更改
avrecorder.Record();
到
NSError error;
var avsession = AVAudioSession.SharedInstance();
avsession.SetCategory(AVAudioSession.CategoryRecord,out error);
avrecorder.Record();
像魅力一样。
答案 4 :(得分:0)
我有同样的问题需要录制和播放。为了解决这个问题,我在“记录”和“播放”功能中重新调用了AVAudioSession。
这对于在设备上而不是在模拟器上出现此问题的人可能会有所帮助!
答案 5 :(得分:0)
我遇到了同样的问题。最后我发现ARC已经发布了我的录音机。因此,您必须在.h文件中声明录制器,即AVAudioRecord *recorder;
。把其他东西放到.m会正常工作。