如何使用PhotoKit访问NSData / NSURL的慢动作视频

时间:2014-10-01 23:43:12

标签: ios photokit phasset

使用新的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预览?

4 个答案:

答案 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对象将来自多个源的媒体数据组合在一起。

导出慢动作视频

为实现这一目标,我基本上经历了一个三步过程:

  1. 为视频
  2. 创建输出网址
  3. 配置导出会话
  4. 导出视频并抓取网址!
  5. 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];
      }
}