Синхронизировать видео в AVPlayerLayer и AVPlayerViewController - PullRequest
0 голосов
/ 17 ноября 2018

Я работаю с AVPlayer, чтобы показать воспроизводимое видео, используя URL в нем.Он состоит из двух частей:

1. Во-первых, я вложил AVPlayer в подслой представления, используя AVPlayerLayer, то есть

var player: AVPlayer?

func configure() {
    let urlString = "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
    if let url = URL(string: urlString) {
        self.player = AVPlayer(url: url)
        let playerLayer = AVPlayerLayer(player: self.player)
        playerLayer.frame = self.view.bounds
        self.view.layer.addSublayer(playerLayer)
        player.play()
    }
}

Приведенный выше код работает нормально, и видео воспроизводится.

2. Во-вторых, на кране UIButton я представляю AVPlayerViewController, используя тот же экземпляр AVPlayerчто я создал ранее, т.е.

@IBAction func onTapVideoButton(_ sender: UIButton) {
    self.player?.pause()
    let controller = AVPlayerViewController()
    controller.player = self.player
    self.present(controller, animated: true) {
        self.player?.play()

    }
}

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

Что яхотите синхронизировать видео в AVPlayerLayer и AVPlayerViewController.

1 Ответ

0 голосов
/ 17 ноября 2018

Я думаю, что есть проблема при совместном использовании плеера, уже созданного для AVPlayerViewController.Я не уверен, почему останавливается, но это не произойдет, если вы создадите новый AVPlayer для этого контроллера.Способ синхронизации вашего проигрывателя и вашего AVPlayerViewController может выглядеть следующим образом:

Сначала вы создаете имя уведомления, которое вы будете использовать при отклонении AVPlayerViewController (apple не дает вам способа узнать, когда пользовательотклонить AVPlayerViewController):

extension Notification.Name {
    static let avPlayerDidDismiss = Notification.Name("avPlayerDidDismiss")
}

Затем вы расширяете AVPlayerViewController, чтобы публиковать это уведомление, когда пользователь собирается уволить, и отправлять время, когда пользователь оставил видео:

extension AVPlayerViewController {

    open override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        if let seekTime = player?.currentTime() {
            let userInfo = ["seekTime": seekTime]
            NotificationCenter.default.post(name: .avPlayerDidDismiss, object: nil, userInfo: userInfo)
        }
    }

}

И в вашем ViewController вы наблюдаете это уведомление, получаете seekTime, который вы хотите использовать, и используете его для настройки вашего avPlayer:

class ViewController: UIViewController {
    var player: AVPlayer?

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        configure()
        NotificationCenter.default.addObserver(self, selector: #selector(avPlayerDidDismiss), name: .avPlayerDidDismiss, object: nil)
    }

    func configure() {
        self.player = getPlayer()
        let playerLayer = AVPlayerLayer(player: self.player)
        playerLayer.frame = self.view.bounds
        self.view.layer.addSublayer(playerLayer)
        self.player?.play()
    }

    @IBAction func onTapVideoButton(_ sender: UIButton) {
        self.player?.pause()
        let controllerPlayer = getPlayer()
        controllerPlayer.currentItem?.seek(to: self.player!.currentTime(), completionHandler: nil)
        let controller = AVPlayerViewController()
        controller.player = controllerPlayer
        self.present(controller, animated: true, completion: {
            controller.player?.play()
        })
    }

    func getPlayer() -> AVPlayer {
        let url = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")!
        return AVPlayer(url: url)
    }

    @objc
    private func avPlayerDidDismiss(_ notification: Notification) {
        if let seekTime = notification.userInfo?["seekTime"] as? CMTime {
            player?.currentItem?.seek(to: seekTime, completionHandler: nil)
            player?.play()
        }
    }
}

Минусы: он отправит уведомление для каждого AVPlayerViewController.Вы используете добавить вас в качестве наблюдателя, когда вам нужна эта информация.Надеюсь, это поможет.

...