Screenshot voor AVPlayer en video

Ik probeer een screenshot te maken van een AVPlayerin een grotere weergave. Ik wil alleen een testraamwerk bouwen, dus privé APIsof welke methode dan ook is goed, omdat het raamwerk niet wordt opgenomen bij het vrijgeven in de AppStore.

Ik heb het geprobeerd met

  • UIGetScreenImage(): werkt goed op simulator maar niet op apparaat
  • snapshotviewafterscreenupdates: het toont de weergave, maar ik kan daar geen UIImagevan maken.
  • drawViewInHierarchyen renderInContextwerken niet met AVPlayer
  • Ik wil AVAssetGeneratorniet gebruiken om afbeeldingen uit video te halen, het is moeilijk om een ​​goede coördinaat te krijgen of de videospeler als subweergave van andere weergaven

Antwoord 1, autoriteit 100%

Ik weet dat je de AVAssetImageGenerator niet wilt gebruiken, maar ik heb hier ook uitgebreid onderzoek naar gedaan en ik geloof dat de enige oplossing momenteel het gebruik van de AVAssetImageGenerator is. Het is niet zo moeilijk als je zegt om de juiste coördinaat te krijgen, omdat je de huidige tijd van je speler moet kunnen krijgen. In mijn App werkt de volgende code perfect:

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

Antwoord 2

AVPlayer die video’s rendert met GPU, dus u kunt deze niet vastleggen met de belangrijkste grafische methoden.

Het is echter mogelijk om afbeeldingen vast te leggen met AVAssetImageGenerator, u moet een CMTime opgeven.


Bijwerken:

Vergeet een screenshot van het hele scherm te maken. AVPlayerItemVideoOutputis mijn uiteindelijke keuze, het ondersteunt video-stoom.

Hier is mijn volledige implementatie: https:// /ZFPlayer/commit/a32c7244f630e69643336b65351463e00e712c7f#diff-2d23591c151edd3536066df7c18e59deR448


Antwoord 3

Hier is de code voor het maken van een screenshot van uw volledige scherm, inclusief de AVPlayer. Je hoeft alleen maar een UIImageView toe te voegen aan je videospeler, die verborgen blijft totdat we de screenshot maken en daarna weer verbergen.

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
}

Antwoord 4

Als u een screenshot van het huidige scherm wilt maken, roept u gewoon de volgende methode aan bij een actiegebeurtenis die u een Image-object geeft.

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

Ik hoop dat dit je zal helpen.


Antwoord 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();

Other episodes