【问题标题】:Correct progress of an offline download with AVAssetDownloadURLSession使用 AVAssetDownloadURLSession 进行离线下载的正确进度
【发布时间】:2019-03-14 10:30:04
【问题描述】:

感谢 AVAssetDownloadURLSession、iOS 11 的 AVAssetDownloadDelegate 使用 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)

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

最终它运行良好,但并不像预期的那么顺利。例如,我花了 3 分钟下载内容,但如果曲目的权重很轻,则进度会在 1 秒内从 70% 跃升至 85%(如果我有 2 首曲目要下载),然后就会变慢。 我想要一个全球性的进步。

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

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

谢谢大家

【问题讨论】:

  • 我很想看看你的代码,我遇到了同样的问题,你的解决方案比我现在的更好。
  • 遗憾的是我还没有找到解决方案,因为我没有足够的时间找到更好的方法。
  • 完全相同的问题 :( 很遗憾他们没有为它添加全局进度。@Guillaume 你能分享你的计算作为参考吗?
  • @mgyky 其实我确实离开了公司,也选择使用其他公司的SDK,不是开源的,所以很抱歉,我不能告诉你。但是,在那之前我所做的是一个近似值。我有 1 个视频文件和 4 个曲目。所以用视频 = 80% 和 4 个轨道 = 20% 进行了计算。它可以正常工作,但由于视频的侧面以及轨道的大小和类型,它可能会很快结束。
  • @Guillaume 感谢您的快速回答 :) 实际上,我观看了 WWDC 2020 探索如何下载和播放 HLS 离线会话,主持人也说了同样的话。无论如何,在开始这部分代码之前,我想看一个例子:) 我的曲目是动态的,有时是 2 个声音,2 个字幕,有时只有 1 个声音,仅此而已。我会弄清楚。谢谢你,祝你在新职位上一切顺利。

标签: ios download avfoundation offline progress


【解决方案1】:

解决方案

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

在我的场景中,作为一个最复杂的数组示例,我有这样的事情:

[English(soun),Turkish(soun),English(sbtl),Turkish(sbtl)]

我们将为所有音频提供 80% 的音频,为所有字幕提供 20%

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

(100*(0,80/2))+(100*(0,80/2))+(100*(0,20/2))+(100(0,20/2))

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

// AVMediaType
enum MediaType: String {
    // Sound
    case soun
        
    // Subtitle
    case sbtl
      
    // Closed Caption
    // case clcp // Removed for simplifying the example.
}

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

var totalDownloadProgressForAsset = [String: Double]()

方法如下:

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
}

当然,我们也可以这样写,这只是举例。

请随意询问。

【讨论】:

  • 嗨 mgykj,您如何确定 allMediaSelection 中的每个 AVMediaSelection 是什么类型?我也有多个音频和字幕,我正在下载,但我无法确定,为每个输入,所以我无法正确地乘以值。谢谢。
  • 嗨 Arijan,您可以使用 let type = MediaType(rawValue: mediaTypeKey) 确定,然后您可以使用 switch 类型分隔每个。获取媒体类型的字符串表示形式(视频、声音、sbtl 等)检查我的答案中的开关块。
  • 您好,我目前正在开发视频下载功能,并尝试更新多个 MediaSelection 下载的进度。我本来以为第一个下载的轨道是MediaVideo类型的轨道,但我似乎只下载音频和字幕,你也一样吗?正如我所见,您在代码示例中只考虑了音频和字幕。
  • 嗨 mgyky,我正在使用 AVAggregateAssetDownloadTask,来自 urlSession:aggregateAssetDownloadTask:didLoad:totalTimeRangesLoaded:timeRangeExpectedToLoad:因为我得到“mediaSelection”,但我无法区分这是什么类型的媒体 (mediaTypeKey)代表被要求,你是如何解决这个问题的?
  • 如果没有,则需要全局的activeDownloadsMap 来跟踪任务,否则无法确定。 /// AVAggregateAssetDownloadTask 内部映射到其对应的 Asset。 fileprivate var activeDownloadsMap = [AVAggregateAssetDownloadTask: Asset]()
猜你喜欢
  • 2020-03-13
  • 2018-03-17
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 2016-08-14
  • 2022-11-02
  • 2013-11-12
相关资源
最近更新 更多