如何正确处理 AVPlayer HTTP 错误?

Posted

技术标签:

【中文标题】如何正确处理 AVPlayer HTTP 错误?【英文标题】:How to correctly handle AVPlayer HTTP error? 【发布时间】:2019-01-05 18:15:01 【问题描述】:

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

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

2019-01-05 13:08:33.908316-0500 Runner[84043:3269818] 可选(错误 域=AVFoundationErrorDomain 代码=-11828 "无法打开" UserInfo=NSLocalizedFailureReason=此媒体格式不是 支持。, NSLocalizedDescription=无法打开, NSUnderlyingError=0x600000781290 错误域=NSOSStatusErrorDomain 代码=-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))")

【问题讨论】:

请分享一些代码 添加了一些任意代码,代码很简单。 【参考方案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

【讨论】:

【参考方案2】:

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

你可以试试这个方法

    使用AVURLAsset并设置AVAssetResourceLoaderDelegate

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

    继续创建播放器并播放音频,委托方法会在出现 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))

【讨论】:

这是一个公平的答案,但playablenot playable 并没有准确说明为什么它不能播放。原因是403我希望能够看到。 这种情况下可以使用URLSession.shared.downloadTask可以检查response.status_code是不是200 检查isPlayable后是这个吗? 我已更新解决方案以解决您的问题 查看它使用AVAssetResourceLoaderDelegate的新解决方案

以上是关于如何正确处理 AVPlayer HTTP 错误?的主要内容,如果未能解决你的问题,请参考以下文章

iOS 7中的iOS 7 AVPlayer AVPlayerItem持续时间不正确

正确处理 AVAssetResourceLoaderDelegate Url

Angularjs 如何对 $http 调用进行正确的错误处理?

AVPlayer 播放错误的视频文件

如何在 .NET MVC 2 中实现正确的 HTTP 错误处理?

Angular 4:如何正确处理应用程序级别的 http 错误作为 Observable 错误?