iOS AVFoundation: conversión de video en imágenes a 60 fps

Estoy tratando de convertir un video completo en una secuencia de imágenes a una velocidad de 60 fps, lo que significa 60 imágenes generadas por segundo de video …

Para hacerlo, estoy usando AVAssetImageGenerator y el método generateCGImagesAsynchronouslyForTimes …

Las cosas van bastante bien, excepto que estoy teniendo serios problemas de performance que aumentan el time de ejecución del procesamiento por lotes (aproximadamente 5 minutos por 13 segundos de video) …

Además, por encima del siguiente tamaño CGSizeMake (512, 324), experimento colisiones …

¿Alguien ya tenía experiencia con este tipo de procesamiento y sabe cómo networkingucir la ejecución de este time, además de poder extraer las imágenes con una resolución más alta?

Debajo está el código que estoy probando …

NSURL *movieURL = [NSURL fileURLWithPath:getCaptureMoviePath()]; AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:movieURL options:nil]; AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; generator.appliesPrefernetworkingTrackTransform=TRUE; generator.requestedTimeToleranceAfter=kCMTimeZero; generator.requestedTimeToleranceBefore=kCMTimeZero; NSMutableArray *thumbTimes=[NSMutableArray arrayWithCapacity:asset.duration.value]; for(int t=0;t < asset.duration.value;t=t+2) { CMTime thumbTime = CMTimeMake(t, asset.duration.timescale); NSLog(@"Time Scale : %d ", asset.duration.timescale); NSValue *v=[NSValue valueWithCMTime:thumbTime]; [thumbTimes addObject:v]; } NSLog(@"thumbTimes array contains %d objects : ", [thumbTimes count]); [asset release]; AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) { if (result != AVAssetImageGeneratorSucceeded) { NSLog(@"couldn't generate thumbnail, error:%@", error); } else { NSLog(@"actual time: %lld/%d (requested: %lld/%d)",actualTime.value,actualTime.timescale,requestedTime.value,requestedTime.timescale); NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"yyyyMMdd-HHmmss"]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *filename = [NSString stringWithFormat:@"%@.png", [formatter stringFromDate:[NSDate date]]]; NSString *filepath = [documentsDirectory stringByAppendingPathComponent:filename]; CFURLRef url = (CFURLRef)[NSURL fileURLWithPath:filepath]; CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL); CGImageDestinationAddImage(destination, im, nil); if (!CGImageDestinationFinalize(destination)) { NSLog(@"Failed to write image to %@", filepath); } CFRelease(destination); } //[generator release]; }; CGSize maxSize = CGSizeMake(512, 324); generator.maximumSize = maxSize; [generator generateCGImagesAsynchronouslyForTimes:thumbTimes completionHandler:handler]; 

Agradeciendotelo de antemano,

j.

Hey @Sooriah Joel intenta usar el siguiente código. Está funcionando bien para mí.

 - (void)generateCMTimesArrayOfAllFramesUsingAsset:(AVURLAsset *)asset { if (cmTimeArray.count>0) { [cmTimeArray removeAllObjects]; } //Generate all frames present in video for(int t=0;t < asset.duration.value;t++) { CMTime thumbTime = CMTimeMake(t,asset.duration.timescale); NSValue *v=[NSValue valueWithCMTime:thumbTime]; [cmTimeArray addObject:v]; } NSLog(@"Array of time %@ count = %d",cmTimeArray, cmTimeArray.count); //NSLog(@"Array count = %d",cmTimeArray.count); } - (void)generateCMTimesArrayOfFrames:(int)framesInterval UsingAsset:(AVURLAsset *)asset { int videoDuration = ceilf(((float)asset.duration.value/asset.duration.timescale)); NSLog(@"Video duration %lld seconds timescale = %d",asset.duration.value,asset.duration.timescale); if (cmTimeArray.count>0) { [cmTimeArray removeAllObjects]; } //Generate limited frames present in video for (int i = 0; i<videoDuration; i++) { int64_t tempInt = i; CMTime tempCMTime = CMTimeMake(tempInt,1); int32_t interval = framesInterval; for (int j = 1; j<framesInterval+1; j++) { CMTime newCMtime = CMTimeMake(j,interval); CMTime addition = CMTimeAdd(tempCMTime, newCMtime); [cmTimeArray addObject:[NSValue valueWithCMTime:addition]]; } } NSLog(@"Array of time %@ count = %d",cmTimeArray, cmTimeArray.count); //NSLog(@"Array count = %d",cmTimeArray.count); } - (void)generateThumbnailsFromVideoURL:(AVURLAsset *)videoAsset { //Generate CMTimes Array of requinetworking frames //1.Generate All Frames //[self generateCMTimesArrayOfAllFramesUsingAsset:asset]; //2.Generate specific frames per second [self generateCMTimesArrayOfFrames:30 UsingAsset:videoAsset]; __block int i = 0; AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){ if (result == AVAssetImageGeneratorSucceeded) { [framesArray addObject:[UIImage imageWithCGImage:im]]; } if (result == AVAssetImageGeneratorFailed) { NSLog(@"Failed with error: %@ code %d", [error localizedDescription],error.code); } if (result == AVAssetImageGeneratorCancelled) { NSLog(@"Canceled"); } i++; imageIndex = i; if(i == cmTimeArray.count) { //Thumbnail generation completed } }; // Launching the process... self.generator = [[AVAssetImageGenerator alloc] initWithAsset:videoAsset]; self.generator.apertureMode = AVAssetImageGeneratorApertureModeCleanAperture; self.generator.appliesPrefernetworkingTrackTransform=TRUE; self.generator.requestedTimeToleranceBefore = kCMTimeZero; self.generator.requestedTimeToleranceAfter = kCMTimeZero; self.generator.maximumSize = CGSizeMake(40, 40); [self.generator generateCGImagesAsynchronouslyForTimes:cmTimeArray completionHandler:handler]; }