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

iOS开发中AVCaptureVideoDataOutput的captureOutput代理方法未被调用问题求助

排查AVCaptureVideoDataOutput的captureOutput不触发问题

先直接回答你的核心疑问:不需要必须设置预览层才能捕获视频输出,很多无预览的相机采集场景(比如后台帧处理、仅做图像分析)都能正常触发captureOutput回调,所以你的问题肯定出在其他配置环节。结合你的代码,我整理了几个关键排查点:

1. 最关键的遗漏:没有启动AVCaptureSession

你的startStreamingCamera方法里完成了输入输出的添加、代理设置,但从未调用captureSession.startRunning()!AVCaptureSession必须启动才会开始采集数据,这是最常见的低级错误。

修改你的代码,在配置完所有输入输出后启动会话:

do {
    let captureDeviceInput = try AVCaptureDeviceInput(device: inputCam!)
    let captureDeviceOutput = AVCaptureVideoDataOutput()
    guard self.captureSession.canAddInput(captureDeviceInput), self.captureSession.canAddOutput(captureDeviceOutput) else {
        return
    }
    self.captureSession.addInput(captureDeviceInput)
    self.captureSession.addOutput(captureDeviceOutput)
    captureDeviceOutput.setSampleBufferDelegate(self, queue: .global())
    
    // 新增:启动采集会话
    self.captureSession.startRunning()
} catch {
    print("配置相机输入输出失败:\(error)") // 建议添加错误日志,方便排查
}

2. 检查CameraPlugin实例的生命周期

看你的调用代码:

guard let videoCaptureDevice = AVCaptureDevice.default(for: AVMediaType.video) else { return }
let camPlugin = CameraPlugin()
camPlugin.startStreamingCamera(cameraId: nil, camera: videoCaptureDevice, listener: self)

这里的camPlugin是局部变量,如果这段代码是在某个方法(比如viewDidLoad)里执行的,方法执行完毕后camPlugin会被ARC销毁,而AVCaptureOutput的代理是弱引用,实例被销毁后自然不会触发回调。

解决方法:把camPlugin保存为当前类的属性,比如:

class YourViewController: UIViewController, VideoSampleListener {
    private var camPlugin: CameraPlugin? // 保存为属性
    
    override func viewDidLoad() {
        super.viewDidLoad()
        guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else { return }
        camPlugin = CameraPlugin()
        camPlugin?.startStreamingCamera(cameraId: nil, camera: videoCaptureDevice, listener: self)
    }
}

3. 确保视频连接处于启用状态

有时候AVCaptureConnection会默认禁用(比如某些设备的特定格式),可以在添加输出后手动启用视频连接:

self.captureSession.addOutput(captureDeviceOutput)
// 新增:启用视频连接
if let videoConnection = captureDeviceOutput.connection(with: .video) {
    videoConnection.isEnabled = true
}
captureDeviceOutput.setSampleBufferDelegate(self, queue: .global())

4. 配置合适的会话预设

你的代码没有设置captureSession.sessionPreset,默认的预设可能和设备支持的格式不兼容,导致无法输出帧数据。建议在添加输入前设置合适的预设,比如:

// 在添加输入前设置
self.captureSession.sessionPreset = .high // 或者根据需求选其他预设,比如 .medium/.hd1920x1080

5. 验证队列的有效性

你用了.global()队列作为代理队列,这本身没问题,但如果是并行队列,要注意videoSampleListener?.receivedVideoSample的线程安全性(比如更新UI必须回到主线程)。如果担心队列问题,可以改用串行队列:

let captureQueue = DispatchQueue(label: "com.yourapp.camera.capture")
captureDeviceOutput.setSampleBufferDelegate(self, queue: captureQueue)

额外建议:添加错误日志

你的catch块是空的,建议打印错误信息,方便排查输入输出添加失败的情况:

catch {
    print("相机配置错误:\(error.localizedDescription)")
}

按照以上步骤排查,应该能解决captureOutput不触发的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 23:09:06