Question

I have searched and read the docs, but I cannot seem to find a solution to this (seemingly-simple) issue I've run into. I have songs exporting working fine from the user's iTunes library, and it downloads into the user's documents folder with no issues every time, but videos just don't seem to work.

I have it showing an MPMediaPickerController (allowsPickingMultipleItems = YES) to allow the user to select either videos or songs from their downloaded library. When done, here is the relavent code I'm using:

- (void)mediaPicker:(MPMediaPickerController*)mediaPicker didPickMediaItems:(MPMediaItemCollection*)mediaItemCollection {
    AVAssetExportSession *exportSession;

    for (MPMediaItem *item in mediaItemCollection.items) {
        NSURL *assetUrl = [item valueForProperty:MPMediaItemPropertyAssetURL];
        MPMediaType type = [[item valueForProperty:MPMediaItemPropertyMediaType] intValue];
        if (type >= MPMediaTypeMovie) {
            exportSession = [[AVAssetExportSession alloc] initWithAsset:[AVAsset assetWithURL:assetUrl] presetName:AVAssetExportPreset640x480];
            exportSession.outputFileType = AVFileTypeQuickTimeMovie;
            filePath = [title stringByAppendingString:@".mov"];
            exportSession.outputURL = [NSURL fileURLWithPath:[[NSFileManager documentDirectory] stringByAppendingPathComponent:filePath]];
        } // .. check for song-types here and set session up appropriately

        [exportSession exportAsynchronouslyWithCompletionHandler:^{
            // never gets into AVAssetExportSessionStatusCompleted here for videos 
        }
    }
}

The error I get every time is the following:

Error Domain=AVFoundationErrorDomain Code=-11820 "Cannot Complete Export" UserInfo=0x1e1a2180 {NSLocalizedRecoverySuggestion=Try exporting again., NSLocalizedDescription=Cannot Complete Export}

Not very helpful. :( I feel like I may be potentially missing something obvious here. Am I going about this the correct way? Is it potentially a problem with me trying to "force" it to MOV-format? Or perhaps needing a different way of setting up the export session?

For reference, I'm using iOS 6.0.1 on my iPhone 5 for testing, with a baseSDK of 6.0. Thanks in advance for any guidance that can be offered on this!

Additional Info #1: something that's odd. It seems to crash immediately with a "SIGTRAP" if I set the outputFileType to "AVFileTypeAppleM4V".. I wanted to try M4V, because when I do a log output of the assetURL, I see something like: ipod-library://item/item.m4v?id=12345. Don't know if that makes a difference or not, but odd that it just crashes like that if I try m4v format. Probably because it's not in the supported filetypes list (see next info point).

Additional Info #2: The supported file types I get (from calling the "supportedFileTypes" method are: "com.apple.quicktime-movie" and "public.mpeg-4". The "exportPresetsCompatibleWithAsset" include all of the video ones, including m4a, low/med/high quality, and the specific dimensions ones. I have tried EVERY combination of all these, such as AVFileTypeQuickTimeMovie and AVFileTypeMPEG4 for fileTypes, and all of the presets, including the low/med/high, and all of the dimension ones. It never fails that I get the "Cannot Complete Export" error.

Additional Info #3: I am also using a Deployment Target of 5.1. But yes, I have tried 6.0, and it gives the same error. :(

Additional Info #4: If needed to know, the movie I'm testing with is a "Pilot" TV show, one video, the first one I saw in iTunes that was free. So I downloaded it for use in this app.

Additional Info #5: Not sure if this is important, but the "hasProtectedContent" method returns YES for the AVAsset (and AVURLAsset if I convert). May not make a difference, but thought I'd throw it out there.

Was it helpful?

Solution

After trying to replicate the issue and doing some testing, I strongly suspect the protected content is an issue. Here's why:

I copied your code, and tested it on my iPod Touch (5th gen, iOS 6.0.1), though instead of coming from a media picker, I just let it loop through all the videos I have on the device (7 of them.) It worked great, and called the completion handler and made proper .mov files in the documents directory of the app sandbox. I moved the .mov files to my Mac and they all played.

These video files had the hasProtectedContent as NO.

So I placed a video file I got from the iTunes store, and confirmed it had the hasProtectedContent as YES. Interestingly, when I try to get the URL from MPMediaItemPropertyAssetURL, I get nil for the protected/iTunes obtained video.

I strongly suspect the media protection is the problem.

Here's the variation of code that I used. I didn't change your conversion code at all, just how the URLs are supplied:

// select all the video files
MPMediaPropertyPredicate *predicate = [MPMediaPropertyPredicate predicateWithValue:[NSNumber numberWithInteger:MPMediaTypeMovie] forProperty:MPMediaItemPropertyMediaType];

MPMediaQuery *query = [[MPMediaQuery alloc] init];
[query addFilterPredicate:predicate];

NSArray *items = [query items];

// now go through them all to export them

NSString* title;
NSURL * url;
AVAssetExportSession *exportSession;
NSString *storePath;
AVAsset *theAsset;

// we fill put the output at this path
NSString *applicationDocumentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];


// loop through the items and export
for (MPMediaItem* item in items)
{
    title = [item valueForProperty:MPMediaItemPropertyTitle];
    url = [item valueForProperty:MPMediaItemPropertyAssetURL];

    NSLog(@"Title: %@, URL: %@",title,url);

    theAsset = [AVAsset assetWithURL:url];

    if ([theAsset hasProtectedContent]) {
        NSLog(@"%@ is protected.",title);
    } else {
        NSLog(@"%@ is NOT protected.",title);
    }

    exportSession = [[AVAssetExportSession alloc] initWithAsset:theAsset presetName:AVAssetExportPreset640x480];

    storePath = [applicationDocumentsDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mov",title]];

    exportSession.outputFileType = AVFileTypeQuickTimeMovie;

    exportSession.outputURL = [NSURL fileURLWithPath:storePath];

    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        NSLog(@"done!");
    }];

}

Out of curiosity, are you checking the AVAsset exportable flag?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top