Search code examples
iosvideoavassetphassetphlivephoto

Extract video portion from Live Photo


Has anyone figured out how to extract the video portion from a Live Photo? I'm working on an app to convert Live Photos into a GIF, and the first step is to get the video file from the Live Photo. It seems like it should be possible, because if you plug in your phone to a Mac you can see the separate image and video files. I've kinda run into a brick wall in the extraction process, and I've tried many ways to do it and they all fail.

The first thing I did was obtain a PHAsset for what I think is the video part of the Live Photo, by doing the following:

    if let livePhoto = info["UIImagePickerControllerLivePhoto"] as? PHLivePhoto {
        let assetResources = PHAssetResource.assetResourcesForLivePhoto(livePhoto)
        for assetRes in assetResources {
            if (assetRes.type == .PairedVideo) {
                let assets = PHAsset.fetchAssetsWithLocalIdentifiers([assetRes.assetLocalIdentifier], options: nil)
                if let asset = assets.firstObject as? PHAsset {

To convert the PHAsset to an AVAsset I've tried:

    asset.requestContentEditingInputWithOptions(nil, completionHandler: { (contentEditingInput, info) -> Void in

        if let url = contentEditingInput?.fullSizeImageURL {
            let movieUrl = url.absoluteString + ".mov"
            let avAsset = AVURLAsset(URL: NSURL(fileURLWithPath: movieUrl), options: nil)
            debugPrint(avAsset)
            debugPrint(avAsset.duration.value)
        }
    })

I don't think this one works because the debug print with the duration.value gives 0. I've also tried without the ".mov" addition and it still doesn't work.

I also tried:

    PHImageManager.defaultManager().requestAVAssetForVideo(asset, options: nil, resultHandler: { (avAsset, audioMix, info) -> Void in
        debugPrint(avAsset)
    })

And the debugPrint(avAsset) prints nil so it doesn't work.

I'm kind of afraid they might have made it impossible to do, it seems like I'm going in circles since it seems like the PHAsset I got is still a Live Photo and not actually a video.


Solution

  • Use the PHAssetResourceManager to get the video file from the PHAssetResource.

    PHAssetResourceManager.defaultManager().writeDataForAssetResource(assetRes, 
        toFile: fileURL, options: nil, completionHandler: 
      {
         // Video file has been written to path specified via fileURL
      }
    

    NOTE: The Live Photo specific APIs were introduced in iOS 9.1