Deepak Sharma Deepak Sharma - 1 year ago 134
iOS Question

App Crashes while getting all the Frames from a video using AVAssetImageGenerator for long videos

I have successfully extracted all the frames from a video and it is working fine for smaller videos but when I try to extract frames from a video more than 60 secs the app crashes on device.

I am extracting 30 frames per second from the video.

Following is the code I have written :-

var videoSec = Float64(0)

func startImageConversion(){
let filePath = NSURL.fileURLWithPath(self.savedVideoURL)
videoSec = self.getVideoTime(filePath)
videoImagesArray = self.getImagesArrayFromVideo(filePath)
print("Images Count \(videoImagesArray.count)")

// MARK: - Video Editor Functions

func getImagesArrayFromVideo(filePath:NSURL) -> NSMutableArray
let imageArray = NSMutableArray()
print("Video Sec is ",videoSec)
let vidSec = Float64(videoSec)

let theOpts = [
AVURLAssetPreferPreciseDurationAndTimingKey : true,
AVURLAssetReferenceRestrictionsKey : 0 // AVAssetReferenceRestrictions.RestrictionForbidNone
let asset = AVURLAsset(URL: filePath, options: theOpts)
let generator = AVAssetImageGenerator(asset: asset)
generator.maximumSize = CGSize(width: Double(self.view.frame.size.width),
height: Double(self.view.frame.size.height))

generator.appliesPreferredTrackTransform = false
generator.requestedTimeToleranceBefore = kCMTimeZero
generator.requestedTimeToleranceAfter = kCMTimeZero
let vid_length:CMTime = asset.duration
let fps = vid_length.timescale
print("Video Lenght :- \(vid_length) FPS is :- \(fps)")

let mainValue = Float64(vid_length.value)

let divide = vidSec*30
let byVal = mainValue/divide

for i in 0.stride(through: Float64(vid_length.value), by: byVal)

var image:CGImage!//UIImage()
let divident = Float64(i)
// let mileSec = Float64(divident / 1000)
// print(Sec)
image = self.generateVideoThumbs(filePath, second: divident,
thumbWidth: Double(self.view.frame.size.width),
generator : generator,
fps : fps

if image != nil {



print("value of Array is ",imageArray.count)

return imageArray


private func getVideoTime(url: NSURL) -> Float64
let videoTime = AVURLAsset(URL: url, options: nil)
print("videoTime.preferredRate = \(videoTime.preferredRate)")
return CMTimeGetSeconds(videoTime.duration)

private func generateVideoThumbs(url: NSURL, second: Float64, thumbWidth: Double, generator:AVAssetImageGenerator, fps: CMTimeScale) -> CGImage! {
let thumbTime = CMTimeMake(Int64(second), fps)
var actualTime : CMTime = CMTimeMake(0, 0)
print("thumbTime - \(thumbTime)")
do {
let ref = try generator.copyCGImageAtTime(thumbTime, actualTime: &actualTime)
print("actualTime - \(actualTime)")
return ref//UIImage(CGImage: ref)
}catch {
return nil

Everything works fine if the video is less than 60 secs or so.
Also it works fine on simulator but disconnects the device without any warning or error.

enter image description here
Any Help will appreciated, Thanks

Answer Source
if image != nil {
var newImage:UIImage = UIImage(CGImage: cgImage)

As in the above answer dive mentioned its the problem with memory. Just use this code. I have tested it and it worked fine.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download