Search code examples
iosswiftvideo-thumbnails

Unable to generate thumbnail from video in gallery


I'm displaying to the user an image picker to select a video from the gallery. That works, i pass the mediatype ["public.movie"] and all the videos of the gallery are displayed to pick up. When the user picks it i receive in my dellegate:

extension VNInventoryCollectionVC: UIImagePickerControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
        let info = convertFromUIImagePickerControllerInfoKeyDictionary(info)
        if let pickedImage = info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.originalImage)] as? UIImage
        {
            pickImageCallback?(pickedImage)
        }
        if let videoURL = info["UIImagePickerControllerReferenceURL"] as? URL
        {
            print(videoURL)
            pickImageCallback?(videoURL)
        }
        dismiss(animated: true)
       
    }
}

After the callback i'm trying to create a image thumbnail from that video, and that is where i'm not able to do it:

let thumbnail = getThumbnailFrom(path: multimedia.video!)
cell.image.image = thumbnail

The function that generates the thumbnail is:

func getThumbnailFrom(path: URL) -> UIImage? {
    do {
        print("Video URL: \(path)")
        print("Video absolute URL: \(path.absoluteURL)")
        //let asset = AVURLAsset(url: path.absoluteURL! , options: nil)
        var asset : AVAsset = AVAsset(url: path.absoluteURL) as! AVAsset
        let imgGenerator = AVAssetImageGenerator(asset: asset)
        imgGenerator.appliesPreferredTrackTransform = true
        let cgImage = try imgGenerator.copyCGImage(at: CMTimeMake(value: 0, timescale: 1), actualTime: nil)
        let thumbnail = UIImage(cgImage: cgImage)

        return thumbnail

    } catch let error {
        print("*** Error generating thumbnail: \(error.localizedDescription)")
        return nil
    }
}

In the console the video url displayed is:

Video URL: assets-library://asset/asset.MP4?id=84D1CEDD-7AE4-4FE5-897E-47608DC2CFF0&ext=MP4
Video absolute URL: assets-library://asset/asset.MP4?id=84D1CEDD-7AE4-4FE5-897E-47608DC2CFF0&ext=MP4

The displayed error is that is unable to open the file. The line that breaks is:

let cgImage = try imgGenerator.copyCGImage(at: CMTimeMake(value: 0, timescale: 1), actualTime: nil)

I suppose the problem is with the url, that i have an assets url and i would require an absolute file path or something like that.


Solution

  • Use UIImagePickerController.InfoKey.mediaURL to key into the info dictionary. UIImagePickerController.InfoKey.referenceURL is deprecated.

    func didSelectVideo(at url: URL) {
        let asset = AVAsset(url: url)
        let generator = AVAssetImageGenerator(asset: asset)
        generator.appliesPreferredTrackTransform = true
        let cgImage = try! generator.copyCGImage(at: CMTimeMake(value: 0, timescale: 1), actualTime: nil)
        let thumbnail = UIImage(cgImage: cgImage)
        cell.image.image = thumbnail
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        dismiss(animated: true) {
            guard let url = info[.mediaURL] as? URL else { return }
            self.didSelectVideo(at: url)
        }
    }