Convert PHAsset (video) to AVAsset, synchronously

≡放荡痞女 提交于 2019-11-30 12:02:30

No, there isn't. But you can build a synchronous version:

dispatch_semaphore_t    semaphore = dispatch_semaphore_create(0);

PHVideoRequestOptions *option = [PHVideoRequestOptions new];
__block AVAsset *resultAsset;

[[PHImageManager defaultManager] requestAVAssetForVideo:videoAsset options:option resultHandler:^(AVAsset * avasset, AVAudioMix * audioMix, NSDictionary * info) {
    resultAsset = avasset;
    dispatch_semaphore_signal(semaphore);
}];

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// yay, we synchronously have the asset
[self doSomethingWithAsset:resultAsset];

However if you do this on the main thread and requestAVAssetForVideo: takes too long, you risk locking up your UI or even being terminated by the iOS watchdog.

It's probably safer to rework your app to work with the asynchronous callback version. Something like this:

__weak __typeof(self) weakSelf = self;

[[PHImageManager defaultManager] requestAVAssetForVideo:videoAsset options:option resultHandler:^(AVAsset * avasset, AVAudioMix * audioMix, NSDictionary * info) {
    dispatch_async(dispatch_get_main_queue(), ^{
        [weakSelf doSomethingWithAsset:avasset];
    });
}];

For Swift 2, you can easily play the video with PHAsset using this method below,

Import File

import AVKit

From PHAsset

static func playVideo (view:UIViewController, asset:PHAsset) {

        guard (asset.mediaType == PHAssetMediaType.Video)

            else {
                print("Not a valid video media type")
                return
        }

        PHCachingImageManager().requestAVAssetForVideo(asset, options: nil, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [NSObject : AnyObject]?) in

            let asset = asset as! AVURLAsset

            dispatch_async(dispatch_get_main_queue(), {

                let player = AVPlayer(URL: asset.URL)
                let playerViewController = AVPlayerViewController()
                playerViewController.player = player
                view.presentViewController(playerViewController, animated: true) {
                    playerViewController.player!.play()
                }
            })
        })
    }

You can try this trick but it is handy when you have 3,4 or maybe 5 phassets that you want to convert to AVAsset :

    [[PHImageManager defaultManager] requestAVAssetForVideo:assetsArray[0] options:option resultHandler:^(AVAsset * avasset, AVAudioMix * audioMix, NSDictionary * info) {
//do something with this asset
       [[PHImageManager defaultManager] requestAVAssetForVideo:assetsArray[1] options:option resultHandler:^(AVAsset * avasset, AVAudioMix * audioMix, NSDictionary * info) {
//so on...
       }
        }

So basically,you can call this method again when you have converted 1 phasset to AVAsset.I know this might not be an efficient code but it should not be forbidden for little purposes.

The following is a Swift 4 implementation that relies on a semaphore to make the request synchronously.

The code is commented to explain the various steps.

func requestAVAsset(asset: PHAsset) -> AVAsset? {
    // We only want videos here
    guard asset.mediaType == .video else { return nil }
    // Create your semaphore and allow only one thread to access it
    let semaphore = DispatchSemaphore.init(value: 1)
    let imageManager = PHImageManager()
    var avAsset: AVAsset?
    // Lock the thread with the wait() command
    semaphore.wait()
    // Now go fetch the AVAsset for the given PHAsset
    imageManager.requestAVAsset(forVideo: asset, options: nil) { (asset, _, _) in
        // Save your asset to the earlier place holder
        avAsset = asset
        // We're done, let the semaphore know it can unlock now
        semaphore.signal()
    }

    return avAsset
}

You can use this:

let asset = info[UIImagePickerControllerPHAsset] as? PHAsset

PHCachingImageManager().requestAVAsset(forVideo: phAsset, options: nil) { (avAsset, _, _) in
    if let avAsset = avAsset {
        print(avAsset)
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!