I have to extract a thumbnail from a video (from url) and I use this code:
NSString *stringUrl = video.stringurl;
NSURL *url = [NSURL URLWithString:stringUrl
I'm trying as well to grab a screenshot from an HLS variable bitrate stream, I.E. M3U8, and none of the methods provided here worked for me.
I did succeed at the end.
First you need to attach an AVPlayerItemVideoOutput
to your player:
self.playerAV = [AVPlayer playerWithURL:localURL];
NSDictionary* settings = @{ (id)kCVPixelBufferPixelFormatTypeKey : [NSNumber numberWithInt:kCVPixelFormatType_32BGRA] };
AVPlayerItemVideoOutput* output = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:settings];
[self.playerAV.currentItem addOutput:output];
Now when you wanna grab the screenshot:
CVPixelBufferRef pixelBuffer = [output copyPixelBufferForItemTime:player.currentTime itemTimeForDisplay:nil];
CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
CIContext *temporaryContext = [CIContext contextWithOptions:nil];
CGImageRef videoImage = [temporaryContext
createCGImage:ciImage
fromRect:CGRectMake(0, 0,
CVPixelBufferGetWidth(pixelBuffer),
CVPixelBufferGetHeight(pixelBuffer))];
image = [UIImage imageWithCGImage:videoImage];
image = [image cropImageToSize:maxSize withProportionDiffLargerThan:IMAGE_PROPORTION_DIFF];
if ( videoImage )
{
CGImageRelease(videoImage);
}
If you are using AVPlayer, you can get the thumbnail like this:
AVAsset *asset = [AVAsset assetWithURL:sourceURL];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
CMTime time = CMTimeMake(1, 1);
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef); // CGImageRef won't be released by ARC
on one of my app i've captured an image from the video url like this:
MPMoviePlayerController *player = [[[MPMoviePlayerController alloc] initWithContentURL:videoURL]autorelease];
UIImage *thumbnail = [player thumbnailImageAtTime:0.0 timeOption:MPMovieTimeOptionNearestKeyFrame];
just passing the url object as videoURL and with the use of MPMoviePlayerController i successfully able to have the image all the time. hope you too will be able to do this with this simple code
AVAssetImageGenerator does not work for HSL videos.
I was able to get an image from the HSL video using the sample code below.
CMTime currentTime = _player.currentItem.currentTime;
CVPixelBufferRef buffer = [_videoOutput copyPixelBufferForItemTime:currentTime itemTimeForDisplay:nil];
CIImage *ciImage = [CIImage imageWithCVPixelBuffer:buffer];
UIImage *thumbImage = [UIImage imageWithCIImage:ciImage];
I was able to solve the same by using the following approach.
Swift 4.1
func createThumbnailForVideo(atURL videoURL: URL , completion : @escaping (UIImage?)->Void) {
let asset = AVAsset(url: videoURL)
let assetImgGenerate = AVAssetImageGenerator(asset: asset)
assetImgGenerate.appliesPreferredTrackTransform = true
let time = CMTimeMakeWithSeconds(1, preferredTimescale: 60)
let times = [NSValue(time: time)]
assetImgGenerate.generateCGImagesAsynchronously(forTimes: times, completionHandler: { _, image, _, _, _ in
if let image = image {
let uiImage = UIImage(cgImage: image)
completion(uiImage)
} else {
completion(nil)
}
})
}
If you are using MPMoviePlayerController
then you can use this code to generate thumbnail from video URL.
NSString *stringUrl = video.stringurl;
NSURL *url = [NSURL URLWithString:stringUrl];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:url];
UIImage *thumbnail = [player thumbnailImageAtTime:1.0 timeOption:MPMovieTimeOptionNearestKeyFrame];
But, using this code, player will start autoplaying audio. So, you have to stop the player with this code :
//Player autoplays audio on init
[player stop];
Update :
Error save image Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed"(OSStatus error -12792.)", NSLocalizedFailureReason=An unknown error occurred (-12792)}
The Error is probably due to use of URLWithString
. I think you should use -fileURLWithPath
instead of URLWithString
.
Sample Code :
NSString *stringUrl = video.stringurl;
NSURL *vidURL = [NSURL fileURLWithPath:stringUrl];
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:vidURL options:nil];
AVAssetImageGenerator *generate = [[AVAssetImageGenerator alloc] initWithAsset:asset];
NSError *err = NULL;
CMTime time = CMTimeMake(1, 60);
CGImageRef imgRef = [generate copyCGImageAtTime:time actualTime:NULL error:&err];
UIImage *thumbnail = [UIImage imageWithCGImage:imgRef];