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

时间:2019-01-19 18:28:31

标签: ios avfoundation avkit

我正在尝试在AVPlayer的时间轴中观察一个时间。

我在主队列上尝试过;这没有用。然后根据this stack overflow post的建议切换到后台队列;两者都没有。寻找有效的解决方案或解释为何不起作用。

text/plain


//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()
                    }

2 个答案:

答案 0 :(得分:3)

可能有两个问题:

  1. addBoundaryTimeObserver的文档规定:

      

    只要您希望播放器调用时间观察者,就必须保持对返回值的强烈引用

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

  2. 确保您注册的观察时间实际上具有正确的值:

    • playerItem.duration 可能不确定(请参阅此属性的文档)
    • 根据资产的类型和加载状态,甚至playerItem的asset的持续时间也可能是未知的,或者是不精确的估计(同样,请参见AVAsset.duration的文档)。

    因此,您注册观察的时间可能永远都不会达到(请注意,可以通过插入CMTimeShow(duration)来方便地检查时间)

解决方法:

  • 如果您只是想在达到playerItem的结尾时停止播放器,则将player.actionAtItemEnd设置为pause可能就足够了

  • 如果在项目结束时需要执行一些自定义逻辑,请使用playerItem作为对象注册AVPlayerItemDidPlayToEndTime通知的观察者。此机制独立于可能的持续时间,因此希望更加可靠

答案 1 :(得分:1)

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...")
    }
}

完美运行。

重要..找不到“ 0”

使用较小的值作为快速解决方案来查找“开始”。