Convertir PHAsset (video) en AVAsset, de manière synchrone

J'ai besoin d'utiliser l'object AVAsset, afin de le jouer en utilisant AVPlayer et AVPlayerLayer. J'ai commencé à utiliser le framework Photos car AssetsLibrary est obsolète. Maintenant, je suis arrivé au point où j'ai un tableau d'objects PHAsset et j'ai besoin de les convertir en AVAsset. J'ai essayé d'énumérer à travers le PHFetchResult et d'allouer un nouvel AVAsset en utilisant la description localisée de PHAsset, mais il ne semble pas y avoir de video quand je la joue.

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

Je suppose que la description localisée n'est pas l'URL absolue de la video.

J'ai également trébuché sur le PHImageManager et le requestAVAssetForVideo, cependant, le paramètre options quand il descend à la video n'a pas une propriété isSynchrounous, ce qui est le cas avec le paramètre d'options d'image.

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

Y a-t-il un moyen synchrone de le faire?

Merci.

    Non, il n'y en a pas. Mais vous pouvez build une version synchrone:

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

    Cependant, si vous faites cela sur le thread principal et que requestAVAssetForVideo: prend trop de time, vous risquez de bloquer votre interface user ou même d'être stoppée par le chien de garde iOS .

    Il est probablement plus sûr de retravailler votre application pour qu'elle fonctionne avec la version de callback asynchronous. Quelque chose comme ça:

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

    Pour Swift 2 , vous pouvez facilement lire la video avec PHAsset utilisant cette méthode ci-dessous,

    Importer le file

     import AVKit 

    De 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() } }) }) } 

    Vous pouvez essayer cette astuce mais c'est pratique quand vous avez 3,4 ou peut-être 5 phassets que vous voulez convertir en 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... } } 

    Donc, fondamentalement, vous pouvez appeler cette méthode à nouveau quand vous avez converti 1 phasset en AVAsset. Je sais que ce n'est peut-être pas un code efficace, mais il ne devrait pas être interdit pour de petites raisons.