Split PHAsset to frames swift

74 Views Asked by At

I need to split video(PHAsset) to frames. Please could anyone write an extension for PHAsset for example to call function like this:

extension PHAsset {
   func getFrame(timecode: Float) -> UIImage? {
      *something*
      return frame
   }
}

You can change parameters in below function. Help!

1

There are 1 best solutions below

2
Asteroid On BEST ANSWER

Try this:

import Photos

extension PHAsset {
    
    func getVideoFrames(completion: @escaping ([UIImage]?) -> Void) {
        guard self.mediaType == .video else { completion(nil); return }
        
        let manager = PHCachingImageManager()
        
        manager.requestAVAsset(forVideo: self, options: nil) { asset, audioMix, info in
            guard let asset = asset else { completion(nil); return }
            let imgGenerator: AVAssetImageGenerator = AVAssetImageGenerator(asset: asset)
            imgGenerator.appliesPreferredTrackTransform = true
            imgGenerator.requestedTimeToleranceBefore = CMTimeMake(value: 1, timescale: 15)
            imgGenerator.requestedTimeToleranceAfter = CMTimeMake(value: 1, timescale: 15)
            let duration: Float64 = CMTimeGetSeconds(asset.duration)
            var frames = [UIImage]()
            for index: Int in 0..<Int(duration) {
                let time: CMTime  = CMTimeMakeWithSeconds(Float64(index), preferredTimescale: 600)
                let cgImage: CGImage
                do {
                    try cgImage = imgGenerator.copyCGImage(at: time, actualTime: nil)
                    frames.append(UIImage(cgImage: cgImage))
                } catch {
                    print("Error generating image: \(error)")
                }
            }
            completion(frames)
        }
    }
}

Usage:

let asset = // Some PHAsset
var frames = [UIImage]()
asset.getVideoFrame { images in 
    if let images = images {
        frames = images
        // Do something
    }
}