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

如何通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 17:09:00