Swift实现iPad相机Picture in Picture(PiP)功能技术咨询
iPad 相机视图 PiP 功能简化实现方案(iOS 16+)
针对iOS 16及以上版本,无需模拟视频通话流程,直接通过AVFoundation结合AVKit的原生API就能实现相机画面的画中画(PiP)功能,步骤如下:
核心优势
- 无需依赖CallKit或模拟通话状态,完全基于原生相机捕获+PiP API实现
- 自定义程度高,可直接控制相机参数、预览界面
- 适配iOS 16+的简化PiP逻辑,代码量少
实现步骤
1. 配置权限与后台模式
- 在
Info.plist中添加NSCameraUsageDescription字段,填写相机使用说明(如"用于显示相机画面的画中画功能") - 在项目后台模式中开启
Audio, AirPlay, and Picture in Picture(确保PiP活跃时相机可在后台持续捕获)
2. 代码实现
导入依赖框架
import AVFoundation import AVKit
定义核心属性
class CameraPiPViewController: UIViewController { private var captureSession: AVCaptureSession! private var previewLayer: AVCaptureVideoPreviewLayer! private var pipController: AVPictureInPictureController?
初始化相机与PiP控制器
func setupCameraAndPiP() { // 请求相机权限 AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in guard granted, let self = self else { return } DispatchQueue.main.async { // 初始化捕获会话 self.captureSession = AVCaptureSession() self.captureSession.sessionPreset = .hd1280x720 // 按需选择分辨率 // 添加前置相机输入 guard let camera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front) else { return } guard let input = try? AVCaptureDeviceInput(device: camera) else { return } if self.captureSession.canAddInput(input) { self.captureSession.addInput(input) } // 创建预览层并添加到视图 self.previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession) self.previewLayer.frame = self.view.bounds self.previewLayer.videoGravity = .resizeAspectFill self.view.layer.addSublayer(self.previewLayer) // 利用预览层的PiP源初始化控制器(iOS 16+新增特性) if let pipSource = self.previewLayer.pictureInPictureSource { self.pipController = AVPictureInPictureController(pictureInPictureSource: pipSource) self.pipController?.delegate = self } // 启动相机捕获 self.captureSession.startRunning() } } }
触发PiP功能(示例:按钮点击)
@IBAction func togglePiP(_ sender: UIButton) { guard let pipController = pipController, pipController.isPictureInPictureSupported else { return } if pipController.isPictureInPictureActive { pipController.stopPictureInPicture() } else { pipController.startPictureInPicture() } }
实现PiP代理(处理状态变化)
extension CameraPiPViewController: AVPictureInPictureControllerDelegate { func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { // PiP启动后可隐藏本地预览层 previewLayer.isHidden = true } func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) { // PiP停止后恢复本地预览 previewLayer.isHidden = false } }
3. 关键说明
- 无需使用
UIImagePickerController:该系统控制器为封装实现,无法获取内部捕获会话或预览层,不支持自定义PiP扩展 - iOS 16+的核心简化点:
AVCaptureVideoPreviewLayer新增pictureInPictureSource属性,直接作为PiP控制器的数据源,无需额外转换视频流 - 后台运行保障:PiP活跃时,系统会自动维持相机捕获会话的后台运行状态,无需额外复杂配置
内容的提问来源于stack exchange,提问作者papay0
相关产品推荐
相关产品推荐

