Comment puis-je append du text en superposition sur une video, puis le réencoder?

Je veux éditer la video de mon application iOS. Je veux du text sur la video source pour les sous-titres de la langue. Je veux ensuite save la video avec ce text superposé. text non seulement le but d'affichage. mais quand j'ouvre la video éditée montre la video mise à jour.

Est-ce possible dans une application iOS? Si c'est le cas, comment?

- (void)addAnimation { NSSsortingng *filePath = [[NSBundle mainBundle] pathForResource:videoName ofType:ext]; AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:[NSURL fileURLWithPath:filePath] 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]]; CGSize videoSize = [clipVideoTrack naturalSize]; UIImage *myImage = [UIImage imageNamed:@"29.png"]; CALayer *aLayer = [CALayer layer]; aLayer.contents = (id)myImage.CGImage; aLayer.frame = CGRectMake(videoSize.width - 65, videoSize.height - 75, 57, 57); aLayer.opacity = 0.65; 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]; CATextLayer *titleLayer = [CATextLayer layer]; titleLayer.ssortingng = @"Text goes here"; titleLayer.font = CFBridgingRetain(@"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 [parentLayer addSublayer:titleLayer]; //ONLY IF WE ADDED TEXT AVMutableVideoComposition* videoComp = [AVMutableVideoComposition videoComposition]; videoComp.renderSize = videoSize; videoComp.frameDuration = CMTimeMake(1, 30); videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer]; 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]; AVAssetExportSession *assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];//AVAssetExportPresetPassthrough assetExport.videoComposition = videoComp; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSSsortingng *documentsDirectory = [paths objectAtIndex:0]; NSSsortingng* VideoName = [NSSsortingng ssortingngWithFormat:@"%@/mynewwatermarkedvideo.mp4",documentsDirectory]; //NSSsortingng *exportPath = [NSTemporaryDirectory() ssortingngByAppendingPathComponent:VideoName]; NSURL *exportUrl = [NSURL fileURLWithPath:VideoName]; if ([[NSFileManager defaultManager] fileExistsAtPath:VideoName]) { [[NSFileManager defaultManager] removeItemAtPath:VideoName error:nil]; } assetExport.outputFileType = AVFileTypeQuickTimeMovie; assetExport.outputURL = exportUrl; assetExport.shouldOptimizeForNetworkUse = YES; //[strRecordedFilename setSsortingng: exportPath]; [assetExport exportAsynchronouslyWithCompletionHandler: ^(void ) { dispatch_async(dispatch_get_main_queue(), ^{ [self exportDidFinish:assetExport]; }); } ]; } -(void)exportDidFinish:(AVAssetExportSession*)session { NSURL *exportUrl = session.outputURL; ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:exportUrl]) { [library writeVideoAtPathToSavedPhotosAlbum:exportUrl completionBlock:^(NSURL *assetURL, NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{ if (error) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Video Saving Failed" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; } else { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Video Saved" message:@"Saved To Photo Album" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; } }); }]; } NSLog(@"Completed"); UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"AlertView" message:@"Video is edited successfully." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; } 

Une façon consiste à créer votre superposition de text en tant que CoreAnimation CATextLayer, à l'attacher à la videoComposition d'AVAssetExportSession, puis à exporter votre video. La video résultante aura l'overlay rendu dessus.

Cela apporte quelques avantages:

  1. vous n'avez pas besoin de vous arrêter à CATextLayer – vous pouvez build des trees CALayer contenant CAGradientLayer, CAShapeLayer, etc.
  2. étant des couches d' animation de base, beaucoup de leurs propriétés sont animables, de sorte que vous obtenez gratuitement des animations de style iOS dans votre video.

Ça a l'air génial, non? Il y a un petit effet secondaire: selon le préréglage d'export que vous utilisez, votre video sera inévitablement réencodée à un taux de rafraîchissement constant – pour moi c'était 30fps. Pour réduire la taille des files, j'avais délibérément baissé mon framerate en omettant les images redondantes, donc pour une bannière statique, c'était un dealbreaker pour moi.

Il existe un exemple de code Apple appelé AVEditDemo qui illustre cette fonctionnalité, entre autres choses. Il y a des instructions pour le find ici .

En utilisant le code Chaitali Jain, les nouvelles videos seront enregistrées sans audio. Y a-t-il quelqu'un qui a une idée sur ce sujet? Merci!