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

Я использую AVPlayer для воспроизведения видео. Я следил за этим видеоруководством Давайте создадим это приложение

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

У меня есть видео продолжительностью 10,43 секунды, и я использую функцию перемотки вперед, которая доводит меня до самого конца.

@objc fileprivate func fastForwardButtonTapped() {

        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-секундной точке, и я не могу заставить его перейти к последним 0,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
    }
})

person Lance Samaria    schedule 15.03.2018    source источник


Ответы (1)


Я провел небольшое исследование, и у AVPlayer есть метод seek:

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

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

В первом аргументе вы указываете время поиска, а во втором и третьем аргументах — kCMTimeZero. Нравится:

// seekTime is the time I’m seeking to
player.seek(to: seekTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)

Я также следовал этому ответу, и хитрость заключалась в том, что когда я инициализировал время поиска для второго аргумента, мне пришлось поставить 1000 для всего работать. Нравится:

let seekTime: CMTime = CMTimeMakeWithSeconds(duration, 1000)

Вот код моей кнопки быстрой перемотки вперед:

@objc fileprivate func fastForwardButtonTapped() {

        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)
}
person Lance Samaria    schedule 17.03.2018
comment
Или вы можете использовать CMTimeScale(NSEC_PER_SEC) вместо 1000. - person Nik Kov; 29.07.2019
comment
Какая польза от этого? - person Lance Samaria; 29.07.2019