How can I determine file size on disk of a video PHAsset in iOS8
Asked Answered
I

3

11

I can request a video PHAsset using the Photos framework in iOS8. I'd like to know how big the file is on disk. There doesn't seem to be a property of PHAsset to determine that. Does anyone have a solution? (Using Photos framework not required)

Incisor answered 24/10, 2014 at 14:27 Comment(0)
L
31

Edit

As for iOS 9.3, using requestImageDataForAsset on a video type PHAsset will result in an image, which is the first frame of the video, so it doesn't work anymore. Use the following method instead, for normal video, request option can be nil, but for slow motion video, PHVideoRequestOptionsVersionOriginal needs to be set.

PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
options.version = PHVideoRequestOptionsVersionOriginal;

[[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
    if ([asset isKindOfClass:[AVURLAsset class]]) {
        AVURLAsset* urlAsset = (AVURLAsset*)asset;

        NSNumber *size;

        [urlAsset.URL getResourceValue:&size forKey:NSURLFileSizeKey error:nil];
        NSLog(@"size is %f",[size floatValue]/(1024.0*1024.0)); //size is 43.703005

    }
}];

//original answer

For PHAsset, use this:

[[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
        float imageSize = imageData.length;
        //convert to Megabytes
        imageSize = imageSize/(1024*1024);
        NSLog(@"%f",imageSize);
 }];

For ALAsset:

ALAssetRepresentation *rep = [asset defaultRepresentation];
float imageSize = rep.size/(1024.0*1024.0);

I tested on one video asset, PHAsset shows the size as 43.703125, ALAsset shows the size as 43.703005.

Edit For PHAsset, another way to get file size. But as @Alfie Hanssen mentioned, it works on normal video, for slow motion video, the following method will return a AVComposition asset in the block, so I added the check for its type. For slow motion video, use the requestImageDataForAsset method.

[[PHImageManager defaultManager] requestAVAssetForVideo:asset options:nil resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
    if ([asset isKindOfClass:[AVURLAsset class]]) {
        AVURLAsset* urlAsset = (AVURLAsset*)asset;
        NSNumber *size;

        [urlAsset.URL getResourceValue:&size forKey:NSURLFileSizeKey error:nil];
        NSLog(@"size is %f",[size floatValue]/(1024.0*1024.0)); //size is 43.703005
        NSData *data = [NSData dataWithContentsOfURL:urlAsset.URL];
        NSLog(@"length %f",[data length]/(1024.0*1024.0)); // data size is 43.703005
    }
}];
Liven answered 24/10, 2014 at 16:16 Comment(12)
Thank you! It's strange that there is no requestVideoDataForAsset... and that requestImageDataForAsset returns the size of the videoIncisor
Yes,you can use requestAVAssetForVideo, which is specifically for video.Liven
This method seems to return an AVComposition (unable to be cast as AVURLAsset). Attempting to do so as shown above results in a crash. iOS 8.1.2.Disquietude
@AlfieHanssen, make sure the asset is a video, I just tested and no crash happened.Liven
Yeah, I just double checked this and they're definitely videos. But it looks like any slomo video is returned as an AVComposition (normal videos are indeed AVURLAssets). Inspecting the info dictionary argument to the completionBlock shows additional metadata: PHAdjustmentDataKey = "<PHAdjustmentData: 0x174244110> identifier=com.apple.video.slomo version=1.1 data=0x174243d50 (200)";. So it looks like it's a good idea to do a class check to confirm that a cast is safe.Disquietude
In iOS 9.3 and above the first method using PHAsset doesn't seems workMaclean
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { float imageSize = imageData.length; //convert to Megabytes imageSize = imageSize/(1024*1024); NSLog(@"%f",imageSize); }];Maclean
I mean this code @gabbler, now i think it returns the size of thumbnail. Can you confirm?Maclean
Yes i moved to next answer. But the problem is call back to the block is not synchronous like first one. Anyway thanks gabblerMaclean
The iOS 9.3 method is returning the following error "The file “IMG_0188.mov” couldn’t be opened because you don’t have permission to view it."Weikert
note: for an AVComposition (Slow-Motion Video) it is not possible to retrieve the file Size through requestImageData(for:) (iOS 10.3, Swift)Jocund
For slow motion video it is AVComposition object. Could not get size for thisDaydream
M
3

Swift version with file size formatting:

    let options = PHVideoRequestOptions()
    options.version = .original

    PHImageManager.default().requestAVAsset(forVideo: asset, options: options) { avAsset, _, _ in
        if let urlAsset = avAsset as? AVURLAsset {  // Could be AVComposition class
            if let resourceValues = try? urlAsset.url.resourceValues(forKeys: [.fileSizeKey]),
                let fileSize = resourceValues.fileSize {

                let formatter = ByteCountFormatter()
                formatter.countStyle = .file
                let string = formatter.string(fromByteCount: Int64(fileSize))

                print(string)
            }
        }
    }
Monometallism answered 7/7, 2020 at 8:36 Comment(0)
U
0

You heave pretty high chance, that video you want to know is's size is not type of AVURLAsset. But it's ok that under the hood there are more files that your video is composited of (for example raw samples, slow-mo time ranges, filters, etc...), because you want to know size of a concrete playable file. I'm not sure how estimated file size meets reality in this case, but this is how it should be done:

PHImageManager.defaultManager().requestExportSessionForVideo(asset, options: nil, exportPreset: AVAssetExportPresetHighestQuality, resultHandler: { (assetExportSession, info) -> Void in // Here you set values that specifies your video (original, after edit, slow-mo, ...) and that affects resulting size. 
    assetExportSession.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(asset.duration, 30)) // Time interval is default from zero to infinite so it needs to be set prior to file size computations. Time scale is I believe (it is "only" preferred value) not important in this case.
    let HERE_YOU_ARE = assetExportSession.estimatedOutputFileLength
})
Unifoliate answered 2/4, 2015 at 17:33 Comment(2)
Just a note, the docs say that assetExportSession.estimatedOutputFileLength will always return 0 for AVAssetExportPresetPassThrough. Beware...Disquietude
note, as it is the estimatedOutputFileLength you can not consider that it is the actual filesize. In my case there was a difference of 30 MB.Jocund

© 2022 - 2024 — McMap. All rights reserved.