我正在初始化一个AVPlayerItem
,它需要一个参数automaticallyLoadedAssetKeys
,它指示在标记为“准备播放”之前需要加载哪些AVAsset
键。
我已经看到人们将duration
属性作为其中一个密钥传递的例子。
但是在AVPlayerItem
的文档中,它讨论了duration
属性,以及如何确保它是有效的。
在加载基础资产的持续时间之前,此属性的值将报告为kCMTimeIndefinite。有两种方法可以确保只有在可用时才访问持续时间的值:
等到玩家项目的
status
是readyToPlay
另一种方法是注册一个KVO,这很好。但是这第一条评论会告诉我,我不需要问duration
会自动加载,因为它应该已经存在了。(?)
如果这是真的,我无法弄清楚为什么有人会将duration
作为自动加载的标志传递,因为它看起来就是这种情况。我在这里错过了什么吗?
有些人这样做是因为有iOS错误(包括在iOS 12.1.4中)有时会导致AVPlayerItem.duration为nan,即使状态为readyToPlay也是如此。例子here和here。
但是,我的经验是在automaticLoadedAssetKeys中指定“持续时间”并不能解决问题 - 尽管Apple的AVPlayerItem文档:
在播放器项目达到状态AVPlayerItem.Status.readyToPlay之前,自动载入的AssetKeys中的每个键的值将由底层AVAsset自动加载;即当项目准备好播放时,通过调用资产属性的statusOfValue(forKey:error :)方法返回的值将是终端状态值之一
我可以获得AVPlayerItem.Status.readyToPlay,其中statusOfValue(forKey:“duration”)返回.loaded,持续时间为nan。
我发现每次工作的唯一解决方案是KVO AVPlayerItem.status(用于.readyToPlay)和AVPlayerItem.duration(用于有效数字),当触发时,检查两者:
if item.status != AVPlayerItem.Status.readyToPlay || !item.duration.isUsableNumber() {
return // not ready yet (for addBoundaryTimeObserver, seek to end, etc.)
}
WhereUsableNunber()只是:
func isUsableNumber() -> Bool {
return isValid && isNumeric && !isIndefinite && !isNegativeInfinity && !isPositiveInfinity
}
对不起,我知道这有点陈旧。但我最近找到了问题的答案。
所以,我意识到我的文档很混乱,而且一直都是正确的文档,如果我看起来更难,我会注意到的。
AVPlayerItem(asset: asset)
默认加载duration
属性。这就像打电话给AVPlayerItem(asset: asset, automaticallyLoadedAssetKeys: ["duration"])
它实际上在文档中说明了这一点,但我完全错过了它。