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

如何解决带Token的视频URL无法在AV Player中播放的问题?

带Token的视频URL无法在AV Player流式播放的解决方案

问题概述

带Token参数的视频URL(示例:http://example.com/video.mp4?token=authtoken)可在Chrome正常播放,但在AV Player中无响应,抛出错误:

Error : Error Domain=AVFoundationErrorDomain Code=-11829 "Cannot Open" UserInfo={NSLocalizedFailureReason=This media may be damaged., NSLocalizedDescription=Cannot Open, NSUnderlyingError=0x600000c8e430 {Error Domain=NSOSStatusErrorDomain Code=-12848 "(null)"}}

现有代码片段:

let urlString = "http://example.com/video/X-ABC- The Super Hero (2000).mp4?token=_CTV24K7jFmNnH2TFH4Ehw&a=1708455493".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
        
let url = URL(string: urlString!)
//url = http://example.com/video/X-ABC-%20The%20Super%20Hero%20(2000).mp4?token=_CTV24K7jFmNnH2TFH4Ehw&a=1708455493
        
Text(url!.absoluteString)
        
VideoPlayer(url: url!, play: $play, time: $time)
            .mute(mute)
            .onBufferChanged { progress in
                // Network loading buffer progress changed
                print(progress)
            }
            .onPlayToEndTime {
                // Play to the end time.
            }
            .onReplay {
                // Replay after playing to the end.
            }
            .onStateChanged { state in
                switch state {
                case .loading:
                    print(url!.absoluteString)
                    print(state)
                case .playing(let totalDuration):
                    print(state)
                case .paused(let playProgress, let bufferProgress):
                    print(state)
                case .error(let error):
                    print(error)
                }
            }

解决方案

1. 修正URL编码逻辑

直接对整个URL字符串调用addingPercentEncoding会重复编码已转义的字符(比如原URL中的&会被再次编码),导致URL无效。正确做法是拆分路径和参数分别编码:

// 拆分原始URL为路径和查询参数两部分
let rawPath = "http://example.com/video/X-ABC- The Super Hero (2000).mp4"
let rawQuery = "token=_CTV24K7jFmNnH2TFH4Ehw&a=1708455493"

// 仅对路径中的特殊字符编码
guard let encodedPath = rawPath.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed),
      let fullUrlString = "\(encodedPath)?\(rawQuery)".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
      let url = URL(string: fullUrlString) else {
    // 编码或URL创建失败的处理逻辑
    return
}

2. 通过请求头传递Token(适配服务端要求)

部分服务端要求Token放在HTTP请求头而非URL参数中,此时需要自定义AVURLAsset的资源加载逻辑:

// 先创建不带Token的基础URL
let baseUrl = URL(string: "http://example.com/video/X-ABC- The Super Hero (2000).mp4")!
let asset = AVURLAsset(url: baseUrl)

// 设置资源加载代理
asset.resourceLoader.setDelegate(self, queue: DispatchQueue.main)

// 实现AVAssetResourceLoaderDelegate协议方法
extension YourViewController: AVAssetResourceLoaderDelegate {
    func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
        guard let requestUrl = loadingRequest.request.url else { return false }
        
        // 构建带Token请求头的请求
        var customRequest = URLRequest(url: requestUrl)
        customRequest.setValue("_CTV24K7jFmNnH2TFH4Ehw", forHTTPHeaderField: "Authorization") // 根据服务端要求调整头字段
        
        // 发起网络请求
        let task = URLSession.shared.dataTask(with: customRequest) { data, response, error in
            if let data = data, let httpResponse = response as? HTTPURLResponse {
                // 响应加载请求
                loadingRequest.dataRequest?.respond(with: data)
                loadingRequest.contentInformationRequest?.contentType = httpResponse.mimeType
                loadingRequest.contentInformationRequest?.contentLength = httpResponse.expectedContentLength
                loadingRequest.finishLoading()
            } else {
                loadingRequest.finishLoading(with: error)
            }
        }
        task.resume()
        return true
    }
}

// 用自定义asset创建PlayerItem并关联到VideoPlayer
let playerItem = AVPlayerItem(asset: asset)
let player = AVPlayer(playerItem: playerItem)
// 后续将player绑定到VideoPlayer组件

3. 检查ATS配置(针对HTTP链接)

如果使用的是HTTP协议,需要在Info.plist中配置允许非HTTPS请求:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

建议优先切换到HTTPS链接,避免ATS限制。

4. 验证Token有效性

错误码-11829可能是Token过期或无效导致的,检查URL中的时间戳参数a=1708455493是否已过期,重新获取有效Token后测试。

内容的提问来源于stack exchange,提问作者Bimal Desai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 11:44:51