iOS摄像头采集会话代码在iOS正常但Catalyst环境崩溃
iOS视频会话代码在Catalyst环境崩溃的解决方案
问题描述
以下用于配置AVCaptureSession视频输入输出的代码在iOS平台运行完全正常:
let videoOutput = AVCaptureVideoDataOutput() guard let cameraDevice = device.device, let captureDeviceInput = try? AVCaptureDeviceInput(device: cameraDevice), self.canAddInput(captureDeviceInput), self.canAddOutput(videoOutput) else { log("FrameExtractor error: could not setup input or output.") return } self.addInput(captureDeviceInput) videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "sample buffer")) self.addOutput(videoOutput) guard let connection = videoOutput.connection(with: CAMERA_FEED_MEDIA_TYPE), connection.isVideoOrientationSupported, connection.isVideoMirroringSupported else { log("FrameExtractor: configureSession: Cannot establish connection") return } if let videoOrientation = getCameraOrientation(device: device) { connection.videoOrientation = videoOrientation } // Mirroring the front camera normalizes the display output for iPad's front camera connection.isVideoMirrored = position == .front
但在Catalyst环境中运行时,执行self.addOutput(videoOutput)会持续崩溃,报错信息翻译如下:
应用因未捕获的异常
NSInternalInconsistencyException终止,原因:无效参数,不满足条件:index>=0 && index<[_currentItems count]
问题原因与修复方案
- 核心原因:Catalyst环境下AVCaptureSession的配置逻辑与纯iOS存在差异,默认配置兼容性不足,且会话状态管理、输入输出添加顺序的要求更严格。
- 修复步骤:
- 提前设置视频输出格式:Catalyst对视频像素格式的兼容性要求更高,添加输出前显式指定兼容格式:
let videoSettings: [String: Any] = [ kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA ] videoOutput.videoSettings = videoSettings - 开启丢弃迟滞帧:避免Catalyst环境下帧队列溢出引发异常:
videoOutput.alwaysDiscardsLateVideoFrames = true - 调整输入输出添加顺序:先添加输出,再添加输入(部分Catalyst版本存在顺序依赖问题):
self.addOutput(videoOutput) self.addInput(captureDeviceInput) - 确保会话处于停止状态:添加输入输出前先停止会话,避免状态冲突:
self.stopRunning()
- 提前设置视频输出格式:Catalyst对视频像素格式的兼容性要求更高,添加输出前显式指定兼容格式:
修复后完整代码示例
let videoOutput = AVCaptureVideoDataOutput() // 配置视频输出参数 let videoSettings: [String: Any] = [ kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA ] videoOutput.videoSettings = videoSettings videoOutput.alwaysDiscardsLateVideoFrames = true guard let cameraDevice = device.device, let captureDeviceInput = try? AVCaptureDeviceInput(device: cameraDevice), self.canAddInput(captureDeviceInput), self.canAddOutput(videoOutput) else { log("FrameExtractor error: could not setup input or output.") return } // 确保会话处于停止状态 self.stopRunning() // 先添加输出,再添加输入 self.addOutput(videoOutput) self.addInput(captureDeviceInput) videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "sample buffer")) guard let connection = videoOutput.connection(with: CAMERA_FEED_MEDIA_TYPE), connection.isVideoOrientationSupported, connection.isVideoMirroringSupported else { log("FrameExtractor: configureSession: Cannot establish connection") return } if let videoOrientation = getCameraOrientation(device: device) { connection.videoOrientation = videoOrientation } connection.isVideoMirrored = position == .front // 按需重新启动会话 self.startRunning()
内容的提问来源于stack exchange,提问作者narner
相关产品推荐
相关产品推荐

