Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS offline HLS file size

In iOS 10, Apple added offline HLS. In the documentation, they mention:

Important: Downloaded HLS assets are stored on disk in a private bundle format. This bundle format may change over time, and developers should not attempt to access or store files within the bundle directly, but should instead use AVFoundation and other iOS APIs to interact with downloaded assets.

It appears the access to information about these files is limited. I'm trying to find the size of the stored file. Here is what I do. After download finishes, I save the relative path

func urlSession(_ session: URLSession, assetDownloadTask: AVAssetDownloadTask, didFinishDownloadingTo location: URL) {
        //Save path
        video?.downloadPath = location.relativePath

    }

later I reconstruct the file path as follows

if let assetPath = workout.downloadPath {
                let baseURL = URL(fileURLWithPath: NSHomeDirectory())
                let assetURL = baseURL.appendingPathComponent(assetPath)

This works:

try FileManager.default.removeItem(at: assetURL)

This does not and returns an error that the file doesn't exist:

let att = try FileManager.default.attributesOfItem(atPath: assetURL.absoluteString)

I can load in the video asset as follows and play it offline with:

let avAsset = AVURLAsset(url: assetURL)

But this returns me an empty array:

let tracks = avAsset.tracks(withMediaType: AVMediaTypeVideo)

Once again I'm just trying to get the file size of an offline HLS asset. It appears the other answers on SO for getting a file size using FileManager don't work for these nor do the answers for getting the size of a loaded AVAsset. Thanks in advance.

like image 451
NickDK Avatar asked Oct 29 '22 11:10

NickDK


2 Answers

Swift 5.3 Solution

Here is how to calculate offline HLS (.movpkg) File Size:

/// Calculates HLS File Size.
/// - Parameter directoryPath: file directory path.
/// - Returns: Human Redable File Size.
func getHLSFileSize(at directoryPath: String) -> String? {
    var result: String? = nil
    let properties: [URLResourceKey] = [.isRegularFileKey,
                                        .totalFileAllocatedSizeKey,
                                        /*.fileAllocatedSizeKey*/]

    guard let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: directoryPath),
                                         includingPropertiesForKeys: properties,
                                         options: .skipsHiddenFiles,
                                         errorHandler: nil) else {

                                            return nil
    }

    let urls: [URL] = enumerator
        .compactMap { $0 as? URL }
        .filter { $0.absoluteString.contains(".frag") }

    let regularFileResources: [URLResourceValues] = urls
        .compactMap { try? $0.resourceValues(forKeys: Set(properties)) }
        .filter { $0.isRegularFile == true }

    let sizes: [Int64] = regularFileResources
        .compactMap { $0.totalFileAllocatedSize! /* ?? $0.fileAllocatedSize */ }
        .compactMap { Int64($0) }

    
    let size = sizes.reduce(0, +)
    result = ByteCountFormatter.string(fromByteCount: Int64(size), countStyle: .file)
    
    return result
}

Usage

if let url = URL(string: localFileLocation),
    let size = self.getHLSFileSize(at: url.path) {
    result = String(size)
}
like image 162
mgyky Avatar answered Nov 14 '22 23:11

mgyky


The only way is to sum all files sizes inside a folder where your downloaded content is stored.

- (NSUInteger)hlsFileSize:(NSURL *)fileURL {

    NSUInteger size = 0;

    let enumerator = [NSFileManager.defaultManager enumeratorAtURL:fileURL includingPropertiesForKeys:nil options:0 errorHandler:nil];
    for (NSURL *url in enumerator) {
        NSError *error = nil;

        // Get values
        let resourceValues = [url resourceValuesForKeys:@[NSURLIsRegularFileKey, NSURLFileAllocatedSizeKey, NSURLNameKey] error:&error];

        // Skip unregular files
        let isRegularFile = [resourceValues[NSURLIsRegularFileKey] boolValue];
        if (!isRegularFile) {
            continue;
        }

        let fileAllocatedSize = [resourceValues[NSURLFileAllocatedSizeKey] unsignedLongLongValue];

        size += fileAllocatedSize;
    }

    return size;
}
like image 22
iUrii Avatar answered Nov 15 '22 00:11

iUrii