NSURL from PHAsset



我正在将我们的应用程序转换为使用iOS8的照片框架,ALAsset框架显然是iOS8下的二等公民。

我遇到的问题是,我们的体系结构确实需要一个NSURL来表示媒体在"磁盘"上的位置。我们使用它将媒体上传到服务器进行进一步处理。

这对ALAsset:来说很容易

    ALAssetRepresentation *rep = [asset defaultRepresentation];
    self.originalVideo = rep.url;

但我只是在PHAsset中看不到这种能力。我想我可以打电话给

    imageManager.requestImageDataForAsset

然后把它写到文件系统中的一个临时位置,但这看起来非常沉重和浪费,更不用说可能很慢了。

有没有办法做到这一点,或者我要重构更多的应用程序,只对iOS7使用NSURL,对iOS8使用其他方法?

如果使用[imageManager requestAVAssetForVideo…],它将返回一个AVAsset。该AVAsset实际上是一个AVURLAsset,所以如果对其进行强制转换,则可以访问它的-url属性。

我不确定你是否能从中创建一个新的资产,但它确实给了你位置。

SWIFT 2.0版本此函数从PHAsset(图像和视频)返回NSURL

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

如果你有一个PHAsset,你可以获得所述资产的url,如下所示:

[asset requestContentEditingInputWithOptions:editOptions
                           completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
    NSURL *imageURL = contentEditingInput.fullSizeImageURL;
}];

使用PHObject的新localIdentifier属性。(PHAsset继承自此)。

它提供了与ALAsset URL类似的功能,即您可以通过调用方法来加载资产

+[PHAsset fetchAssetsWithLocalIdentifiers:identifiers options:options]

以上所有解决方案都不适用于慢动作视频。我发现一个处理所有视频资产类型的解决方案是:

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

请在此处查看此答案。

还有这个。

根据我的经验,您需要首先将资产导出到磁盘,以便获得完全可访问/可靠的URL。

链接到上面的答案描述了如何做到这一点。

只想从@jlw 的评论中发布隐藏的宝石

@rishu1992对于slo-mo视频,请获取AVComposition的AVCompositionTrack(属于mediaType AVMediaTypeVideo),获取其第一个段(类型为AVCompositionTrackSegment),然后访问其sourceURL属性。–jlw 2015年8月25日11:52

PHAsset的url拼写中,我曾经在Swift 2上准备了一个util函数(尽管仅用于播放PHAsset的视频)。在这个答案中分享它,可能会对某人有所帮助。

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

请检查此答案

这里有一个方便的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

我对视频文件也有类似的问题,对我有效的是:

NSString* assetID = [asset.localIdentifier substringToIndex:(asset.localIdentifier.length - 7)];
NSURL* videoURL = [NSURL URLWithString:[NSString stringWithFormat:@"assets-library://asset/asset.mov?id=%@&ext=mov", assetID]];

其中资产为PHAsset。

最新更新