简体   繁体   English

为什么AVPlayer边界时间观察器不起作用?

[英]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: 可能有两个问题:

  1. 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. 由于您的初始代码未保留对返回的内部不透明时间观察者的引用,因此观察者可能会立即释放,因此永远不会被调用。

  2. Make sure the time you register for observing actually has the correct value: 确保您注册的观察时间实际上具有正确的值:

    • playerItem.duration may be indefinite (see documentation of this property) playerItem.duration可能是不确定的(请参阅此属性的文档)
    • even the duration of the playerItem's 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 此机制独立于可能的精度持续时间,因此希望更加可靠

2019 simple example .. 2019简单的例子..

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. 完美运作。

Important .. it won't find "0" 重要..它将找不到“ 0”

Use a small value to find the "beginning" as a quick solution. 使用一个较小的值找到“开始”作为快速解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM