Video : insérer une image dans une vidéo

Bonjour à  tous


Je cherche par le biais d'AVAsset d'insérer une image dans une séquence vidéo. J'ai bien trouvé quelque chose sur le net mais ... qui ne fonctionne pas : l'image n'est pas insérée. Pourtant tout m'a l'air correcte, sachant que la vidéo et l'image ne sont pas nul après déboggage ... mais mon niveau sous objectiveC n'est pas extraordinaire !!


 


Si quelqu'un peut me dire ce qui cloche, voici le code


 


 


Merci d'avance



-(IBAction)addImage:(id)sender
{
//create the AVURLAsset first:
NSURL *monUrl = [NSURL URLWithString:@file:////Developer/xCode%20Divers/xCode4/EssaiVideoAV/Sequence3.mov];
AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:monUrl options:nil];

AVMutableComposition* mixComposition = [AVMutableComposition composition];

AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVAssetTrack *clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)
ofTrack:clipVideoTrack
atTime:kCMTimeZero error:nil];

[compositionVideoTrack setPreferredTransform:[[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] preferredTransform]];

//create the layer with the watermark image:
NSImage *myImage = [[NSImage alloc]initByReferencingFile:@file:////Developer/xCode%20Divers/xCode4/EssaiVideoAV/Punk.jpg];
myImage.size = NSMakeSize(20, 20);
CALayer *aLayer = [CALayer layer];
aLayer.contents = (id)myImage;
aLayer.frame = CGRectMake(5, 25, 57, 57); //Needed for proper display. We are using the app icon (57x57). If you use 0,0 you will not see it
aLayer.opacity = 0.65; //Feel free to alter the alpha here


CGSize videoSize = [clipVideoTrack naturalSize];

//want text instead:
CATextLayer *titleLayer = [CATextLayer layer];
titleLayer.string = @Text goes here;
titleLayer.font = @Helvetica;
titleLayer.fontSize = videoSize.height / 6;
//?? titleLayer.shadowOpacity = 0.5;
titleLayer.alignmentMode = kCAAlignmentCenter;
titleLayer.bounds = CGRectMake(0, 0, videoSize.width, videoSize.height / 6); //You may need to adjust this for proper display


// sorts the layer in proper order:
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];
[parentLayer addSublayer:titleLayer]; //ONLY IF WE ADDED TEXT


//creating the composition and add the instructions to insert the layer:
AVMutableVideoComposition* videoComp = [[AVMutableVideoComposition videoComposition] retain];
videoComp.renderSize = videoSize;
videoComp.frameDuration = CMTimeMake(1, 30);
videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

/// instruction
AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, [mixComposition duration]);
AVAssetTrack *videoTrack = [[mixComposition tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVMutableVideoCompositionLayerInstruction* layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction];
videoComp.instructions = [NSArray arrayWithObject: instruction];


//export

NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, 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 *assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetMediumQuality];//AVAssetExportPresetPassthrough
assetExport.videoComposition = videoComp;


assetExport.outputFileType = AVFileTypeQuickTimeMovie;
assetExport.outputURL = exportURL;
assetExport.shouldOptimizeForNetworkUse = YES;

[assetExport exportAsynchronouslyWithCompletionHandler:
^(void ) {
[assetExport release];
//YOUR FINALIZATION CODE HERE
}
];

[videoAsset release];

}


Réponses

  • CéroceCéroce Membre, Modérateur
    C'est difficile à  dire sans débogueur, mais il me semble que cet exemple n'insère pas une image, mais effectue une incrustation.

    Tu dis que ça ne fonctionne pas... c'est vague. As-tu une vidéo en sortie ?
  • Bonjour Céroce


    Oui j'ai une vidéo en sortie mais uniquement de la vidéo importée sans l'incrustation

  • CéroceCéroce Membre, Modérateur
    avril 2017 modifié #4
    Es-tu sûr que les images sont chargées ? (à  noter que le débogueur est capable d'afficher l'aperçu d'une NSImage).
    Parce que si ce n'est pas le cas, ça met juste le contents des CALayer à  nil, ce qui est permis, et tu n'auras pas de plantage.
  • Alors le NSImage n'est pas à  nil (je n'ai pas vu comment le débogguer affiche l'image) et la CALAyer n'est pas à  nil non plus

  • Cliques droit sur l'objet l'UIImage dans la colonne gauche de ton debugger, puis t'as une popup ou tu peux dire que tu veux voir l'image.


  • OK merci pour l'info...bien pratique


     


    Donc en effet, l'image n'était pas chargée : rien au preview et du coup j'ai voulu l'afficher directement dans mon appli et rien non plus. Comprends pas puisque la NSImage n'est pas nul. Bref donc j'ai procédé autrement en incorporant l'image directement dans mon appli et j'ai utilisé     NSImage *myImage = [NSImage  imageNamed:@Punk.jpg];


    et là  ça marche... Du coup, je ne comprends pas pourquoi l'image n'a pas été chargée avant (d'autant que NSImage n'est pas mal !) avec 

    NSImage *myImage = [[NSImage alloc]initByReferencingFile:@file:////Developer/xCode%20Divers/xCode4/EssaiVideoAV/Punk.jpg];

     

    Dans l'attente de vous lire et merci encore

  • J'aimerais savoir, cherches-tu à  faire de l'image subliminal ou souhaites-tu donner de l'information au spectateur ?


  • CéroceCéroce Membre, Modérateur
    avril 2017 modifié #9
    -[NSImage initByReferencingFile] lit l'image de façon paresseuse, c'est à  dire que tant qu'on ne cherche pas vraiment à  l'utiliser, l'image n'est pas chargée. Si le fichier n'existe pas, tu obtiens donc une instance de NSImage valide, mais qui ne chargera pas d'image.

    Le chemin de ton fichier a la forme d'une URL, c'est le problème. ça devrait plutôt être du genre "Developer/xCode Divers/xCode4/EssaiVideoAV/Punk.jpg".
  • En réponse à  tablier, je cherche surtout à  essayer de maitriser tant bien que mal AVFoundation !!!


     


    Et merci à  Céroce pour ton aide


Connectez-vous ou Inscrivez-vous pour répondre.