Je suis en train de convertir notre application pour utiliser le cadre de photos d'iOS8, le cadre d'ALAsset est clairement un citoyen de seconde classe sous iOS8.
J'ai un problème, c'est que notre architecture veut vraiment un NSURL qui représente l'emplacement du média sur le "disque". Nous l'utilisons pour télécharger le support sur nos serveurs pour un traitement ultérieur.
C'était facile avec ALAsset:
ALAssetRepresentation *rep = [asset defaultRepresentation];
self.originalVideo = rep.url;
Mais je ne vois tout simplement pas cette capacité dans PHAsset. Je suppose que je peux appeler:
imageManager.requestImageDataForAsset
puis écrivez-le sur un emplacement temporaire dans le système de fichiers, mais cela semble terriblement lourd et inutile, sans parler de la lenteur potentielle.
Existe-t-il un moyen d'obtenir ceci ou vais-je avoir plus de refactor de mon application pour utiliser uniquement NSURLs pour iOS7 et une autre méthode pour iOS8?
Si vous utilisez [imageManager
requestAVAssetForVideo
...], il retournera une AVAsset
. AVAsset est en fait une AVURLAsset
, donc si vous le lancez, vous pouvez accéder à la propriété -url
.
Je ne sais pas si vous pouvez créer un nouvel actif à partir de cela, mais cela vous donne l'emplacement.
Version Swift 2.0 Cette fonction renvoie NSURL à partir de PHAsset (image et vidéo)
func getAssetUrl(mPhasset : PHAsset, completionHandler : ((responseURL : NSURL?) -> Void)){
if mPhasset.mediaType == .Image {
let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
return true
}
mPhasset.requestContentEditingInputWithOptions(options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [NSObject : AnyObject]) -> Void in
completionHandler(responseURL : contentEditingInput!.fullSizeImageURL)
})
} else if mPhasset.mediaType == .Video {
let options: PHVideoRequestOptions = PHVideoRequestOptions()
options.version = .Original
PHImageManager.defaultManager().requestAVAssetForVideo(mPhasset, options: options, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [NSObject : AnyObject]?) -> Void in
if let urlAsset = asset as? AVURLAsset {
let localVideoUrl : NSURL = urlAsset.URL
completionHandler(responseURL : localVideoUrl)
} else {
completionHandler(responseURL : nil)
}
})
}
}
Si vous avez un PHAsset, vous pouvez obtenir l'URL de cet actif de la manière suivante:
[asset requestContentEditingInputWithOptions:editOptions
completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
NSURL *imageURL = contentEditingInput.fullSizeImageURL;
}];
Utilisez la nouvelle propriété localIdentifier
de PHObject. (PHAsset en hérite).
Il fournit une fonctionnalité similaire à une URL ALAsset, à savoir que vous pouvez charger des actifs en appelant la méthode.
+[PHAsset fetchAssetsWithLocalIdentifiers:identifiers options:options]
Toutes les solutions ci-dessus ne fonctionneront pas pour les vidéos au ralenti. Une solution que j'ai trouvée gère tous les types d'actifs vidéo est la suivante:
func createFileURLFromVideoPHAsset(asset: PHAsset, destinationURL: NSURL) {
PHCachingImageManager().requestAVAssetForVideo(self, options: nil) { avAsset, _, _ in
let exportSession = AVAssetExportSession(asset: avAsset!, presetName: AVAssetExportPresetHighestQuality)!
exportSession.outputFileType = AVFileTypeMPEG4
exportSession.outputURL = destinationURL
exportSession.exportAsynchronouslyWithCompletionHandler {
guard exportSession.error == nil else {
log.error("Error exporting video asset: \(exportSession.error)")
return
}
// It worked! You can find your file at: destinationURL
}
}
}
Je veux juste poster le joyau caché d'un commentaire de @jlw
@ rishu1992 Pour les vidéos au ralenti, récupérez le .Composition de l'AV. AVCompositionTrack (de mediaType AVMediaTypeVideo), récupérez son premier segment (de type AVCompositionTrackSegment), puis accédez à son fichier propriété sourceURL. - Jlw 25 août 15 à 11:52
En spécifiant l'url de PHAsset
, j'avais déjà préparé une fonction util sur Swift 2 (bien que pour la lecture de vidéos de PHAsset
). Le partager dans cette réponse pourrait aider quelqu'un.
static func playVideo (view:UIViewController, asset:PHAsset)
Veuillez vérifier ceci Réponse
Voici une catégorie pratique de PHAsset:
@implementation PHAsset (Utils)
- (NSURL *)fileURL {
__block NSURL *url = nil;
switch (self.mediaType) {
case PHAssetMediaTypeImage: {
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.synchronous = YES;
[PHImageManager.defaultManager requestImageDataForAsset:self
options:options
resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
url = info[@"PHImageFileURLKey"];
}];
break;
}
case PHAssetMediaTypeVideo: {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[PHImageManager.defaultManager requestAVAssetForVideo:self
options:nil
resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
if ([asset isKindOfClass:AVURLAsset.class]) {
url = [(AVURLAsset *)asset URL];
}
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
break;
}
default:
break;
}
return url;
}
@end
J'ai eu un problème similaire avec les fichiers vidéo, ce qui a fonctionné pour moi était:
NSString* assetID = [asset.localIdentifier substringToIndex:(asset.localIdentifier.length - 7)];
NSURL* videoURL = [NSURL URLWithString:[NSString stringWithFormat:@"assets-library://asset/asset.mov?id=%@&ext=mov", assetID]];
Où atout est PHAsset.