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

如何在AVKit中选择新视频时关闭画中画(PiP)播放的视频?

解决AVKit画中画模式下切换视频无法关闭旧视频的问题

嘿,这个场景我太熟悉了!当视频进入画中画(PiP)模式后,AVPlayerViewController确实会失去对它的直接控制权,这时候调用dismiss肯定没用——因为PiP是系统层面在管理视频了。不过别担心,有个很直接的解决方案,核心就是用AVPictureInPictureController来管理PiP状态,而不是只依赖AVPlayerViewController。

关键思路

你需要全局持有两个对象:

  • 当前正在播放的AVPlayer实例
  • 对应的AVPictureInPictureController实例

这样当用户选择新视频时,你可以直接通过AVPictureInPictureController停止旧视频的PiP状态,再清理旧播放器,最后启动新视频。

修改后的代码实现

// 在你的ViewController类中添加全局变量
var currentPlayer: AVPlayer?
var currentPiPController: AVPictureInPictureController?

func play(FileName filename: String, FileType type: String) {
    // 先处理正在播放的旧视频(包括PiP状态)
    if let existingPlayer = currentPlayer, let pipController = currentPiPController {
        // 如果旧视频正处于PiP模式,直接停止
        if pipController.isPictureInPictureActive {
            pipController.stopPictureInPicture()
        }
        // 暂停播放器并释放资源
        existingPlayer.pause()
        currentPlayer = nil
        currentPiPController = nil
    }
    
    // 准备新视频的播放
    guard let path = Bundle.main.path(forResource: filename, ofType: type) else {
        print("找不到指定视频文件")
        return
    }
    let url = URL(fileURLWithPath: path)
    let newPlayer = AVPlayer(url: url)
    currentPlayer = newPlayer
    
    let playerVC = AVPlayerViewController()
    playerVC.player = newPlayer
    
    // 初始化PiP控制器(先检查设备是否支持PiP)
    if AVPictureInPictureController.isPictureInPictureSupported() {
        currentPiPController = AVPictureInPictureController(playerLayer: playerVC.playerLayer!)
    }
    
    // 全屏呈现新视频并开始播放
    present(playerVC, animated: true) {
        newPlayer.play()
    }
}

为什么这样能解决问题?

  • AVPictureInPictureController是专门用来管理PiP状态的系统类,不管视频是不是处于AVPlayerViewController的控制下,它都能直接操作PiP的启停
  • 全局持有播放器和PiP控制器,确保你能准确找到并清理旧的播放实例,避免多个视频同时播放

额外注意事项

  1. 别忘了在Info.plist中添加画中画权限描述:
    <key>NSPictureInPictureUsageDescription</key>
    <string>允许视频以画中画模式播放,方便您同时使用应用其他功能</string>
    
  2. 如果用户的设备不支持PiP(比如部分旧机型),isPictureInPictureSupported()会返回false,这时候直接暂停旧播放器就行,不会有问题

内容的提问来源于stack exchange,提问作者iOSProgrammingIsFun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:08:04