获取iOS 6视频的所有帧

3
我希望能够将iOS6中视频的所有帧存储到NSArray中。 我使用以下代码:
-(void) getAllImagesFromVideo
{
   imagesArray = [[NSMutableArray alloc] init];
   times = [[NSMutableArray alloc] init];

   for (Float64 i = 0; i < 15; i += 0.033) // For 25 fps in 15 sec of Video
   {
       CMTime time = CMTimeMakeWithSeconds(i, 60);
      [times addObject:[NSValue valueWithCMTime:time]];
   } 

   [imageGenerator generateCGImagesAsynchronouslyForTimes:times completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) {

      if (result == AVAssetImageGeneratorSucceeded)
      {
         UIImage *generatedImage = [[UIImage alloc] initWithCGImage:image];

         [imagesArray addObject:generatedImage];
     }
   }];
}

在iPad模拟器上延迟为90~100秒,在iPad设备上,收到内存警告并最终崩溃。
有什么想法或解决方案?是否使用另一个更低级别的框架/库? C++? 对我来说非常重要!帮帮我!:)
谢谢!

你可以使用FFmpeg框架从视频中提取帧。 - Dipen Panchasara
是的,我知道那个,但我不知道怎么做。能帮忙吗?谢谢!:) - Javi Campaña
1
我认为iPhone内存无法容纳400张图像,建议将图像保存在文档目录中。如果您仍然对示例感兴趣,请告诉我,我会写一个答案。 - ekeren
@ekeren 我使用了其他方法,但我想看看你的答案!谢谢!;) - Javi Campaña
最终你使用了什么? - ekeren
嘿@JaviCampaña,你是怎么解决这个问题的?我也遇到了完全相同的问题。 - Rahul Mane
2个回答

12

您需要:

  1. 按照@zimmryan所提到的使用CGImageRelease
  2. 在循环中使用@autoreleasepool块
  3. 不要将图像存储在内存中,而是将它们存储在文档目录中

这是我的做法:(请注意,我使用同步版本来提取图像,如果您选择异步版本,这应该不重要)

AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
generator.requestedTimeToleranceAfter =  kCMTimeZero;
generator.requestedTimeToleranceBefore =  kCMTimeZero;
for (Float64 i = 0; i < CMTimeGetSeconds(asset.duration) *  FPS ; i++){
  @autoreleasepool {
    CMTime time = CMTimeMake(i, FPS);
    NSError *err;
    CMTime actualTime;
    CGImageRef image = [generator copyCGImageAtTime:time actualTime:&actualTime error:&err];
    UIImage *generatedImage = [[UIImage alloc] initWithCGImage:image];
    [self saveImage: generatedImage atTime:actualTime]; // Saves the image on document directory and not memory
    CGImageRelease(image);
  }
}

编辑:

在创建大量临时对象时,您应始终考虑使用@autoreleasepool(请参阅https://developer.apple.com/library/mac/documentation/cocoa/conceptual/memorymgmt/articles/mmAutoreleasePools.html)。


你能在UIImageView上查看“generatedImage”吗? - Anil

5
听起来你可能会遇到375张图片的内存问题。尝试使用此方法,它可能提供更好的内存管理。
-(void) getAllImagesFromVideo
{
   imagesArray = [[NSMutableArray alloc] initWithCapacity:375];
   times = [[NSMutableArray alloc] initWithCapacity:375];

   for (Float64 i = 0; i < 15; i += 0.033) // For 25 fps in 15 sec of Video
   {
       [times addObject:[NSValue valueWithCMTime:CMTimeMakeWithSeconds(i, 60)]];
   } 

   [imageGenerator generateCGImagesAsynchronouslyForTimes:times completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) {
       if (result == AVAssetImageGeneratorSucceeded)
       {
           [imagesArray addObject:[UIImage imageWithCGImage:image]];
           CGImageRelease(image);
       }
   }];
}

谢谢,但仍然崩溃,有任何想法吗? - Javi Campaña
考虑到将更多的UIImage保存到NSArray中会占用大量内存。 - Javi Campaña
当您查看崩溃日志时,是否告诉您操作系统因为使用了过多的内存而终止了您的应用程序?如果是这样,请考虑以较低的分辨率保存图像,使用JPEG压缩,并/或异步将它们写入磁盘,而不是将它们存储在内存中。 - zimmryan
您可以通过设置imageGenerator.maximumSize = CGSizeMake(320, 180)或其他任何大小来更改输出大小,而不是完整分辨率。 - zimmryan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接