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

如何在Swift中使用AVAssetResourceLoaderDelegate为AVPlayer的HLS分片URL追加自定义参数?

如何在Swift中使用AVAssetResourceLoaderDelegate为AVPlayer的HLS分片URL追加自定义参数?

看起来你已经找对了核心方向,但AVAssetResourceLoaderDelegate的用法里有几个容易踩的小坑,导致你的代码没达到预期效果。我来帮你梳理下问题点,再给出修正后的完整方案~

原代码的核心问题

  1. 直接调用finishLoading()太草率:AVPlayer的资源加载器在收到重定向指令后,需要时间去处理新的URL请求,你直接结束加载会导致它跳过这个过程,拿不到正确的分片数据。
  2. 未处理相对URL:你的HLS播放列表里的.ts路径都是相对地址,原代码里的originalURL可能不是完整的绝对URL,直接追加参数会失效。
  3. 重定向逻辑不完整:设置redirect后,需要让系统自己去处理新请求,而不是强制结束加载流程。

修正后的完整实现

下面是调整后的代码,我会把关键修改点标出来:

1. 主ViewController部分(保留核心逻辑,新增调试日志)

import AVFoundation
import UIKit

class ViewController: UIViewController {

    var player: AVPlayer?
    var playerLayer: AVPlayerLayer?

    override func viewDidLoad() {
        super.viewDidLoad()
        setupPlayer()
    }

    func setupPlayer() {
        guard let playlistURL = URL(string: "https://your_hls_stream_url.m3u8") else {
            print("❌ 无效的播放列表URL")
            return
        }
        
        let asset = AVURLAsset(url: playlistURL)
        let loaderDelegate = CustomResourceLoaderDelegate(basePlaylistURL: playlistURL)
        // 单独用一个队列处理资源加载,避免阻塞主线程
        asset.resourceLoader.setDelegate(loaderDelegate, queue: DispatchQueue(label: "com.yourapp.resourceLoader.queue"))
        
        let playerItem = AVPlayerItem(asset: asset)
        player = AVPlayer(playerItem: playerItem)
        
        // 配置播放器层
        playerLayer = AVPlayerLayer(player: player)
        playerLayer?.frame = view.bounds
        playerLayer?.videoGravity = .resizeAspect
        if let layer = playerLayer {
            view.layer.addSublayer(layer)
        }
        
        player?.play()
    }
}

2. 修正后的ResourceLoaderDelegate

class CustomResourceLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate {
    // 记录主播放列表的URL,用来拼接分片的相对路径
    private let basePlaylistURL: URL
    
    init(basePlaylistURL: URL) {
        self.basePlaylistURL = basePlaylistURL
        super.init()
    }

    func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
        guard let requestURL = loadingRequest.request.url else {
            loadingRequest.finishLoading(with: NSError(domain: "com.yourapp.error", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效的请求URL"]))
            return false
        }
        
        // 只处理.ts分片的请求,非分片请求交给系统默认处理
        guard requestURL.pathExtension.lowercased() == "ts" else {
            return false
        }
        
        // 1. 把相对URL转成绝对URL
        let absoluteSegmentURL: URL
        if requestURL.host != nil {
            absoluteSegmentURL = requestURL
        } else {
            // 拼接主播放列表的base URL和相对分片路径
            absoluteSegmentURL = basePlaylistURL.appending(path: requestURL.path())
        }
        
        // 2. 追加自定义参数,保留原有参数(如果有)
        var urlComponents = URLComponents(url: absoluteSegmentURL, resolvingAgainstBaseURL: false)
        let customParams = [
            URLQueryItem(name: "paramKey1", value: "paramValue1"),
            URLQueryItem(name: "paramKey2", value: "paramValue2")
        ]
        urlComponents?.queryItems = (urlComponents?.queryItems ?? []) + customParams
        
        guard let modifiedURL = urlComponents?.url else {
            loadingRequest.finishLoading(with: NSError(domain: "com.yourapp.error", code: -2, userInfo: [NSLocalizedDescriptionKey: "无法生成修改后的URL"]))
            return false
        }
        
        print("🔄 分片URL已修改为: \(modifiedURL.absoluteString)")
        
        // 3. 设置重定向,让系统自动处理新URL的请求
        let redirectedRequest = URLRequest(url: modifiedURL)
        loadingRequest.redirect = redirectedRequest
        
        // 返回true,告诉系统我们已经处理了重定向,它会继续后续流程
        return true
    }
}

关键修改点说明

  1. 新增basePlaylistURL记录:专门用来处理HLS里的相对分片路径,把它转成绝对URL后再追加参数,解决了相对路径无法直接追加参数的问题。
  2. 重定向逻辑调整:设置redirect后直接返回true,让AVPlayer的资源加载系统自己去处理新URL的请求,不再强制结束加载流程。
  3. 完善错误处理:给各种异常情况(比如无效URL、无法生成新URL)添加了错误回调,方便调试定位问题。
  4. 保留原有参数:如果分片URL本身已经带业务参数,会保留原有参数再追加自定义的,避免覆盖必要的业务逻辑。

调试小技巧

可以用Charles抓包工具查看每个.ts请求的URL,或者在Delegate里打印日志,确认自定义参数是否已经成功追加,这样能快速排查问题。

备注:内容来源于stack exchange,提问作者Sidd Redkar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 09:39:51