AVAudioRecorder不会录制以前录制的IF电影&发挥

时间:2010-11-10 19:13:17

标签: iphone uiimagepickercontroller mpmovieplayercontroller avaudiorecorder

我的iPhone应用程序使用“AVAudioRecorder”进行录音。它还使用“UIImagePickerController”来录制电影,使用“MPMoviePlayerController”来播放电影。

一切正常,直到我连续做三件事:

  1. 使用UIImagePickerController录制电影
  2. 使用MPMoviePlayerController播放录制的电影
  3. 尝试使用AVAudioRecorder进行录音
  4. 当我在步骤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!");
    }
    

    之前有没有人遇到过这个问题?

6 个答案:

答案 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(或其任何子类)。你真的只想做一次。他们的关键是使用这个序列:

  1. 加载AVAsset(例如,如果您从文件加载,直接使用AVURLAsset或将其添加到AVMutableComposition并使用它)并保留对它的引用。在你完成之前不要放手。加载它是一直需要的。
  2. 一旦你准备好玩:用你的资产实例化AVPlayerItem,然后用AVPlayerItem实现AVPlayer并播放它。不要保留对AVPlayerItem的引用,AVPlayer将保留对它的引用,并且无论如何你都不能将它重用于其他播放器。
  3. 一旦完成播放,立即销毁 AVPlayer ...释放它,将其var设置为nil,无论你需要做什么。 **
  4. 现在你可以录制了。 AVPlayer不存在,因此AVAudioRecorder可以随心所欲。
  5. 当您准备再次播放时,使用您已加载的资产重新实例化AVPlayerItem& AVPlayer。同样,这是微不足道的。资产已经加载,所以不应该有延迟。
  6. **请注意,销毁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会正常工作。