10

我的iPhone應用程序使用「AVAudioRecorder」進行錄音。它還使用「UIImagePickerController」記錄電影和「MPMoviePlayerController」播放電影。AVAudioRecorder不會記錄IF電影以前錄製和播放

一切工作正常,直到我做三件事成一排:

  1. 錄製電影中使用的UIImagePickerController
  2. 播放使用的MPMoviePlayerController
  3. 嘗試撥打語音使用記錄AVAudioRecorder
  4. 錄製的動畫

當我在步驟3中調用AVAudioRecorder的「記錄」方法時,它返回NO指示失敗,但沒有提示爲什麼(來自Appl e!)AVAudioRecorder的audioRecorderEncodeErrorDidOccur委託方法永遠不會被調用,並且在設置錄像機時我不會收到其他錯誤。

我的第一個猜測是電影錄製/播放正在修改「AVAudioSession」的共享實例,使得它阻止了錄音機的工作。但是,我手動將AVAudioSession的category屬性設置爲「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!"); 
} 

有沒有人碰到這個問題?

回答

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 
} 
+0

謝謝,我遇到了同樣的問題,無法弄清楚發生錯誤的時間! – 2011-08-27 16:51:55

+0

謝謝,它有幫助。 – 2013-02-14 07:02:27

0

我在MonoTouch的同樣的問題,並調整Monotouch的答案爲rmomins

改變

avrecorder.Record(); 

NSError error; 
var avsession = AVAudioSession.SharedInstance(); 
avsession.SetCategory(AVAudioSession.CategoryRecord,out error); 

avrecorder.Record(); 

就像一個魅力。

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 ......鬆開,設置它的變種爲零,無論你需要做的。 **
  4. 現在您可以錄製。 AVPlayer不存在,所以AVAudioRecorder可以自由地做它的事情。
  5. 當您準備再次播放時,使用您已經加載的資產重新實例化AVPlayerItem & AVPlayer。再次,這是微不足道的。該資產已經被加載,所以不應該有延遲。

**請注意,銷燬AVPlayer可能不僅僅是釋放它並將其var設置爲零。最有可能的是,您還添加了定期時間觀察員來跟蹤播放進度。當你這樣做時,你會收到一個你應該堅持的不透明物體。如果您不從播放器中刪除此項目並釋放它/將其設置爲零,AVPlayer將不會釋放。看起來,Apple創建了一個有意的保留週期,您必須手動中止。你破壞AVPlayer所以,如果你需要(例如):

[_player removeTimeObserver:_playerObserver]; 
[_playerObserver release]; //Only if you're not using ARC 
_playerObserver = nil; 

作爲一個側面說明,你也可能已設置了NSNotifications(我用一個來確定當玩家完成遊戲)......不忘記刪除這些。

2

有同樣的問題。我的解決方案是在開始錄製會話之前停止播放電影。我的代碼與rmomin的代碼類似。

0

我有同樣的問題來記錄和播放。爲了解決這個問題,我記得在「記錄」和「播放」功能中的AVAudioSession。

這可能有助於在設備上而不是在模擬器上出現此問題的人!

0

我得到了同樣的問題。最後我發現ARC已經發布了我的錄音機。因此,您必須在.h文件中聲明刻錄機,即AVAudioRecord *recorder;。將其他東西放在.m將正常工作。