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

如何让AVCaptureVideoDataOutputSampleBufferDelegate每隔1秒执行一次方法?

实现AVCaptureVideoDataOutputDelegate每隔1秒执行一次操作

首先要明确:绝对不要在captureOutput方法内直接使用sleep或等待逻辑,这会阻塞AVCaptureSession的采集队列,导致视频卡顿、丢帧,甚至会话崩溃。

正确的做法是通过时间戳过滤,只在满足1秒间隔时执行目标操作,具体实现如下:

方案1:使用Date记录执行时间

在你的类中添加一个属性存储上次执行操作的时间:

private var lastExecutionTime: Date = Date.distantPast

修改captureOutput方法,每次回调时检查时间间隔:

func captureOutput(_ output: AVCaptureOutput,
                   didOutput sampleBuffer: CMSampleBuffer,
                   from connection: AVCaptureConnection) {
    let currentTime = Date()
    // 判断与上次执行的时间差是否达到1秒
    guard currentTime.timeIntervalSince(lastExecutionTime) >= 1.0 else {
        return
    }
    
    // 更新时间戳,避免重复触发
    lastExecutionTime = currentTime
    
    // 在这里执行你的业务操作
    processSampleBuffer(sampleBuffer)
}

// 示例业务处理方法
private func processSampleBuffer(_ buffer: CMSampleBuffer) {
    // 比如提取图像帧、进行图像分析等操作
}

方案2:使用高精度媒体时间(推荐)

如果需要更精准的时间控制,可以使用CACurrentMediaTime(),它基于系统媒体时钟,精度比Date更高:

private var lastExecutionTime: CFTimeInterval = 0.0

func captureOutput(_ output: AVCaptureOutput,
                   didOutput sampleBuffer: CMSampleBuffer,
                   from connection: AVCaptureConnection) {
    let currentTime = CACurrentMediaTime()
    guard currentTime - lastExecutionTime >= 1.0 else {
        return
    }
    
    lastExecutionTime = currentTime
    processSampleBuffer(sampleBuffer)
}

补充说明

  • 这两种方案都不会干扰AVCaptureSession的正常采集流程,只是过滤掉不需要处理的帧,保证采集效率。
  • 如果你的操作比较耗时,建议将业务逻辑放到后台队列执行,避免阻塞采集队列:
private func processSampleBuffer(_ buffer: CMSampleBuffer) {
    DispatchQueue.global().async {
        // 耗时操作放在这里
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 10:05:35