如何正确处理AVPlayer HTTP错误?

时间:2019-01-05 18:15:02

标签: ios swift avplayer

当请求从Web服务器播放mp3文件时,如果该服务器返回禁止的403,则在检查AVPlayer当前项目错误时,不清楚如何处理该错误。

来自AVPlayer的错误消息并不表示它是403 ...

  

2019-01-05 13:08:33.908316-0500 Runner [84043:3269818]可选(错误   域= AVFoundationErrorDomain代码= -11828“无法打开”   UserInfo = {NSLocalizedFailureReason =此媒体格式不是   支持。NSLocalizedDescription =无法打开,   NSUnderlyingError = 0x600000781290 {Error Domain = NSOSStatusErrorDomain   Code = -12847“(null)”}})

该错误表明不支持该媒体,但是甚至从未访问过该媒体。反正有没有看到AVPlayer请求中的HTTP错误代码?

在Android上测试相同文件时,我能够正确地看到来自Android本机MediaPlayer的403错误代码(Android的错误比iOS的AVPlayer更好,更有用)。

由于缺少正确的错误消息,因此很难向用户正常显示准确的错误。

任意代码示例:

    let url = URL(string: "some 403 server url")
    let playerItem:AVPlayerItem = AVPlayerItem(url: url!)
    player = AVPlayer(playerItem: playerItem)
    player.play()

检查错误将打印上面引用的消息。

NSLog("\(String(describing: player.currentItem?.error))")

2 个答案:

答案 0 :(得分:1)

这是一个可能的解决方案,而不是使用URL初始化AVPlayerItem

您可以尝试这种方法

  1. 使用AVURLAsset并设置AVAssetResourceLoaderDelegate

  2. 使用委托方法   func resourceLoader(_ resourceLoader:AVAssetResourceLoader, didCancel authenticationChallenge: URLAuthenticationChallenge)

  3. 继续创建播放器并播放音频,当出现403错误时,委托方法将让您知道。

这是示例代码

class ResourceLoadingDelegate:NSObject, AVAssetResourceLoaderDelegate {
      func resourceLoader(_ resourceLoader: AVAssetResourceLoader,
                    didCancel authenticationChallenge:  URLAuthenticationChallenge) {
    /// handle the authentication challenge
    print(authenticationChallenge.error.debugDescription)
   }
}

   let asset = AVURLAsset(url: URL(string: "some 403 url")!)

   asset.resourceLoader.setDelegate(ResourceLoadingDelegate(), queue:  DispatchQueue.global(qos: .userInitiated))

答案 1 :(得分:1)

使用KVO观察playItem的状态,如下所示:

self.playItem.addObserver(self, forKeyPath: "status", options: .new, context: nil)

然后在方法中:

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        let playerItem = object as! AVPlayerItem
        if keyPath == "status", playerItem.status == .failed{
            if let error = playerItem.error as NSError? {
                let errorCode = error.code
            }
        }
}

您可以在此处找到定义的代码: documentation