AVPlayer, когда пользователь ищет видео, должен сделать паузу - PullRequest
0 голосов
/ 06 сентября 2018

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

Есть ли способ сделать это?
Это то, что у меня сейчас есть в моем плеере.

final class PlayerViewController {
    private var playPosition: Int = 0
    private var didInitialSetup = false
    var mainPlayerItem: AVPlayerItem?
    var player: AVPlayer?
    var playerController: AVPlayerViewController!

    private var avPlayerItems: [AVPlayerItem] = []

    weak var delegate: PlayerViewControllerDelegate?

    override var mainPlayerItem: AVPlayerItem? {
        willSet {
            observers.forEach { observer in
                observer.invalidate()
            }
            observers.removeAll()

            let statusObserver = newValue?.observe(\.status, options: [.old, .new], changeHandler: { [weak self] item, _ in
                guard let strongSelf = self else { return }
                switch item.status {
                case .readyToPlay:
                    if strongSelf.didInitialSetup == false {
                        strongSelf.initialSetup()
                    }
                case .failed:
                    if let playError = item.error {
                        strongSelf.displayError(error: playError)
                    }
                case .unknown:
                    break
                }
            })

            if let observer = statusObserver {
                self.observers.append(observer)
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.loadAVPlayerItems()
    }

    // MARK: - Private methods

    private func loadAVPlayerItems() {
        self.player = AVQueuePlayer(items: self.avPlayerItems)
        self.playerController.player = self.player
        self.player?.play()

        let rateObserver = self.player?.observe(\.rate, options: [.new], changeHandler: { [weak self] player, _ in
            guard let strongSelf = self else { return }
            if player.rate == 0 {
                strongSelf.cancelNext()
            }
        })

        if let observer = rateObserver {
            self.observers.append(observer)
        }

        if let lastItem = avPlayerItems.last {
            NotificationCenter.default.addObserver(self, selector: #selector(self.playerItemDidReachEnd), name: .AVPlayerItemDidPlayToEndTime, object: lastItem)
        }
    }

    @objc func playerItemDidReachEnd() {
        if let time = self.player?.currentItem?.currentTime() {
            self.eventsLogger?.playerDidComplete(playHeadCMTime: time)
        }

        self.playheadTimer?.invalidate()
        self.playheadTimer = nil

        self.mainPlayerItem = nil
        self.player?.pause()
        self.playPosition = 0

        self.dismiss(animated: true, completion: nil)
    }

    private func initialSetup() {
        guard self.isViewLoaded && (self.view.window != nil) else {
            self.player?.pause()
            return
        }

        self.didInitialSetup = true

        let timePosition = CMTime(seconds: Double(self.playPosition), preferredTimescale: CMTimeScale(NSEC_PER_SEC))
        if self.playPosition > 1 {
            self.player?.seek(to: timePosition)
        }

        self.eventsLogger?.playerDidStart(playHeadCMTime: timePosition)
        self.playheadTimer?.invalidate()
        self.playheadTimer = nil
        self.startPlayheadTimer()
    }
}
class CustomAVPlayer: AVPlayer {
    override func seek(to time: CMTime, toleranceBefore: CMTime, toleranceAfter: CMTime, completionHandler: @escaping (Bool) -> Void) {
        super.seek(to: time, toleranceBefore: toleranceBefore, toleranceAfter: toleranceAfter, completionHandler: completionHandler)
        print(">> user scrubbing")
    }
}

1 Ответ

0 голосов
/ 07 сентября 2018

Я постараюсь ответить на основании того, что я понимаю, и ссылаясь на общий случай.

Кроме того, я предполагаю, что вы создаете свой собственный видеоплеер.


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

  • AVPlayerItem's playbackBufferEmpty: Вы получите уведомление при поиске вперед. Если ваше видео не закончено играть. Как правило, вы должны сделать паузу, когда буфер пуст, и возобновить, когда его нет.

  • AVPlayer rate: Вообще говоря, если это не 1.0 и проигрыватель не приостановлен, вы должны сделать паузу. Это если вы ожидаете нормальную скорость воспроизведения. Однако, если вы поддерживаете разные скорости воспроизведения (например, используете что-то вроде canPlaySlowForward), вам, возможно, придется немного поиграть с ним.

    Apple говорит :

    Значение 0.0 приостанавливает видео, а значение 1.0 воспроизводит текущий элемент с естественной скоростью.

  • AVPlayer status

  • AVPlayerItem's status


Когда я говорю «наблюдай», я имею в виду использовать что-то вроде observeValueForKeyPath:ofObject:change:context: в классе, в котором находится ваш игрок.

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

...