Размер файла HLS в автономном режиме iOS

В iOS 10 Apple добавила автономный HLS. В документации они упоминают:

Важно: загруженные ресурсы HLS хранятся на диске в формате закрытого пакета. Этот формат пакета может меняться со временем, и разработчикам не следует пытаться напрямую обращаться к файлам или хранить их в пакете, а вместо этого следует использовать AVFoundation и другие API-интерфейсы iOS для взаимодействия со загруженными активами.

Оказывается, доступ к информации об этих файлах ограничен. Я пытаюсь найти размер сохраненного файла. Вот что я делаю. После завершения загрузки я сохраняю относительный путь

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

    }

позже я реконструирую путь к файлу следующим образом

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

Это работает:

try FileManager.default.removeItem(at: assetURL)

Это не так и возвращает ошибку, что файл не существует:

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

Я могу загрузить видеоактив следующим образом и воспроизвести его в автономном режиме с помощью:

let avAsset = AVURLAsset(url: assetURL)

Но это возвращает мне пустой массив:

let tracks = avAsset.tracks(withMediaType: AVMediaTypeVideo)

Еще раз я просто пытаюсь получить размер файла автономного актива HLS. Похоже, что другие ответы на SO для получения размера файла с помощью FileManager не работают для них, равно как и ответы для получения размера загруженного AVAsset. Заранее спасибо.


person NickDK    schedule 03.03.2017    source источник


Ответы (3)


Единственный способ — суммировать все размеры файлов внутри папки, в которой хранится загруженный вами контент.

- (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;
}
person iUrii    schedule 21.06.2018

Решение Swift 5.3

Вот как рассчитать размер автономного файла HLS (.movpkg):

/// 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
}

Применение

if let url = URL(string: localFileLocation),
    let size = self.getHLSFileSize(at: url.path) {
    result = String(size)
}
person mgyky    schedule 09.11.2020
comment
Аккуратно и чисто ???? - person Pankaj Gaikar; 01.06.2021

Попробуйте это вместо этого:

let att = try FileManager.default.attributesOfItem(atPath: assetURL.path)
person Andrew    schedule 03.03.2017
comment
Эй, теперь я действительно получаю атрибуты, однако размер файла кажется совершенно неправильным. Я скачал два файла, и они оба возвращают 204 для let fileSize = attr[FileAttributeKey.size] as! UInt64 Во-первых, ни один из них не должен быть таким маленьким, и оба они очень разных размеров. - person NickDK; 06.03.2017
comment
Та же проблема здесь. - person Julius; 02.08.2017
comment
Раньше у меня была та же проблема, поэтому я (в общем) использую функцию из этого списка, чтобы получить правильные оценки размера файла: noreferrer">gist.github.com/blender/a75f589e6bd86aa2121618155cbdf827 При использовании allocatedSizeOfDirectory(at:) с URL вашего ресурса это должно работать. Я получил 1435750400 байт, что соответствует оценке памяти телефона для этого актива (1,44 ГБ). - person fruitcoder; 24.02.2018