Get a current frame from Youtube YTPlayerView

1.1k views Asked by At

Does anyone know a working solution to make a screenshot of a youtube video on iOS ? A standard "UIView to UIImage" solutions like snapshotting current graphic context or a layer of the view don't work as I get only a black, empty video player with Youtube logo on it, without the actual video.

I tried to snapshot the view's presentationLayer but then I get the BAD_ACCESS error. I heard it has something to do with CSS/HTML5 inside the UIWebView (which is used to display the youtube player).

Has anyone succeeded on that ?

1

There are 1 answers

0
Joe Rosen On

Bartek Uchanski, thank you again, your response pointed me in the right direction.

For my particular application I still needed to rely on Google's YouTube iOS Player Helper API for video playback, however to extract a thumbnail (which seems to be impossible directly with the Google YouTube API) I loaded a separate "shadow" mp4 stream from YouTube, relying on both the XCDYouTubeClient library and AVAsset/AVFoundation framework to extract and save a thumbnail image. (Unfortunately [player thumbnailImageAtTime:] is deprecated hence my workaround below.)

1) Use the XCDYouTubeClient API to extract an e.g. mp4 video stream URL from a YouTube 11 character video identifier; you could also parse the YouTube video's HTML page for the same stream URL(s) but I found it (much) easier to simply use the XCDYouTubeClient API.

2) Once you've retrieved the URL to the video stream then use the AVAsset/AVFoundation framework to extract a thumbnail.

(I've shorthanded my actual app code here, but the general concept is as follows.)

NSString *videoid = @"9bZkp7q19f0"; // youtube 11 character video identifier
[[XCDYouTubeClient defaultClient] getVideoWithIdentifier:videoid completionHandler:^(XCDYouTubeVideo *video, NSError *error) {
  if (video) {
    // available youtube urls; e.g. itag=160 mp4 video only, 256x144
    if (video.streamURLs[[NSNumber numberWithInt:160]]) {
      // grab thumbnail from specified video stream @ specified time, e.g. @ 30 secs
      AVAsset *asset = [AVAsset assetWithURL:[NSURL URLWithString:[[video.streamURLs[[NSNumber numberWithInt:160]] description] stringByRemovingPercentEncoding]]];
      AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
      CGImageRef imageRef = [imageGenerator copyCGImageAtTime:CMTimeMakeWithSeconds(30.0,NSEC_PER_SEC) actualTime:NULL error:NULL];
      UIImage *ytvideo_thumbnail = [UIImage imageWithCGImage:imageRef];
      CGImageRelease(imageRef);
      // save thumbnail to camera roll
      UIImageWriteToSavedPhotosAlbum(ytvideo_thumbnail,nil,nil,nil);
    }
  }
}];