Stop Camera recording and save file when entering background

2.8k views Asked by At

I've been looking for the answer for 2 days, but I can't seem to get it right...

I have an example app that records audio and video from the device using a AVCaptureSession and a AVCaptureMovieFileOutput.

When I start recording I call:

[self.movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];

And it starts recording to the file. If I press the button again it stops recording

[self.movieFileOutput stopRecording];

Everything works well, but when I enter background (incoming call or HOME press) I get an error in the delegate method: didFinishRecordingToOutputFileAtURL

My desired action should be saving / completing the file on entering the background. If I call stopRecording on "applicationDidEnterBackground" it will enter background before the applicationDidEnterBackground is called. On entering the active state it is called.... and generates an error and leaves a corrupted movie file...

It seems that it hasn't got enough time to save the file.

What am I missing here?

This is my Error

Error Domain=AVFoundationErrorDomain Code=-11818 "Recording Stopped" UserInfo=0x17594e20 {NSLocalizedRecoverySuggestion=Stop any other actions using the recording device and try again., NSUnderlyingError=0x175d3500 "The operation couldn’t be completed. (OSStatus error -16133.)", NSLocalizedDescription=Recording Stopped}

AVErrorSessionWasInterrupted = -11818
2

There are 2 answers

1
Melih Büyükbayram On BEST ANSWER

NSOperationQueue is the recommended way to perform multi-threaded tasks to avoid blocking the main thread. Background thread is used for tasks that you want to perform while your application is inactive, like GPS indications or Audio streaming.

If your application is running in foreground, you don't need background thread at all.

For simple tasks, you can add a operation to a queue using a block:

NSOperationQueue* operationQueue = [[NSOperationQueue alloc] init];
[operationQueue addOperationWithBlock:^{
    // Perform long-running tasks without blocking main thread
}];

More info about NSOperationQueue and how to use it.

- (void)applicationWillResignActive:(UIApplication *)application {
    bgTask = [application beginBackgroundTaskWithExpirationHandler:^{

      // Wait until the pending operations finish
      [operationQueue waitUntilAllOperationsAreFinished];

      [application endBackgroundTask: bgTask];
      bgTask = UIBackgroundTaskInvalid;
    }]; 
}
4
Krishna Kumar On

You can handle saving in applicationWillResignActive: and then you can continue your process in background.