I'm trying to get the first frame from the selected video in a UIImagePickerController
to show in a UIImageView
, but I do not know if it's possible. If it is, how would I do it?
Asked
Active
Viewed 6,342 times
13

memmons
- 40,222
- 21
- 149
- 183
-
similar question http://stackoverflow.com/questions/1347562/getting-thumbnail-from-a-video-url-or-data-in-iphone-sdk – Bo. May 27 '12 at 09:51
1 Answers
28
You can do this in one of two ways. The first way is to use the MPMoviePlayerController
to grab the thumbnail:
MPMoviePlayerController *moviePlayer = [[MPMoviePlayerController alloc]
initWithContentURL:videoURL];
moviePlayer.shouldAutoplay = NO;
UIImage *thumbnail = [moviePlayer thumbnailImageAtTime:time
timeOption:MPMovieTimeOptionNearestKeyFrame];
This works, but MPMoviePlayerController
is not a particularly lightweight object and not particularly fast grabbing thumbnails.
The preferred way is to use the new AVAssetImageGenerator
in AVFoundation. This is fast, lightweight and more flexible than the old way. Here's a helper method that will return an autoreleased image from the video.
+ (UIImage *)thumbnailImageForVideo:(NSURL *)videoURL
atTime:(NSTimeInterval)time
{
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
NSParameterAssert(asset);
AVAssetImageGenerator *assetIG =
[[AVAssetImageGenerator alloc] initWithAsset:asset];
assetIG.appliesPreferredTrackTransform = YES;
assetIG.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels;
CGImageRef thumbnailImageRef = NULL;
CFTimeInterval thumbnailImageTime = time;
NSError *igError = nil;
thumbnailImageRef =
[assetIG copyCGImageAtTime:CMTimeMake(thumbnailImageTime, 60)
actualTime:NULL
error:&igError];
if (!thumbnailImageRef)
NSLog(@"thumbnailImageGenerationError %@", igError );
UIImage *thumbnailImage = thumbnailImageRef
? [[UIImage alloc] initWithCGImage:thumbnailImageRef]
: nil;
return thumbnailImage;
}
Asynchronous usage
- (void)thumbnailImageForVideo:(NSURL *)videoURL atTime:(NSTimeInterval)time completion:(void (^)(UIImage *)) completion
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
NSParameterAssert(asset);
AVAssetImageGenerator *assetIG =
[[AVAssetImageGenerator alloc] initWithAsset:asset];
assetIG.appliesPreferredTrackTransform = YES;
assetIG.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels;
CGImageRef thumbnailImageRef = NULL;
CFTimeInterval thumbnailImageTime = time;
NSError *igError = nil;
thumbnailImageRef =
[assetIG copyCGImageAtTime:CMTimeMake(thumbnailImageTime, 60)
actualTime:NULL
error:&igError];
if (!thumbnailImageRef)
NSLog(@"thumbnailImageGenerationError %@", igError );
UIImage *thumbnailImage = thumbnailImageRef
? [[UIImage alloc] initWithCGImage:thumbnailImageRef]
: nil;
dispatch_async(dispatch_get_main_queue(), ^{
completion(thumbnailImage);
});
});
}
-
for other who tries to use this: pay attention if the videoURL was created by fileURLWithPath or URLWithString (when you have the path in NSString*) – user1105951 Nov 16 '13 at 12:22
-
Just a question (and a heads up) - above method is sync yeah? Best to toss it into another thread. – Jai Govindani Mar 04 '14 at 10:31
-
-
[assetIG copyCGImageAtTime:CMTimeMake(thumbnailImageTime, 60) <== why is 60? – hungbm06 May 09 '16 at 12:03