IOS: AVPlayer - taking a snapshot of the current frame of the video

I spent the whole day and went through a lot of SO answers, Apple links, documentation, etc., but didn’t.

I want a simple thing: I play the video using AVPlayer and I want to pause it and get the current frame as a UIImage . What is it.

My video is a m3u8 file located on the Internet, it plays normally in AVPlayerLayer without any problems.

What I tried:

  • AVAssetImageGenerator . It does not work, the copyCGImageAtTime:actualTime: error: method returns null ref ref. According to the answer here, AVAssetImageGenerator does not work for video streaming.
  • Take a snapshot of the player view. I tried first renderInContext: on AVPlayerLayer , but then I realized that it does not create such “special” layers. Then I found a new method introduced in iOS 7 - drawViewHierarchyInRect:afterScreenUpdates: which should be able to display special layers as well, but no luck, still got a UI snapshot with an empty black area where the video is displayed.
  • AVPlayerItemVideoOutput . I have added a video output for my AVPlayerItem , however whenever I call hasNewPixelBufferForItemTime: it returns NO . I think the problem is that the video is streaming again and I am not alone with this problem.
  • AVAssetReader I thought to try, but decided not to lose time after searching for a related question here .

So, is there no way to get a snapshot of something that I still see right now on the screen? I can not believe this.

+5
source share
2 answers

AVPlayerItemVideoOutput works fine for me with m3u8. Maybe because I will not advise hasNewPixelBufferForItemTime and just call copyPixelBufferForItemTime ? This code creates a CVPixelBuffer instead of a UIImage , but there are answers that describe how to do this .

This answer is mostly read here

 #import "ViewController.h" #import <AVFoundation/AVFoundation.h> @interface ViewController () @property (nonatomic) AVPlayer *player; @property (nonatomic) AVPlayerItem *playerItem; @property (nonatomic) AVPlayerItemVideoOutput *playerOutput; @end @implementation ViewController - (void)setupPlayerWithLoadedAsset:(AVAsset *)asset { NSDictionary* settings = @{ (id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA) }; self.playerOutput = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:settings]; self.playerItem = [AVPlayerItem playerItemWithAsset:asset]; [self.playerItem addOutput:self.playerOutput]; self.player = [AVPlayer playerWithPlayerItem:self.playerItem]; AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; playerLayer.frame = self.view.frame; [self.view.layer addSublayer:playerLayer]; [self.player play]; } - (IBAction)grabFrame { CVPixelBufferRef buffer = [self.playerOutput copyPixelBufferForItemTime:[self.playerItem currentTime] itemTimeForDisplay:nil]; NSLog(@"The image: %@", buffer); } - (void)viewDidLoad { [super viewDidLoad]; NSURL *someUrl = [NSURL URLWithString:@"http://qthttp.apple.com.edgesuite.net/1010qwoeiuryfg/sl.m3u8"]; AVURLAsset *asset = [AVURLAsset URLAssetWithURL:someUrl options:nil]; [asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"tracks"] completionHandler:^{ NSError* error = nil; AVKeyValueStatus status = [asset statusOfValueForKey:@"tracks" error:&error]; if (status == AVKeyValueStatusLoaded) { dispatch_async(dispatch_get_main_queue(), ^{ [self setupPlayerWithLoadedAsset:asset]; }); } else { NSLog(@"%@ Failed to load the tracks.", self); } }]; } @end 
+2
source

AVAssetImageGenerator is the best way to take a snapshot of a video, this method returns asynchronously a UIImage :

 var player:AVPlayer? = // ... func screenshot(handler:((UIImage)->Void)) { guard let player = player , let asset = player.currentItem?.asset else { return } let imageGenerator = AVAssetImageGenerator(asset: asset) imageGenerator.appliesPreferredTrackTransform = true let times = [NSValue(CMTime:player.currentTime())] imageGenerator.generateCGImagesAsynchronouslyForTimes(times) { _, image, _, _, _ in if image != nil { handler(UIImage(CGImage: image!)) } } } 

(It Swift 2.3)

+2
source

All Articles