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

理解AVCaptureSession中时间对CMSampleBuffers的作用及同步方法

关于iOS相机预录10秒功能的音视频时序与缓冲管理方案

核心机制澄清

AVCaptureSession的synchronizationClock是音视频同步的核心——所有输出的CMSampleBuffer的时间戳都基于这个系统维护的时钟生成,音视频流的时间线天然对齐,不需要手动设置或替换这个时钟。你不用纠结如何修改捕获会话的时间尺度,依赖这个时钟的时间戳就能保证同步。

样本缓冲的时长控制与对应关系

视频缓冲(60fps单帧)

你可以通过配置AVCaptureVideoDataOutput的videoSettings强制输出60fps的单帧样本:

videoOutput.videoSettings = [
    kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA,
    AVVideoWidthKey as String: 1920,
    AVVideoHeightKey as String: 1080,
    AVVideoFrameRateKey as String: 60
]

此时每个视频CMSampleBuffer包含1帧,时长固定为1/60秒,可通过以下代码验证:

let duration = CMSampleBufferGetDuration(videoSampleBuffer)
let durationSeconds = CMTimeGetSeconds(duration) // 输出约0.016666秒

音频缓冲的适配

音频缓冲的时长由硬件采样率和输出缓冲区大小决定(比如48kHz采样率下,800样本的缓冲时长约为800/48000≈0.0167秒),无法强行设置为1/60秒。但你不需要追求音视频缓冲的数量一一对应,只要基于synchronizationClock的时间戳来对齐时间线即可。

预录10秒的缓冲管理方案

不要用简单数组存储所有缓冲(会导致内存暴涨),建议基于时间戳维护带过期清理的队列:

  1. 为音视频分别创建线程安全的队列(比如DispatchQueue保护的[CMSampleBuffer])
  2. 每次收到新样本时,先记录其presentationTimeStamp,然后过滤队列中所有时间戳早于当前时间戳 - 10秒的缓冲:
let currentTime = CMSampleBufferGetPresentationTimeStamp(newSample)
let tenSecondsAgo = CMTimeSubtract(currentTime, CMTimeMakeWithSeconds(10, preferredTimescale: 600))
// 清理视频队列
videoBufferQueue = videoBufferQueue.filter {
    CMSampleBufferGetPresentationTimeStamp($0) >= tenSecondsAgo
}
// 音频队列执行同样的清理逻辑
audioBufferQueue = audioBufferQueue.filter {
    CMSampleBufferGetPresentationTimeStamp($0) >= tenSecondsAgo
}
  1. 注意:存储CMSampleBuffer时需要调用CMSampleBufferMakeDataReady并保留引用,避免缓冲区被提前释放。

音视频写入AVAssetWriter的同步要点

  1. 启动AVAssetWriter时,确保使用与捕获会话一致的时间基准:
assetWriter.startWriting()
assetWriter.startSession(atSourceTime: CMSampleBufferGetPresentationTimeStamp(firstVideoSample))
  1. 分别将音视频队列中的样本写入对应的AVAssetWriterInput,不需要刻意匹配缓冲数量——只要所有样本的时间戳基于synchronizationClock,AVAssetWriter会自动处理音视频同步。

关键误解纠正

  • 不需要手动设置捕获会话的时间尺度或CMClock,系统会自动维护synchronizationClock保证音视频时间线对齐;
  • 音视频缓冲的时长不需要严格相等,时间戳才是同步的核心依据;
  • 预录功能更优的实现是用临时文件存储(而非内存队列),比如持续向AVAssetWriter写入临时文件,录制时截取最后10秒片段,避免内存压力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 02:45:18