【问题标题】:Get all frames of Video IOS 6获取视频IOS 6的所有帧
【发布时间】:2013-07-02 22:01:00
【问题描述】:

我想将 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 framework从视频中提取帧
  • 是的,我知道,但我不知道怎么做。有什么帮助吗?谢谢! :)
  • 我认为 iPhone 内存无法容纳 400 张图像,我建议将图像保存在您的文档目录中。如果您仍然对示例感兴趣,请告诉我,我会写一个答案
  • @ekeren 我使用其他方法,但我想看看你的答案!谢谢! ;)
  • 补充,你最终用了什么?

标签: ios objective-c avfoundation frame-rate image-generation


【解决方案1】:

你需要:

  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' 吗?
【解决方案2】:

听起来您遇到了 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);
       }
   }];
}

【讨论】:

  • 谢谢,但仍然崩溃,知道吗?
  • 想一想,将更多 UIImages 保存到 NSArray 会占用大量内存。
  • 当您查看崩溃日志时,它是否告诉您操作系统因使用过多内存而杀死了您的应用程序?如果是这样,请考虑以较低的分辨率保存图像,使用 jpeg 压缩,和/或将它们异步写入磁盘而不是将它们存储在内存中。
  • 您可以通过设置 imageGenerator.maximumSize = CGSizeMake(320, 180) 或任何其他大小而不是全分辨率来更改输出大小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-14
  • 2023-03-27
  • 2022-11-27
  • 1970-01-01
  • 2014-05-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多