Swift iOS -CMTimeMakeWithSeconds: предупреждение: ошибка -0,433 внесена из-за очень низкого масштаба времени

Я использую AVPlayer для воспроизведения видео. Я следовал этому видео-уроку Let's Build That App

Я использую UISlider/ скруббер, чтобы соответствовать текущему кадру / времени видео.

У меня есть видео продолжительностью 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-секундных. Я получаю предупреждение:

введите описание изображения здесь

Значение слайдера определяется в player?.addPeriodicTimeObserver() И из-за этого, когда я нажимаю ускоренную перемотку вперед, а не ползунок, идущий до самого конца, он останавливается на пару пунктов дальше (обратите внимание на пробел):

введите описание изображения здесь

Как я могу получить более точные значения, чтобы мой ползунок мог чистить до конца?

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 ответ

Решение

Я провел некоторое исследование и AVPlayer имеет seek метод на это:

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

С помощью этого метода вы можете установить допуск на него, чтобы компенсировать усеченное переполнение, которое в моей ситуации составляло дополнительные -0,433 секунды.

В первом аргументе вы указываете время вашего поиска, а во втором и третьем аргументах - kCMTimeZero,

Я последовал этому ответу, и хитрость была в том, что, когда я инициализировал время поиска второго аргумента, мне нужно было положить 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)
}
Другие вопросы по тегам