mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-06-21 03:41:55 +03:00
Miscellaneous fixes (#23394)
* serialize OpenVINO inference per process to prevent concurrent-inference segfault * clean up * add max scaling meta to login page * add more detect section field messages * fix icon layout in settings field messages * tweak edit icon color
This commit is contained in:
parent
b751025339
commit
a4f077b128
@ -15,6 +15,9 @@ from frigate.util.rknn_converter import auto_convert_model, is_rknn_compatible
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Process-wide lock serializing all OpenVINO compile/inference calls
|
||||
_OPENVINO_LOCK = threading.Lock()
|
||||
|
||||
|
||||
def is_arm64_platform() -> bool:
|
||||
"""Check if we're running on an ARM platform."""
|
||||
@ -326,18 +329,16 @@ class OpenVINOModelRunner(BaseModelRunner):
|
||||
except Exception as e:
|
||||
logger.debug(f"NPU_TURBO not supported by driver: {e}")
|
||||
|
||||
# Compile model
|
||||
# Compile model under the shared lock
|
||||
with _OPENVINO_LOCK:
|
||||
self.compiled_model = self.ov_core.compile_model(
|
||||
model=model_path, device_name=device
|
||||
)
|
||||
|
||||
# Create reusable inference request
|
||||
self.infer_request = self.compiled_model.create_infer_request()
|
||||
self.input_tensor: ov.Tensor | None = None
|
||||
|
||||
# Thread lock to prevent concurrent inference (needed for JinaV2 which shares
|
||||
# one runner between text and vision embeddings called from different threads)
|
||||
self._inference_lock = threading.Lock()
|
||||
self.input_tensor: ov.Tensor | None = None
|
||||
|
||||
if not self.complex_model:
|
||||
try:
|
||||
@ -382,9 +383,11 @@ class OpenVINOModelRunner(BaseModelRunner):
|
||||
Returns:
|
||||
List of output tensors
|
||||
"""
|
||||
# Lock prevents concurrent access to infer_request
|
||||
# Needed for JinaV2: genai thread (text) + embeddings thread (vision)
|
||||
with self._inference_lock:
|
||||
# Shared lock serializes inference across every OpenVINO runner in this
|
||||
# process — both the shared-runner JinaV2 case (genai text thread +
|
||||
# embeddings vision thread) and distinct runners running on separate
|
||||
# threads (e.g. the ArcFace face-model build vs the LPR detector).
|
||||
with _OPENVINO_LOCK:
|
||||
from frigate.embeddings.types import EnrichmentModelTypeEnum
|
||||
|
||||
if self.model_type in [EnrichmentModelTypeEnum.arcface.value]:
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/images/branding/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<title>Frigate</title>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
|
||||
@ -1908,7 +1908,11 @@
|
||||
"fpsGreaterThanFive": "Setting the detect FPS higher than 5 is not recommended. Higher values may cause performance issues and will not provide any benefit.",
|
||||
"disabled": "Object detection is disabled. Snapshots, review items, and enrichments such as face recognition, license plate recognition, and Generative AI will not function.",
|
||||
"resolutionShouldBeMultipleOfFour": "For best results, detect width and height should be multiples of 4. Other even values may produce visual artifacts or slight distortion in the detect stream.",
|
||||
"aspectRatioMismatch": "The width and height you've entered don't match the aspect ratio of your current detect resolution. This may produce a stretched or distorted image."
|
||||
"aspectRatioMismatch": "The width and height you've entered don't match the aspect ratio of your current detect resolution. This may produce a stretched or distorted image.",
|
||||
"maxFramesSet": "Setting max frames overrides default behavior and disables stationary object tracking. There are very few situations where this is needed, use with caution.",
|
||||
"squareResolution": "A square detect resolution is unusual. The detect width and height should match your camera's aspect ratio (for example, 16:9), not the dimensions of the object detection model. A mismatched aspect ratio can stretch the image and reduce detection accuracy.",
|
||||
"resolutionHigh": "This detect resolution is higher than recommended and may cause increased resource usage without improving detection accuracy. A detect resolution at or below 1080p is recommended for most cameras.",
|
||||
"globalResolutionMultipleCameras": "A global detect resolution is set while multiple cameras are configured. Unless all cameras share the same resolution and aspect ratio, the detect width and height should be defined per camera to match each camera's native aspect ratio."
|
||||
},
|
||||
"objects": {
|
||||
"genaiNoDescriptionsProvider": "You must configure a GenAI provider with the 'descriptions' role for descriptions to be generated."
|
||||
|
||||
@ -15,13 +15,13 @@ const severityVariantMap: Record<
|
||||
function SeverityIcon({ severity }: { severity: string }) {
|
||||
switch (severity) {
|
||||
case "info":
|
||||
return <LuInfo className="size-4" />;
|
||||
return <LuInfo className="size-4 shrink-0" />;
|
||||
case "warning":
|
||||
return <LuTriangleAlert className="size-4" />;
|
||||
return <LuTriangleAlert className="size-4 shrink-0" />;
|
||||
case "error":
|
||||
return <LuCircleAlert className="size-4" />;
|
||||
return <LuCircleAlert className="size-4 shrink-0" />;
|
||||
default:
|
||||
return <LuInfo className="size-4" />;
|
||||
return <LuInfo className="size-4 shrink-0" />;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -18,11 +18,11 @@ const severityVariantMap: Record<
|
||||
function SeverityIcon({ severity }: { severity: MessageSeverity }) {
|
||||
switch (severity) {
|
||||
case "info":
|
||||
return <LuInfo className="size-4" />;
|
||||
return <LuInfo className="size-4 shrink-0" />;
|
||||
case "warning":
|
||||
return <LuTriangleAlert className="size-4" />;
|
||||
return <LuTriangleAlert className="size-4 shrink-0" />;
|
||||
case "error":
|
||||
return <LuCircleAlert className="size-4" />;
|
||||
return <LuCircleAlert className="size-4 shrink-0" />;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,8 +11,12 @@ const detect: SectionConfigOverrides = {
|
||||
condition: (ctx) =>
|
||||
ctx.level === "camera" && ctx.formData?.enabled === false,
|
||||
},
|
||||
],
|
||||
fieldMessages: [
|
||||
{
|
||||
key: "detect-resolution-not-multiple-of-four",
|
||||
field: "width",
|
||||
position: "before",
|
||||
messageKey: "configMessages.detect.resolutionShouldBeMultipleOfFour",
|
||||
severity: "warning",
|
||||
condition: (ctx) => {
|
||||
@ -23,8 +27,59 @@ const detect: SectionConfigOverrides = {
|
||||
return isEvenButNotFour(width) || isEvenButNotFour(height);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "detect-global-resolution-multiple-cameras",
|
||||
field: "width",
|
||||
position: "before",
|
||||
messageKey: "configMessages.detect.globalResolutionMultipleCameras",
|
||||
severity: "info",
|
||||
condition: (ctx) => {
|
||||
if (ctx.level !== "global") return false;
|
||||
const width = ctx.formData?.width as number | null | undefined;
|
||||
const height = ctx.formData?.height as number | null | undefined;
|
||||
if (typeof width !== "number" && typeof height !== "number") {
|
||||
return false;
|
||||
}
|
||||
const cameraCount = Object.keys(ctx.fullConfig?.cameras ?? {}).length;
|
||||
return cameraCount > 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "detect-resolution-high",
|
||||
field: "width",
|
||||
position: "before",
|
||||
messageKey: "configMessages.detect.resolutionHigh",
|
||||
severity: "warning",
|
||||
condition: (ctx) => {
|
||||
const width = ctx.formData?.width as number | null | undefined;
|
||||
const height = ctx.formData?.height as number | null | undefined;
|
||||
if (typeof width !== "number" || typeof height !== "number") {
|
||||
return false;
|
||||
}
|
||||
return Math.min(width, height) > 1080;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "detect-square-resolution",
|
||||
field: "width",
|
||||
position: "before",
|
||||
messageKey: "configMessages.detect.squareResolution",
|
||||
severity: "warning",
|
||||
condition: (ctx) => {
|
||||
const width = ctx.formData?.width as number | null | undefined;
|
||||
const height = ctx.formData?.height as number | null | undefined;
|
||||
return (
|
||||
typeof width === "number" &&
|
||||
typeof height === "number" &&
|
||||
width > 0 &&
|
||||
width === height
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "detect-aspect-ratio-mismatch",
|
||||
field: "width",
|
||||
position: "before",
|
||||
messageKey: "configMessages.detect.aspectRatioMismatch",
|
||||
severity: "warning",
|
||||
condition: (ctx) => {
|
||||
@ -55,8 +110,6 @@ const detect: SectionConfigOverrides = {
|
||||
return Math.abs(newRatio - savedRatio) > 0.01;
|
||||
},
|
||||
},
|
||||
],
|
||||
fieldMessages: [
|
||||
{
|
||||
key: "fps-greater-than-five",
|
||||
field: "fps",
|
||||
@ -71,6 +124,31 @@ const detect: SectionConfigOverrides = {
|
||||
return detectFps != null && streamFps != null && detectFps > 5;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "max-frames-set",
|
||||
field: "stationary.max_frames",
|
||||
messageKey: "configMessages.detect.maxFramesSet",
|
||||
severity: "warning",
|
||||
position: "after",
|
||||
condition: (ctx) => {
|
||||
const stationary = ctx.formData?.stationary as
|
||||
| {
|
||||
max_frames?: {
|
||||
default?: number | null;
|
||||
objects?: Record<string, number>;
|
||||
} | null;
|
||||
}
|
||||
| null
|
||||
| undefined;
|
||||
const maxFrames = stationary?.max_frames;
|
||||
if (!maxFrames) return false;
|
||||
return (
|
||||
typeof maxFrames.default === "number" ||
|
||||
(maxFrames.objects != null &&
|
||||
Object.keys(maxFrames.objects).length > 0)
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
fieldOrder: [
|
||||
"enabled",
|
||||
@ -81,9 +159,9 @@ const detect: SectionConfigOverrides = {
|
||||
"max_disappeared",
|
||||
"annotation_offset",
|
||||
"stationary",
|
||||
"interval",
|
||||
"threshold",
|
||||
"max_frames",
|
||||
"stationary.interval",
|
||||
"stationary.threshold",
|
||||
"stationary.max_frames",
|
||||
],
|
||||
restartRequired: [],
|
||||
fieldGroups: {
|
||||
@ -129,9 +207,6 @@ const detect: SectionConfigOverrides = {
|
||||
"max_disappeared",
|
||||
"annotation_offset",
|
||||
"stationary",
|
||||
"interval",
|
||||
"threshold",
|
||||
"max_frames",
|
||||
],
|
||||
advancedFields: [],
|
||||
},
|
||||
|
||||
@ -283,7 +283,7 @@ export function CameraGroupSelector({ className }: CameraGroupSelectorProps) {
|
||||
afterSelect?.();
|
||||
}}
|
||||
>
|
||||
<LuPencil className="size-5 text-primary" />
|
||||
<LuPencil className="size-5 text-primary-variant" />
|
||||
</Button>,
|
||||
);
|
||||
}
|
||||
@ -376,7 +376,7 @@ export function CameraGroupSelector({ className }: CameraGroupSelectorProps) {
|
||||
onMouseEnter={() => showTooltip("edit")}
|
||||
onMouseLeave={() => showTooltip(undefined)}
|
||||
>
|
||||
<LuPencil className="size-4 text-primary" />
|
||||
<LuPencil className="size-4 text-primary-variant" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipPortal>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user