You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS 15/16使用makeAssetDownloadTask下载HLS仅完成部分的问题求助

问题:AVAssetDownloadURLSession下载HLS点播流仅完成部分内容,无法完整下载

在iOS 15和iOS 16系统中,使用AVAssetDownloadURLSession的makeAssetDownloadTask方法同时播放并下载HLS点播流,初始状态正常(下载快、可立即播放),但几秒后下载停止,通过loadedTimeRanges发现仅下载了约15分钟的音频内容。相关示例代码如下:

@objc func createDownloadSession() {
    // Create new background session configuration.
    let configuration = URLSessionConfiguration.background(withIdentifier: "TestAppSession")
    configuration.timeoutIntervalForResource = 60 * 60 * 2
    
    // Create a new AVAssetDownloadURLSession with background configuration, delegate, and queue
    downloadSession = AVAssetDownloadURLSession(configuration: configuration,
                                                assetDownloadDelegate: self,
                                                delegateQueue: OperationQueue.main)
}

@objc func downloadAndCreatePlayerItem(_ url: URL) -> AVPlayerItem? {
    // Create new AVAssetDownloadTask for the desired asset
    let asset = AVURLAsset(url: url)

    // Create the task to download the track.
    let downloadTask = downloadSession.makeAssetDownloadTask(asset: asset,
                                                         assetTitle: "Test Title",
                                                         assetArtworkData: nil,
                                                         options: nil)

    // Start task
    downloadTask!.resume()

    // Return the URL asset
    return AVPlayerItem(asset: downloadTask!.urlAsset)
}

需解决的问题:如何实现完整HLS流的下载?是否遇到系统限流?前台应用使用后台会话是否有遗漏设置?


解决方案

1. 配置下载选项,强制完整下载

系统默认会优先保障播放,仅预加载播放所需的超前内容(通常10-20分钟)。要触发完整下载,需在创建downloadTask时传入指定选项,告知系统下载全部媒体资产:

let options: [String: Any] = [
    // 强制下载所有媒体资产,而非仅预加载播放内容
    AVAssetDownloadTaskOptionDownloadAllMediaAssetsKey: true,
    // 设置足够高的最低码率,确保下载最高质量的完整流(需高于流中所有码率值)
    AVAssetDownloadTaskOptionMinimumRequiredMediaBitrateKey: NSNumber(value: 1000000)
]

let downloadTask = downloadSession.makeAssetDownloadTask(asset: asset,
                                                     assetTitle: "Test Title",
                                                     assetArtworkData: nil,
                                                     options: options)

2. 正确实现URLSessionAVAssetDownloadDelegate回调

必须实现相关代理方法,处理下载进度、完成状态及错误重试,确保下载过程的稳定性:

// 监控下载进度
func urlSession(_ session: URLSession, assetDownloadTask: AVAssetDownloadTask, didLoad timeRange: CMTimeRange, totalTimeRangesLoaded loadedTimeRanges: [NSValue], timeRangeExpectedToLoad: CMTimeRange) {
    // 可在此处跟踪下载进度,排查是否出现停滞
}

// 下载完成处理
func urlSession(_ session: URLSession, assetDownloadTask: AVAssetDownloadTask, didFinishDownloadingTo location: URL) {
    // 处理本地已下载的媒体文件,比如移动到指定目录
}

// 下载错误处理
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
    if let error = error {
        let nsError = error as NSError
        // 网络中断等可恢复错误,主动重试任务
        if nsError.code == NSURLErrorNetworkConnectionLost {
            task.resume()
        }
    }
}

3. 优化后台会话配置

即使应用处于前台,后台会话的部分配置也会影响下载持续性,需调整:

let configuration = URLSessionConfiguration.background(withIdentifier: "TestAppSession")
// 延长请求超时时间
configuration.timeoutIntervalForRequest = 60
// 延长资源超时时间到24小时,避免长时下载被中断
configuration.timeoutIntervalForResource = 60 * 60 * 24
// 启用网络恢复自动重试
configuration.waitsForConnectivity = true

4. 解除播放进度对下载的限制

默认情况下,播放进度会影响下载调度:若播放速度慢于下载速度,系统会暂停下载以节省资源。如需强制完整下载,可采取两种方式:

  • 暂时暂停播放器(player.rate = 0),待下载到一定进度后再恢复播放;
  • 使用独立的AVAssetDownloadTask负责下载,同时用另一个AVPlayer直接播放原始HLS URL,让下载任务不受播放进度干扰。

关于系统限流的说明

应用处于前台时,系统对后台下载的资源限制较低,出现15分钟左右的下载停止,并非系统限流导致,而是默认的预加载调度策略——系统仅下载保障当前及近期播放所需的内容,当播放进度未跟上下载进度时,会自动暂停后续下载。

内容的提问来源于stack exchange,提问作者Brian Schrameck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:57:16