Convierta PHAsset (video) en AVAsset, sincrónicamente

Necesito usar el object AVAsset, para poder jugarlo con AVPlayer y AVPlayerLayer. Comencé a usar el marco de fotos porque AssetsLibrary está en desuso. Ahora llegué al punto en que tengo una matriz de objects PHAsset y necesito convertirlos a AVAsset. Intenté enumerar a través de PHFetchResult y asignar un nuevo AVAsset usando la descripción localizada de PHAsset, pero no parece mostrar ningún video cuando lo juego.

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

Supongo que la descripción localizada no es la url absoluta del video.

También me topé con el PHImageManager y el requestAVAssetForVideo, sin embargo, el parámetro de opciones cuando se trata de video no tiene una propiedad isSynchrounous, como es el caso del parámetro de opciones de image.

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

¿Hay una manera sincrónica de hacer esto?

Gracias.

No, no hay Pero puedes build una versión síncrona:

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

Sin embargo, si hace esto en el hilo principal y requestAVAssetForVideo: toma demasiado time, corre el riesgo de bloquear su UI o, incluso, de ser cancelado por el perro guardián de iOS .

Probablemente sea más seguro volver a trabajar con su aplicación para que funcione con la versión de callback asíncrona. Algo como esto:

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

Para Swift 2 , puede reproducir fácilmente el video con PHAsset usando este método a continuación,

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

Puedes probar este truco pero es útil cuando tienes 3,4 o tal vez 5 phassets que quieres convertir a 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... } } 

Básicamente, puede llamar a este método nuevamente cuando haya convertido 1 phasset a AVAsset. Sé que esto podría no ser un código eficiente, pero no debería estar prohibido con pequeños propósitos.