如何转换CameraX ImageInfo时间戳为currentTimeMillis格式
问题本质
imageProxy.getImageInfo().getTimestamp()返回的时间戳默认以**设备开机后经过的时长(含深度睡眠)**为基准,单位是纳秒,和System.currentTimeMillis()返回的UTC墙钟时间基准完全不同,二者数值没有直接可比性,你日志里17万亿级别的数值就是纳秒级的开机时长,换算后约为开机4.7小时,和当时的系统时间差值是固定偏移量。
转换方案
推荐方案(适配CameraX 1.0及以上正式版)
直接通过ImageInfo自带的时间戳来源标识判断基准,转换误差最小:
// 在analyze(ImageProxy imageProxy)回调内执行 val imgInfo = imageProxy.imageInfo val frameUtcMs = when (imgInfo.timestampSource) { // 时间戳本身就是UTC基准,纳秒转毫秒即可 ImageInfo.TIMESTAMP_SOURCE_REALTIME -> imgInfo.timestamp / 1_000_000 // 时间戳为开机时长基准,计算偏移后转换 ImageInfo.TIMESTAMP_SOURCE_UNKNOWN -> { val offset = System.currentTimeMillis() - SystemClock.elapsedRealtime() (imgInfo.timestamp / 1_000_000) + offset } // 兜底取回调触发时的系统时间 else -> System.currentTimeMillis() }
注意:时间偏移不要在应用启动时提前计算,每次处理帧时实时计算即可,避免设备运行中网络校时修改系统墙钟导致的偏移误差。
兼容方案(适配你当前使用的alpha版本)
你项目中使用的1.1.0-alpha09系列版本尚未开放timestampSource接口,该版本下CameraX返回的帧时间戳固定来自相机硬件的传感器时间戳,基准和SystemClock.elapsedRealtimeNanos()完全一致,直接用偏移转换即可:
// alpha版本专用转换逻辑 val sensorTsNs = imageProxy.imageInfo.timestamp val currentElapsedMs = SystemClock.elapsedRealtime() val currentWallMs = System.currentTimeMillis() val timeOffset = currentWallMs - currentElapsedMs val frameWallTsMs = (sensorTsNs / 1_000_000) + timeOffset
避坑说明
- 不要用
System.nanoTime()计算偏移,该值不统计设备深度睡眠时长,和相机传感器时间戳基准不匹配,会出现固定偏差 - 该转换方式的误差通常在10ms以内,完全满足帧时间对齐、帧信息打标、录像时间同步等常规场景需求
- 你提供的日志中,帧时间戳17268452439387纳秒换算为开机时长毫秒值为17268452ms,叠加当时的系统时间偏移后,和你打印的
System.currentTimeMillis()返回值完全匹配。
内容的提问来源于stack exchange,提问作者normidar
相关产品推荐
相关产品推荐

