You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 22:20:04