Get the last frame from the video

I am trying to get the last frame from a video. The last frame, not the last second (because I have very fast videos, one second can have different scenes).

I wrote code like this for testing:

private func getLastFrame(from item: AVPlayerItem) -> UIImage? {
    let imageGenerator = AVAssetImageGenerator(asset: item.asset)

    imageGenerator.requestedTimeToleranceAfter = kCMTimeZero
    imageGenerator.requestedTimeToleranceBefore = kCMTimeZero

    let composition = AVVideoComposition(propertiesOf: item.asset)
    let time = CMTimeMakeWithSeconds(item.asset.duration.seconds, composition.frameDuration.timescale)

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

      

But I always get this error when trying to execute it:

Domain = AVFoundationErrorDomain Code = -11832 "Unable to open" UserInfo = {NSUnderlyingError = 0x170240180 {Domain = NSOSStatusErrorDomain Code = -12431 "(null)"}, NSLocalizedFailureReason = This media cannot be used to open.} NSLocalizedDesc

If I remove requestedTimeTolerance

(so it defaults to infinite), everything is fine, but I always get a brighter image than what I have in the video (maybe this is because the last frame was not captured? Or CGImage -> UIImage transform there are some problems?)

Questions:

  • Why am I getting an error when setting a zero tolerance? How do I get the last frame?
  • Why might the captured images be overbrighted that in the video? For example, if I write code like this:

    self.videoLayer.removeFromSuperlayer()
    self.backgroundImageView.image = getLastFrame(from: playerItem)
    
          

I see a "brightness transition" (the video was darker, the image was brighter).

Update 1

I found a related issue: AVAssetImageGenerator fails when copying an image , but this issue is not resolved.

+3


source to share





All Articles