如何防止AVPictureInPictureController在视频结束后自动关闭
解决AVQueuePlayer播放结束后画中画窗口消失的问题
问题原因
当AVQueuePlayer播放完所有视频项后,播放器状态变为completed,AVPictureInPictureController检测到关联播放器无活跃播放内容,会自动退出画中画模式。
可行解决方案
1. 监听播放结束,重置到最后一帧维持活跃状态
注册播放结束通知,在最后一个视频播放完成时,将播放器定位到最后一帧,避免进入completed状态:
// 注册通知(建议在viewDidLoad中执行) NotificationCenter.default.addObserver(self, selector: #selector(onPlaybackEnded(_:)), name: .AVPlayerItemDidPlayToEndTime, object: nil) @objc private func onPlaybackEnded(_ notification: Notification) { guard let finishedItem = notification.object as? AVPlayerItem, let currentItem = queuePlayer.currentItem, finishedItem == currentItem, queuePlayer.items().last == currentItem else { return } // 定位到最后一帧(减去0.01秒避免触发结束逻辑) let finalFrame = CMTimeMakeWithSeconds(currentItem.duration.seconds - 0.01, preferredTimescale: 600) queuePlayer.seek(to: finalFrame) } // 记得在deinit中移除通知 deinit { NotificationCenter.default.removeObserver(self) }
2. 替换最后一项为自身并暂停(备选)
如果希望停在最后一帧,也可以在播放结束后,将当前播放项替换为自身并暂停在末尾:
@objc private func onPlaybackEnded(_ notification: Notification) { guard let finishedItem = notification.object as? AVPlayerItem, let currentItem = queuePlayer.currentItem, finishedItem == currentItem, queuePlayer.items().last == currentItem else { return } queuePlayer.pause() queuePlayer.replaceCurrentItem(with: currentItem) queuePlayer.seek(to: currentItem.duration) }
3. 利用PIP代理状态监听辅助验证
实现AVPictureInPictureControllerDelegate,在状态变化时确认播放器状态,确保PIP窗口不意外退出:
extension YourViewController: AVPictureInPictureControllerDelegate { func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { // 检查是否因播放结束导致退出 if let currentItem = queuePlayer.currentItem, queuePlayer.currentTime() >= currentItem.duration { // 再次执行seek到最后一帧,维持播放器活跃状态 queuePlayer.seek(to: CMTimeMakeWithSeconds(currentItem.duration.seconds - 0.01, preferredTimescale: 600)) } } }
核心要点
- 始终保持AVPlayer处于
readyToPlay或paused状态,避免进入completed状态,这是维持PIP窗口的关键 - 通知注册和移除要配对,避免内存泄漏
内容的提问来源于stack exchange,提问作者Abhinay
相关产品推荐
相关产品推荐

