mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-08-07 03:11:15 +03:00
Tweaks (#22656)
* tweak language * show validation errors in json response * fix export hwaccel args field in UI * increase annotation offset consts * fix save button race conditions, add reset spinner, and fix enrichments profile leak - Disable both Save and SaveAll buttons while either operation is in progress so users cannot trigger concurrent saves - Show activity indicator on Reset to Default/Global button during the API call - Enrichments panes (semantic search, genai, face recognition) now always show base config fields regardless of profile selection in the header dropdown * fix genai additional_concerns validation error with textarea array widget The additional_concerns field is list[str] in the backend but was using the textarea widget which produces a string value, causing validation errors. Created a TextareaArrayWidget that converts between array (one item per line) and textarea display, and switched additional_concerns to use it * populate and sort global audio filters for all audio labels * add column labels in profiles view * enforce a minimum value of 2 for min_initialized * reuse widget and refactor for multiline * fix * change record copy preset to transcode audio to aac
This commit is contained in:
@@ -613,6 +613,34 @@ def config_set(request: Request, body: AppConfigSetBody):
|
||||
|
||||
try:
|
||||
config = FrigateConfig.parse(new_raw_config)
|
||||
except ValidationError as e:
|
||||
with open(config_file, "w") as f:
|
||||
f.write(old_raw_config)
|
||||
f.close()
|
||||
logger.error(
|
||||
f"Config Validation Error:\n\n{str(traceback.format_exc())}"
|
||||
)
|
||||
error_messages = []
|
||||
for err in e.errors():
|
||||
msg = err.get("msg", "")
|
||||
# Strip pydantic "Value error, " prefix for cleaner display
|
||||
if msg.startswith("Value error, "):
|
||||
msg = msg[len("Value error, ") :]
|
||||
error_messages.append(msg)
|
||||
message = (
|
||||
"; ".join(error_messages)
|
||||
if error_messages
|
||||
else "Check logs for error message."
|
||||
)
|
||||
return JSONResponse(
|
||||
content=(
|
||||
{
|
||||
"success": False,
|
||||
"message": f"Error saving config: {message}",
|
||||
}
|
||||
),
|
||||
status_code=400,
|
||||
)
|
||||
except Exception:
|
||||
with open(config_file, "w") as f:
|
||||
f.write(old_raw_config)
|
||||
|
||||
@@ -71,6 +71,7 @@ class DetectConfig(FrigateBaseModel):
|
||||
default=None,
|
||||
title="Minimum initialization frames",
|
||||
description="Number of consecutive detection hits required before creating a tracked object. Increase to reduce false initializations. Default value is fps divided by 2.",
|
||||
ge=2,
|
||||
)
|
||||
max_disappeared: Optional[int] = Field(
|
||||
default=None,
|
||||
|
||||
+21
-10
@@ -614,6 +614,21 @@ class FrigateConfig(FrigateBaseModel):
|
||||
if self.ffmpeg.hwaccel_args == "auto":
|
||||
self.ffmpeg.hwaccel_args = auto_detect_hwaccel()
|
||||
|
||||
# Populate global audio filters for all audio labels
|
||||
all_audio_labels = {
|
||||
label
|
||||
for label in load_labels("/audio-labelmap.txt", prefill=521).values()
|
||||
if label
|
||||
}
|
||||
|
||||
if self.audio.filters is None:
|
||||
self.audio.filters = {}
|
||||
|
||||
for key in sorted(all_audio_labels - self.audio.filters.keys()):
|
||||
self.audio.filters[key] = AudioFilterConfig()
|
||||
|
||||
self.audio.filters = dict(sorted(self.audio.filters.items()))
|
||||
|
||||
# Global config to propagate down to camera level
|
||||
global_config = self.model_dump(
|
||||
include={
|
||||
@@ -672,12 +687,6 @@ class FrigateConfig(FrigateBaseModel):
|
||||
detector_config.model = model
|
||||
self.detectors[key] = detector_config
|
||||
|
||||
all_audio_labels = {
|
||||
label
|
||||
for label in load_labels("/audio-labelmap.txt", prefill=521).values()
|
||||
if label
|
||||
}
|
||||
|
||||
for name, camera in self.cameras.items():
|
||||
modified_global_config = global_config.copy()
|
||||
|
||||
@@ -755,7 +764,7 @@ class FrigateConfig(FrigateBaseModel):
|
||||
)
|
||||
|
||||
# Default min_initialized configuration
|
||||
min_initialized = int(camera_config.detect.fps / 2)
|
||||
min_initialized = max(int(camera_config.detect.fps / 2), 2)
|
||||
if camera_config.detect.min_initialized is None:
|
||||
camera_config.detect.min_initialized = min_initialized
|
||||
|
||||
@@ -801,11 +810,13 @@ class FrigateConfig(FrigateBaseModel):
|
||||
if camera_config.audio.filters is None:
|
||||
camera_config.audio.filters = {}
|
||||
|
||||
audio_keys = all_audio_labels
|
||||
audio_keys = audio_keys - camera_config.audio.filters.keys()
|
||||
for key in audio_keys:
|
||||
for key in sorted(all_audio_labels - camera_config.audio.filters.keys()):
|
||||
camera_config.audio.filters[key] = AudioFilterConfig()
|
||||
|
||||
camera_config.audio.filters = dict(
|
||||
sorted(camera_config.audio.filters.items())
|
||||
)
|
||||
|
||||
# Add default filters
|
||||
object_keys = camera_config.objects.track
|
||||
if camera_config.objects.filters is None:
|
||||
|
||||
@@ -47,7 +47,7 @@ class ModelTypeEnum(str, Enum):
|
||||
class ModelConfig(BaseModel):
|
||||
path: Optional[str] = Field(
|
||||
None,
|
||||
title="Custom Object detection model path",
|
||||
title="Custom object detector model path",
|
||||
description="Path to a custom detection model file (or plus://<model_id> for Frigate+ models).",
|
||||
)
|
||||
labelmap_path: Optional[str] = Field(
|
||||
|
||||
@@ -465,6 +465,16 @@ PRESETS_RECORD_OUTPUT = {
|
||||
"-c:a",
|
||||
"aac",
|
||||
],
|
||||
# NOTE: This preset originally used "-c:a copy" to pass through audio
|
||||
# without re-encoding. FFmpeg 7.x introduced a threaded pipeline where
|
||||
# demuxing, encoding, and muxing run in parallel via a Scheduler. This
|
||||
# broke audio streamcopy from RTSP sources: packets are demuxed correctly
|
||||
# but silently dropped before reaching the muxer (0 bytes written). The
|
||||
# issue is specific to RTSP + streamcopy; file inputs and transcoding both
|
||||
# work. Transcoding AAC audio is very lightweight (~30KiB per 10s segment)
|
||||
# and adds negligible CPU overhead, so this is an acceptable workaround.
|
||||
# The benefits of FFmpeg 7.x — particularly the removal of gamma correction
|
||||
# hacks required by earlier versions — outweigh this trade-off.
|
||||
"preset-record-generic-audio-copy": [
|
||||
"-f",
|
||||
"segment",
|
||||
@@ -476,8 +486,10 @@ PRESETS_RECORD_OUTPUT = {
|
||||
"1",
|
||||
"-strftime",
|
||||
"1",
|
||||
"-c",
|
||||
"-c:v",
|
||||
"copy",
|
||||
"-c:a",
|
||||
"aac",
|
||||
],
|
||||
"preset-record-mjpeg": [
|
||||
"-f",
|
||||
|
||||
Reference in New Issue
Block a user