From de593c8e3f2d97ab4dae6384d72498b81466ddb7 Mon Sep 17 00:00:00 2001 From: GuoQing Liu <842607283@qq.com> Date: Tue, 24 Mar 2026 21:40:11 +0800 Subject: [PATCH] docs: add shm calulator (#22103) * docs: add shm calulator * feat: update shm calculator tips && style --- docs/docs/frigate/installation.md | 17 +- docs/src/components/ShmCalculator/index.jsx | 201 ++++++++++++++++++ .../ShmCalculator/styles.module.css | 131 ++++++++++++ 3 files changed, 335 insertions(+), 14 deletions(-) create mode 100644 docs/src/components/ShmCalculator/index.jsx create mode 100644 docs/src/components/ShmCalculator/styles.module.css diff --git a/docs/docs/frigate/installation.md b/docs/docs/frigate/installation.md index be147c4ad..a115ecf97 100644 --- a/docs/docs/frigate/installation.md +++ b/docs/docs/frigate/installation.md @@ -3,6 +3,8 @@ id: installation title: Installation --- +import ShmCalculator from '@site/src/components/ShmCalculator' + Frigate is a Docker container that can be run on any Docker host including as a [Home Assistant App](https://www.home-assistant.io/apps/). Note that the Home Assistant App is **not** the same thing as the integration. The [integration](/integrations/home-assistant) is required to integrate Frigate into Home Assistant, whether you are running Frigate as a standalone Docker container or as a Home Assistant App. :::tip @@ -77,20 +79,7 @@ The default shm size of **128MB** is fine for setups with **2 cameras** detectin The Frigate container also stores logs in shm, which can take up to **40MB**, so make sure to take this into account in your math as well. -You can calculate the **minimum** shm size for each camera with the following formula using the resolution specified for detect: - -```console -# Template for one camera without logs, replace and -$ python -c 'print("{:.2f}MB".format(( * * 1.5 * 20 + 270480) / 1048576))' - -# Example for 1280x720, including logs -$ python -c 'print("{:.2f}MB".format((1280 * 720 * 1.5 * 20 + 270480) / 1048576 + 40))' -66.63MB - -# Example for eight cameras detecting at 1280x720, including logs -$ python -c 'print("{:.2f}MB".format(((1280 * 720 * 1.5 * 20 + 270480) / 1048576) * 8 + 40))' -253MB -``` + The shm size cannot be set per container for Home Assistant Apps. However, this is probably not required since by default Home Assistant Supervisor allocates `/dev/shm` with half the size of your total memory. If your machine has 8GB of memory, chances are that Frigate will have access to up to 4GB without any additional configuration. diff --git a/docs/src/components/ShmCalculator/index.jsx b/docs/src/components/ShmCalculator/index.jsx new file mode 100644 index 000000000..b7e13ed79 --- /dev/null +++ b/docs/src/components/ShmCalculator/index.jsx @@ -0,0 +1,201 @@ +import React, { useState, useEffect } from "react"; +import Admonition from "@theme/Admonition"; +import styles from "./styles.module.css"; + +const ShmCalculator = () => { + const [width, setWidth] = useState(1280); + const [height, setHeight] = useState(720); + const [cameraCount, setCameraCount] = useState(1); + const [result, setResult] = useState("26.32MB"); + const [singleCameraShm, setSingleCameraShm] = useState("26.32MB"); + const [totalShm, setTotalShm] = useState("26.32MB"); + + const calculate = () => { + if (!width || !height || !cameraCount) { + setResult("Please enter valid values"); + setSingleCameraShm("-"); + setTotalShm("-"); + return; + } + + // Single camera base SHM calculation (excluding logs) + // Formula: (width * height * 1.5 * 20 + 270480) / 1048576 + const singleCameraBase = + (width * height * 1.5 * 20 + 270480) / 1048576; + setSingleCameraShm(`${singleCameraBase.toFixed(2)}mb`); + + // Total SHM calculation (multiple cameras, including logs) + const totalBase = singleCameraBase * cameraCount; + const finalResult = totalBase + 40; // Default includes logs +40mb + + setTotalShm(`${(totalBase + 40).toFixed(2)}mb`); + + // Format result + if (finalResult < 1) { + setResult(`${(finalResult * 1024).toFixed(2)}kb`); + } else if (finalResult >= 1024) { + setResult(`${(finalResult / 1024).toFixed(2)}gb`); + } else { + setResult(`${finalResult.toFixed(2)}mb`); + } + }; + + const formatWithUnit = (value) => { + const match = value.match(/^([\d.]+)(mb|kb|gb)$/i); + if (match) { + return ( + <> + {match[1]}{match[2]} + + ); + } + return value; + }; + + const applyPreset = (w, h, count) => { + setWidth(w); + setHeight(h); + setCameraCount(count); + calculate(); + }; + + useEffect(() => { + calculate(); + }, [width, height, cameraCount]); + + return ( +
+
+

SHM Calculator

+

+ Calculate required shared memory (SHM) based on camera resolution and + count +

+ + + The resolution below is the detect stream resolution, + not the record stream resolution. SHM size is + determined by the detect resolution used for object detection.{" "} + + Learn more about choosing a detect resolution. + + + + {width * height > 1280 * 720 && ( + + Using a detect resolution higher than 720p is not recommended. + Higher resolutions do not improve object detection accuracy and will + consume significantly more resources. + + )} + +
+
+
+ + setWidth(Number(e.target.value))} + /> +
+
+ +
+
+ + setHeight(Number(e.target.value))} + /> +
+
+
+ +
+ + setCameraCount(Number(e.target.value))} + /> +
+ +
+

Calculation Result

+
+ {formatWithUnit(result)} +
+
+

+ Single Camera: {formatWithUnit(singleCameraShm)} +

+

+ Formula: (width × height × 1.5 × 20 + 270480) ÷ + 1048576 +

+ {cameraCount > 1 && ( +

+ Total ({cameraCount} cameras): {formatWithUnit(totalShm)} +

+ )} +

+ With Logs: + 40mb +

+
+
+ +
+

Common Presets

+
+ + + + +
+
+
+
+ ); +}; + +export default ShmCalculator; diff --git a/docs/src/components/ShmCalculator/styles.module.css b/docs/src/components/ShmCalculator/styles.module.css new file mode 100644 index 000000000..5b48f4942 --- /dev/null +++ b/docs/src/components/ShmCalculator/styles.module.css @@ -0,0 +1,131 @@ +.shmCalculator { + margin: 2rem 0; + max-width: 600px; +} + +.card { + background: var(--ifm-background-surface-color); + border: 1px solid var(--ifm-border-color); + border-radius: 12px; + padding: 2rem; + box-shadow: var(--ifm-global-shadow-lw); +} + +[data-theme='light'] .card { + background: var(--ifm-color-emphasis-100); + border: 1px solid var(--ifm-color-emphasis-300); +} + +.title { + margin: 0 0 0.5rem 0; + font-size: 1.5rem; + color: var(--ifm-font-color-base); + font-weight: var(--ifm-font-weight-semibold); +} + +.description { + margin: 0 0 1.5rem 0; + color: var(--ifm-font-color-secondary); + font-size: 0.9rem; +} + +.formGroup { + margin-bottom: 1rem; +} + +.label { + display: block; + margin-bottom: 0.25rem; + color: var(--ifm-font-color-base); + font-weight: var(--ifm-font-weight-semibold); + font-size: 0.9rem; +} + +.input { + width: 100%; + padding: 0.5rem 0.75rem; + border: 1px solid var(--ifm-border-color); + border-radius: 6px; + background: var(--ifm-background-color); + color: var(--ifm-font-color-base); + font-size: 0.95rem; + transition: border-color 0.2s, box-shadow 0.2s; +} + +[data-theme='light'] .input { + background: #fff; + border: 1px solid #d0d7de; +} + +.input:focus { + outline: none; + border-color: var(--ifm-color-primary); + box-shadow: 0 0 0 3px var(--ifm-color-primary-lightest); +} + +.resultSection { + margin-top: 1rem; + padding: 1.5rem; + background: var(--ifm-background-color); + border-radius: 8px; + border: 1px solid var(--ifm-border-color); +} + +[data-theme='light'] .resultSection { + background: #f6f8fa; + border: 1px solid #d0d7de; +} + +.resultSection h4 { + margin: 0 0 1rem 0; + color: var(--ifm-font-color-base); + font-weight: var(--ifm-font-weight-semibold); +} + +.resultValue { + text-align: center; + padding: 1rem; + background: var(--ifm-color-primary); + border-radius: 6px; + margin-bottom: 1rem; +} + +.resultNumber { + font-size: 2rem; + font-weight: var(--ifm-font-weight-bold); + color: #fff; +} + +.formulaDisplay { + font-size: 0.85rem; + color: var(--ifm-font-color-secondary); + line-height: 1.6; +} + +.formulaDisplay p { + margin: 0.25rem 0; +} + +.formulaDisplay strong { + color: var(--ifm-font-color-base); +} + +.unit { + text-transform: uppercase; +} + +.presets { + margin-top: 1.5rem; +} + +.presets h4 { + margin: 0 0 0.75rem 0; + color: var(--ifm-font-color-base); + font-weight: var(--ifm-font-weight-semibold); +} + +.presetButtons { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; +}