0 votes
in Education by (1.7m points)
I am trying to get a thumbnail image from a video from a URL using AVFoundation but I am getting a black blank image as attached.

The video URL is https://www.riptide.tv/app/assets/2/3/small_3001190658061_2.mp4

Below is my code:

func videoSnapshot(videoURL: String, imgName : String) -> UIImage? {

        let asset = AVAsset(url: URL(string: videoURL)!)

        let assetImgGenerate = AVAssetImageGenerator(asset: asset)

        assetImgGenerate.appliesPreferredTrackTransform = true

    let time = CMTimeMakeWithSeconds(Float64(1), preferredTimescale: 100)

        do {

            let img = try assetImgGenerate.copyCGImage(at: time, actualTime: nil)

            let thumbnail = UIImage(cgImage: img)

            downloadedThumbnails.updateValue(thumbnail, forKey: imgName)

            return thumbnail

        } catch {

            return UIImage(named: imgName)

        }

}

black img extracted

JavaScript questions and answers, JavaScript questions pdf, JavaScript question bank, JavaScript questions and answers pdf, mcq on JavaScript pdf, JavaScript questions and solutions, JavaScript mcq Test , Interview JavaScript questions, JavaScript Questions for Interview, JavaScript MCQ (Multiple Choice Questions)

1 Answer

0 votes
by (1.7m points)
If you change your code to

func videoSnapshot(videoURL: String, imgName : String) -> UIImage? {

    let asset = AVAsset(url: URL(string: videoURL)!)

    let assetImgGenerate = AVAssetImageGenerator(asset: asset)

    assetImgGenerate.appliesPreferredTrackTransform = true

    let time = CMTimeMakeWithSeconds(Float64(5), preferredTimescale: 100)

    do {

        let img = try assetImgGenerate.copyCGImage(at: time, actualTime: nil)

        let thumbnail = UIImage(cgImage: img)

        return thumbnail

    } catch {

        return UIImage(named: imgName)

    }

}

thats 5 seconds in. You can see the thumbnail generated.

This is because AVAssetImageGenerator is pretty flexible in what times it gets its frames

func videoSnapshot(videoURL: String, imgName : String) -> UIImage? {

    let asset = AVAsset(url: URL(string: videoURL)!)

    let assetImgGenerate = AVAssetImageGenerator(asset: asset)

    assetImgGenerate.appliesPreferredTrackTransform = true

    assetImgGenerate.requestedTimeToleranceAfter = .zero

    assetImgGenerate.requestedTimeToleranceBefore = .zero

    let time = CMTimeMakeWithSeconds(Float64(1), preferredTimescale: 100)

    do {

        let img = try assetImgGenerate.copyCGImage(at: time, actualTime: nil)

        let thumbnail = UIImage(cgImage: img)

        return thumbnail

    } catch {

        return UIImage(named: imgName)

    }

}

Setting

assetImgGenerate.requestedTimeToleranceAfter = .zero

assetImgGenerate.requestedTimeToleranceBefore = .zero

ensures you get a frame accurate thumbnail.

For more info see https://developer.apple.com/documentation/avfoundation/avassetimagegenerator/1390571-requestedtimetolerancebefore

Related questions

0 votes
1 answer
0 votes
1 answer
0 votes
1 answer
0 votes
1 answer
...