Почему AVPlayer Boundary Time Observer не работает? - PullRequest
0 голосов
/ 19 января 2019

Я пытаюсь наблюдать время на временной шкале моего AVPlayer.

Я пробовал это в главной очереди; который не работал. Затем я переключился на фоновую очередь, как советовалось с это сообщение о переполнении стека ; что не с ни. Ищете рабочее решение или объяснение, почему это не работает.

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

Обновление: После сохранения строгой ссылки на возвращаемое значение наблюдателя я установил точку останова в обратном вызове. Это все еще не работает.

 //add boundary time notification
                    boundaryTimeObserver = avLayer.player!.addBoundaryTimeObserver(forTimes: [NSValue(time: avLayer.player!.currentItem!.duration)], queue: DispatchQueue.main){

                        self.avLayer.player!.pause()
                    }

Ответы [ 2 ]

0 голосов
/ 26 июля 2019

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"

Используйте небольшое значение, чтобы найти«начало» как быстрое решение.

0 голосов
/ 20 января 2019

Возможны две проблемы:

  1. В документации для addBoundaryTimeObserver указано:

    Вы должны сохранять строгую ссылку на возвращаемое значение, пока вы хотите, чтобы наблюдатель времени вызывал игрок

    Поскольку ваш исходный код не сохраняет ссылку на возвращенный внутренний непрозрачный наблюдатель времени, вероятно, наблюдатель освобождается немедленно и, следовательно, никогда не вызывается.

  2. Убедитесь, что время, которое вы регистрируете для наблюдения, действительно имеет правильное значение:

    • playerItem.duration может быть неопределенным (см. Документацию по этому свойству)
    • даже длительность элемента PlayerItem asset может быть неизвестна, или неточная оценка, в зависимости от типа актива и состояния загрузки (снова см. Документацию AVAsset.duration об этом).

    Как следствие, время, которое вы регистрируете для наблюдения, может никогда не быть достигнуто (обратите внимание, что время можно легко проверить, вставив CMTimeShow(duration))

Подходы для решения этой проблемы:

  • если вы просто хотите остановить игрока, когда достигнут конец playerItem, установки player.actionAtItemEnd в pause может быть достаточно

  • Если вам нужно выполнить некоторую пользовательскую логику, когда достигается конец элемента, зарегистрируйте наблюдателя для уведомлений AVPlayerItemDidPlayToEndTime с playerItem в качестве объекта. Этот механизм не зависит от, возможно, точных сроков и, следовательно, более надежен

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...