ioscropavassetwriter

Is it possible fully crop a video with AVAssetWriter?


I am using AVAssetWriter to create a video file, I want to crop it and came upon the keys for AVVideoCleanApertureKey. This lets me set a viewport for the video, which looks like it is cropping the video. But in reality it doesn't, the full frame is still present in the video file, and wether the "crop" is used seems to be up to the view player.

So, is there a way to make discard the "outside" data around the viewport with AVAssetWriter? Or do I need to change my approach completely.

These images show the same video file, but only QuickTime cares about the viewport.

enter image description here


Solution

  • I believe the direct answer to the question is NO. So in the end I switched over to AVMutableVideoComposition and AVAssetExportSession as other answers around the web suggested.

        AVAsset *video = [AVAsset assetWithURL:outputURL];
        AVAssetTrack *assetVideoTrack = [[video tracksWithMediaType:AVMediaTypeVideo] lastObject];
        AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:assetVideoTrack];
        CGAffineTransform transform = CGAffineTransformMakeTranslation(-self.rect.origin.x, -self.rect.origin.y);
        [layerInstruction setTransform:transform atTime:kCMTimeZero];
        AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
        instruction.layerInstructions = @[layerInstruction];
        instruction.timeRange = assetVideoTrack.timeRange;
        AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
        
        // https://stackoverflow.com/questions/22883525/avassetexportsession-giving-me-a-green-border-on-right-and-bottom-of-output-vide
        videoComposition.renderSize = CGSizeMake(floor(self.rect.size.width / 16) * 16, 
                                                 floor(self.rect.size.height / 16) * 16);
        videoComposition.renderScale = 1.0;
        
        videoComposition.frameDuration = CMTimeMake(1, 30);
        videoComposition.instructions = @[instruction];
        AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:video presetName:AVAssetExportPreset1280x720];
        exportSession.shouldOptimizeForNetworkUse = NO;
        exportSession.outputFileType = AVFileTypeMPEG4;
        exportSession.videoComposition = videoComposition;
        exportSession.outputURL = outputURL2;
    
        [exportSession exportAsynchronouslyWithCompletionHandler:^{ 
            NSLog(@"done processing video!");
        }];