将PHAsset(video)同步转换为AVAsset

我需要使用AVAsset对象,才能使用AVPlayer和AVPlayerLayer进行播放。 由于AssetsLibrary已被弃用,我开始使用Photos框架。 现在我已经到了我有一个PHAsset对象的数组,我需要将它们转换为AVAsset。 我尝试通过PHFetchResult枚举并使用PHAsset的本地化描述来分配一个新的AVAsset,但是当我播放它时似乎没有显示任何video。

PHAssetCollection *assetColl = [self scaryVideosAlbum]; PHFetchResult *getVideos = [PHAsset fetchAssetsInAssetCollection:assetColl options:nil]; [getVideos enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL *stop) { NSURL *videoUrl = [NSURL URLWithString:asset.localizedDescription]; AVAsset *avasset = [AVAsset assetWithURL:videoUrl]; [tempArr addObject:avasset]; }]; 

我假设本地化的描述不是video的绝对url。

我也偶然发现了PHImageManager和requestAVAssetForVideo,但是,当涉及video的选项参数没有isSynchrounous属性时,图像选项参数就是这种情况。

  PHVideoRequestOptions *option = [PHVideoRequestOptions new]; [[PHImageManager defaultManager] requestAVAssetForVideo:videoAsset options:option resultHandler:^(AVAsset * _Nullable avasset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) { 

有没有同步的方式来做到这一点?

谢谢。

不,没有。 但是你可以build立一个同步版本:

 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]; 

但是,如果您在主线程和requestAVAssetForVideo:上执行此操作requestAVAssetForVideo:时间太长,则可能会导致您的UI被locking,甚至被iOS监视程序终止。

重做您的应用程序以使用asynchronouscallback版本可能更安全。 像这样的东西:

 __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]; }); }]; 

对于Swift 2 ,您可以使用下面的这种方法轻松地使用PHAsset播放video,

导入文件

 import AVKit 

来自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() } }) }) } 

你可以尝试这个技巧,但是当你想要转换成AVAsset的时候,你可以使用3,4个或者5个phasset:

  [[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... } } 

所以基本上,你可以再次调用这个方法,当你已经转换1阶段AVAsset.I知道这可能不是一个有效的代码,但它不应该被禁止的小目的。