2011-05-13 54 views
15

我试图将来自相机的视频与静态图像(水印)混合使用。使用AVVideoCompositionCoreAnimationTool在CALayer中将静态图像与静态图像混合使用

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

- (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; 
    } 
}]; 

}

回答

10

玩弄后,我结束了在除了上面的代码这样的事情,也改变了使用的方法来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]; 

希望它可以帮助别人。

+2

我有一个类似的问题(见[这里](http://stackoverflow.com/questions/6749216/how- to-properly-export-calayer-on-top-of-avmutablecomposition-with-avassetexports)),但是出了点问题。你认为你能帮助我吗? – 2011-07-19 14:57:49

2

我得到了这个工作!继承人的代码!我没有写大部分内容,我只是调整了一些,但唯一的问题是视频本身是否在纵向模式下旋转为横向模式?然后在它的肖像视频的横向,但图像是正确的一面!

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; 
    } 
}]; 

}

+9

不应该你的形象是tits.png? – 2014-02-18 11:12:08

+1

@NicolasManzini不,苹果文件中说它boobs.png – NSGodMode 2016-04-04 23:15:51

+0

LMFAO。我的错。这段代码被用在我为一家公司工作的项目中,我只是复制/粘贴它而不检查内容。天啊。 – Maximilian 2016-04-06 23:14:38