Screenshot for AVPlayer and Video Screenshot for AVPlayer and Video ios ios

Screenshot for AVPlayer and Video


I know you don't want to use the AVAssetImageGenerator but I've also researched this extensively and I believe the only solution currently is using the AVAssetImageGenerator. It's not that difficult as you say to get the right coordinate because you should be able to get the current time of your player. In my App the following code works perfectly:

-(UIImage *)getAVPlayerScreenshot {    AVURLAsset *asset = (AVURLAsset *)self.playerItem.asset;    AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];    imageGenerator.requestedTimeToleranceAfter = kCMTimeZero;    imageGenerator.requestedTimeToleranceBefore = kCMTimeZero;    CGImageRef thumb = [imageGenerator copyCGImageAtTime:self.playerItem.currentTime                                              actualTime:NULL                                                   error:NULL];    UIImage *videoImage = [UIImage imageWithCGImage:thumb];    CGImageRelease(thumb);    return videoImage;}


AVPlayer rending videos using GPU, so you cannot capture it using core graphics methods.

However that’s possible to capture images with AVAssetImageGenerator, you need specify a CMTime.


Update:

Forget to take a screenshot of the entire screen. AVPlayerItemVideoOutput is my final choice, it supports video steam.

Here is my full implementation: https://github.com/BB9z/ZFPlayer/commit/a32c7244f630e69643336b65351463e00e712c7f#diff-2d23591c151edd3536066df7c18e59deR448


Here is code for taking a screenshot of you entire screen, including the AVPlayer. You only need to add a UIImageView on top of your videoplayer, which stays hidden until we take the screenshot and then we hide it again.

func takeScreenshot() -> UIImage? {    //1 Hide all UI you do not want on the screenshot    self.hideButtonsForScreenshot()    //2 Create an screenshot from your AVPlayer    if let url = (self.overlayPlayer?.currentItem?.asset as? AVURLAsset)?.url {          let asset = AVAsset(url: url)          let imageGenerator = AVAssetImageGenerator(asset: asset)          imageGenerator.requestedTimeToleranceAfter = CMTime.zero          imageGenerator.requestedTimeToleranceBefore = CMTime.zero        if let thumb: CGImage = try? imageGenerator.copyCGImage(at: self.overlayPlayer!.currentTime(), actualTime: nil) {            let videoImage = UIImage(cgImage: thumb)            //Note: create an image view on top of you videoPlayer in the exact dimensions, and display it before taking the screenshot            // mine is created in the storyboard            // 3 Put the image from the screenshot in your screenshotPhotoView and unhide it            self.screenshotPhotoView.image = videoImage            self.screenshotPhotoView.isHidden = false        }    }        //4 Take the screenshot    let bounds = UIScreen.main.bounds    UIGraphicsBeginImageContextWithOptions(bounds.size, true, 0.0)    self.view.drawHierarchy(in: bounds, afterScreenUpdates: true)    let image = UIGraphicsGetImageFromCurrentImageContext()    UIGraphicsEndImageContext()        //5 show all UI again that you didn't want on your screenshot    self.showButtonsForScreenshot()    //6 Now hide the screenshotPhotoView again    self.screenshotPhotoView.isHidden = true    self.screenshotPhotoView.image = nil    return image}