【问题标题】:Getting a thumbnail from a video url or data in iOS从 iOS 中的视频 url 或数据获取缩略图
【发布时间】:2010-11-23 18:29:34
【问题描述】:

我正在尝试从 iphone 3GS 相机拍摄的视频中获取缩略图(第一帧),以便显示它。如何做到这一点?

【问题讨论】:

标签: ios iphone video thumbnails


【解决方案1】:
-(UIImage *)generateThumbImage : (NSString *)filepath
{
    NSURL *url = [NSURL fileURLWithPath:filepath];

    AVAsset *asset = [AVAsset assetWithURL:url];
    AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
    imageGenerator.appliesPreferredTrackTransform = YES;
    CMTime time = [asset duration];
    time.value = 0;
    CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
    UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);  // CGImageRef won't be released by ARC

    return thumbnail;
}

您可以使用 time.value 获取帧假设您想要 1 秒帧然后使用

time.value = 1000 //Time in milliseconds

【讨论】:

  • @Diken Shah 我如何在视频的第 n 秒获取缩略图。我设置了 time.value=n 但我仍然得到第一帧
  • 要可靠地获取不同时间索引的缩略图,您需要在 imageGenerator 上设置 requestedTimeTolerance 属性,如本答案中所述。 stackoverflow.com/questions/39525253/…
【解决方案2】:

这个问题的答案是,现在可以在 4.0 iOS 中使用 AVFoundation 获取缩略图,下面的代码中的类属性 url 是电影 url,可以解决问题(您可以随时获取缩略图,在例如它在时间 0)

-(void)generateImage
{
    AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:self.url options:nil];
    AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    generator.appliesPreferredTrackTransform=TRUE;
    [asset release];
    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);
        }
        [button setImage:[UIImage imageWithCGImage:im] forState:UIControlStateNormal];
        thumbImg=[[UIImage imageWithCGImage:im] retain];
        [generator release];
    };

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

}

【讨论】:

  • 该代码运行良好。 AVAssettImageGenerator 的唯一缺点是目前它使用关键帧,它们通常以一秒的间隔间隔 - 所以你无法获得比这更精细的分辨率。如果您只是想制作一些缩略图以在时间线上展开,那可能没问题,但如果您想读取连续的帧,这将行不通。在这种情况下,您必须使用 AVAssetReader,它有一些自己的怪癖,或者 MPMovieController,它具有帧精确的缩略图方法。
  • 感谢这个线程是旧的,但只是想补充一点 MPMoviePlayerController(见下文)是一个更快的选择。上面的代码需要 5-10 秒来生成缩略图,而 MPMovie 几乎是即时的。
  • 我尝试了上述方法从视频中获取拇指图像,但没有像 1.5 那样给出所有拇指。 @AndyMilburn 您能否提供任何示例链接以使用 AVAssetReader 获取拇指。
  • @AndyMilburn 这并不完全正确,如果您将 requestedTimeToleranceBefore/After 设置为更小的值,您可以获得间距更近的缩略图。
  • @GuybrushThreepwood 我已经用 5 个不同的视频同时尝试了这种方法,所有缩略图在一秒钟内就准备好了;需要注意的一点是,您应该使用 GCD 来更新 UI。
【解决方案3】:
NSURL *videoURL = [NSURL fileURLWithPath:url];

MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];

        UIImage *thumbnail = [player thumbnailImageAtTime:1.0 timeOption:MPMovieTimeOptionNearestKeyFrame];

        //Player autoplays audio on init
        [player stop];
        [player release];

查看此链接以获取替代方法: thumbnailImageAtTime: now deprecated - What's the alternative?

【讨论】:

  • @Maulik 我尝试了上面的代码来生成图像,它工作正常,但是我没有得到视频时间线我怎么能得到这个你有什么想法吗
  • 缩略图不显示时间。如果您知道这一点,请您编辑您的代码吗?
  • 我可以用它来截取视频而不是创建缩略图吗?
  • 我正在使用这个网址 sciencentral.com/news/image_db/2024515/… 我得到零缩略图。请帮忙
  • thumbnailImageAtTime: 现已弃用,仅供访问此线程的任何人参考。
【解决方案4】:

我发现的最佳方法...MPMoviePlayerController thumbnailImageAtTime:timeOption

【讨论】:

  • 我想说的最好的方法是使用 AVFoundation
  • 实际上在测试中我发现这种方法比上面列出的 AVAsset 代码要快得多。
  • 我正在使用这个网址 sciencentral.com/news/image_db/2024515/… 我得到零缩略图。请帮忙
  • 但是在这种方法中,第一个视频应该立即播放,而不是只提供帧的缩略图。所以最好使用 AVURLAsset 来获取任何视频文件的缩略图。
【解决方案5】:

SWIFT 2.0

您可以通过两种方式快速生成 1. AVFoundation 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)")
            }
        }

【讨论】:

【解决方案6】:

Swift 2 代码:

func previewImageForLocalVideo(url:NSURL) -> UIImage?
{
    let asset = AVAsset(URL: url)
    let imageGenerator = AVAssetImageGenerator(asset: asset)
    imageGenerator.appliesPreferredTrackTransform = true

    var time = asset.duration
    //If possible - take not the first frame (it could be completely black or white on camara's videos)
    time.value = min(time.value, 2)

    do {
        let imageRef = try imageGenerator.copyCGImageAtTime(time, actualTime: nil)
        return UIImage(CGImage: imageRef)
    }
    catch let error as NSError
    {
        print("Image generation failed with error \(error)")
        return nil
    }
}

【讨论】:

【解决方案7】:

对于 Swift 3.0

func createThumbnailOfVideoFromFileURL(_ strVideoURL: String) -> UIImage?{

let asset = AVAsset(url: URL(string: strVideoURL)!)
let assetImgGenerate = AVAssetImageGenerator(asset: asset)
assetImgGenerate.appliesPreferredTrackTransform = true
let time = CMTimeMakeWithSeconds(Float64(1), 100)
do {
  let img = try assetImgGenerate.copyCGImage(at: time, actualTime: nil)
  let thumbnail = UIImage(cgImage: img)
  return thumbnail
} catch {
  /* error handling here */
}
return nil   }

【讨论】:

    【解决方案8】:

    斯威夫特 4

    func generateThumbnail(for asset:AVAsset) -> UIImage? {
        let assetImgGenerate : AVAssetImageGenerator = AVAssetImageGenerator(asset: asset)
        assetImgGenerate.appliesPreferredTrackTransform = true
        let time = CMTimeMake(value: 1, timescale: 2)
        let img = try? assetImgGenerate.copyCGImage(at: time, actualTime: nil)
        if img != nil {
            let frameImg  = UIImage(cgImage: img!)
           return frameImg
        }
        return nil
    }
    

    使用方法:

       func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true) {
    
            switch mediaType {
            case kUTTypeMovie:
                guard info[UIImagePickerController.InfoKey.mediaType] != nil, let url = info[UIImagePickerController.InfoKey.mediaURL] as? URL else { return }
                let asset = AVAsset(url: url)
                guard let img = self.generateThumbnail(for: asset) else {
                    print("Error: Thumbnail can be generated.")
                    return
                }
                print("Image Size: \(img.size)")
                break
            default:
                break
            }
        }
    }
    

    【讨论】:

      【解决方案9】:

      对于 Swift 5

      import AVKit
      

      代码:

      // Get Thumbnail Image from URL
      fileprivate func getThumbnailFromUrl(_ url: String?, _ completion: @escaping ((_ image: UIImage?)->Void)) {
      
          guard let url = URL(string: url ?? "") else { return }
          DispatchQueue.main.async {
              let asset = AVAsset(url: url)
              let assetImgGenerate = AVAssetImageGenerator(asset: asset)
              assetImgGenerate.appliesPreferredTrackTransform = true
      
              let time = CMTimeMake(value: 2, timescale: 1)
              do {
                  let img = try assetImgGenerate.copyCGImage(at: time, actualTime: nil)
                  let thumbnail = UIImage(cgImage: img)
                  completion(thumbnail)
              } catch {
                  print("Error :: ", error.localizedDescription)
                  completion(nil)
              }
          }
      }
      

      用法 :: 拍摄一个图像视图

      @IBOutlet weak var imgThumbnail: UIImageView!
      

      然后在调用 getThumbnailFromUrl 方法后,以 URL String 作为参数的缩略图

      self.getThumbnailFromUrl(videoURL) { [weak self] (img) in
      
              guard let _ = self else { return }
              if let img = img {
                  self?.imgThumbnail.image = img
              }
          }
      

      请尝试一下,如果它已满,请评论 谢谢

      【讨论】:

      • 我正在使用这个解决方案对我来说效果很好。谢谢 Rohan Aryan
      【解决方案10】:

      也许这对面临同样问题的其他人有用。我需要一个简单的解决方案来为图像、PDF 和视频创建缩略图。为了解决这个问题,我创建了以下库。

      https://github.com/prine/ROThumbnailGenerator

      用法很简单: var thumbnailImage = ROThumbnail.getThumbnail(url)

      它在内部具有三种不同的实现,并根据文件扩展名创建缩略图。如果您需要另一个文件扩展名的缩略图创建器,您可以轻松添加自己的实现。

      【讨论】:

      【解决方案11】:

      Swift 2.1以所需的时间间隔获取缩略图

      func getPreviewImageForVideoAtURL(videoURL: NSURL, atInterval: Int) -> UIImage? {
          print("Taking pic at \(atInterval) second")
          let asset = AVAsset(URL: videoURL)
          let assetImgGenerate = AVAssetImageGenerator(asset: asset)
          assetImgGenerate.appliesPreferredTrackTransform = true
          let time = CMTimeMakeWithSeconds(Float64(atInterval), 100)
          do {
              let img = try assetImgGenerate.copyCGImageAtTime(time, actualTime: nil)
              let frameImg = UIImage(CGImage: img)
              return frameImg
          } catch {
              /* error handling here */
          }
          return nil
      }
      

      【讨论】:

        【解决方案12】:

        当您将“fileURLWithPath”更改为“URLWithString”时,您将获得来自 URL 的缩略图。

        就我而言,它是这样工作的。

        NSURL *url = [NSURL URLWithString:filepath];
        AVAsset *asset = [AVAsset assetWithURL:url];
        AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
        CMTime time = [asset duration];
        time.value = 0;
        CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
        UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
        CGImageRelease(imageRef);
        
        return thumbnail;
        

        【讨论】:

          猜你喜欢
          • 2011-05-25
          • 2020-05-16
          • 2011-06-18
          • 2013-11-01
          • 1970-01-01
          • 2023-03-22
          • 2011-10-12
          • 1970-01-01
          • 2020-06-26
          相关资源
          最近更新 更多