2011-05-13 12 views
15

Estoy intentando mezclar video, viniendo de la cámara con una imagen estática (marca de agua).Mezclar video con imagen estática en CALayer usando AVVideoCompositionCoreAnimationTool

He revisado las preguntas y respuestas aquí y algunos ejemplos, incluido WWDC AVEditDemo de Apple y que finalizó con el siguiente código. Desafortunadamente, el video exportado no contiene la capa con la imagen. Alguna idea?

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

}

Respuesta

10

Después de jugar acabé con algo como esto en una adición al código anterior, también cambia el método utilizado para 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]; 

espero que ayude a alguien.

+2

Estoy teniendo un problema similar (ver [aquí] (http://stackoverflow.com/questions/6749216/how- to-properly-export-calayer-on-top-of-avmutablecomposition-with-avassetexports)) pero algo sale mal. ¿Crees que puedes ayudarme? –

2

¡tengo esto para trabajar! aquí está el código! No escribí la mayor parte, acabo de ajustar un poco, ¿pero el único problema es que el video en sí se gira para el paisaje en modo vertical? y luego en el paisaje su video de retrato, ¡pero la imagen está boca arriba!

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

y aquí está el código de exportación

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

¿No debería su imagen ser tits.png? –

+1

@NicolasManzini no, en los documentos de Apple dice boobs.png – NSGodMode

+0

LMFAO. Mi error. Este código fue utilizado en un proyecto en el que trabajé para una empresa y lo copié/pegué sin verificar el contenido. Oh mi. – Maximilian

Cuestiones relacionadas