Search code examples
iosios8avcapturesessionavassetexportsession

Cropping a video with AVAsset/AVCaptureSession


I'm trying to crop a video into a square. I already have an AVCaptureSession setup that produces a rectangle resolution .mov file. So I'm just trying to crop it with some code I found here. Here is my code:

-(void)cropVideo:(NSURL*)videoURL{


// input file
AVAsset* asset = [AVAsset assetWithURL:videoURL];

AVMutableComposition *composition = [AVMutableComposition composition];
[composition  addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

// input clip
AVAssetTrack *clipVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

// make it square
AVMutableVideoComposition* videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.renderSize = CGSizeMake(clipVideoTrack.naturalSize.height, clipVideoTrack.naturalSize.height);
videoComposition.frameDuration = CMTimeMake(1, 30);

AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30) );

// rotate to portrait
AVMutableVideoCompositionLayerInstruction* transformer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:clipVideoTrack];
CGAffineTransform t1 = CGAffineTransformMakeTranslation(clipVideoTrack.naturalSize.height, -(clipVideoTrack.naturalSize.width - clipVideoTrack.naturalSize.height) /2 );
CGAffineTransform t2 = CGAffineTransformRotate(t1, M_PI_2);

CGAffineTransform finalTransform = t2;
[transformer setTransform:finalTransform atTime:kCMTimeZero];
instruction.layerInstructions = [NSArray arrayWithObject:transformer];
videoComposition.instructions = [NSArray arrayWithObject: instruction];

// export
exporter = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality] ;
exporter.videoComposition = videoComposition;

NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
NSURL *fileURL = [[tmpDirURL URLByAppendingPathComponent:@"final"] URLByAppendingPathExtension:@"mov"];

exporter.outputURL=fileURL;
exporter.outputFileType=AVFileTypeQuickTimeMovie;

[exporter exportAsynchronouslyWithCompletionHandler:^(void){
    NSLog(@"Exporting done!");
    NSLog(@"exporter's outputURL is %@", exporter.outputURL);
    self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
    [self.view addSubview:self.moviePlayer.view];
    self.moviePlayer.fullscreen = YES;
    [self.moviePlayer play];
    
}];}

However, after running the exporter, the movie doesn't play in self.moviePlayer. It just goes "Loading..". Note that I tested the moviePlayer with the original videoURL parameter and that plays fine. Any ideas on what I'm doing wrong?

Thanks


Solution

  • Need:

    dispatch_async(dispatch_get_main_queue(), ^{
      //play movie here
    });
    

    in the completion handler.