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

如何基于现有视频指定CMTimeRange创建仅含轨迹帧的新AVAsset视频

实现轨迹帧过滤导出的方案

你可以根据你的使用场景选择以下两种实现方式:

方案1:离线处理本地已有视频(推荐,稳定性更高)

这种方式适合处理已经录制完成的本地视频文件,实现逻辑如下:

  • 初始化AVAssetReader读取原视频的帧数据,同时初始化AVAssetWriter配置和原视频一致的输出参数(分辨率、编码格式、帧率等),减少不必要的转码损耗。
  • 按顺序读取原视频的每一个CMSampleBuffer,拿到帧对应的CMTime,送入VNDetectTrajectoriesRequest执行轨迹检测,检测逻辑可以完全复用你现有回调中的实现。
  • 每次检测拿到结果后,收集所有VNDetectedTrajectoryObservation返回的CMTimeRange,将重叠或连续的时间范围提前合并。
  • 二次遍历原视频的所有帧(或者在首次检测时同步判断),如果当前帧的时间落在已合并的有效时间范围内,就将该帧原封不动写入AVAssetWriter,写入时保留帧的原始时间戳,避免音画不同步。
  • 如果原视频带有音轨,需要同步筛选出落在有效时间范围内的音频帧写入AVAssetWriter,或者在视频轨道处理完成后拼接对应时间段的音频。

如果不需要自定义编码逻辑,你可以用更简单的实现替代手动帧读写:

完成全视频的轨迹检测、合并完所有有效时间范围后,创建AVMutableComposition,仅将原视频中对应有效时间段的视频、音频轨道插入到合成器中,最后直接用AVAssetExportSession导出合成资源即可,代码量更少,系统兼容性更好。


方案2:实时拍摄时边检测边导出

这种方式适合在摄像头录制的同时直接生成过滤后的视频,可直接复用你现有回调逻辑:

  • 提前初始化好AVAssetWriter以及对应视频、音频写入输入。
  • 在cameraViewController(_:didReceiveBuffer:orientation:)回调中,当检测到detectTrajectoryRequest.results不为空时,直接将当前回调收到的CMSampleBuffer写入AVAssetWriter即可。
  • 注意将写入逻辑放到和轨迹检测同个串行队列执行,避免检测耗时高于帧间隔导致的时间戳错乱、丢帧问题。

关键实现提示

你可以在现有的processTrajectoryObservations方法中新增时间范围收集逻辑,不需要改动原有检测流程:

// 全局维护的已合并有效时间范围集合
var mergedValidTimeRanges: [CMTimeRange] = []

func processTrajectoryObservations(_ controller: CameraViewController, _ results: [VNObservation]) {
    let trajectoryRanges = results.compactMap { $0 as? VNDetectedTrajectoryObservation }.map(\.timeRange)
    // 合并新的有效时间范围到全局集合,可自行实现CMTimeRange合并逻辑
    mergedValidTimeRanges = mergeOverlappingRanges(mergedValidTimeRanges + trajectoryRanges)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 18:36:04