Search code examples
iosavfoundationavplayerphotokit

Issue playing slow-mo AVAsset in AVPlayer


I'm trying to play an slow motion video (filmed by the user's iPhone) in an AVPlayer.

I am retrieving the AVAsset with a request on a PHAsset from a picker:

   [manager requestAVAssetForVideo:PHAsset
                           options:videoRequestOptions
                     resultHandler:^(AVAsset * avasset, AVAudioMix * audioMix, NSDictionary * info) {}];

The problem is once it plays, I get this error:

 -[AVComposition URL]: unrecognized selector sent to instance 0x138d17f40

However, if I set this option on the manager request, it will play as normal speed video at 120/240fps and no crashes:

  videoRequestOptions.version = PHVideoRequestOptionsVersionOriginal;

Whats going on? The default version property is PHVideoRequestOptionsVersionCurrent which incorporates slow motion, user edits and trims, etc.

I would like to play that video version. Thanks


Solution

  • So it turns out that slow motion videos are passed as AVComposition.

    You can export that into a video file / URL, and then handle it like any other video.

    Solution here: https://overflow.buffer.com/2016/02/29/slow-motion-video-ios/

    //Output URL
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = paths.firstObject;
    NSString *myPathDocs =  [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"mergeSlowMoVideo-%d.mov",arc4random() % 1000]];
    NSURL *url = [NSURL fileURLWithPath:myPathDocs];
    
    //Begin slow mo video export
    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];
    exporter.outputURL = url;
    exporter.outputFileType = AVFileTypeQuickTimeMovie;
    exporter.shouldOptimizeForNetworkUse = YES;
    
    [exporter exportAsynchronouslyWithCompletionHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            if (exporter.status == AVAssetExportSessionStatusCompleted) {
                NSURL *URL = exporter.outputURL;
                NSData *videoData = [NSData dataWithContentsOfURL:URL];
    
                 // Upload
                 [self uploadSelectedVideo:video data:videoData];
             }
        });
    }];