2
votes

I cannot get AVAssetExportSession to work when the application is in the background.

My application has the Background Mode "Background Fetch" enabled.

When this UIApplicationDelegate method is called

func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void)  

is called I use AVAssetExportSession to export an AVAsset, using the method:

exportAsynchronouslyWithCompletionHandler

I then receive this error:

Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSUnderlyingError=0x147dae560 {Error Domain=NSOSStatusErrorDomain Code=-16980 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-16980), NSLocalizedDescription=The operation could not be completed} 

However, when I have the background mode "Audio, Airplay and Picture in Picture", the export works.

This is great, however our submission is being rejected because we do not play any audio in the background.

is there any other way to export video in the background?

Cheers, Red

STEPS TO REPRODUCE I have created a sample project to show this issue.

Download from: http://up.red.to/WKo1MMstzD

  • Run the app on a device
  • Accept the permissions
  • Press the home button
  • In Xcode, go to Debug -> Simulate Background Refresh
  • See error (printed in console and shown as a local notification)
1
Hi @Red did you found any solution of your problem?Manish
Hi @Red, did you find a solution to his or the root cause of the error? Our app is being rejected too because of this.DennisA
@DennisA hey! Unfortunately, I did not. We decided to just perform the export when the app reopened. We did think about adding a feature that would give us a reason to use the "Audio, Airplay and Picture in Picture" permission, but ended up not doing that.Red Davis

1 Answers

1
votes

Your question:

is there any other way to export video in the background?

Absolutely, with some limitations.

NSProcessInfo has a set of APIs for requesting more time to finish tasks when the application is in the background. For example:

id activity = [[NSProcessInfo processInfo] beginActivityWithOptions:NSActivityAutomaticTerminationDisabled reason:@"Good Reason"];
[exportSession exportAsynchronouslyWithCompletionHandler:^{
    [[NSProcessInfo processInfo] endActivity:activity];
}];

That will get you more time. There are other APIs intended for synchronous operations, and in either case your application should still be prepared for the system to not allow more time. This was covered extensively in sessions at WWDC 2015.

You must also make sure that your background activity is not writing to a protected portion of the filesystem. Make sure the output location has the correct NSFileProtection attributes set to allow access even when the device is locked.

Now, specifically with background fetch you have a very limited amount of time to complete your work and call the background fetch completion handler. The background fetch API is intended to be used with NSURLSession to schedule background downloads that are executed out of your application process. Using the NSProcessInfo API will probably not buy you any more time here, and the background fetch API is a very poor fit for encoding/exporting media. The time required to complete for even small media files would exceed the time limit for the background fetch handler.