【问题标题】:current time after AVPlayer seek is incorrectAVPlayer seek 后的当前时间不正确
【发布时间】:2020-03-17 10:44:07
【问题描述】:
func seekFullRead(seconds: Float64, completion: (() -> ())? = nil) {
    let targetTime:CMTime = CMTimeMakeWithSeconds(seconds, preferredTimescale: 60000)
    fullReadPlayer?.currentItem?.seek(to: targetTime, toleranceBefore: .zero, toleranceAfter: .zero, completi[enter image description here][1]onHandler: { (finish) in
        if finish {
            completion?()
        }
    })
}

fullReadTimeObserver = fullReadPlayer?.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 10), queue: DispatchQueue.main, using: { [weak self](time) in
        guard let self = self else { return }
        if self.fullReadPlayer?.status == .readyToPlay {
            self.delegate?.audioPlayer(self, didUpdateCurrentTime: time.seconds, teach: nil)
        }
    })

当我搜索到 4.57 秒时,会先显示正确的当前时间,然后当前时间会向前 0.2 秒,但会在当前时间向前 0.2 秒后开始播放。

日志:

当前时间:1.30104062

当前时间:1.401042787

寻求:4.579999923706055

当前时间:1.498295786

当前时间:4.579983333333334

当前时间:4.319330793

当前时间:4.319642834

当前时间:4.401050459

当前时间:4.501045084

当前时间:4.601038959

【问题讨论】:

  • 要去刺一下。您是否尝试过在您的 seekTo: 完成块中暂停播放,直到进入您的 if(finish){} 块后再继续播放?
  • 只是为了让您了解为什么会看到此打印输出。寻求在异步(单独)线程上运行,而不是在您的计时器上运行。假设您在 1.4 秒和 1.5 秒之间触发了搜索,假设是 1.45。因此,如果该查找线程花费了超过 0.05 秒的时间完成,则具有当前时间变量的线程仍将计数 0.1 + 当前值。它实际上在 1.5 到 1.6 秒之间的某个时间完成,这就是为什么您现在看到新时间的原因。
  • 我试过seek前暂停,seek完成后播放,还是一样的问题
  • @fswedison 你找到解决方法了吗?我在播放时看到了相同的行为,似乎 currentTime 在执行搜索完成后没有更新(但之后它得到了正确的值):/
  • 搜索后,后续播放似乎跳回到最近的音频块的开头。我在无音频视频文件中获得了所需的行为,但是一旦我添加音频,我认为它想从缓冲区的开头开始读取音频。我希望它至少为 currentTime 和观察者提供准确的时间,即使它不遵守 0 容差......似乎是一个错误

标签: swift avplayer


【解决方案1】:

我认为 NSGangster 说得有道理。观察者计时器和搜索在不同的进程上。这对我来说意味着我必须自己处理这些差异。

我在互联网上没有找到答案,也没有找到纠正方法,但我确实找到了解决方法:我可以使用像“isSeekInProgress”这样的变量来标记是否更新进度条用户界面。如下图:

var isSeekInProgress: Bool = false  // Marker  

let targetTime:CMTime = CMTimeMakeWithSeconds(seconds, preferredTimescale: 60000)
isSeekInProgress = true // Mark
fullReadPlayer?.currentItem?.seek(to: targetTime, toleranceBefore: .zero, toleranceAfter: .zero, completi[enter image description here][1]onHandler: { (finish) in
    if finish {
        isSeekInProgress = false // Unmark
        completion?()
    }
})

有些人在搜索时暂停播放器,然后在完成块中恢复播放,但如果您希望在擦洗时继续播放,这将不起作用。上面的例子相当轻松,你所要做的就是检查:

if !playbackManager.isSeekInProgress {
    progressSlider.value = playbackManager.progress
}

并且在下一次定期观察员通知期间,您的进度将会更新。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多