AVURLAsset loadValuesAsynchronously 永不失败

Posted

技术标签:

【中文标题】AVURLAsset loadValuesAsynchronously 永不失败【英文标题】:AVURLAsset loadValuesAsynchronously never fail 【发布时间】:2017-09-14 22:42:39 【问题描述】:

我正在阅读并尝试 Apple 关于加载视频资产的示例代码。

但我注意到AVURLAsset 上的loadValuesAsynchronously 功能永远不会失败,即使我在设备上打开飞行模式或在我的 Mac 上关闭 wifi。有人知道在什么情况下loadValuesAsynchronously 将无法加载密钥?

这是相对的sample code:

asset.loadValuesAsynchronously(forKeys: PlayerViewController.assetKeysRequiredToPlay) 

    /*
        The asset invokes its completion handler on an arbitrary queue.
        To avoid multiple threads using our internal state at the same time
        we'll elect to use the main thread at all times, let's dispatch
        our handler to the main queue.
    */
    DispatchQueue.main.async() 
        /*
            This method is called when the `AVAsset` for our URL has 
            completed the loading of the values of the specified array 
            of keys.
        */

        /*
            Test whether the values of each of the keys we need have been
            successfully loaded.
        */
        for key in PlayerViewController.assetKeysRequiredToPlay 
            var error: NSError?

            if asset.statusOfValue(forKey: key, error: &error) == .failed 
                let stringFormat = NSLocalizedString("error.asset_%@_key_%@_failed.description", comment: "Can't use this AVAsset because one of it's keys failed to load")

                let message = String.localizedStringWithFormat(stringFormat, title, key)

                self.handleError(with: message, error: error)

                return
            
        

        // We can't play this asset.
        if !asset.isPlayable || asset.hasProtectedContent 
            let stringFormat = NSLocalizedString("error.asset_%@_not_playable.description", comment: "Can't use this AVAsset because it isn't playable or has protected content")

            let message = String.localizedStringWithFormat(stringFormat, title)

            self.handleError(with: message)

            return
        

        /*
            We can play this asset. Create a new AVPlayerItem and make it
            our player's current item.
        */
        self.loadedAssets[title] = asset

        let name = (thumbnailResourceName as NSString).deletingPathExtension
        let type = (thumbnailResourceName as NSString).pathExtension
        let path = Bundle.main.path(forResource: name, ofType: type)!

        let thumbnail = UIImage(contentsOfFile: path)!

        self.assetTitlesAndThumbnails[asset.url] = (title, thumbnail)
    

【问题讨论】:

【参考方案1】:

终于想通了,回答我自己的问题:我一直在使用 HLS 视频,并且 URL 的格式为 https://www.foo.com/master.m3u8loadValuesAsynchronously 不会执行任何网络操作来确定 URL 是否包含有效的 HLS 文件。这就是“可播放”键始终有效的原因:

static let assetKeysRequiredToPlay = [
    "playable",
    "hasProtectedContent"
]

但是,如果我还添加了一些播放信息,例如“持续时间”和“曲目”,那么如果没有任何网络连接,它将失败,因为它需要实际加载信息。更多细节参考这个答案:https://***.com/a/31418812/1035008

【讨论】:

以上是关于AVURLAsset loadValuesAsynchronously 永不失败的主要内容,如果未能解决你的问题,请参考以下文章

AVURLAsset 拒绝加载视频

AVURLAsset的缓存行为

为啥 AVURLAsset 不加载文件?

AVURLAsset 加载 webvtt 文件

AVURLAsset loadValuesAsynchronously 永不失败

使用多个音频类型的 AVAsset 轨道切换 AVURLAsset 的音轨