iOS16视频通话App后台无法持续采集摄像头视频,求解决方案
iOS 16+ 实现视频通话应用后台摄像头持续运行(类似Zoom/WhatsApp)
问题描述
我正在开发一款视频通话应用,需求是当用户将应用切换至后台时,通话中的另一方仍能看到该用户的摄像头视频。根据苹果官方文档,iOS 16及以上版本可通过AVCaptureSession对象的isMultitaskingCameraAccessSupported检查后,开启isMultitaskingCameraAccessEnabled来实现此功能。我已在Info.plist中启用多窗口功能,并编写了如下代码,但问题仍未解决。请问如何实现类似Zoom和WhatsApp的后台摄像头持续运行效果?
class AVCaptureSessionHelper { let captureSession = AVCaptureSession() func startCapturingSession() { captureSession.beginConfiguration() if #available(iOS 16.0, *) { if captureSession.isMultitaskingCameraAccessSupported { captureSession.isMultitaskingCameraAccessEnabled = true } } captureSession.commitConfiguration() DispatchQueue.global(qos: .background).async { self.captureSession.startRunning() } } func stopCapturing() { DispatchQueue.global(qos: .background).async { self.captureSession.stopRunning() } } }
解决方案
要实现后台摄像头持续运行,除了开启isMultitaskingCameraAccessEnabled,还需要完成以下关键配置和代码调整:
1. 添加后台模式权限
在Info.plist中添加以下后台模式,确保应用在后台能保持活跃并访问摄像头:
audio(音频后台模式):视频通话依赖音频,此权限是后台运行的基础voip(VoIP后台模式):让系统优先保持应用活跃,适用于通话类应用
对应的Info.plist键值对:
<key>UIBackgroundModes</key> <array> <string>audio</string> <string>voip</string> </array>
2. 调整AVCaptureSession配置顺序
必须先添加摄像头输入到会话,再启用多任务摄像头访问,否则配置不会生效。修改你的代码如下:
class AVCaptureSessionHelper { let captureSession = AVCaptureSession() private var videoInput: AVCaptureDeviceInput? func startCapturingSession() { captureSession.beginConfiguration() // 1. 添加前置摄像头输入 guard let cameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front) else { captureSession.commitConfiguration() return } do { videoInput = try AVCaptureDeviceInput(device: cameraDevice) if captureSession.canAddInput(videoInput!) { captureSession.addInput(videoInput!) } } catch { captureSession.commitConfiguration() return } // 2. 启用多任务摄像头访问(iOS 16+) if #available(iOS 16.0, *) { if captureSession.isMultitaskingCameraAccessSupported { captureSession.isMultitaskingCameraAccessEnabled = true } } captureSession.commitConfiguration() // 用userInitiated优先级队列启动会话,保证执行优先级 DispatchQueue.global(qos: .userInitiated).async { self.captureSession.startRunning() } } func stopCapturing() { DispatchQueue.global(qos: .userInitiated).async { self.captureSession.stopRunning() } } }
3. 确保会话对象被强引用
AVCaptureSessionHelper实例必须被全局对象或视图控制器强持有,避免被ARC自动释放。例如,在通话页面的ViewController中声明:
let captureHelper = AVCaptureSessionHelper()
4. 处理系统权限
确保已向用户申请摄像头和麦克风权限,且用户已授权:
// 申请摄像头权限 AVCaptureDevice.requestAccess(for: .video) { granted in if granted { // 权限通过后启动会话 } } // 申请麦克风权限(视频通话必须) AVCaptureDevice.requestAccess(for: .audio) { granted in // 处理音频权限结果 }
5. 避免会话在后台被终止
- 不要在
applicationDidEnterBackground中暂停AVCaptureSession,开启多任务访问后,会话可在后台持续运行 - 监控应用内存使用情况,避免因内存压力被系统强制终止
内容的提问来源于stack exchange,提问作者Daniel Vivek
相关产品推荐
相关产品推荐

