18

I have made a library collectionview filled with videos i fetch from the Photos framework, i use thumbnails to display all the different videos using the following method

func requestImageForAsset(_ asset: PHAsset!, targetSize targetSize: CGSize, contentMode contentMode: PHImageContentMode, options options: PHImageRequestOptions!, resultHandler resultHandler: ((UIImage!, [NSObject : AnyObject]!) -> Void)!) -> PHImageRequestID

which works fine. But my videos always start with a black frame, so all the thumbnails are black. can I offset the frame from which it takes a snapshot image?

Andy Jacobs
  • 15,187
  • 13
  • 60
  • 91

3 Answers3

12

This is code i have used in my project which works like a charm for me

func generateThumnail(url: URL) -> UIImage? {
    let asset = AVAsset(url: url)
    let assetImgGenerate = AVAssetImageGenerator(asset: asset)
    assetImgGenerate.appliesPreferredTrackTransform = true
    assetImgGenerate.maximumSize = CGSize(width: 100, height: 100)
    let time = CMTimeMake(1, 30)

    if let img = try? assetImgGenerate.copyCGImage(at: time, actualTime: nil) {
        return UIImage(cgImage: img)
    }
    return nil
}

The above function will return the image at 1 sec of the video

This is the way of passing the assetUrl of your video to get the thumbnail

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {

    let mediaType = info[UIImagePickerControllerMediaType] as! String
    if (mediaType == kUTTypeMovie as! String){
        let tempVideo = info[UIImagePickerControllerMediaURL] as! URL
        if let thumbnail = self.generateThumbnail(url: tempVideo) {
            // Use your thumbnail
        }
jovanjovanovic
  • 4,158
  • 3
  • 22
  • 32
Manu Gupta
  • 1,759
  • 1
  • 14
  • 22
8

You can fetch the associated AVAsset object with

func requestAVAssetForVideo(_ asset: PHAsset,
                options options: PHVideoRequestOptions?,
          resultHandler resultHandler: (AVAsset?,
                                 AVAudioMix?,
              [NSObject : AnyObject]?) -> Void) -> PHImageRequestID

then load that asset into an AVAssetImageGenerator which is capable of fetching time-specific thumbnails via

func copyCGImageAtTime(_ requestedTime: CMTime,
        actualTime actualTime: UnsafeMutablePointer<CMTime>,
             error outError: NSErrorPointer) -> CGImage!
emb
  • 405
  • 3
  • 5
2

I think you need to be looking at the AVFoundation libraries to decode the video and grab the frame you want yourself.

To update the placeholders in the library looking at the docs it seems that you need to create a PHAssetChangeRequest and set the placeholderForCreatedAsset property on it. Then you need to request that the change be performed by the library within a changeblock.

Note: If this is only for your use you can set the placeholder frame within Photos and that should be reflected in your app.

Joseph Lord
  • 6,446
  • 1
  • 28
  • 32