mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-06 12:01:14 +03:00
add defaults
This commit is contained in:
parent
f6350b421e
commit
f63e4c5452
@ -1173,10 +1173,11 @@
|
|||||||
"noModelSelected": "Select a Frigate+ model"
|
"noModelSelected": "Select a Frigate+ model"
|
||||||
},
|
},
|
||||||
"toast": {
|
"toast": {
|
||||||
"saveSuccess": "Settings saved — restart Frigate to apply",
|
"saveSuccess": "Detectors and model settings saved. Restart Frigate to apply changes.",
|
||||||
"saveError": "Failed to save detector and model settings"
|
"saveError": "Failed to save detector and model settings"
|
||||||
},
|
},
|
||||||
"unsavedChanges": "Unsaved detector and model changes"
|
"unsavedChanges": "Unsaved detector and model changes",
|
||||||
|
"restartRequired": "Restart required (detector or model changed)"
|
||||||
},
|
},
|
||||||
"triggers": {
|
"triggers": {
|
||||||
"documentTitle": "Triggers",
|
"documentTitle": "Triggers",
|
||||||
|
|||||||
@ -1,4 +1,11 @@
|
|||||||
import { useCallback, useContext, useEffect, useMemo, useState } from "react";
|
import {
|
||||||
|
useCallback,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
import { Trans, useTranslation } from "react-i18next";
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { LuExternalLink, LuFilter } from "react-icons/lu";
|
import { LuExternalLink, LuFilter } from "react-icons/lu";
|
||||||
@ -65,6 +72,39 @@ type FrigatePlusModel = {
|
|||||||
height: number;
|
height: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const TYPE_MODEL_DEFAULTS: Record<string, ConfigSectionData> = {
|
||||||
|
cpu: {
|
||||||
|
path: "/cpu_model.tflite",
|
||||||
|
labelmap_path: "/labelmap.txt",
|
||||||
|
width: 320,
|
||||||
|
height: 320,
|
||||||
|
input_tensor: "nhwc",
|
||||||
|
input_pixel_format: "rgb",
|
||||||
|
input_dtype: "int",
|
||||||
|
model_type: "ssd",
|
||||||
|
},
|
||||||
|
edgetpu: {
|
||||||
|
path: "/edgetpu_model.tflite",
|
||||||
|
labelmap_path: "/labelmap.txt",
|
||||||
|
width: 320,
|
||||||
|
height: 320,
|
||||||
|
input_tensor: "nhwc",
|
||||||
|
input_pixel_format: "rgb",
|
||||||
|
input_dtype: "int",
|
||||||
|
model_type: "ssd",
|
||||||
|
},
|
||||||
|
openvino: {
|
||||||
|
path: "/openvino-model/ssdlite_mobilenet_v2.xml",
|
||||||
|
labelmap_path: "/openvino-model/coco_91cl_bkgr.txt",
|
||||||
|
width: 300,
|
||||||
|
height: 300,
|
||||||
|
input_tensor: "nhwc",
|
||||||
|
input_pixel_format: "bgr",
|
||||||
|
input_dtype: "int",
|
||||||
|
model_type: "ssd",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const STATUS_BAR_KEY = "detectors_and_model";
|
const STATUS_BAR_KEY = "detectors_and_model";
|
||||||
|
|
||||||
const deriveInitialState = (config: FrigateConfig): PageState => {
|
const deriveInitialState = (config: FrigateConfig): PageState => {
|
||||||
@ -73,9 +113,7 @@ const deriveInitialState = (config: FrigateConfig): PageState => {
|
|||||||
const plusEnabled = Boolean(config.plus?.enabled);
|
const plusEnabled = Boolean(config.plus?.enabled);
|
||||||
|
|
||||||
// The reliable signal that a Plus model is currently active is the
|
// The reliable signal that a Plus model is currently active is the
|
||||||
// `model.plus.id` metadata — the backend resolves `plus://...` paths to a
|
// `model.plus.id` metadata
|
||||||
// local cache path at runtime, so `model.path` can't be relied on for
|
|
||||||
// detection.
|
|
||||||
let modelTab: ModelTab;
|
let modelTab: ModelTab;
|
||||||
if (plusModelId) {
|
if (plusModelId) {
|
||||||
modelTab = "plus";
|
modelTab = "plus";
|
||||||
@ -178,6 +216,41 @@ export default function DetectorsAndModelSettingsView({
|
|||||||
return first?.type;
|
return first?.type;
|
||||||
}, [state]);
|
}, [state]);
|
||||||
|
|
||||||
|
// fill in defaults when detector type changes
|
||||||
|
const prevDetectorTypeRef = useRef<string | undefined>(undefined);
|
||||||
|
useEffect(() => {
|
||||||
|
const newType = currentDetectorType;
|
||||||
|
const prevType = prevDetectorTypeRef.current;
|
||||||
|
prevDetectorTypeRef.current = newType;
|
||||||
|
if (prevType === undefined || prevType === newType) return;
|
||||||
|
if (!newType || !(newType in TYPE_MODEL_DEFAULTS)) return;
|
||||||
|
|
||||||
|
const defaults = TYPE_MODEL_DEFAULTS[newType];
|
||||||
|
setChildPending((prev) => {
|
||||||
|
const next: Record<string, ConfigSectionData> = {
|
||||||
|
...prev,
|
||||||
|
model: defaults,
|
||||||
|
};
|
||||||
|
if (newType === "openvino") {
|
||||||
|
const detectorsCurrent = (prev.detectors ?? state?.detectors ?? {}) as {
|
||||||
|
[key: string]: { device?: string };
|
||||||
|
};
|
||||||
|
const entries = Object.entries(detectorsCurrent);
|
||||||
|
if (entries.length > 0) {
|
||||||
|
const [firstKey, firstValue] = entries[0];
|
||||||
|
if (!firstValue?.device) {
|
||||||
|
next.detectors = {
|
||||||
|
...detectorsCurrent,
|
||||||
|
[firstKey]: { ...firstValue, device: "CPU" },
|
||||||
|
} as ConfigSectionData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [currentDetectorType]);
|
||||||
|
|
||||||
const isModelCompatible = useCallback(
|
const isModelCompatible = useCallback(
|
||||||
(model: FrigatePlusModel) =>
|
(model: FrigatePlusModel) =>
|
||||||
currentDetectorType
|
currentDetectorType
|
||||||
@ -294,17 +367,38 @@ export default function DetectorsAndModelSettingsView({
|
|||||||
? { path: `plus://${state.plusModelId}` }
|
? { path: `plus://${state.plusModelId}` }
|
||||||
: state.customModel;
|
: state.customModel;
|
||||||
|
|
||||||
|
const detectorKeysChanged =
|
||||||
|
JSON.stringify(Object.keys(state.detectors).sort()) !==
|
||||||
|
JSON.stringify(Object.keys(snapshot.detectors).sort());
|
||||||
|
|
||||||
setIsSaving(true);
|
setIsSaving(true);
|
||||||
try {
|
try {
|
||||||
if (tabChanged) {
|
if (tabChanged) {
|
||||||
await axios.put("config/set", {
|
// Best-effort cleanup of the prior model's fields
|
||||||
requires_restart: 0,
|
try {
|
||||||
config_data: { model: null },
|
await axios.put("config/set", {
|
||||||
});
|
requires_restart: 0,
|
||||||
|
config_data: { model: null },
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
// intentional no-op — see comment above
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detectorKeysChanged) {
|
||||||
|
// Best-effort cleanup
|
||||||
|
try {
|
||||||
|
await axios.put("config/set", {
|
||||||
|
requires_restart: 0,
|
||||||
|
config_data: { detectors: null },
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
// intentional no-op — see comment above
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await axios.put("config/set", {
|
await axios.put("config/set", {
|
||||||
requires_restart: 1,
|
requires_restart: 0,
|
||||||
config_data: {
|
config_data: {
|
||||||
detectors: state.detectors,
|
detectors: state.detectors,
|
||||||
model: modelPayload,
|
model: modelPayload,
|
||||||
@ -319,6 +413,13 @@ export default function DetectorsAndModelSettingsView({
|
|||||||
setChildPending({});
|
setChildPending({});
|
||||||
setResetKey((k) => k + 1);
|
setResetKey((k) => k + 1);
|
||||||
|
|
||||||
|
addMessage(
|
||||||
|
"detectors_and_model_restart",
|
||||||
|
t("detectorsAndModel.restartRequired"),
|
||||||
|
undefined,
|
||||||
|
"detectors_and_model_restart",
|
||||||
|
);
|
||||||
|
|
||||||
toast.success(t("detectorsAndModel.toast.saveSuccess"), {
|
toast.success(t("detectorsAndModel.toast.saveSuccess"), {
|
||||||
position: "top-center",
|
position: "top-center",
|
||||||
action: (
|
action: (
|
||||||
@ -342,7 +443,7 @@ export default function DetectorsAndModelSettingsView({
|
|||||||
} finally {
|
} finally {
|
||||||
setIsSaving(false);
|
setIsSaving(false);
|
||||||
}
|
}
|
||||||
}, [state, snapshot, globalMutate, t]);
|
}, [state, snapshot, globalMutate, addMessage, t]);
|
||||||
|
|
||||||
const onUndo = useCallback(() => {
|
const onUndo = useCallback(() => {
|
||||||
if (snapshot) {
|
if (snapshot) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user