4

Been struggling to make it work. I am generating the Video Thumbnails but it's loading really heavily in a collection view. I would like to cache them and I can not find a solution.

This is the code I am using:

func previewImageFromVideo(url:NSURL) -> UIImage? {


    let asset = AVAsset(url: url as URL)
    let imageGenerator = AVAssetImageGenerator(asset:asset)
    imageGenerator.appliesPreferredTrackTransform = true
    imageGenerator.maximumSize = CGSize(width: 250, height: 120)

    var time = asset.duration
    time.value = min(time.value,2)

    do {
        let imageRef = try imageGenerator.copyCGImage(at: time, actualTime: nil)
        return UIImage(cgImage: imageRef)
    } catch {
        return nil
    }
}

I've made them very small, but still connecting every time to the server. Please help.

pfx
  • 20,323
  • 43
  • 37
  • 57
Marian Petrisor
  • 262
  • 2
  • 19

3 Answers3

7

You can use the URLCache:

func previewImageFromVideo(url: NSURL) -> UIImage? {
    let url = url as URL
    let request = URLRequest(url: url)
    let cache = URLCache.shared

    if
        let cachedResponse = cache.cachedResponse(for: request),
        let image = UIImage(data: cachedResponse.data)
    {
        return image
    }

    let asset = AVAsset(url: url)
    let imageGenerator = AVAssetImageGenerator(asset: asset)
    imageGenerator.appliesPreferredTrackTransform = true
    imageGenerator.maximumSize = CGSize(width: 250, height: 120)

    var time = asset.duration
    time.value = min(time.value, 2)

    var image: UIImage?

    do {
        let cgImage = try imageGenerator.copyCGImage(at: time, actualTime: nil)
        image = UIImage(cgImage: cgImage)
    } catch { }

    if
        let image = image,
        let data = UIImagePNGRepresentation(image),
        let response = HTTPURLResponse(url: url, statusCode: 200, httpVersion: nil, headerFields: nil)
    {
        let cachedResponse = CachedURLResponse(response: response, data: data)

        cache.storeCachedResponse(cachedResponse, for: request)
    }

    return image
}
par
  • 17,361
  • 4
  • 65
  • 80
1

I created this extension to create and cache video thumbnail of videos coming from file manager.

You can use like it like this:

 let videoURL = URL(fileURLWithPath: self.videoPath)
 let thumbnailImage = videoURL.createVideoThumbnail()

The extension code :

let imageCache = NSCache<AnyObject, AnyObject>()

extension URL {

   func createVideoThumbnail() -> UIImage? {

    if let imageFromCache = imageCache.object(forKey: self as AnyObject) as? UIImage {
        return imageFromCache
    }

    let asset = AVAsset(url: self)
    let imageGenerator = AVAssetImageGenerator(asset: asset)
    imageGenerator.appliesPreferredTrackTransform = true
    imageGenerator.maximumSize = CGSize(width: 250, height: 120)

    var time = asset.duration
    time.value = min(time.value, 2)

    do {
        let cgImage = try imageGenerator.copyCGImage(at: time, actualTime: nil)
        let image = UIImage(cgImage: cgImage)
        imageCache.setObject(image as AnyObject, forKey: self as AnyObject)
        return image
    } catch let err {
        print(err)
     }
    return UIImage()
  }
}
Krishna Raj Salim
  • 7,331
  • 5
  • 34
  • 66
Yassine En
  • 144
  • 2
  • 8
1

You can use Kingfisher to generate the thumbnail.

Note:- It will handle all the cache work for you.

Usage:-

Step 1

import Kingfisher

Step 2

guard let url = URL(string: videoUrlString) else { return }
self.imageView.kf.setImage(with: AVAssetImageDataProvider(assetURL: url, seconds: 1))

Here is the link of Kingfisher SDK

Note:- It will work fine with latest version of kingfisher/ higher or equals to version 7.2.3