I am trying to acquire a thumbnail (of the first frame) from a video taken from iphone 3GS camera so i can display it. Anyone been successful at doing this? If so, how to do?

10 Answers 11

Best method I've found... MPMoviePlayerController thumbnailImageAtTime:timeOption

1 upvote
  flag
The best method i would say is using AVFoundation – Daniel
2 upvote
  flag
Actually on testing I find this method is much faster than the AVAsset code listed above. – GuybrushThreepwood
upvote
  flag
I'm using this url sciencentral.com/news/image_db/2024515/… I get nil thumbnail image. please help – ruyamonis346
1 upvote
  flag
But in this method first video should play at once than only it gives thumbnail image of frame. So its better use AVURLAsset for getting thumbnail image of any video file. – Diken Shah
up vote 68 down vote accepted

The answer to this question is that one can now with 4.0 iOS get thumbnails using AVFoundation, the following code where the class property url is the movie url, will do the trick (you can get the thumbnail at any time, in the example its at time 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];

}
7 upvote
  flag
That code works great. The only downside of AVAssettImageGenerator is that presently it uses keyframes, which are typically spaced at one-second intervals -- so you can't get any finer resolution than that. If you're just trying to make some thumbnails to spread out over a timeline it's probably fine, but if you're trying to read consecutive frames, this won't work. In that case you have to use AVAssetReader, which has some quirks of its own, or MPMovieController, which has thumbnail methods that are frame-accurate. – Andy Milburn
3 upvote
  flag
Appreciate this thread is old, but just want to add that MPMoviePlayerController (see below) is a much faster option. The code above takes a good 5-10 seconds to generate a thumbnail, whereas MPMovie is almost instant. – GuybrushThreepwood
upvote
  flag
I have try the above method to get thumb image from video but is not giving all thumb like at time 1.5 . @AndyMilburn can you give any sample link to get thumb using AVAssetReader. – Crazy Developer
upvote
  flag
@AndyMilburn That's not exactly true, if you set requestedTimeToleranceBefore/After to smaller values you can get more closely spaced thumbnails. – Nick
upvote
  flag
Gives me the error AVErrorOperationNotSupportedForAsset . plz help – ruyamonis346
2 upvote
  flag
@GuybrushThreepwood I've tried this method with 5 different videos at the same time and all thumbnails are ready within a second; one thing to note is that you should use GCD to update the UI. – Ja͢ck
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];

Check this link for an alternative: thumbnailImageAtTime: now deprecated - What's the alternative?

upvote
  flag
@Maulik i tried above code to generate image its working fine,but i am not getting video time line how can i get this also do u have any idea – Bad Boy
upvote
  flag
the thumbnail image is not displaying the time. Can you please edit your code if you know this? – user1673099
upvote
  flag
will I be able to use this for screen capturing the video and not for creating thumbnail? – Little Tiny Dev
upvote
  flag
I'm using this url sciencentral.com/news/image_db/2024515/… I get nil thumbnail image. please help – ruyamonis346
upvote
  flag
Isn't this approach much less memory friendly than the AVAssetImageGenerator approach? The way I understand it - the whole video needs to be loaded into memory in order to generate a single image. – Stavash
upvote
  flag
It worked fine. – user523234
6 upvote
  flag
thumbnailImageAtTime: is deprecated now, just FYI to anyone who visits this thread. – Chris C
-(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;
}

you can get the frame using the time.value suppose you want to 1 second frame then use the

time.value = 1000 //Time in milliseconds
3 upvote
  flag
@Diken Shah How Do i Get a thumbnail at n th second of the video. I set time.value=n but still i get the first frame – Pranav Jaiswal

SWIFT 2.0

You can generate in swift in two ways 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)")
            }
        }
upvote
  flag
solution 1 works in most cases for me but not always do you know why ? //allinonescript.com/questions/37374008/… – Sam
1 upvote
  flag
Actually i will take a tour on your post in free time. Thanks for your comment :) – Dharmbir Singh

Swift 2 code:

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
    }
}
upvote
  flag
It works in most cases but not always do you know why? //allinonescript.com/questions/37374008/… – Sam

Maybe this is useful for someone else who faces the same problem. I needed an easy solution for creating a thumbnail for Images, PDFs and Videos. To solve that problem I've created the following Library.

https://github.com/prine/ROThumbnailGenerator

The usage is very straightforward: var thumbnailImage = ROThumbnail.getThumbnail(url)

It has internally three different implementations and depending on the file extension it does create the thumbnail. You can easily add your own implementation if you need a thumbnail creator for another file extension.

upvote
  flag
It works in most cases but not always do you know why? //allinonescript.com/questions/37374008/… – Sam

Swift 2.1 Getting thumbnails at required time intervals

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
}

You will get Thumbnail Image From URL when you change "fileURLWithPath" to "URLWithString".

In My case it worked like this.

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;

For 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   }

Not the answer you're looking for? Browse other questions tagged or ask your own question.