Tomar la image en miniatura del video siempre devuelve nula

Estoy intentando get la primera miniatura de un video.

Probé lo siguiente:

UNO

AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:_moviePath] options:nil]; AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset]; gen.appliesPrefernetworkingTrackTransform = YES; CMTime time = CMTimeMakeWithSeconds(0.0, 600); NSError *error = nil; CMTime actualTime; CGImageRef image = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error]; UIImage *thumb = [[UIImage alloc] initWithCGImage:image]; CGImageRelease(image); NSLog(@"the error is %@: image is %@: url is %@: ",error,_mainThumbnail,[NSURL fileURLWithPath:_moviePath] ); 

Sin embargo, mi logging es:

 the error is (null): image is (null): url is file:///private/var/mobile/Applications/D1293BDC-EA7E-4AC7-AD3C-1BA3548F37D6/tmp/trim.6F0C4631-E5E8-43CD-BF32-9B8F09D4ACF1.MOV: 

DOS

 AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:_moviePath] options:nil]; AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; generator.appliesPrefernetworkingTrackTransform=TRUE; CMTime thumbTime = CMTimeMakeWithSeconds(0,30); AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){ if (result != AVAssetImageGeneratorSucceeded) { NSLog(@"couldn't generate thumbnail, error:%@", error); } _mainThumbnail.image = [UIImage imageWithCGImage:im]; NSLog(@"thumbnails %@ ",_mainThumbnail.image); }; CGSize maxSize = CGSizeMake(320, 180); generator.maximumSize = maxSize; [generator generateCGImagesAsynchronouslyForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:thumbTime]] completionHandler:handler]; 

El log thumnails nulo.

¿Por qué la image es nula? Miré en otros foros, y sugirieron usar fileURLWithPath, que ya estoy usando.

Estoy usando ios7

Puedes probar este método. Toma el primer fotogtwig del video en la URL dada y lo devuelve como UIImage .

 - (UIImage *)thumbnailFromVideoAtURL:(NSURL *)url { AVAsset *asset = [AVAsset assetWithURL:url]; // Get thumbnail at the very start of the video CMTime thumbnailTime = [asset duration]; thumbnailTime.value = 0; // Get image from the video at the given time AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; CGImageRef imageRef = [imageGenerator copyCGImageAtTime:thumbnailTime actualTime:NULL error:NULL]; UIImage *thumbnail = [UIImage imageWithCGImage:imageRef]; CGImageRelease(imageRef); return thumbnail; } 

El método no verifica los errores, ya que mi código lo usa, está bien, solo se devuelve nil si falla algo.


Edit: aclaración de los valores de CMTime

CMTime tiene

  • timescale – piense en esto como un FPS (fotogtwigs por segundo) del video (25 FPS -> 1 s del video tiene 25 fotogtwigs de video)
  • value : identificación del marco de hormigón. En el código anterior, esto dice en qué marco deseas tomar la miniatura.

Para calcular el cuadro en el momento exacto, debe realizar este cálculo:

 value = timescale * seconds_to_skip 

que es el equivalente a

 "Frame of the video to take" = "FPS" * "Number of seconds to skip" 

Si desea tomar, por ejemplo, 1er cuadro del segundo segundo del video, de hecho, quiere saltear el primer segundo del video. Entonces usaría:

 CMTime thumbnailTime = [asset duration]; thumbnailTime.value = thumbnailTime.timescale * 1; 

Otra mirada: quiere omitir los primeros 1 segundos del video y tomar una miniatura. Es decir, en 25 FPS, quiere omitir 25 fotogtwigs. Entonces CMTime.value = 25 (saltee 25 cuadros).

Por si alguien cometió el mismo error que yo:

Echa un vistazo a si la URL se genera con el método apropiado. No debe get una contrafusión para las URL locales y web del file.

En caso de file de video local, use el siguiente código:

 NSURL *movieURL = [NSURL fileURLWithPath:_moviePath]; AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:movieURL options:nil]; 

En caso de file de video de internet, use el siguiente código:

 NSURL *movieURL = [NSURL URLWithString:_moviePath]; AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:movieURL options:nil]; 

Utilizo este fragment con éxito para get una captura de pantalla del video:

 - (UIImage *)currentItemScreenShot { AVURLAsset *asset = (AVURLAsset *)playerItem_.asset; AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; imageGenerator.appliesPrefernetworkingTrackTransform = YES; CGImageRef thumb = [imageGenerator copyCGImageAtTime:CMTimeMakeWithSeconds(0, 1.0) actualTime:NULL error:NULL]; UIImage *image = [UIImage imageWithCGImage:thumb]; CGImageRelease(thumb); [imageGenerator release]; return image; } 

Pero en mi caso, lo estoy haciendo dos segundos después de que el video se importó correctamente en la aplicación. (Tenía problemas con la orientación de la image, a veces no devolvía ninguna image o media image si lo hacía una vez que se importaba el video).