16

I would like to get an AVAsset video file size, not the video's resolution, but the file weight in KB.

A solution would be to calculate an estimated filesize from the duration and the estimatedDataRate, but this seems to be a lot just to get a filesize.

I have checked all data embedded in AVAssetTrack it doesn't seems to be in there. Even an estimated filesize would be nice.

CodeBender
  • 35,668
  • 12
  • 125
  • 132
TheSquad
  • 7,385
  • 8
  • 40
  • 79

6 Answers6

17

Here is a simple Swift 4.x / 3.x extension to get you the size of any AVURLAsset:

import AVFoundation

extension AVURLAsset {
    var fileSize: Int? {
        let keys: Set<URLResourceKey> = [.totalFileSizeKey, .fileSizeKey]
        let resourceValues = try? url.resourceValues(forKeys: keys)

        return resourceValues?.fileSize ?? resourceValues?.totalFileSize
    }
}

This returns an optional Int, since both resourceValues.fileSize and resouceValues.totalFileSize return optional Ints.

While it is certainly possible to modify it to return a 0 instead of nil, I choose not to since that would not be accurate. You do not know for sure that it is size 0, you just can't get the value.

To call it:

let asset = AVURLAsset(url: urlToYourAsset)
print(asset.fileSize ?? 0)

If the size returns nil, than it will print 0, or a different value if you so choose.

CodeBender
  • 35,668
  • 12
  • 125
  • 132
  • 2
    you can remove three line of your code `do, catch, return nil` by adding `?` operator after `try` – zombie Sep 24 '17 at 21:02
  • @zombie Thanks, I went through and pruned it some more as well to make it even smaller. – CodeBender Sep 25 '17 at 02:38
  • How I can achieve this for AVAsset and not AVURLAsset? – Roi Mulia Nov 29 '17 at 10:17
  • @RoiMulia You can't, Apple's description for AVAsset ( https://developer.apple.com/documentation/avfoundation/avasset ) explains this in the second paragraph, about how you need to subclass with AVURLAsset to have access to the URL, as an AVAsset does not have that information. – CodeBender Nov 29 '17 at 19:02
  • Thanks! I'll guess i'll search for a work around than :) – Roi Mulia Nov 29 '17 at 22:10
  • 1
    Note that this approach is valid only for URLs that point into the local filesystem. HTTP URLs will return nil for both fields. – GSnyder Jun 12 '18 at 06:55
11

Using your method I get the correct answer. I post this for anyone looking, I look forward to a simpler alternative for AVAssets in the IPOD Library

AVURLAsset* asset;
asset = [[AVURLAsset alloc]initWithURL:realAssetUrl options:nil];
NSArray *tracks = [asset tracks];
float estimatedSize = 0.0 ;
for (AVAssetTrack * track in tracks) {
        float rate = ([track estimatedDataRate] / 8); // convert bits per second to bytes per second
        float seconds = CMTimeGetSeconds([track timeRange].duration);
        estimatedSize += seconds * rate;
}
float sizeInMB = estimatedSize / 1024 / 1024;
float sizeinGB = sizeInMB / 1024;

This gives me 2.538 GB which is what I see in ITunes.

Ryan Heitner
  • 13,119
  • 6
  • 77
  • 119
3

I solved this by requesting the size from the file url. The sample below will provide the number of bytes. Just divide the number by 1024 to get the number of KB.

If you need to get the file size of a single file, you can do it by constructing a file URL to it and querying the URL's attributes directly.

NSURL *fileURL = [NSURL fileURLWithPath:filePath];
NSNumber *fileSizeValue = nil;
[fileURL getResourceValue:&fileSizeValue
                   forKey:NSURLFileSizeKey
                    error:nil];
if (fileSizeValue) {
    NSLog(@"value for %@ is %@", fileURL, fileSizeValue);
}
devnull69
  • 16,402
  • 8
  • 50
  • 61
agressen
  • 459
  • 1
  • 5
  • 17
1

Here is @agressen 's answer in Swift 2

extension AVAsset {
  var g_fileSize: Double {
    guard let avURLAsset = self as? AVURLAsset else { return 0 }

    var result: AnyObject?
    try? avURLAsset.URL.getResourceValue(&result, forKey: NSURLFileSizeKey)

    if let result = result as? NSNumber {
      return result.doubleValue
    } else {
      return 0
    }
  }
}
onmyway133
  • 45,645
  • 31
  • 257
  • 263
  • Shouldn't one return result.unsignedLongLongValue instead? And didn't you forget to take care of that optional try? – SirEnder Sep 26 '16 at 16:30
0

Another way I've found which gives the same result is to use the FileManager.

NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *attrs = [fileManager attributesOfItemAtPath:filePath error: NULL];
_fileSize = [attrs fileSize];
  • 1
    This actually gives a size of 204 bytes consistently with any HLS asset. No need to say this can't be right. – Julius Aug 01 '17 at 22:37
0

May be this answer will help some one which is support to Swift 3:

if(videoAsset!.isKind(of: AVURLAsset.self)){
    if let avassetURL = videoAsset as? AVURLAsset {
        var urlAsset : URL = avassetURL.url

        var keys = Set<URLResourceKey>()
        keys.insert(URLResourceKey.totalFileSizeKey)
        keys.insert(URLResourceKey.fileSizeKey)
        do{
            let URLResourceValues = try urlAsset.resourceValues(forKeys: keys)
            if let fileSize = URLResourceValues.fileSize{}
            if let totalFileSize = URLResourceValues.totalFileSize{}
        }catch _{}
    }
}
Sumit singh
  • 2,398
  • 1
  • 15
  • 30
Nicoara Talpes
  • 710
  • 1
  • 13
  • 28