mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-10-06 23:02:49 +03:00
Refactor model scene definitions (#24508)
CI / AMD64 Build (push) Canceled after 0s
CI / AMD64 Smoke Test (push) Canceled after 0s
CI / ARM Build (push) Canceled after 0s
CI / Jetson Jetpack 6 (push) Canceled after 0s
CI / AMD64 Extra Build (push) Canceled after 0s
CI / ARM Extra Build (push) Canceled after 0s
CI / Synaptics Build (push) Canceled after 0s
CI / Assemble and push default build (push) Canceled after 0s
CI / AMD64 Build (push) Canceled after 0s
CI / AMD64 Smoke Test (push) Canceled after 0s
CI / ARM Build (push) Canceled after 0s
CI / Jetson Jetpack 6 (push) Canceled after 0s
CI / AMD64 Extra Build (push) Canceled after 0s
CI / ARM Extra Build (push) Canceled after 0s
CI / Synaptics Build (push) Canceled after 0s
CI / Assemble and push default build (push) Canceled after 0s
* Refactor model scene definitions * Cleanup * Validate model paths in the UI * Handle form validation
This commit is contained in:
@@ -10,6 +10,7 @@ import type { FrigateConfig } from "@/types/frigateConfig";
|
||||
import type { HealthProblem } from "@/types/health";
|
||||
import { getSectionConfig } from "@/utils/configUtil";
|
||||
import { activeCameras } from "@/utils/health";
|
||||
import { getSceneLabel } from "@/utils/modelUtil";
|
||||
import { resolveMessageKey } from "@/utils/runtimeOverrides";
|
||||
|
||||
function healthMessages(
|
||||
@@ -119,10 +120,7 @@ export function evaluateConfigHealth(
|
||||
section === "models" && Array.isArray(sectionData)
|
||||
? sectionData.map((model, index) => ({
|
||||
formData: model as ConfigSectionData,
|
||||
scope: t(
|
||||
`detectionModels.scenes.${(model as { scene?: string }).scene || "all"}`,
|
||||
{ ns: "views/settings" },
|
||||
),
|
||||
scope: getSceneLabel(t, (model as { scene?: string }).scene),
|
||||
idSuffix: `model${index}`,
|
||||
}))
|
||||
: [
|
||||
|
||||
@@ -11,6 +11,7 @@ import type {
|
||||
import type { EmbeddingsStats, FrigateStats, GpuVendor } from "@/types/stats";
|
||||
import { EmbeddingThreshold, InferenceThreshold } from "@/types/graph";
|
||||
import { summarizeDevices } from "@/utils/detectionHardware";
|
||||
import { getSceneLabel } from "@/utils/modelUtil";
|
||||
import { isReplayCamera } from "@/utils/cameraUtil";
|
||||
import { resolveCameraName } from "@/hooks/use-camera-friendly-name";
|
||||
|
||||
@@ -142,9 +143,7 @@ export function detectionRows({
|
||||
const modelRunners = names.slice(cursor, cursor + model.devices.length);
|
||||
cursor += model.devices.length;
|
||||
|
||||
const label = t(`detectionModels.scenes.${model.scene || "all"}`, {
|
||||
ns: "views/settings",
|
||||
});
|
||||
const label = getSceneLabel(t, model.scene);
|
||||
const id = `detection:${index}`;
|
||||
const detail = probeFailed
|
||||
? t("health.hardware.probeUnavailable", {
|
||||
|
||||
@@ -1,10 +1,49 @@
|
||||
import type { TFunction } from "i18next";
|
||||
import type { HiddenFieldContext } from "@/types/configForm";
|
||||
import { DetectionModelConfig, FrigateConfig } from "@/types/frigateConfig";
|
||||
|
||||
/** The scene of the model used by cameras that don't name one. */
|
||||
export const DEFAULT_SCENE = "default";
|
||||
|
||||
/** Display name for a scene; custom scenes are shown as the user named them. */
|
||||
export function getSceneLabel(t: TFunction, scene: string | undefined): string {
|
||||
if (!scene || scene === DEFAULT_SCENE) {
|
||||
return t("detectionModels.scenes.default", { ns: "views/settings" });
|
||||
}
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
/**
|
||||
* The scenes a detect section can choose from: those of the configured models,
|
||||
* default first when a default model exists, plus the saved scene when no model
|
||||
* uses it, so it can still be seen and changed.
|
||||
*/
|
||||
export function getSceneChoices(
|
||||
ctx: Pick<HiddenFieldContext, "fullConfig" | "fullCameraConfig" | "level">,
|
||||
): string[] {
|
||||
const scenes = [
|
||||
...new Set(
|
||||
ctx.fullConfig.models?.map((model) => model.scene || DEFAULT_SCENE),
|
||||
),
|
||||
].sort((a, b) => Number(b === DEFAULT_SCENE) - Number(a === DEFAULT_SCENE));
|
||||
const saved =
|
||||
(ctx.level !== "global"
|
||||
? ctx.fullCameraConfig?.detect?.scene
|
||||
: undefined) ?? ctx.fullConfig.detect?.scene;
|
||||
|
||||
if (saved && !scenes.includes(saved)) {
|
||||
scenes.push(saved);
|
||||
}
|
||||
|
||||
return scenes;
|
||||
}
|
||||
|
||||
/**
|
||||
* The model a camera runs on, matched by the camera's detect scene.
|
||||
*
|
||||
* Falls back to the model for every scene, then to the only configured model,
|
||||
* which is what the backend does when a camera does not name a scene.
|
||||
* Falls back to the default model, then to the only configured model, which
|
||||
* is what the backend does when a camera does not name a scene.
|
||||
*/
|
||||
export function getModelForCamera(
|
||||
config?: FrigateConfig,
|
||||
@@ -26,7 +65,7 @@ export function getModelForCamera(
|
||||
}
|
||||
}
|
||||
|
||||
return models.find((model) => model.scene == "all") ?? models[0];
|
||||
return models.find((model) => model.scene == DEFAULT_SCENE) ?? models[0];
|
||||
}
|
||||
|
||||
/** The model used when the question is not about a specific camera. */
|
||||
|
||||
Reference in New Issue
Block a user