简体   繁体   English

在AVPlayerLayer和AVPlayerViewController中同步视频

[英]Sync video in AVPlayerLayer and AVPlayerViewController

I'm working with AVPlayer to show the playing video using a URL in it. 我正在使用AVPlayer来显示播放视频,其中包含一个URL There are 2 parts to it: 它有两个部分:

1. Firstly, I've embedded the AVPlayer to a view's sublayer using AVPlayerLayer , ie 1.首先,我使用AVPlayerLayerAVPlayer嵌入到视图的子层中,即

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

The above code is working fine and the video is playing. 上面的代码工作正常,视频正在播放。

2. Secondly, on a UIButton tap, I'm presenting a AVPlayerViewController using the same AVPlayer instance that I created earlier, ie 2.其次,在UIButton tap上,我使用我之前创建的相同AVPlayer实例呈现AVPlayerViewController ,即

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

    }
}

The problem I'm facing here is, after the AVPlayerViewController opens, the video stops playing but the audio still plays on. 我面临的问题是,在AVPlayerViewController打开后,视频停止播放但音频仍在播放。

What I want is to sync the video in both AVPlayerLayer and AVPlayerViewController . 我想要的是同步 AVPlayerLayerAVPlayerViewController 的视频

I think there is a problem when sharing a player already created to the AVPlayerViewController. 我认为将已经创建的播放器共享到AVPlayerViewController时会出现问题。 I'm not sure why is stoping but it wont happen if you create a new AVPlayer for that controller. 我不知道为什么要停止,但如果你为该控制器创建一个新的AVPlayer,它就不会发生。 A way to sync your player and your AVPlayerViewController could be like this: 同步播放器和AVPlayerViewController的方法可能是这样的:

First, you create a Notification Name that you'll use when the AVPlayerViewController is dismiss (apple does not give you a way to know when the user dismiss the AVPlayerViewController): 首先,您创建一个通知名称,当AVPlayerViewController被解雇时您将使用该通知名称(苹果不会让您知道用户何时解雇AVPlayerViewController):

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

Then, you extend AVPlayerViewController to post this notification when is going to be dismiss and to send the time when the user left the video: 然后,您将扩展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)
        }
    }

}

And in your ViewController you observe that notification, get the seekTime you want to go and use it to setup your avPlayer: 在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()
        }
    }
}

Cons: It will send the notification for every AVPlayerViewController. 缺点:它将为每个AVPlayerViewController发送通知。 You use add you as an observer when you need this info. 您需要在需要此信息时将您添加为观察者。 Hope it can help. 希望它可以提供帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM