ios - 在 AVPlayerLayer 和 AVPlayerViewController 中同步视频
问题描述
我正在AVPlayer
使用其中的 a 来显示正在播放的视频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
解决方案
我认为将已经创建的播放器共享到 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 发送通知。当您需要此信息时,您可以使用将您添加为观察者。希望它可以提供帮助。
推荐阅读
- java - 如何在 kotlin 中实现相同的功能?
- java - 启动 Waves 节点 com 扩展 com.wavesplatform.dex.Matcher
- sql - SQL 从表部门明智地获取至少 2 个薪水
- python - pandas 将 int 或 string 转换为 float
- node.js - fetch : o 'Access-Control-Allow-Origin' 标头出现在请求的资源上:react 和 node
- sql-server - 为什么 SQL Server 数据源的下拉列表中缺少 .accdb?
- c# - 为什么接受引用类型的泛型方法不接受可空类型作为参数?
- postgresql - Postgres 行级策略问题
- amazon-redshift - Redshift:无法删除用户所有者默认权限
- excel - 如何使用两个变量在给定一列的情况下隔离表的行