为什么我的AVPlayer无法正常工作?

时间:2017-06-14 16:04:39

标签: ios aes avplayer hls

我无法连接到通过HLS与128位加密连接的实时流,它是一个Azure媒体流。服务器还需要一个授权令牌,该令牌通过HTTP标头Authorization提供,类型为Bearer <insert token here>

我的代码是:

let url = "http://<redacted>"

let headers = ["Authorization": "Bearer <token redacted>"]
let options = ["AVURLAssetHTTPHeaderFieldsKey": headers]

let avAsset = AVURLAsset(url: URL(string: url)!, options: options)
let avItem = AVPlayerItem(asset: avAsset)
player = AVPlayer(playerItem: avItem)

player.play()

我已经调试了网络呼叫,AVPlayer发出了2个呼叫,一个用于查看是否有新版本(我猜测是从我在该呼叫上收到的304),还有一个用于获取流。这些调用分别返回304 Not Modified和206 Partial Content。

这些电话:

304 call

206 call

我没有听到任何声音,但设备上的任何其他声音都被静音(应该如此)。这告诉我播放接收的数据存在问题。我的同事可以在Android上加载流,只需在此处执行操作,我可以在http://ampdemo.azureedge.net/azuremediaplayer.html上加载。

我通过抓取player.currentItem?.status来检查播放器的状态,这是failedplayer.currentItem?.error

  

错误域= AVFoundationErrorDomain代码= -11828&#34;无法打开&#34; UserInfo = {NSUnderlyingError = 0x60800005a610 {Error Domain = NSOSStatusErrorDomain Code = -12847&#34;(null)&#34;},NSLocalizedFailureReason =不支持此媒体格式。,NSLocalizedDescription =无法打开}

编辑:我尝试进一步调试。我实施了AVAssetResourceLoaderDelegate,并在resourceLoader:shouldWaitForLoadingOfRequestedResource:中添加了以下代码:

func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
    DispatchQueue.main.async {
        var request = loadingRequest.request

        var headers = request.allHTTPHeaderFields!
        if headers["Authorization"] == nil {
            headers["Authorization"] = "Bearer <token>"
        } else {
            print("Auth header exists: \(headers)")
        }

        request.url = URL(string: self.url)!
        request.allHTTPHeaderFields = headers

        URLSession(configuration: URLSessionConfiguration.default).dataTask(with: request) {
            data, response, error in

            if let error = error {
                print(error)
                loadingRequest.finishLoading(with: error)
            } else {
                loadingRequest.dataRequest?.respond(with: data!)
                loadingRequest.finishLoading()
            }
        }.resume()
    }

    return true
}

我只在尚未存在时添加Authorization标题。我认为在所有调用中覆盖Authorization标头可能会破坏加密。

由于resourceLoader:shouldWaitForLoadingOfRequestedResource:仅在请求使用httphttps以外的方案时被调用,因此我将http://替换为mycustomscheme://。这也是我在这里设置网址的原因,因为请求中的原始网址没有有效的网址方案。

这种方式对我来说更好,因为我可以查看请求和响应,因为它们正在发生。没有更多的Burp Suite来调试电话。

我现在遇到的问题是我收到了我期望的数据(播放器确实执行了两次相同的请求),但当我检查player.currentItem?.status时,这是failedplayer.currentItem?.error

  

错误域= NSURLErrorDomain代码= -1001&#34;请求超时。&#34; UserInfo = {NSLocalizedDescription =请求超时。,NSUnderlyingError = 0x60000005f320 {错误域= NSOSStatusErrorDomain代码= -1001&#34;(null)&#34;}}

对我来说似乎很奇怪,因为Android和网络版本没有问题,我会暂停。

我查看了Android代码,他使用的是<url>.ism/manifest(format=m3u8-aapl-v3)而不是<url>.ism/manifest。如果我使用该网址,则会获得相同的failed状态,但错误为

  

错误域= AVFoundationErrorDomain代码= -11800&#34;操作无法完成&#34; UserInfo = {NSUnderlyingError = 0x608000059e60 {Error Domain = NSOSStatusErrorDomain Code = -12936&#34;(null)&#34;},NSLocalizedFailureReason =发生未知错误(-12936),NSLocalizedDescription =操作无法完成}

好的,我得到了它的工作,但我不知道它为什么有用,为什么它没有工作。我输入了Android执行的URL作为第二次调用来获取流,这个URL嵌入了质量信息。它的格式为<url>.ism/QualityLevels(3782)/Manifest(video,format=m3u8-aapl-v3,audiotrack=aac_UND_2_192)

有谁能解释这里发生了什么?

0 个答案:

没有答案