如何通过Camera2 API在Surface TextureView上叠加动态FPS与相机运行时长
实现结论
可以通过Camera2 API实现帧计数、FPS统计和运行时长的获取与叠加显示。
实现思路
- 运行时长统计:在相机CaptureSession初始化完成的回调中记录启动时间戳,每次刷新显示时用当前时间减去启动时间戳,格式化后即可得到相机运行时长。
- 帧计数与FPS统计:Camera2的
CaptureCallback.onCaptureCompleted回调每触发一次对应一帧捕获完成,在该回调中累加帧计数;固定时间间隔(比如1秒)统计该间隔内的帧数,通过帧数/时间间隔计算得到实时FPS。 - 叠加显示推荐直接在布局中把TextureView和半透明TextView层叠放置,TextView放在上层,计算完数据后直接更新TextView内容即可,无需额外做OpenGL绘制,开发成本更低。
核心代码片段
全局变量定义
// 相机启动时间戳 private long mCameraStartTimeMs = 0; // 累计帧计数 private long mTotalFrameCount = 0; // 上一次计算FPS的时间戳 private long mLastFpsCalcTimeMs = 0; // 上一次计算FPS时的帧计数 private long mLastFpsFrameCount = 0; // 当前实时FPS值 private float mCurrentFps = 0f; // 显示统计信息的TextView,布局中放在TextureView上层即可 private TextView mStatsInfoTv;
初始化启动时间
在CameraCaptureSession配置完成的回调中初始化统计基准值:
@Override public void onConfigured(@NonNull CameraCaptureSession session) { // 原有相机启动、预览请求发送逻辑不变 mCameraStartTimeMs = System.currentTimeMillis(); mTotalFrameCount = 0; mLastFpsCalcTimeMs = mCameraStartTimeMs; mLastFpsFrameCount = 0; }
帧统计与FPS计算
在CaptureRequest的捕获完成回调中统计帧数据:
@Override public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) { super.onCaptureCompleted(session, request, result); mTotalFrameCount++; long currentTimeMs = System.currentTimeMillis(); // 每1秒计算一次FPS if (currentTimeMs - mLastFpsCalcTimeMs >= 1000) { long frameDiff = mTotalFrameCount - mLastFpsFrameCount; long timeDiffMs = currentTimeMs - mLastFpsCalcTimeMs; mCurrentFps = (frameDiff * 1000f) / timeDiffMs; // 更新FPS统计基准 mLastFpsCalcTimeMs = currentTimeMs; mLastFpsFrameCount = mTotalFrameCount; // 更新界面显示 updateStatsUI(); } }
信息更新显示
private void updateStatsUI() { long runningTimeMs = System.currentTimeMillis() - mCameraStartTimeMs; int seconds = (int) (runningTimeMs / 1000); int minutes = seconds / 60; seconds = seconds % 60; String infoText = String.format("运行时长:%02d:%02d\n实时FPS:%.1f\n总帧数:%d", minutes, seconds, mCurrentFps, mTotalFrameCount); // 切到主线程更新UI runOnUiThread(() -> mStatsInfoTv.setText(infoText)); }
注意事项
onCaptureCompleted回调运行在子线程,更新UI必须切换到主线程,否则会触发线程异常。- 如果需要FPS显示更稳定,可以把统计间隔调整到2-3秒,减少瞬时帧率波动的影响。
- 不要在
onCaptureCompleted中添加耗时操作,否则会降低实际帧率,也会影响统计结果的准确性。
内容的提问来源于stack exchange,提问作者Prasad Reddy
相关产品推荐
相关产品推荐

