使用AVVideoCompositionCoreAnimationTool将video与静态图像混合在CALayer中

我正试图将来自相机的video与静态图像(水印)混合在一起。

我已经检查了这里的问题和答案,还有一些例子,包括来自Apple的WWDC AVEditDemo,并以下面的代码结束。 不幸的是,导出的video不包含图像的图层。 有任何想法吗?

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { /// incoming video NSURL *videoURL = [info valueForKey:UIImagePickerControllerMediaURL]; /// UIImage into CALayer UIImage *myImage = [UIImage imageNamed:@"m1h.png"]; CALayer *aLayer = [CALayer layer]; aLayer.contents = (id)myImage.CGImage; AVURLAsset* url = [AVURLAsset URLAssetWithURL:videoURL options:nil]; AVMutableComposition *videoComposition = [AVMutableComposition composition]; NSError *error; NSFileManager *fileManager = [NSFileManager defaultManager]; AVMutableCompositionTrack *compositionVideoTrack = [videoComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; AVAssetTrack *clipVideoTrack = [[url tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [url duration]) ofTrack:clipVideoTrack atTime:kCMTimeZero error:&error]; AVMutableVideoComposition* videoComp = [[AVMutableVideoComposition videoComposition] retain]; videoComp.renderSize = CGSizeMake(640, 480); videoComp.frameDuration = CMTimeMake(1, 30); videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithAdditionalLayer:aLayer asTrackID:2]; /// instruction AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30) ); AVMutableVideoCompositionLayerInstruction* layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:clipVideoTrack]; instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction]; videoComp.instructions = [NSArray arrayWithObject: instruction]; /// outputs NSString *filePath = nil; filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; filePath = [filePath stringByAppendingPathComponent:@"temp.mov"]; NSLog(@"exporting to: %@", filePath); if ([fileManager fileExistsAtPath:filePath]) { BOOL success = [fileManager removeItemAtPath:filePath error:&error]; if (!success) NSLog(@"FM error: %@", [error localizedDescription]); } /// exporting AVAssetExportSession *exporter; exporter = [[AVAssetExportSession alloc] initWithAsset:videoComposition presetName:AVAssetExportPresetHighestQuality] ; exporter.videoComposition = videoComp; exporter.outputURL=[NSURL fileURLWithPath:filePath]; exporter.outputFileType=AVFileTypeQuickTimeMovie; [statusLabel setText:@"processing..."]; [exporter exportAsynchronouslyWithCompletionHandler:^(void){ switch (exporter.status) { case AVAssetExportSessionStatusFailed: NSLog(@"exporting failed"); break; case AVAssetExportSessionStatusCompleted: NSLog(@"exporting completed"); UISaveVideoAtPathToSavedPhotosAlbum(filePath, self, @selector(video:didFinishSavingWithError:contextInfo:), NULL); break; case AVAssetExportSessionStatusCancelled: NSLog(@"export cancelled"); break; } }]; 

}

在玩完之后,我除了上面的代码之外还有类似的东西,还改变了使用方法videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:

 CALayer *parentLayer = [CALayer layer]; CALayer *videoLayer = [CALayer layer]; parentLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height); videoLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height); [parentLayer addSublayer:videoLayer]; [parentLayer addSublayer:aLayer]; videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer]; 

希望它有助于某人。

我得到这个工作! inheritance人的代码! 我没有写大部分的,我只是调整了一些,但唯一的问题是video本身是旋转为纵向模式的风景? 然后在它的肖像video的风景,但形象正面朝上!

 CALayer *aLayer = [CALayer layer]; aLayer.frame = CGRectMake(5, 0, 320, 480); aLayer.bounds = CGRectMake(5, 0, 320, 480); aLayer.contents = (id) [UIImage imageNamed:@"image.png"].CGImage; aLayer.opacity = 0.5; aLayer.backgroundColor = [UIColor clearColor].CGColor; NSURL *url = [NSURL fileURLWithPath:[urlsOfVideos objectAtIndex:self.pageControl.currentPage]]; AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url options:nil]; cmp = [AVMutableComposition composition]; AVMutableCompositionTrack *trackA = [cmp addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; AVAssetTrack *sourceVideoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; [trackA insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset duration]) ofTrack:sourceVideoTrack atTime:kCMTimeZero error:nil] ; animComp = [AVMutableVideoComposition videoComposition]; animComp.renderSize = CGSizeMake(320, 480); animComp.frameDuration = CMTimeMake(1,30); CALayer *parentLayer = [CALayer layer]; CALayer *videoLayer = [CALayer layer]; parentLayer.frame = CGRectMake(0, 0, 320, 480); videoLayer.frame = CGRectMake(0, 0, 320, 480); [parentLayer addSublayer:videoLayer]; [parentLayer addSublayer:aLayer]; animComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer]; AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; instruction.timeRange = CMTimeRangeMake(kCMTimeZero, [asset duration]); AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:trackA]; //[layerInstruction setTrackID:2]; [layerInstruction setOpacity:1.0 atTime:kCMTimeZero]; instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction] ; animComp.instructions = [NSArray arrayWithObject:instruction]; [self exportMovie:self]; 

这里是导出代码

 -(IBAction) exportMovie:(id)sender{ NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *tempPath = [docPaths objectAtIndex:0]; NSLog(@"Temp Path: %@",tempPath); NSString *fileName = [NSString stringWithFormat:@"%@/output-anot.MOV",tempPath]; NSFileManager *fileManager = [NSFileManager defaultManager] ; if([fileManager fileExistsAtPath:fileName ]){ //NSError *ferror = nil ; //BOOL success = [fileManager removeItemAtPath:fileName error:&ferror]; } NSURL *exportURL = [NSURL fileURLWithPath:fileName]; AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:cmp presetName:AVAssetExportPresetHighestQuality] ; exporter.outputURL = exportURL; exporter.videoComposition = animComp; exporter.outputFileType= AVFileTypeQuickTimeMovie; [exporter exportAsynchronouslyWithCompletionHandler:^(void){ switch (exporter.status) { case AVAssetExportSessionStatusFailed:{ NSLog(@"Fail"); break; } case AVAssetExportSessionStatusCompleted:{ NSLog(@"Success"); break; } default: break; } }]; 

}