I have VideoThumbnailManager and It serves to cache with SDWebImage the image of the video and display it to the user. But the Video thumbnail is showing 2 on the collectionview. but when I scroll, the collectionview changes and becomes correct. how do i solve this problem?
result :
//
// VideoThumbnailManager.swift
// Created by erhan demirci on 26.04.2023.
import Foundation
import AVFoundation
import SDWebImage
class VideoThumbnailManager {
static let shared = VideoThumbnailManager()
func generateThumbnailImage(for videoURL: URL, completion: @escaping (UIImage?) -> Void) {
let options: SDWebImageOptions = [.scaleDownLargeImages, .continueInBackground]
let cacheKey = SDWebImageManager.shared.cacheKey(for: videoURL)
if let cachedImage = SDImageCache.shared.imageFromCache(forKey: cacheKey) {
// Return cached image if available
completion(cachedImage)
} else {
// Generate new thumbnail image
let asset = AVAsset(url: videoURL)
let imageGenerator = AVAssetImageGenerator(asset: asset)
imageGenerator.appliesPreferredTrackTransform = true
imageGenerator.maximumSize = CGSize(width: 100, height: 100)
let timestamp = CMTime(seconds: 1.0, preferredTimescale: 60)
imageGenerator.generateCGImagesAsynchronously(forTimes: [NSValue(time: timestamp)]) { (requestedTime, cgImage, actualTime, result, error) in
if let cgImage = cgImage {
let thumbnailImage = UIImage(cgImage: cgImage)
completion(thumbnailImage)
// Cache thumbnail image
if let data = thumbnailImage.jpegData(compressionQuality: 0.8) {
SDImageCache.shared.storeImageData(toDisk: data, forKey: cacheKey)
}
} else {
completion(nil)
}
}
}
}
}
my collection view cell
class TemplateCell: UICollectionViewCell {
@IBOutlet weak var thumbnailImageView: UIImageView!
func configure(with videoURL: URL) {
self.videoURL = videoURL
}
func loadVideo() {
guard let videoURL = self.videoURL else {
return
}
// use the VideoCacheManager to get the video asset and thumbnail image
VideoThumbnailManager.shared.generateThumbnailImage(for: videoURL) { thumbnail in
DispatchQueue.main.async {
self.thumbnailImageView.image = thumbnail
}
}
}
func unloadVideo() {
self.videoPlayerLayer?.removeFromSuperlayer()
//self.videoPlayerLayer = nil
}
}
I use on collection view like that:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
///....
cell.configure(with: myUrl)
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
videoCell.loadVideo()
}
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
videoCell.unloadVideo()
}

You can read this answer to understand why this is happening. https://stackoverflow.com/a/76261182/5973760
There are different ways to get this done, try to implement below code.
Here you need to change the completion of your
generateThumbnailImage()function along with image pass the video url also.You can check the other approach also: https://stackoverflow.com/a/31844232/5973760