How can I programmatically capture a screenshot of

2019-07-31 03:46发布

问题:

I want to capture a screenshot of a playing video in xcode. How can I do it programmatically? I found a screenshot method in apple document as following. The method works fine if I just want to take a screenshot of a view. However, it fails to work with a playing video.

- (UIImage*)screenshot 
{
    // Create a graphics context with the target size
    // On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
    // On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
    CGSize imageSize = [[UIScreen mainScreen] bounds].size;
    if (NULL != UIGraphicsBeginImageContextWithOptions)
        UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
    else
        UIGraphicsBeginImageContext(imageSize);

    CGContextRef context = UIGraphicsGetCurrentContext();

    // Iterate over every window from back to front
    for (UIWindow *window in [[UIApplication sharedApplication] windows]) 
    {
        if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen])
        {
            // -renderInContext: renders in the coordinate space of the layer,
            // so we must first apply the layer's geometry to the graphics context
            CGContextSaveGState(context);
            // Center the context around the window's anchor point
            CGContextTranslateCTM(context, [window center].x, [window center].y);
            // Apply the window's transform about the anchor point
            CGContextConcatCTM(context, [window transform]);
            // Offset by the portion of the bounds left of and above the anchor point
            CGContextTranslateCTM(context,
                                  -[window bounds].size.width * [[window layer] anchorPoint].x,
                                  -[window bounds].size.height * [[window layer] anchorPoint].y);

            // Render the layer hierarchy to the current context
            [[window layer] renderInContext:context];

            // Restore the context
            CGContextRestoreGState(context);
        }
    }

    // Retrieve the screenshot image
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return image;
}

I need to capture a screenshot of a playing video. Any idea?

回答1:

Hope this pice of code will help

Capture screenshot of a playing video

- (void)setupVideoPlayerView
{
videoPlayerVC = [[AVPlayerViewController alloc] init];
videoPlayerVC.view.frame = self.videoPlayerView.bounds;
videoPlayerVC.videoGravity = AVLayerVideoGravityResizeAspectFill
[videoPlayerView addSubview:_videoPlayerVC.view];
[videoPlayerVC setShowsPlaybackControls:NO];
videoPlayerVC.player = [AVPlayer playerWithURL:[NSURL URLWithString:kVideoURL];
[videoPlayerVC.player play];
}

- (UIImage *)snapImageFromRuningVideo
{
AVAsset *assest = [self.videoPlayerVC.player.currentItem asset];
AVAssetImageGenerator *imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:assest];
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:self.videoPlayerVC.player.currentItem.currentTime actualTime:nil error:nil];
UIImage *screengrab = [UIImage imageWithCGImage:imageRef];
return screengrab;
}

here just create AVPlayerViewController if you want controller bar or just instantiate AVPlayer and bind the URL of the Video and play.

whenever you want to capture a snapshot of the running video at that time on button click of Snapshot you can call method "snapImageFromRuningVideo" which will return UIImage object reference.

AVPlayer internally create AVPlayerItem and AVAsset object. now create AVAssetImageGenerator object just by using AVAsset object then copy the image at a time from when you want to take the snapshot by calling "CGImageRef imageRef = [imageGenerator copyCGImageAtTime:self.videoPlayerVC.player.currentItem.currentTime actualTime:nil error:nil];"

here we have to pass player current time at the instant of taking the snapshot