在 AVPlayerLayer 和 AVPlayerViewController 中同步视频
Posted
技术标签:
【中文标题】在 AVPlayerLayer 和 AVPlayerViewController 中同步视频【英文标题】:Sync video in AVPlayerLayer and AVPlayerViewController 【发布时间】:2018-11-17 14:35:25 【问题描述】:我正在使用 AVPlayer
来显示正在播放的视频,其中使用了 URL
。它有两个部分:
1. 首先,我使用AVPlayerLayer
将AVPlayer
嵌入到视图的子层中,即
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
打开后,视频停止播放但音频仍在播放。
我想要的是在AVPlayerLayer
和AVPlayerViewController
中同步视频。
【问题讨论】:
让 player = AVPlayer(url: url) ?您已经有一个名为 player 的类变量。 我的错误。是的,我有类变量。我会编辑它。 【参考方案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 发送通知。当您需要此信息时,您可以使用将您添加为观察者。希望它可以提供帮助。
【讨论】:
非常感谢这个解决方案。真的很感激。以上是关于在 AVPlayerLayer 和 AVPlayerViewController 中同步视频的主要内容,如果未能解决你的问题,请参考以下文章
在没有动画效果的avplayerlayer上设置videogravity