我想在更大的视图中截取AVPlayer
的屏幕截图。我想只构建一个测试框架,所以私有APIs
或任何方法都是好的,因为在发布到AppStore时不会包含框架。
我尝试过使用
UIGetScreenImage()
:适用于模拟器但不适用于设备snapshotviewafterscreenupdates
:它会显示视图但我无法从中创建UIImage
。drawViewInHierarchy
和renderInContext
不适用于AVPlayer
AVAssetGenerator
从视频中获取图片,很难获得良好的坐标或视频播放器作为其他视图的子视图答案 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();