直接回答
ImageInfo.getTimestamp 是附着在图像元数据上的时间戳,但 CameraX 文档说明其细节取决于提供图像的来源。ImageAnalysis.Analyzer 文档说图像时间戳以纳秒计且单调,并可在绑定到同一 camera instance 的 use case 之间比较。这是有边界的比较规则,不代表帧时间等于应用回调执行时间、推理完成时间或 UI 显示时间。 对 Camera2,CaptureResult.SENSOR_TIMESTAMP 表示传感器活动阵列第一行开始曝光的时间。CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE 指定该时间的来源;两项均从 API 21 起提供。REALTIME 表示 Camera2 文档定义的时间基准与 SystemClock.elapsedRealtimeNanos 相同。UNKNOWN 则只有单调递增属性,但起点未指定,不能一般化地与另一台相机或系统时钟比较。应把源类型作为时间戳身份的一部分,而不是可忽略的附加字段。 有效的同钟比较不只是两个递增数字。记录 CameraX 库版本、camera instance 或 camera ID、绑定的 use case、可取得的传感器时间源、时间戳数值及准确图像/采集身份。一次 Camera2 capture 的 SENSOR_TIMESTAMP 会出现在该次采集生成的所有图像缓冲中,且输出间相同。CameraX ImageInfo 时间戳与 Camera2 CaptureResult 只有在所选实现提供文档保证或经实测验证的关联时,才能当作同一采集;不能只因回调顺序接近就配对,输出可能延迟、丢弃、转换,或由 wrapper 提供。 采集时刻要与交付时刻分开。记录 ImageInfo.getTimestamp 为图像时间;如需衡量交付延迟,另用具名 SystemClock 字段记录回调入口。两者相减不自动等于相机处理延迟:时钟起点可能不同,回调会排队,传感器源也可能是 UNKNOWN。不要用附近的一次轮询校准 UNKNOWN,再报告一个可复用偏移去对齐 elapsedRealtimeNanos、boot time、音频或第二台相机。没有受支持共同时间源或采集身份关联时,跨域映射保持 unknown。 时间戳不代表滚动快门图像的所有像素同时曝光。Camera2 将 SENSOR_TIMESTAMP 定义为传感器阵列第一行开始曝光的时间,不同行可能在不同时间曝光。单一图像时间可以作为文档定义的帧锚点,但不是每个视觉事件的逐像素时间、保证的中点,也不是设备精度界限。若任务需要行级时间、滚动快门校正或传感器融合,应另行定义并引用对应采集元数据,不能把整帧默认为瞬时场景。 REALTIME 有用之处是 Android 文档说明它与 elapsedRealtimeNanos 共用时钟;这不保证相机曝光精度、回调延迟、音视频同步质量或任意设备上的测量精度。测试准确数据路径,只报告受支持的比较范围:CameraX 同 camera instance 的帧顺序,或 REALTIME 传感器时间戳与文档规定的同域值。UNKNOWN 应保留来源和 camera identity,只在该 stream 的文档范围内比较;不能把关系推广到另一台相机、系统启动时钟、音频路径或墙上时间。 安全的测试记录包括 camera ID/session、CameraX 版本和 use case、传感器时间源、ImageInfo 时间戳、可用的 Camera2 CaptureResult 身份与 SENSOR_TIMESTAMP、单独记录的回调到达时钟,以及必要时的方向/裁剪状态和关联方法。测试同相机多个 use case、重绑或切换相机、analyzer 延迟、缺失/partial capture result,以及设备实际报告的各类时间源。合成值只能验证比较代码,不能证明设备传感器时钟或 CameraX 到 Camera2 的采集身份映射。 本文不重复 AudioRecord.framePosition 到应用 read 分块的对齐方法。音频采集有不同的时间戳 API 和坐标原点。共同教训仅是时钟来源与事件身份必须明确;不能借用音频公式、假设 REALTIME 消除了所有同步误差,也不声称 Cove 当前读取 CameraX 分析时间戳。把时钟来源、采集身份、回调到达作为独立字段;不支持的元数据关系保持 unknown。
分析器回调晚于相机采集结果到达
相机功能分别记录 ImageProxy 帧和 Camera2 capture result。团队想把延迟的视觉结果关联回采集事件,并与应用事件时间比较;但尚未读取 SENSOR_INFO_TIMESTAMP_SOURCE,也未证明两个回调属于同一次采集。
决策
把 CameraX 图像时间、Camera2 传感器源/时间、采集身份和回调到达分别记录。只有文档支持的共同源和已验证的同次采集关联才能跨域比较。
预期结果
报告可保留同相机帧顺序或文档支持的 REALTIME 比较;不支持的跨源映射保持 unknown,不宣称逐像素时刻或设备精度。
需要收集的证据
只有将以下证据与同一模型文件和测试运行关联起来,结论才可复核:
- ANDROID-CAMERA-TIMESTAMP-SOURCE-2026-10:官方事实卡记录 Camera2 SENSOR_TIMESTAMP、UNKNOWN/REALTIME 和首行曝光语义;共享时钟不等于精度或 Cove 实现证明。
- ANDROID-CAMERAX-ANALYSIS-2026-01:CameraX Analysis 提供 ImageProxy 与时间戳上下文;同相机 use case 的可比范围仍依官方 API 文档。
- ANDROID-TIMEBASE-2026-10:单调系统时钟只在具备共同基准的边界内比较;不能把 UNKNOWN 传感器源硬贴到 elapsedRealtime。
发布结论只对所记录的配置和验收集有效;扩大适用范围需要更多记录。
实施流程
- 固定相机路径和时间戳 API. 记录 CameraX 版本、provider 实现(若已知)、camera ID/session、绑定的 use case、API 级别,以及时间来自 ImageInfo、Camera2 CaptureResult 还是两者。不要以回调到达时刻替代图像时间。
- 读取并保留传感器时钟来源. Camera2 场景在可用时查询 SENSOR_INFO_TIMESTAMP_SOURCE,并将 UNKNOWN/REALTIME 与每次比较一起保存。文档只为 REALTIME 规定与 elapsedRealtimeNanos 同域;UNKNOWN 起点不明,不得靠猜测校准其他系统。
- 先证明采集身份再合并记录. 只有使用文档保证的关联或经版本固定、受控观察验证的同帧关系,才将 CameraX ImageInfo 时间戳与 CaptureResult 配对。记录缺失/partial result 与丢帧;仅凭回调顺序不算帧身份。
- 将回调到达存入独立时钟字段. 需要衡量交付延迟时,用具名系统时钟记录回调入口;只有来源文档证明时钟域相同时才做比较。否则保留两个原始值并标为无法相减;队列延迟与时间源原点是不同未知量。
- 尊重曝光与滚动快门语义. 把 SENSOR_TIMESTAMP 解释为该次采集第一行开始曝光。不能称为整帧中点或逐像素时刻;若使用行时间元数据,应放入另有文档的 rolling-shutter 方法。
- 测试支持与未知来源行为. 测试同相机 use case、相机重绑/切换、延迟回调、缺失 capture result 和实际报告的各类时钟源。断言 UNKNOWN 不做跨设备或音频合并,REALTIME 也不生成精度承诺;合成时钟值只验证代码。
让每个阶段的状态都可观察。失败信息应指出阶段、模型、运行时和恢复动作,同时避免记录用户私密内容。
验收标准
- ImageInfo 时间戳、Camera2 SENSOR_TIMESTAMP 与回调到达作为独立事件保存,并关联可用的 camera/session identity 与时间源。
- UNKNOWN 时间戳不跨相机、elapsedRealtime/boot 时钟、音频或应用回调时钟比较,除非具体集成有文档支持的共同源;否则映射保持 unknown。
- REALTIME 仅在文档规定的共享时钟域内与 elapsedRealtimeNanos 比较;不推导曝光精度、回调延迟或同步质量。
- CameraX 到 Camera2 的合并必须有文档或版本/设备实测的采集身份;SENSOR_TIMESTAMP 描述首行曝光起点,不说成整帧同时曝光。
决策对照表
| 维度 | 选择或证据 | 解读方式 |
|---|---|---|
| ImageInfo 时间戳 | 图像来源提供的元数据时间 | CameraX 说明细节依来源而异,同一 camera instance 的 use case 可按文档比较;回调到达是另一个事件。 |
| Camera2 SENSOR_TIMESTAMP | 活动阵列首行开始曝光的时间 | 标记传感器采集锚点;滚动快门下并非每行使用同一曝光时刻。 |
| UNKNOWN 时间源 | 起点未指定的单调时间值 | 只保留文档支持的同相机范围;不推断它等于 elapsedRealtime、音频或其他相机时钟。 |
| REALTIME 时间源 | Camera2 文档规定与 elapsedRealtimeNanos 同域 | 允许比较时钟域,但不保证测量精度或音视频同步质量。 |
需要避免的失败模式
- 把 ImageInfo 时间戳当作 analyzer 回调到达时间、推理完成或 UI 显示时间。
- 未读取 SENSOR_INFO_TIMESTAMP_SOURCE,就假设单调时间戳等于 elapsedRealtimeNanos。
- 仅凭两个回调顺序相近,就认定 ImageInfo 与 CaptureResult 属于同一帧。
还要避免静默回退、版本未固定、缺少取消处理,以及把不同配置的结果混在一起下结论。失败运行也应与成功记录一并保存。
最小复现记录
| 层级 | 记录内容 |
|---|---|
| 设备 | 厂商、型号、芯片、内存档位、操作系统版本 |
| 软件 | 应用版本和 Git 提交号 |
| 模型 | 系列、变体、版本、格式、文件长度、摘要、量化方式 |
| 运行时 | 名称、版本、请求后端及实际后端证据 |
| 工作负载 | 样例版本、输入摘要、提示词摘要、输出策略 |
| 结果 | 完成、失败、取消、回退及保护隐私的诊断信息 |
发布检查表
- ☐ 主要搜索问题已回答,且没有未经支持的数字。
- ☐ 所有模型文件和运行时版本均已固定。
- ☐ 代表性任务和失败处理策略均有说明。
- ☐ 生命周期、取消、清理和回退均已测试。
- ☐ 用户内容与网络边界均有说明。
- ☐ 结论只适用于被记录的配置。
- ☐ 新增测试结果时链接到原始方法或证据。
来源与相关证据
- AndroidX CameraX ImageInfo API:来源定义的图像时间戳
- AndroidX CameraX ImageAnalysis.Analyzer API:同相机时间戳比较
- Android CameraCharacteristics API:SENSOR_INFO_TIMESTAMP_SOURCE
- Android CaptureResult API:SENSOR_TIMESTAMP
- Android CameraMetadata API:UNKNOWN 与 REALTIME 时间域
中文部署与排错专题见。奇连 AI 端侧专题。
常见问题
能否用 ImageInfo.getTimestamp 减去回调到达时间?
只有准确时间源和回调时钟被文档证明使用同一原点,且采集身份已建立时才可以。否则减法混合事件/时钟域;保留原值并把延迟标为 unknown。
Camera2 UNKNOWN 时间戳能否与音频或 elapsedRealtimeNanos 比较?
不要默认可以。UNKNOWN 起点未指定,Camera2 只支持其文档范围内的相机比较。音频、另一台相机、boot clock 和应用回调都应保持独立,除非精确集成提供有支持的关系。
REALTIME 是否能证明相机和音频精确同步?
不能。它只表示文档规定的时钟基准与 elapsedRealtimeNanos 相同;并不证明曝光精度、回调延迟、帧身份关联、滚动快门校正或同步误差界限。
SENSOR_TIMESTAMP 是整帧每个像素的时刻吗?
不是。Camera2 把它定义为首行开始曝光。滚动快门下不同的行可能有不同曝光时刻,应把该值作为文档定义的采集锚点,而不是整个场景同时成像的时间。