AVPlayer和视频的屏幕截图

时间:2014-04-25 07:00:40

标签: ios objective-c testing

我想在更大的视图中截取AVPlayer的屏幕截图。我想只构建一个测试框架,所以私有APIs或任何方法都是好的,因为在发布到AppStore时不会包含框架。

我尝试过使用

  • UIGetScreenImage():适用于模拟器但不适用于设备
  • snapshotviewafterscreenupdates:它会显示视图但我无法从中创建UIImage
  • drawViewInHierarchyrenderInContext不适用于AVPlayer
  • 我不想使用AVAssetGenerator从视频中获取图片,很难获得良好的坐标或视频播放器作为其他视图的子视图

5 个答案:

答案 0 :(得分:8)

我知道你不想使用AVAssetImageGenerator,但我也对此进行了广泛的研究,我相信目前唯一的解决方案是使用AVAssetImageGenerator。你说要获得正确的坐标并不困难,因为你应该能够得到你的玩家的当前时间。在我的应用程序中,以下代码完美运行:

-(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;
}

答案 1 :(得分:0)

这里是截取整个屏幕截图的代码,包括 AVPlayer。你只需要在你的视频播放器顶部添加一个 UIImageView,它会一直隐藏,直到我们截取屏幕截图,然后我们再次隐藏它。

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
}

答案 2 :(得分:-1)

AVPlayer使用GPU渲染视频,因此您无法使用核心图形方法捕获它。

但是,可以使用AVAssetImageGenerator捕获图像,您需要指定CMTime。

答案 3 :(得分:-2)

如果你想获取当前屏幕的截图,只需在任何给你Image对象的动作事件上调用以下方法。

-(UIImage *) screenshot
{
    UIGraphicsBeginImageContext(self.view.bounds.size);
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *sourceImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    //now we will position the image, X/Y away from top left corner to get the portion we want
    UIGraphicsBeginImageContext(sourceImage.size);
    [sourceImage drawAtPoint:CGPointMake(0, 0)];
    UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    //To write image on divice.
    //UIImageWriteToSavedPhotosAlbum(croppedImage,nil, nil, nil);

    return croppedImage;
}

希望这会对你有所帮助。

答案 4 :(得分:-5)

CGRect grabRect = CGRectMake(0,0,320,568);// size you want to take screenshot of. 

if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
   UIGraphicsBeginImageContextWithOptions(grabRect.size, NO, [UIScreen mainScreen].scale);
 } else {
      UIGraphicsBeginImageContext(grabRect.size);
}
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, -grabRect.origin.x, -grabRect.origin.y);
[self.view.layer renderInContext:ctx];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();