没有AVAsset的纯色的AVMutableComposition

这是我的最终目标:我想使用AVVideoCompositionCoreAnimationTool从Core Animation创buildvideo。 我不会在这个组合中使用现有的AVAsset。

我的问题是, 我怎样才能使用AVMutableComposition制作静态纯色video给定的时间? 在我弄清楚之后,我可以添加animation。

这是我的代码:

 - (void)exportVideo { AVMutableComposition *mixComposition = [AVMutableComposition composition]; CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(10, 600)); [mixComposition insertEmptyTimeRange:timeRange]; AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; [videoTrack insertEmptyTimeRange:timeRange]; AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; mainInstruction.timeRange = timeRange; mainInstruction.backgroundColor = [UIColor blueColor].CGColor; AVMutableVideoComposition *mainComposition = [AVMutableVideoComposition videoComposition]; mainComposition.renderSize = CGSizeMake(500, 500); mainComposition.instructions = [NSArray arrayWithObject:mainInstruction]; mainComposition.frameDuration = CMTimeMake(1, 30); NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"FinalVideo-%d.mov",arc4random() % 1000]]; NSURL *url = [NSURL fileURLWithPath:myPathDocs]; AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality]; exporter.outputURL = url; exporter.outputFileType = AVFileTypeQuickTimeMovie; exporter.shouldOptimizeForNetworkUse = YES; exporter.videoComposition = mainComposition; [exporter exportAsynchronouslyWithCompletionHandler:^{ dispatch_async(dispatch_get_main_queue(), ^{ [self exportDidFinish:exporter]; }); }]; } 

我知道你必须添加至less一个轨道到mixComposition,所以我已经添加了一个video轨道,并插入一个空的时间范围,但是当我调用exportAsynchronouslyWithCompletionHandler ,处理程序永远不会被调用。 我可以在调用导出后的任意时间内添加一个dispatch_after ,并观察导出器的状态为AVAssetExportSessionStatusExporting

我究竟做错了什么?

在几个月前玩了这个之后,我发现唯一可靠的方法就是在AVMutableCompositionTrack中使用一个简短的空白video,然后覆盖所需的图层。

由于模拟器中的错误,我在一个月前上传了一个项目到GitHub。 如果你愿意,你可以在这里下载这个空白的video。

 -(void)exportVideo { CGSize renderingSize = CGSizeMake(640, 360); // The desired size of your video float displayDuration = 2.0f; //The duration of the desired video, in seconds NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"FinalVideo-%d.mov",arc4random() % 1000]]; NSURL *url = [NSURL fileURLWithPath:myPathDocs]; NSError *error; [[NSFileManager defaultManager] removeItemAtURL:url error:&error]; mutableComposition = [AVMutableComposition composition]; mutableCompositionVideoTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; videoComposition = [AVMutableVideoComposition videoComposition]; videoComposition.renderSize = renderingSize; videoComposition.frameDuration = CMTimeMake(1, 30); CALayer *parentLayer = [CALayer layer]; CALayer *videoLayer = [CALayer layer]; parentLayer.frame = CGRectMake(0, 0, videoComposition.renderSize.width, videoComposition.renderSize.height); videoLayer.frame = CGRectMake(0, 0, videoComposition.renderSize.width, videoComposition.renderSize.height); [parentLayer addSublayer:videoLayer]; videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer]; NSString *path = [[NSBundle mainBundle] pathForResource:@"blank_1080p" ofType:@"mp4"]; NSURL *trackUrl = [NSURL fileURLWithPath:path]; AVAsset *asset = [AVAsset assetWithURL:trackUrl]; AVAssetTrack *track = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; [mutableCompositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,CMTimeMakeWithSeconds(displayDuration, 600)) ofTrack:track atTime:kCMTimeZero error:nil]; CALayer *imageLayer = [CALayer layer]; imageLayer.bounds = parentLayer.frame; imageLayer.anchorPoint = CGPointMake(0.5, 0.5); imageLayer.position = CGPointMake(CGRectGetMidX(imageLayer.bounds), CGRectGetMidY(imageLayer.bounds)); imageLayer.backgroundColor = [UIColor blueColor].CGColor; imageLayer.contentsGravity = kCAGravityResizeAspectFill; [parentLayer addSublayer:imageLayer]; AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(displayDuration, 600)); videoComposition.instructions = @[instruction]; exporter = [[AVAssetExportSession alloc] initWithAsset:mutableComposition presetName:AVAssetExportPresetHighestQuality]; exporter.outputURL = url; exporter.videoComposition = videoComposition; exporter.outputFileType= AVFileTypeMPEG4; exporter.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(displayDuration, 600)); exporter.shouldOptimizeForNetworkUse = YES; [exporter exportAsynchronouslyWithCompletionHandler:^(void){ dispatch_async(dispatch_get_main_queue(), ^{ [self exportDidFinish:exporter]; }); }]; }