Seamus Seamus - 4 months ago 74
iOS Question

AVAssetExportSession,AVMutableVideoComposition make video more red

I got video from livephoto, and export video like this more times.

It's become more red than source livephoto. It's a bug?

Here is export code and there is a demo project at the end.

- (void)clipMovie:(NSString *)path block:(void (^)(BOOL success))completionBlock
{
UIColor *bgcolor = (UIColor *)[UIColor blackColor];

AVURLAsset *videoasset = [[AVURLAsset alloc]initWithURL:[NSURL fileURLWithPath:path] options:nil];

AVMutableComposition *composition = [AVMutableComposition composition];
NSError *error;
[composition insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoasset.duration) ofAsset:videoasset atTime:kCMTimeZero error:&error];

AVMutableVideoCompositionInstruction *videoInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
videoInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, composition.duration);
videoInstruction.backgroundColor = bgcolor.CGColor;


if ([[composition tracksWithMediaType:AVMediaTypeVideo] count] > 0)
{
AVAssetTrack *videoTrack = [[composition tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

AVMutableVideoCompositionLayerInstruction *cropLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];

// CGSize naturalSize = videoTrack.naturalSize;

CGSize renderSize = CGSizeMake(1080, 1080);

AVAssetTrack *videoTracktmp = [[videoasset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
CGAffineTransform transform = videoTracktmp.preferredTransform;

CGRect drawrect = CGRectMake(0, 0, 1080, 1080);

[cropLayer setTransform:transform atTime:kCMTimeZero];

CALayer *backgroundLayer = [CALayer layer];
// [backgroundLayer setContents:(id)self.patternBgView.image.CGImage];
backgroundLayer.frame = CGRectMake(0, 0, renderSize.width, renderSize.height);
[backgroundLayer setMasksToBounds:YES];
backgroundLayer.backgroundColor = bgcolor.CGColor;

CALayer *videoLayer = [CALayer layer];


videoLayer.frame = CGRectMake(drawrect.origin.x, (renderSize.height-drawrect.size.height-drawrect.origin.y), drawrect.size.width, drawrect.size.height);
CALayer *parentLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, renderSize.width, renderSize.height);
[parentLayer addSublayer:backgroundLayer];
[parentLayer addSublayer:videoLayer];

AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];
videoInstruction.layerInstructions = @[cropLayer];
videoComposition.instructions = @[videoInstruction];

videoComposition.renderSize = CGSizeMake(renderSize.width, renderSize.height);
videoComposition.frameDuration = CMTimeMake(1, 15);

AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:videoasset presetName:AVAssetExportPresetHighestQuality];
exportSession.shouldOptimizeForNetworkUse = YES;
exportSession.videoComposition = videoComposition;
// exportSession.metadata = videoasset.metadata;

NSString *path = [[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"] stringByAppendingPathComponent:@"a"];
BOOL bo = [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
NSString *result = [path stringByAppendingPathComponent:@"a.mov"];

NSString *exportVideoPath = result;
// NSLog(@"%@",result);

if ([[NSFileManager defaultManager] fileExistsAtPath:exportVideoPath]) {
[[NSFileManager defaultManager] removeItemAtPath:exportVideoPath error:nil];
}

NSURL *exportURL = [NSURL fileURLWithPath:exportVideoPath];
exportSession.outputURL = exportURL;
// exportSession.metadata = [self updateMetadata:videoasset.metadata];
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
switch ((int)exportSession.status) {
case AVAssetExportSessionStatusFailed:{
// NSLog (@"FAIL");
completionBlock(NO);
break;
}
case AVAssetExportSessionStatusCompleted: {
// NSLog (@"SUCCESS");
completionBlock(YES);
break;
}
};
});

}];
}

}


then the video is more red than source livephoto.



here is demo link on github


  1. run project

  2. it will present imagepicker after 1s.

  3. select the livephoto

  4. and click chose

  5. then the new video save to your album. It's become red!


Answer

Opps! Just do it!

AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:videoasset presetName:AVAssetExportPresetPassthrough];

This export option will cause the media of all tracks to be passed through to the output exactly as stored in the source asset, except for tracks for which passthrough is not possible, usually because of constraints of the container format as indicated by the specified outputFileType. This option is not included in the arrays returned by -allExportPresets and -exportPresetsCompatibleWithAsset.