使用 NotificationCenter 在 AVPlayer 中交替播放视频文件
Using NotificationCenter to alternate videos files in AVPlayer
我正致力于在 Swift 中实现一个视频播放器,它将检测视频是否已停止播放,然后播放第二个。当第二个停止播放时,第一个视频应该会再次播放。
这是我设置播放器、资产和播放器项目的地方:
//Create URLs
let movieOneURL: URL = URL(fileURLWithPath: movieOnePath)
let movieTwoURL: URL = URL(fileURLWithPath: movieTwoPath)
//Create Assets
let assetOne = AVAsset(url: movieOneURL)
let assetTwo = AVAsset(url: movieTwoURL)
//Create Player Items
avPlayerItemOne = AVPlayerItem(asset: assetOne)
avPlayerItemTwo = AVPlayerItem(asset: assetTwo)
avplayer = AVPlayer(playerItem: avPlayerItemOne)
let avPlayerLayer = AVPlayerLayer(player: avplayer)
avPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
avPlayerLayer.frame = UIScreen.main.bounds
movieView.layer.addSublayer(avPlayerLayer)
//Config player
avplayer .seek(to: kCMTimeZero)
avplayer.volume = 0.0
这里是我设置通知以检测播放器是否到达视频文件末尾的地方:
NotificationCenter.default.addObserver(self, selector: #selector(self.playerItemDidReachEnd), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: avplayer.currentItem)
...调用此选择器:
func playerItemDidReachEnd(_ notification: Notification) {
// avplayer.seek(to: kCMTimeZero)
changePlayerAsset()
// avplayer.play()
}
...然后将切换出资产:
func changePlayerAsset(){
if avplayer.currentItem == avPlayerItemOne {
avplayer.replaceCurrentItem(with: avPlayerItemTwo)
avplayer.play()
} else if avplayer.currentItem == avPlayerItemTwo {
avplayer.replaceCurrentItem(with: avPlayerItemOne)
avplayer.play()
}
}
这在第一次运行时非常完美 - 当第一部电影播放完后,下一部电影就会开始播放。
我遇到的问题是我的通知观察者似乎只注册了一次;在第一个视频结束时...当第二个视频完全停止播放时,不会触发通知。
谁知道为什么会这样
您的通知处理程序未被第二项调用的原因是这一点,在您注册通知处理程序的末尾:object: avplayer.currentItem
。当 那个项目 播放完毕时,处理程序被调用一次,但是当下一个项目播放完毕时,通知被发布到另一个 object
- 另一个项目 - 而不是t 匹配您注册的内容,因此您的处理程序不会被调用。如果您在注册处理程序时将 object
更改为 nil
,它将在 any 项目完成时被调用,这更接近您所追求的。
也就是说,这不是做你想做的事的好方法 - 手动换出项目可能会产生成本和每次播放时加载每个项目的延迟。您最好使用内置功能来按顺序播放视频并循环播放它们,即 AVQueuePlayer 和 AVPlayerLooper。 .
的答案中有一个如何同时使用两者的示例
我正致力于在 Swift 中实现一个视频播放器,它将检测视频是否已停止播放,然后播放第二个。当第二个停止播放时,第一个视频应该会再次播放。
这是我设置播放器、资产和播放器项目的地方:
//Create URLs
let movieOneURL: URL = URL(fileURLWithPath: movieOnePath)
let movieTwoURL: URL = URL(fileURLWithPath: movieTwoPath)
//Create Assets
let assetOne = AVAsset(url: movieOneURL)
let assetTwo = AVAsset(url: movieTwoURL)
//Create Player Items
avPlayerItemOne = AVPlayerItem(asset: assetOne)
avPlayerItemTwo = AVPlayerItem(asset: assetTwo)
avplayer = AVPlayer(playerItem: avPlayerItemOne)
let avPlayerLayer = AVPlayerLayer(player: avplayer)
avPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
avPlayerLayer.frame = UIScreen.main.bounds
movieView.layer.addSublayer(avPlayerLayer)
//Config player
avplayer .seek(to: kCMTimeZero)
avplayer.volume = 0.0
这里是我设置通知以检测播放器是否到达视频文件末尾的地方:
NotificationCenter.default.addObserver(self, selector: #selector(self.playerItemDidReachEnd), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: avplayer.currentItem)
...调用此选择器:
func playerItemDidReachEnd(_ notification: Notification) {
// avplayer.seek(to: kCMTimeZero)
changePlayerAsset()
// avplayer.play()
}
...然后将切换出资产:
func changePlayerAsset(){
if avplayer.currentItem == avPlayerItemOne {
avplayer.replaceCurrentItem(with: avPlayerItemTwo)
avplayer.play()
} else if avplayer.currentItem == avPlayerItemTwo {
avplayer.replaceCurrentItem(with: avPlayerItemOne)
avplayer.play()
}
}
这在第一次运行时非常完美 - 当第一部电影播放完后,下一部电影就会开始播放。
我遇到的问题是我的通知观察者似乎只注册了一次;在第一个视频结束时...当第二个视频完全停止播放时,不会触发通知。
谁知道为什么会这样
您的通知处理程序未被第二项调用的原因是这一点,在您注册通知处理程序的末尾:object: avplayer.currentItem
。当 那个项目 播放完毕时,处理程序被调用一次,但是当下一个项目播放完毕时,通知被发布到另一个 object
- 另一个项目 - 而不是t 匹配您注册的内容,因此您的处理程序不会被调用。如果您在注册处理程序时将 object
更改为 nil
,它将在 any 项目完成时被调用,这更接近您所追求的。
也就是说,这不是做你想做的事的好方法 - 手动换出项目可能会产生成本和每次播放时加载每个项目的延迟。您最好使用内置功能来按顺序播放视频并循环播放它们,即 AVQueuePlayer 和 AVPlayerLooper。