diff --git a/web/public/locales/en/views/system.json b/web/public/locales/en/views/system.json index faaff31c9..460a1d337 100644 --- a/web/public/locales/en/views/system.json +++ b/web/public/locales/en/views/system.json @@ -135,7 +135,11 @@ }, "shm": { "title": "SHM (shared memory) allocation", - "warning": "The current SHM size of {{total}}MB is too small. Increase it to at least {{min_shm}}MB." + "warning": "The current SHM size of {{total}}MB is too small. Increase it to at least {{min_shm}}MB.", + "frameLifetime": { + "title": "Frame lifetime", + "description": "Each camera has {{frames}} frame slots in shared memory. At the fastest camera's frame rate, each frame is available for approximately {{lifetime}}s before being overwritten." + } }, "cameraStorage": { "title": "Camera Storage", diff --git a/web/src/types/stats.ts b/web/src/types/stats.ts index 8b22849be..1046e0b47 100644 --- a/web/src/types/stats.ts +++ b/web/src/types/stats.ts @@ -86,6 +86,7 @@ export type StorageStats = { used: number; mount_type: string; min_shm?: number; + shm_frame_count?: number; }; export type PotentialProblem = { diff --git a/web/src/views/system/StorageMetrics.tsx b/web/src/views/system/StorageMetrics.tsx index 2c222d6c3..d36200849 100644 --- a/web/src/views/system/StorageMetrics.tsx +++ b/web/src/views/system/StorageMetrics.tsx @@ -89,6 +89,35 @@ export default function StorageMetrics({ timezone, ); + const shmFrameLifetime = useMemo(() => { + if (!stats || !config) { + return undefined; + } + + const shmFrameCount = stats.service.storage["/dev/shm"]?.shm_frame_count; + + if (!shmFrameCount || shmFrameCount <= 0) { + return undefined; + } + + let maxCameraFps = 0; + + for (const [name, camStats] of Object.entries(stats.cameras)) { + if (config.cameras[name]?.enabled && camStats.camera_fps > 0) { + maxCameraFps = Math.max(maxCameraFps, camStats.camera_fps); + } + } + + if (maxCameraFps === 0) { + return undefined; + } + + return { + frames: shmFrameCount, + lifetime: Math.round((shmFrameCount / maxCameraFps) * 10) / 10, + }; + }, [stats, config]); + if (!cameraStorage || !stats || !totalStorage || !config) { return; } @@ -148,43 +177,68 @@ export default function StorageMetrics({