【问题标题】:Getting a thumbnail of a *.mov video IOS获取 *.mov 视频 IOS 的缩略图
【发布时间】:2013-11-01 02:04:48
【问题描述】:

我想获得用 iPhone/iPAD 拍摄的视频 (*.mov) 的缩略图。我正在尝试为此使用 AVFoundation 库并收到此错误:

couldn't generate thumbnail, error:Error Domain=AVFoundationErrorDomain Code=-11822 "Cannot Open" UserInfo=0x15d90a30 {NSLocalizedDescription=Cannot Open, NSLocalizedFailureReason=This media format is not supported.}

代码:

NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir=[paths objectAtIndex:0];
NSString *videoPath=[documentDir stringByAppendingPathComponent:[NSString stringWithFormat:@"videos/%@.mov",videoName]];


    AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:videoPath options:nil];
    AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    generator.appliesPreferredTrackTransform=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);
        }
        self.img.image=[UIImage imageWithCGImage:im];
    };

    CGSize maxSize = CGSizeMake(320, 180);
    generator.maximumSize = maxSize;
    [generator generateCGImagesAsynchronouslyForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:thumbTime]] completionHandler:handler];

我用我的应用录制了视频,并希望显示它们的缩略图。

【问题讨论】:

    标签: ios iphone video avfoundation video-thumbnails


    【解决方案1】:

    这里是...(从这个链接获取-Getting video snapshot for thumbnail

    - (UIImage *)thumbnailImageFromURL:(NSURL *)videoURL {
        AVURLAsset *asset = [[AVURLAsset alloc] initWithURL: videoURL options:nil];
        AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
        NSError *err = NULL;
        CMTime requestedTime = CMTimeMake(1, 60);     // To create thumbnail image
        CGImageRef imgRef = [generator copyCGImageAtTime:requestedTime actualTime:NULL error:&err];
        NSLog(@"err = %@, imageRef = %@", err, imgRef);
    
        UIImage *thumbnailImage = [[UIImage alloc] initWithCGImage:imgRef];
        CGImageRelease(imgRef);    // MUST release explicitly to avoid memory leak
    
        return thumbnailImage;
    }
    

    【讨论】:

    • 感谢@Ashok,只需稍加修改即可正常工作。节省了我的时间。放弃你的答案。
    • 看看下面这个@jr.root.cs 的回答。不要忘记释放 imgRef。
    • 太好了,有什么办法可以让CMTimeMake作为播放视频的暂停时间
    • 不要忘记添加 generator.appliesPreferredTrackTransform = YES; 修复图像方向
    • 嗨,这段代码工作正常。但是当我有更多的视频 URL 时它会很慢。
    【解决方案2】:

    我没有足够的声誉来发表评论,但上面的示例缺少 CGImageRelease(imageRef)...

    最终的方法应该是这样的:

    - (UIImage*)loadImage {
    
        AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:vidURL options:nil];
        AVAssetImageGenerator *generate = [[AVAssetImageGenerator alloc] initWithAsset:asset];
        NSError *err = NULL;
        CMTime time = CMTimeMake(1, 60);
        //Grab image
        CGImageRef imgRef = [generate copyCGImageAtTime:time actualTime:NULL error:&err];
        NSLog(@"err==%@, imageRef==%@", err, imgRef);
    
        UIImage* finalImage = [[UIImage alloc] initWithCGImage:imgRef];
        CGImageRelease(imageRef);
        return finalImage;
    }
    

    我花了一段时间才意识到......所以也许它会对某人有所帮助。

    【讨论】:

      【解决方案3】:

      您可以通过两种方式快速生成 1. AVAssetImageGenerator 2. MPMoviePlayerController

      1. 
      
          func generateThumnail(url : NSURL) -> UIImage{
                  var asset : AVAsset = AVAsset.assetWithURL(url) as AVAsset
                  var assetImgGenerate : AVAssetImageGenerator = AVAssetImageGenerator(asset: asset)
                  assetImgGenerate.appliesPreferredTrackTransform = true
                  var error       : NSError? = nil
                  var time        : CMTime = CMTimeMake(1, 30)
                  var img         : CGImageRef = assetImgGenerate.copyCGImageAtTime(time, actualTime: nil, error: &error)
                  var frameImg    : UIImage = UIImage(CGImage: img)!
      
                  return frameImg
              }
      
      2. 
      
          override func viewDidLoad() {
                  super.viewDidLoad()
                  var moviePlayer         : MPMoviePlayerController!  = MPMoviePlayerController(contentURL: moviePlayManager.movieURL)
                  moviePlayer.view.frame   = CGRect(x: self.view.frame.origin.x, y: self.view.frame.origin.y, width:
                                             self.view.frame.size.width, height: self.view.frame.height)
                  moviePlayer.fullscreen   = true
                  moviePlayer.controlStyle = MPMovieControlStyle.None
                  NSNotificationCenter.defaultCenter().addObserver(self,
              selector: "videoThumbnailIsAvailable:",
              name: MPMoviePlayerThumbnailImageRequestDidFinishNotification,
              object: nil)
      
      
              let thumbnailTimes = 3.0
              moviePlayer.requestThumbnailImagesAtTimes([thumbnailTimes],
                      timeOption: .NearestKeyFrame)
              }
      
          func videoThumbnailIsAvailable(notification: NSNotification){
      
              if let player = moviePlayer{
                  let thumbnail =
                  notification.userInfo![MPMoviePlayerThumbnailImageKey] as? UIImage
      
                  if let image = thumbnail{
      
                      /* We got the thumbnail image. You can now use it here */
                      println("Thumbnail image = \(image)")
                  }
              }
      

      【讨论】:

      • 我确实尝试了第一种方法...但它不起作用...并给出fatal error: unexpectedly found nil while unwrapping an Optional value 因为 img 没有任何价值
      • 请让我知道哪个值是 nil,因为这是由于传递 nil 值而发生的。
      • 不,可能 b assets(assetImgGenerate) nil
      【解决方案4】:

      您需要检查视频轨道中的每个视频片段是否为空。

      + (UIImage*)getVideoPreViewImage:(AVAsset *)asset atTimeSec:(double)timeSec
      {
          if (!asset) {
              return nil;
          }
      
      
          AVAssetTrack *videoTrack = [asset tracksWithMediaType:AVMediaTypeVideo].firstObject;
          NSArray<AVAssetTrackSegment *> *segs = videoTrack.segments;
          if (!segs.count) {
              return nil;
          }
          CMTime currentStartTime = kCMTimeZero;
          for (NSInteger i = 0; i < segs.count; i ++) {
              if (!segs[i].isEmpty) {
                  currentStartTime = segs[i].timeMapping.target.start;
                  break;
              }
          }
      
          CMTime coverAtTimeSec = CMTimeMakeWithSeconds(timeSec, asset.duration.timescale);
      
          if (CMTimeCompare(coverAtTimeSec, asset.duration) == 1 || CMTimeCompare(coverAtTimeSec, currentStartTime) == -1) {
              coverAtTimeSec = currentStartTime;
          }
      
          AVAssetImageGenerator *assetGen = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
          assetGen.requestedTimeToleranceBefore = kCMTimeZero;
          assetGen.requestedTimeToleranceAfter = kCMTimeZero;
          assetGen.appliesPreferredTrackTransform = YES;
      
      
          NSError *error = nil;
          CGImageRef image = [assetGen copyCGImageAtTime:coverAtTimeSec actualTime:NULL error:&error];
          if (error) {
              return nil;
          }
          UIImage *videoImage = [UIImage imageWithCGImage:image];
      
      
          CGImageRelease(image);
          return videoImage;
      }
      

      【讨论】:

        猜你喜欢
        • 2014-11-20
        • 1970-01-01
        • 2011-05-25
        • 2013-08-31
        • 2017-10-21
        • 2011-05-12
        • 2011-06-18
        • 1970-01-01
        • 2020-08-27
        相关资源
        最近更新 更多