fix: stale frigate mapping reconciliation, recognize opt-out, cold start notice
- At upload start, diff tracker vs live Frigate file list and remove any mappings for files no longer present; corrects effective_count so manually deleted files don't permanently consume quota slots - Add ENABLE_FRIGATE_SCORES config (default true); when false, skips all recognize_face calls and falls back to blur scores for quality replacement - Print a dim notice when FRIGATE_SCORE_THRESHOLD is set but pre_run_count is zero, so users know the gate is deferred to the next run Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,7 @@ STRATEGY=auto
|
||||
# BLUR_THRESHOLD=120.0 # Laplacian blur threshold; lower = accept more blur (default: 120.0)
|
||||
# MAX_AUTO_IMAGES=80 # Hard cap on auto-diversity selection (default: 80)
|
||||
# FRIGATE_SCORE_THRESHOLD=0.0 # Quality gate: remove images scoring below this after upload (0 = disabled; requires at least one prior run)
|
||||
# ENABLE_FRIGATE_SCORES=true # Call Frigate's recognize endpoint after each upload to store quality scores (default: true; adds ~200ms per upload)
|
||||
|
||||
# ── Caching & Models ──────────────────────────────────────────────────────────
|
||||
# FORCE_CPU=true # Disable GPU, fall back to CPU
|
||||
|
||||
@@ -32,6 +32,7 @@ class _Config:
|
||||
MAX_AUTO_IMAGES: int = 80
|
||||
QUALITY_REPLACEMENT: bool = True
|
||||
FRIGATE_SCORE_THRESHOLD: float = 0.0
|
||||
ENABLE_FRIGATE_SCORES: bool = True
|
||||
|
||||
# People filtering
|
||||
MIN_FACE_COUNT: int = 0
|
||||
@@ -64,6 +65,7 @@ class _Config:
|
||||
self.MAX_AUTO_IMAGES = int(os.getenv("MAX_AUTO_IMAGES", "80"))
|
||||
self.QUALITY_REPLACEMENT = os.getenv("QUALITY_REPLACEMENT", "true").lower() in ("true", "1", "yes")
|
||||
self.FRIGATE_SCORE_THRESHOLD = float(os.getenv("FRIGATE_SCORE_THRESHOLD", "0.0"))
|
||||
self.ENABLE_FRIGATE_SCORES = os.getenv("ENABLE_FRIGATE_SCORES", "true").lower() in ("true", "1", "yes")
|
||||
self.FACE_MARGIN = float(os.getenv("FACE_MARGIN", "0.15"))
|
||||
self.USE_FULL_RESOLUTION = os.getenv("USE_FULL_RESOLUTION", "true").lower() in ("true", "1", "yes")
|
||||
self.ENABLE_FACE_ALIGNMENT = os.getenv("ENABLE_FACE_ALIGNMENT", "true").lower() in ("true", "1", "yes")
|
||||
|
||||
+17
-2
@@ -357,6 +357,17 @@ def upload_to_frigate(jobs: list[dict]) -> None:
|
||||
known_frigate_files_at_start: set[str] = get_tracked_frigate_filenames(name)
|
||||
else:
|
||||
known_frigate_files_at_start: set[str] = set(_snapshot)
|
||||
# Remove tracker mappings for files that no longer exist in Frigate
|
||||
# (manually deleted, or cleaned up outside winnow). This corrects the
|
||||
# effective_count so those slots are available for new uploads.
|
||||
stale = get_tracked_frigate_filenames(name) - known_frigate_files_at_start
|
||||
for stale_fn in stale:
|
||||
remove_frigate_file(name, stale_fn)
|
||||
if stale:
|
||||
progress.console.print(
|
||||
f" [dim]{name}: cleared {len(stale)} stale mapping(s)"
|
||||
" (file(s) no longer in Frigate)[/dim]"
|
||||
)
|
||||
effective_count = get_tracked_frigate_file_count(name)
|
||||
pre_run_count = effective_count
|
||||
quality_replacement = job.get("config", {}).get("quality_replacement", False)
|
||||
@@ -367,6 +378,10 @@ def upload_to_frigate(jobs: list[dict]) -> None:
|
||||
effective_threshold = max(Config.FRIGATE_SCORE_THRESHOLD, _dynamic or 0.0)
|
||||
if _dynamic is not None and _dynamic > Config.FRIGATE_SCORE_THRESHOLD:
|
||||
logger.debug(f"{name}: dynamic Frigate score threshold {_dynamic:.3f}")
|
||||
if pre_run_count == 0:
|
||||
progress.console.print(
|
||||
f" [dim]{name}: first run — quality gate will apply from the next run[/dim]"
|
||||
)
|
||||
else:
|
||||
effective_threshold = 0.0
|
||||
actually_uploaded: list[tuple[str, str | None]] = []
|
||||
@@ -397,7 +412,7 @@ def upload_to_frigate(jobs: list[dict]) -> None:
|
||||
progress.console.print(f" [dim]⏭ {fname}: at cap, quality replacement disabled[/dim]")
|
||||
progress.advance(upload_task)
|
||||
continue
|
||||
using_fscore = has_frigate_scores(name)
|
||||
using_fscore = has_frigate_scores(name) and Config.ENABLE_FRIGATE_SCORES
|
||||
if using_fscore:
|
||||
candidate_score = recognize_face(fpath)
|
||||
if candidate_score is None:
|
||||
@@ -458,7 +473,7 @@ def upload_to_frigate(jobs: list[dict]) -> None:
|
||||
|
||||
asset_id = asset_map.get(fname)
|
||||
if asset_id:
|
||||
post_fscore = recognize_face(fpath)
|
||||
post_fscore = recognize_face(fpath) if Config.ENABLE_FRIGATE_SCORES else None
|
||||
mark_uploaded(
|
||||
asset_id,
|
||||
person_name=name,
|
||||
|
||||
Reference in New Issue
Block a user