使用新的Photo框架,我可以使用NSData
访问requestImageDataForAsset
个PHAssets。我还可以使用返回的PHImageFileURLKey
的{{1}}访问文件网址。
info NSDictionary
这适用于图像和普通视频。
但是,当资产是PHAssetMediaSubtypeVideoHighFrameRate(慢动作视频)时,返回的数据对应于包含视频第一帧的JPG文件(NSData,dataUTI和信息字典都指向同一个jpg文件) 。例如,这是为慢动作视频返回的URL和dataUTI:
PHImageFileURLKey = “文件:///var/mobile/Media/PhotoData/Metadata/DCIM/100APPLE/IMG_0642.JPG”; PHImageFileUTIKey =“public.jpeg”;
为什么会这样? 如何访问慢动作视频的NSData / NSURL而不是JPG预览?
答案 0 :(得分:11)
疯狂地测试每一个选项之后我发现了问题。
为慢动作视频返回JPG图像的责任是PHImageRequestOptionsVersionCurrent
属性的默认PHImageRequestOptions.version
值。
只需将版本分配给PHImageRequestOptionsVersionUnadjusted或PHImageRequestOptionsVersionOriginal将返回原始慢动作视频。
PHImageRequestOptions * imageRequestOptions = [[PHImageRequestOptions alloc] init];
imageRequestOptions.version = PHImageRequestOptionsVersionUnadjusted;
// or
imageRequestOptions.version = PHImageRequestOptionsVersionOriginal;
我认为这是一种意想不到的行为,因为我不期望慢动作视频的“当前”版本是静止图像(可能是应用了慢动作效果的视频,而不是照片)。
希望这对某人有用。
答案 1 :(得分:9)
重要的是要注意慢动作视频的类型为AVComposition而不是AVURLAsset。 AVComposition对象将来自多个源的媒体数据组合在一起。
为实现这一目标,我基本上经历了一个三步过程:
PHVideoRequestOptions *options = [PHVideoRequestOptions new];
options.networkAccessAllowed = YES;
[[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
if(([asset isKindOfClass:[AVComposition class]] && ((AVComposition *)asset).tracks.count == 2)){
//slow motion videos. See Here: https://overflow.buffer.com/2016/02/29/slow-motion-video-ios/
//Output URL of the slow motion file.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = paths.firstObject;
NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"mergeSlowMoVideo-%d.mov",arc4random() % 1000]];
NSURL *url = [NSURL fileURLWithPath:myPathDocs];
//Begin slow mo video export
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL = url;
exporter.outputFileType = AVFileTypeQuickTimeMovie;
exporter.shouldOptimizeForNetworkUse = YES;
[exporter exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
if (exporter.status == AVAssetExportSessionStatusCompleted) {
NSURL *URL = exporter.outputURL;
self.filePath=URL.absoluteString;
// NSData *videoData = [NSData dataWithContentsOfURL:URL];
//
//// Upload
//[self uploadSelectedVideo:video data:videoData];
}
});
}];
}
}];
请在iOS中查看这个精彩的blog慢动作视频。
答案 2 :(得分:2)
以下是Swift 3/4的代码段
PHImageManager.default().requestAVAsset(forVideo: asset,
options: nil,
resultHandler: { (asset, _, _) in
// AVAsset has two sub classes: AVComposition and AVAssetURL
// AVComposition for slow mo vid
// AVAssetURL for normal videos
// For slow motion video checking for AVCompostion
// Creating an exporter to write the video into local file path and using the same to play/upload
if asset!.isKind(of: AVComposition.self){
let avCompositionAsset = asset as! AVComposition
if avCompositionAsset.tracks.count > 1{
let exporter = AVAssetExportSession(asset: avCompositionAsset, presetName: AVAssetExportPresetHighestQuality)
exporter!.outputURL = self.fetchOutputURL()
exporter!.outputFileType = AVFileTypeMPEG4
exporter!.shouldOptimizeForNetworkUse = true
exporter!.exportAsynchronously {
DispatchQueue.main.sync {
// Use this url for uploading or playing a video
let url = exporter!.outputURL
}
}
}
}else{
// Normal video, are stored as AVAssetURL
let url = (asset as! AVURLAsset).url
}
})
// Fetch local path
func fetchOutputURL() -> URL{
let documentDirectory = getDocumentsDirectory() as NSString
let path = documentDirectory.appendingPathComponent("test.mp4")
return URL(fileURLWithPath:path)
}
答案 3 :(得分:1)
// video slo-mo
PHVideoRequestOptions *options=[[PHVideoRequestOptions alloc]init];
options.version=PHVideoRequestOptionsVersionOriginal;
从PHImageManager请求AVAsset
[[PHImageManager defaultManager] requestAVAssetForVideo:videoAsset options:options resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info)
{
if ([asset isKindOfClass:[AVURLAsset class]])
{
// use URL to get file content
NSURL *URL = [(AVURLAsset *)asset URL];
NSData *videoData=[NSData dataWithContentsOfURL:URL];
NSNumber *fileSizeValue = nil;
[URL getResourceValue:&fileSizeValue forKey:NSURLFileSizeKey error:nil];
}
}