LightningStryk
LightningStryk

Reputation: 940

How to resume a recording using AVAudioRecorder?

I am writing an application that uses the AVAudioRecorder class. It works great except for when a phone call comes in. I am handling this per apple's guidelines of using the AVAudioRecorderDelegate methods

– (void) audioRecorderBeginInterruption:
– (void) audioRecorderEndInterruption:

It works great until the interruption ends and I attempt to "resume" the recording by calling the record method again (per the documentation). However it does not resume my recording but instead throws out the old one and starts up an entirely new one in its place. I have not been able to find a solution to this problem, if anyone has figured this out, or if it is a bug with apple's AVAudioRecorder please let me know. I really hope I do not have to write this using AudioQueues.

thanks

Upvotes: 8

Views: 3159

Answers (4)

coreyd303
coreyd303

Reputation: 87

There isn't actually a bug (at least not anymore). The current documentation (2023) for the method states that calling .record() will implicitly call .prepareToRecord() which creates a NEW file at the specified URL. Apple's docs clearly state that if a file exists at the URL it will be overwritten. In other words, "resuming" recording is impossible with the provided APIs. The only way to achieve this with AVAudioRecorder is to create multiple files and merge them. It should be noted that Apple's documentation of AVAudioRecorder.record() is misleading as it does in fact say "Starts or resumes audio recording".

https://developer.apple.com/documentation/avfaudio/avaudiorecorder/1388252-record https://developer.apple.com/documentation/avfaudio/avaudiorecorder/1389435-preparetorecord

Upvotes: 2

Liron Sher
Liron Sher

Reputation: 241

My solution was:

  1. Start record on temp file

  2. Watch for AVAudioSessionInterruptionNotificatio

  3. On AVAudioSessionInterruptionTypeBegan - stop the recording.
  4. On AVAudioSessionInterruptionTypeEnded - Start new recording.
  5. When the user stops - Marge the files.

Full Code

     [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(audioSessionInterruptionNotification:)
                                             name:AVAudioSessionInterruptionNotification
                                           object:audioSession];



    -(void)audioSessionInterruptionNotification:(NSNotification*)notification {
    NSString* seccReason = @"";
    //Check the type of notification, especially if you are sending multiple AVAudioSession events here
    NSLog(@"Interruption notification name %@", notification.name);
    NSError *err = noErr;
    if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) {
    seccReason = @"Interruption notification received";

    //Check to see if it was a Begin interruption
    if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeBegan]]) {
        seccReason = @"Interruption began";
        NSLog(@"Interruption notification name %@ audio pause", notification.name);

        dispatch_time_t restartTime = dispatch_time(DISPATCH_TIME_NOW,
                                                    0.01 * NSEC_PER_SEC);
        dispatch_after(restartTime, dispatch_get_global_queue(0, 0), ^{
            AVAudioRecorder *recorder = [[self recorderPool] objectForKey:lastRecID];
            if (recorder) {
                if(recorder.isRecording) {
                    [recorder stop];
                    NSLog(@"Interruption notification name Pauseing recording %@", lastRecID);
                } else {
                    NSLog(@"Interruption notification name Already Paused %@", lastRecID);
                }
            }else {
                NSLog(@"Interruption notification name recording %@ not found", lastRecID);
            }
              NSLog(@"Interruption notification Pauseing recording status %d",recorder.isRecording);
        });

    } else if([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] isEqualToNumber:[NSNumber numberWithInt:AVAudioSessionInterruptionTypeEnded]]){
        seccReason = @"Interruption ended!";
         NSLog(@"Interruption notification name %@ audio resume", notification.name);
        //Start New Recording
        dispatch_time_t restartTime = dispatch_time(DISPATCH_TIME_NOW,
                                                    0.1 * NSEC_PER_SEC);
        dispatch_after(restartTime, dispatch_get_global_queue(0, 0), ^{
            AVAudioRecorder *recorder = [[self recorderPool] objectForKey:lastRecID];
            NSLog(@"Interruption notification Resumeing recording status %d",recorder.isRecording);
            if (recorder) {
                if(!recorder.isRecording) {
                    NSString *filePath = [[self orgFileNames] objectForKey:lastRecID];
                    NSArray * fileNames =[[self fileNames] objectForKey:lastRecID];
                    NSString *tmpFileName = [self gnrTempFileName:filePath AndNumber:fileNames.count];
                    [[[self fileNames] objectForKey:lastRecID] addObject:tmpFileName];
                    NSURL *url = [NSURL fileURLWithPath:tmpFileName];
                    NSError *error = nil;
                    recorder = [[AVAudioRecorder alloc] initWithURL:url settings:recordSetting error:&error];
                    if (![recorder record]) {
                        NSLog(@"Interruption notification Error Resumeing recording %@",tempRecorder);
                        return;
                    }
                    [[self recorderPool] setObject:recorder forKey:lastRecID];
                    NSLog(@"Interruption notification nameResumeing recording %@",lastRecID);
                }else {
                     NSLog(@"Interruption notification Already Recording %d",recorder.isRecording);
                }
            }else {
                NSLog(@"Interruption notification name recording %@ not found",lastRecID);
            }
        });
      }
     } 
    }

Upvotes: 1

LightningStryk
LightningStryk

Reputation: 940

Looks like its a bug with apple's API. Great fun....

This was the response we received from a support ticket.

"The behavior you described is a bug and unfortunately there's nothing in the API that you can change to work around to actually append to the original recording. The interruption is resulting in capturing only the audio recorded after the interruption. You could try and stop the recording after the interruption then creating a new file after which would at least not cause the user to loose any information, but the result would be two separate files.

Please file a bug report at for this issue since bugs filed by external developers are critical when iOS engineering is evaluating critical features of fixes to address. It's easily reproducible but if you have a test app you can include please do, iOS engineering like having apps that show the bug directly. "

Upvotes: 9

Krishna Rambathri
Krishna Rambathri

Reputation: 129

You will try by using this piece of code

-(IBAction)pauseandplay:(id)sender
{
    BOOL status= [player isPlaying];
    if(status)
    {
    [pauseplay setImage:[UIImage imageNamed:@"play.png"]];
    [player pause];
    }
    else
    {
    [pauseplay setImage:[UIImage imageNamed:@"icon-pause.png"]];
    [player play];
    updateTimer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:@selector(updateCurrentTime) userInfo:player repeats:YES];
    }
}

Upvotes: -4

Related Questions