Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Photos framework image from video at a certain frame

I have made a library collectionview filled with videos i fetch from the Photos framework, i use thumbnails to display all the different videos using the following method

func requestImageForAsset(_ asset: PHAsset!, targetSize targetSize: CGSize, contentMode contentMode: PHImageContentMode, options options: PHImageRequestOptions!, resultHandler resultHandler: ((UIImage!, [NSObject : AnyObject]!) -> Void)!) -> PHImageRequestID

which works fine. But my videos always start with a black frame, so all the thumbnails are black. can I offset the frame from which it takes a snapshot image?

like image 215
Andy Jacobs Avatar asked Sep 01 '15 08:09

Andy Jacobs


3 Answers

This is code i have used in my project which works like a charm for me

func generateThumnail(url: URL) -> UIImage? {
    let asset = AVAsset(url: url)
    let assetImgGenerate = AVAssetImageGenerator(asset: asset)
    assetImgGenerate.appliesPreferredTrackTransform = true
    assetImgGenerate.maximumSize = CGSize(width: 100, height: 100)
    let time = CMTimeMake(1, 30)

    if let img = try? assetImgGenerate.copyCGImage(at: time, actualTime: nil) {
        return UIImage(cgImage: img)
    }
    return nil
}

The above function will return the image at 1 sec of the video

This is the way of passing the assetUrl of your video to get the thumbnail

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {

    let mediaType = info[UIImagePickerControllerMediaType] as! String
    if (mediaType == kUTTypeMovie as! String){
        let tempVideo = info[UIImagePickerControllerMediaURL] as! URL
        if let thumbnail = self.generateThumbnail(url: tempVideo) {
            // Use your thumbnail
        }
like image 191
Manu Gupta Avatar answered Nov 04 '22 21:11

Manu Gupta


You can fetch the associated AVAsset object with

func requestAVAssetForVideo(_ asset: PHAsset,
                options options: PHVideoRequestOptions?,
          resultHandler resultHandler: (AVAsset?,
                                 AVAudioMix?,
              [NSObject : AnyObject]?) -> Void) -> PHImageRequestID

then load that asset into an AVAssetImageGenerator which is capable of fetching time-specific thumbnails via

func copyCGImageAtTime(_ requestedTime: CMTime,
        actualTime actualTime: UnsafeMutablePointer<CMTime>,
             error outError: NSErrorPointer) -> CGImage!
like image 34
emb Avatar answered Nov 04 '22 20:11

emb


I think you need to be looking at the AVFoundation libraries to decode the video and grab the frame you want yourself.

To update the placeholders in the library looking at the docs it seems that you need to create a PHAssetChangeRequest and set the placeholderForCreatedAsset property on it. Then you need to request that the change be performed by the library within a changeblock.

Note: If this is only for your use you can set the placeholder frame within Photos and that should be reflected in your app.

like image 2
Joseph Lord Avatar answered Nov 04 '22 21:11

Joseph Lord