2011-05-13 10 views
15

Próbuję połączyć wideo pochodzące z aparatu ze statycznym obrazem (znak wodny).Miksowanie wideo ze statycznym obrazem w CALayerze za pomocą AVVideoCompositionCoreAnimationTool

Sprawdziłem tutaj pytania/odpowiedzi i kilka przykładów, w tym WWDC AVEditDemo firmy Apple i zakończyłem poniższym kodem. Niestety wyeksportowane wideo nie zawiera warstwy z obrazem. Jakieś pomysły?

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

}

Odpowiedz

10

Po odtworzeniu całego skończyło się z czymś takim w uzupełnieniu do powyższego kodu, także zmieniając stosowaną metodą 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]; 

Nadzieja pomaga kogoś.

+2

Mam podobny problem (patrz [tutaj] (http://stackoverflow.com/questions/6749216/how- aby poprawnie eksportować-calayer-on-top-of-avmutablecomposition-with-avassetexports), ale coś idzie nie tak. Myślisz, że możesz mi pomóc? –

2

Mam to do roboty! Oto kod! Nie napisałem większości, po prostu poprawiłem niektóre, ale jedynym problemem jest to, że sam film jest obracany dla krajobrazu w trybie portretu? a następnie w krajobrazie jego portret wideo, ale obraz jest prawą stroną do góry!

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

i oto kod eksportujący

-(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

czy Twój obraz nie powinien być tits.png? –

+1

@NicolasManzini nie, w dokumentach jabłkowych jest napisane boobs.png – NSGodMode

+0

LMFAO. Mój błąd. Ten kod został użyty w projekcie, nad którym pracowałem dla firmy i po prostu go skopiuję/wklejam bez sprawdzania zawartości. o mój. – Maximilian

Powiązane problemy