使用 AVAssetDownloadURLSession 更正离线下载的进度

Gui*_*ume 7 offline progress download avfoundation ios

由于 AVAssetDownloadURLSession、AVAssetDownloadDelegate for iOS 11 使用 makeAssetDownloadTask(...) 和 aggregateAssetDownloadTask(...) 方法,我正在下载离线视频。

一切正常,但我只想让用户尽可能准确地了解每次下载的进度。

为此,我使用:

- urlSession(_ session: URLSession, assetDownloadTask: AVAssetDownloadTask, didLoad timeRange: CMTimeRange, totalTimeRangesLoaded loadedTimeRanges: [NSValue], timeRangeExpectedToLoad: CMTimeRange)

- urlSession(_ session: URLSession, aggregateAssetDownloadTask: AVAggregateAssetDownloadTask, didLoad timeRange: CMTimeRange, totalTimeRangesLoaded loadedTimeRanges: [NSValue], timeRangeExpectedToLoad: CMTimeRange, for mediaSelection: AVMediaSelection)
Run Code Online (Sandbox Code Playgroud)

使用这些方法,我可以分别计算视频和每个曲目(音频/字幕)的下载进度。所以我假设视频占下载量的 70%,对于曲目,它是 30% 除以曲目数量。我将每个项目的下载进度存储在一个临时字典中(乘以它们的比率),并添加每个下载进度以具有全局表示。

最后它工作正常,但并不像预期的那样顺利。例如,我花了 3 分钟来下载内容,但如果曲目的重量较轻,则进度会在 1 秒内从 70% 跳到 85%(如果我有 2 首曲目要下载),然后立即放慢速度。我想有一个全球性的进步。

我绝对对这个解决方案不满意,但我目前没有找到另一个解决方案。

你们中的一些人有什么想法/解决方案吗?

谢谢你们

mgy*_*yky 1

解决方案

首先,这只是我的情况,您应该根据您的需要更新方法。

在我的场景中,作为最复杂的数组示例,我有这样的内容:

[English(soun),Turkish(soun),English(sbtl),Turkish(sbtl)]
Run Code Online (Sandbox Code Playgroud)

我们将为音频(所有音频)提供 80%为所有字幕提供 20%

总的计算公式一定是这样的:

(100*(0,80/2))+(100*(0,80/2))+(100*(0,20/2))+(100(0,20/2))
Run Code Online (Sandbox Code Playgroud)

我们需要一个枚举来表示AVMediaType

// AVMediaType
enum MediaType: String {
    // Sound
    case soun
        
    // Subtitle
    case sbtl
      
    // Closed Caption
    // case clcp // Removed for simplifying the example.
}
Run Code Online (Sandbox Code Playgroud)

此外,我们需要一个字典来处理资产下载进度:

var totalDownloadProgressForAsset = [String: Double]()
Run Code Online (Sandbox Code Playgroud)

这是方法:

public func getTotalProgress() -> Double {
    var result = 0.0
    let soundMultiplier          = 0.80
    let subtitleMultiplier       = 0.20
    var soundCount = 0
    var subtitleCount  = 0
    
    for (key, _) in totalDownloadProgressForAsset {
        let mediaTypeKey = String(key.suffix(4))
        let type = MediaType(rawValue: mediaTypeKey)
        
        switch type {
        case .soun:
            soundCount += 1
        case .sbtl:
            subtitleCount += 1
        case .none:
            break
        }
    }
                    
    for (key, value) in totalDownloadProgressForAsset {
        let mediaTypeKey = String(key.suffix(4))
        let type = MediaType(rawValue: mediaTypeKey)
        
        switch type {
        case .soun:
            result += Double(value*(soundMultiplier/Double(soundCount)))
        case .sbtl:
            result += Double(value*(subtitleMultiplier/Double(subtitleCount)))
        case .none:
            break
        }
    }
    
    return result
}
Run Code Online (Sandbox Code Playgroud)

当然,我们可以换一种写法,这只是举例。

如有任何疑问,请随时询问。