首页 文章

Swift iOS -CMTimeMakeWithSeconds:警告:由于时间刻度非常低而引入了-0.433的错误

提问于
浏览
1

我正在使用AVPlayer播放视频 . 我按照这个视频教程Let's Build That App

我使用UISlider / scrubber来跟随视频的当前帧/时间 .

我有一个10.43秒的视频,我使用快进功能,将我带到最后 .

@objc fileprivate func handleFastForward(){

        guard let playerItem = playerItem else { return }
        guard let player = player else { return }

        let duration: Float64 = CMTimeGetSeconds(playerItem.duration)
        let seekTime: CMTime = CMTimeMakeWithSeconds(duration, 1)
        player.seek(to: seekTime)
}

视频进入最后但问题是滑块只能达到10秒点,我无法让它到达最后的.43秒 . 我收到一条警告信息:

enter image description here

滑块的值在 player?.addPeriodicTimeObserver() 中确定 . 因此,当我按下快进而不是滑块到达最后时,它会停止几个点(注意空白区域):

enter image description here

如何获得更准确的值,以便我的滑块可以一直擦洗到最后?

playerItem?.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status),
                                options: [.old, .new],
                                context: &playerItemContext)

let interval = CMTime(value: 1, timescale: 2)

timeObserverToken = player?.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main, using: {
    [weak self] (progressTime) in

    let seconds = CMTimeGetSeconds(progressTime)

    let secondsString = String(format: "%02d", Int(seconds) % 60)
    let minutesString = String(format: "%02d", Int(seconds) / 60)

    self?.currentTimeLabel.text = "\(minutesString):\(secondsString)"

    if let duration = self?.playerItem!.duration{

        let durationSeconds = CMTimeGetSeconds(duration)
        self?.slider.value = Float(seconds / durationSeconds) // SLIDER IS UPDATED HERE
    }
})

1 回答

  • 3

    我做了一些研究, AVPlayer 有一个 seek 方法:

    seek(to: <CMTime>, toleranceBefore: <CMTime>, toleranceAfter: <CMTime>)
    

    使用此方法,您可以在其上设置公差以补偿截断溢出,在我的情况下,这是额外的-0.433秒 .

    在第一个参数中,你把你所寻求的时间放在 kCMTimeZero 中的第二个和第三个参数中 .

    我跟着this answer并且诀窍就是当我为第二个参数初始化我的寻找时间时,我必须将1000用于一切工作 .

    let seekTime: CMTime = CMTimeMakeWithSeconds(duration, 1000)
    

    这是我的快进按钮的代码:

    @objc fileprivate func handleFastForward(){
    
            guard let playerItem = playerItem else { return }
            guard let player = player else { return }
    
            let duration: Float64 = CMTimeGetSeconds(playerItem.duration)
            let seekTime: CMTime = CMTimeMakeWithSeconds(duration, 1000)
            player.seek(to: seekTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
    }
    

相关问题