【问题标题】:Sync video in AVPlayerLayer and AVPlayerViewController在 AVPlayerLayer 和 AVPlayerViewController 中同步视频
【发布时间】:2018-11-17 14:35:25
【问题描述】:

我正在使用 AVPlayer 来显示正在播放的视频,其中使用了 URL。它有两个部分:

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

上面的代码工作正常,视频正在播放。

2. 其次,在点击UIButton 时,我使用之前创建的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()

    }
}

我在这里面临的问题是,AVPlayerViewController 打开后,视频停止播放但音频仍在播放。

我想要的是在AVPlayerLayerAVPlayerViewController同步视频

【问题讨论】:

  • 让 player = AVPlayer(url: url) ?您已经有一个名为 player 的类变量。
  • 我的错误。是的,我有类变量。我会编辑它。

标签: ios swift avplayer avplayerviewcontroller avplayerlayer


【解决方案1】:

我认为将已经创建的播放器共享到 AVPlayerViewController 时会出现问题。我不确定为什么会停止,但如果您为该控制器创建一个新的 AVPlayer,它就不会发生。一种同步播放器和 AVPlayerViewController 的方法可能是这样的:

首先,您创建一个通知名称,当 AVPlayerViewController 关闭时您将使用该名称(苹果没有让您知道用户何时关闭 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 发送通知。当您需要此信息时,您可以使用将您添加为观察者。希望它可以提供帮助。

【讨论】:

  • 非常感谢这个解决方案。真的很感激。
猜你喜欢
  • 2017-03-18
  • 1970-01-01
  • 2016-12-30
  • 2015-10-02
  • 2016-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多