[英]Why is AVPlayer Boundary Time Observer not working?
I am trying to observe a time in the timeline of my AVPlayer. 我正在尝试在AVPlayer的时间轴中观察时间。
I tried this on the main queue; 我在主队列上尝试过; which did not work.
这没有用。 I then switched to a background queue, as advised from this stack overflow post ;
然后,根据该堆栈溢出文章的建议,我切换到了后台队列; which did not with either.
两者都没有。 Looking for a working solution or an explanation as to why this isn't working.
寻找有效的解决方案或解释为何不起作用。
//add boundary time notification to global queue
avLayer.player!.addBoundaryTimeObserver(forTimes: [NSValue(time: avLayer.player!.currentItem!.duration)], queue: DispatchQueue.main){
self.avLayer.player!.pause()
}
//add boundary time notification to background queue
avLayer.player!.addBoundaryTimeObserver(forTimes: [NSValue(time: avLayer.player!.currentItem!.duration)], queue: DispatchQueue.global(qos: .userInteractive)){
self.avLayer.player!.pause()
}
Update: After retaining a strong reference to the return value of the observer, I set a breakpoint in the callback.
更新:在保留对观察者返回值的强引用之后,我在回调中设置了一个断点。 It is still not working.
它仍然无法正常工作。
//add boundary time notification
boundaryTimeObserver = avLayer.player!.addBoundaryTimeObserver(forTimes: [NSValue(time: avLayer.player!.currentItem!.duration)], queue: DispatchQueue.main){
self.avLayer.player!.pause()
}
There may be two problems: 可能有两个问题:
As the documentation for addBoundaryTimeObserver
states: 正如
addBoundaryTimeObserver
的文档addBoundaryTimeObserver
:
You must maintain a strong reference to the returned value as long as you want the time observer to be invoked by the player
只要您希望播放器调用时间观察器,就必须对返回值保持强烈的引用
As your initial code does not keep a reference to the returned internal opaque time observer, the observer probably is released immediately and thus is never called. 由于您的初始代码未保留对返回的内部不透明时间观察者的引用,因此观察者可能会立即释放,因此永远不会被调用。
Make sure the time you register for observing actually has the correct value: 确保您注册的观察时间实际上具有正确的值:
asset
may be unknown, or an in-precise estimation, depending on the type of the asset and loading state (again, see documentation of AVAsset.duration
on this). asset
类型和加载状态( AVAsset.duration
,请参见AVAsset.duration
文档),甚至playerItem asset
的持续时间也可能是未知的,或者是不精确的估算值。 As a consequence, the time you register for observing may never be reached (note that the time can easily be checked by inserting a CMTimeShow(duration)
) 结果,您注册观察的时间可能永远都不会达到(请注意,可以通过插入
CMTimeShow(duration)
轻松地检查CMTimeShow(duration)
)
Approaches to resolve this: 解决此问题的方法:
if you just want to stop the player when the playerItem's end is reached, setting player.actionAtItemEnd
to pause
may be sufficient 如果您只是想在到达playerItem的结尾时停止播放器,则将
player.actionAtItemEnd
设置为pause
可能就足够了
if you need to execute some custom logic when the item's end is reached, register an observer for AVPlayerItemDidPlayToEndTime
notifications with the playerItem as object. 如果您需要在到达项目结尾时执行一些自定义逻辑,请使用playerItem作为对象注册
AVPlayerItemDidPlayToEndTime
通知的观察者。 This mechanism is independent from possibly in-precise durations and so hopefully more reliable 此机制独立于可能的精度持续时间,因此希望更加可靠
var player = AVPlayer()
var token: Any?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let u = "https... "
let playerItem = AVPlayerItem(url: URL(string: u)!)
player = AVPlayer(playerItem: playerItem)
player.play()
token = player.addBoundaryTimeObserver(
forTimes: [0.5 as NSValue],
queue: DispatchQueue.main) { [weak self] in
self?.spinner.stopAnimating()
print("The audio is in fact beginning about now...")
}
}
Works perfectly. 完美运作。
Use a small value to find the "beginning" as a quick solution. 使用一个较小的值找到“开始”作为快速解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.