mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-05-09 15:05:26 +03:00
Compare commits
No commits in common. "05ef72f3a56423cb51ff330be41b1be8f329367e" and "a2639b54bdf802382ff6f52e3a3cebd4694b5556" have entirely different histories.
05ef72f3a5
...
a2639b54bd
@ -911,7 +911,7 @@ cameras:
|
|||||||
user: admin
|
user: admin
|
||||||
# Optional: password for login.
|
# Optional: password for login.
|
||||||
password: admin
|
password: admin
|
||||||
# Optional: Skip TLS verification and disable digest authentication for the ONVIF server (default: shown below)
|
# Optional: Skip TLS verification from the ONVIF server (default: shown below)
|
||||||
tls_insecure: False
|
tls_insecure: False
|
||||||
# Optional: Ignores time synchronization mismatches between the camera and the server during authentication.
|
# Optional: Ignores time synchronization mismatches between the camera and the server during authentication.
|
||||||
# Using NTP on both ends is recommended and this should only be set to True in a "safe" environment due to the security risk it represents.
|
# Using NTP on both ends is recommended and this should only be set to True in a "safe" environment due to the security risk it represents.
|
||||||
|
|||||||
@ -251,22 +251,20 @@ class ReviewDescriptionProcessor(PostProcessorApi):
|
|||||||
if not primary_segments:
|
if not primary_segments:
|
||||||
return "No concerns were found during this time period."
|
return "No concerns were found during this time period."
|
||||||
|
|
||||||
# Build hierarchical structure: each primary event with its contextual items
|
# For each primary segment, find overlapping contextual items from other cameras
|
||||||
events_with_context = []
|
all_items_for_summary = []
|
||||||
|
|
||||||
for primary_seg in primary_segments:
|
for primary_seg in primary_segments:
|
||||||
# Start building the primary event structure
|
# Add the primary item with marker
|
||||||
primary_item = copy.deepcopy(primary_seg["metadata"])
|
primary_item = copy.deepcopy(primary_seg["metadata"])
|
||||||
primary_item["camera"] = primary_seg["camera"]
|
primary_item["_is_primary"] = True
|
||||||
primary_item["start_time"] = primary_seg["start_time"]
|
primary_item["_camera"] = primary_seg["camera"]
|
||||||
primary_item["end_time"] = primary_seg["end_time"]
|
all_items_for_summary.append(primary_item)
|
||||||
|
|
||||||
# Find overlapping contextual items from other cameras
|
# Find overlapping contextual items from other cameras
|
||||||
primary_start = primary_seg["start_time"]
|
primary_start = primary_seg["start_time"]
|
||||||
primary_end = primary_seg["end_time"]
|
primary_end = primary_seg["end_time"]
|
||||||
primary_camera = primary_seg["camera"]
|
primary_camera = primary_seg["camera"]
|
||||||
contextual_items = []
|
|
||||||
seen_contextual_cameras = set()
|
|
||||||
|
|
||||||
for seg in segments:
|
for seg in segments:
|
||||||
seg_camera = seg["camera"]
|
seg_camera = seg["camera"]
|
||||||
@ -281,25 +279,21 @@ class ReviewDescriptionProcessor(PostProcessorApi):
|
|||||||
seg_end = seg["end_time"]
|
seg_end = seg["end_time"]
|
||||||
|
|
||||||
if seg_start < primary_end and primary_start < seg_end:
|
if seg_start < primary_end and primary_start < seg_end:
|
||||||
# Avoid duplicates if same camera has multiple overlapping segments
|
|
||||||
if seg_camera not in seen_contextual_cameras:
|
|
||||||
contextual_item = copy.deepcopy(seg["metadata"])
|
contextual_item = copy.deepcopy(seg["metadata"])
|
||||||
contextual_item["camera"] = seg_camera
|
contextual_item["_is_primary"] = False
|
||||||
contextual_item["start_time"] = seg_start
|
contextual_item["_camera"] = seg_camera
|
||||||
contextual_item["end_time"] = seg_end
|
contextual_item["_related_to_camera"] = primary_camera
|
||||||
contextual_items.append(contextual_item)
|
|
||||||
seen_contextual_cameras.add(seg_camera)
|
|
||||||
|
|
||||||
# Add context array to primary item
|
if not any(
|
||||||
primary_item["context"] = contextual_items
|
item.get("_camera") == seg_camera
|
||||||
events_with_context.append(primary_item)
|
and item.get("time") == contextual_item.get("time")
|
||||||
|
for item in all_items_for_summary
|
||||||
|
):
|
||||||
|
all_items_for_summary.append(contextual_item)
|
||||||
|
|
||||||
total_context_items = sum(
|
|
||||||
len(event.get("context", [])) for event in events_with_context
|
|
||||||
)
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f"Summary includes {len(events_with_context)} primary events with "
|
f"Summary includes {len(primary_segments)} primary items and "
|
||||||
f"{total_context_items} total contextual items"
|
f"{len(all_items_for_summary) - len(primary_segments)} contextual items"
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.config.review.genai.debug_save_thumbnails:
|
if self.config.review.genai.debug_save_thumbnails:
|
||||||
@ -310,7 +304,7 @@ class ReviewDescriptionProcessor(PostProcessorApi):
|
|||||||
return self.genai_client.generate_review_summary(
|
return self.genai_client.generate_review_summary(
|
||||||
start_ts,
|
start_ts,
|
||||||
end_ts,
|
end_ts,
|
||||||
events_with_context,
|
all_items_for_summary,
|
||||||
self.config.review.genai.debug_save_thumbnails,
|
self.config.review.genai.debug_save_thumbnails,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -177,60 +177,78 @@ Each line represents a detection state, not necessarily unique individuals. Pare
|
|||||||
self,
|
self,
|
||||||
start_ts: float,
|
start_ts: float,
|
||||||
end_ts: float,
|
end_ts: float,
|
||||||
events: list[dict[str, Any]],
|
segments: list[dict[str, Any]],
|
||||||
debug_save: bool,
|
debug_save: bool,
|
||||||
) -> str | None:
|
) -> str | None:
|
||||||
"""Generate a summary of review item descriptions over a period of time."""
|
"""Generate a summary of review item descriptions over a period of time."""
|
||||||
time_range = f"{datetime.datetime.fromtimestamp(start_ts).strftime('%B %d, %Y at %I:%M %p')} to {datetime.datetime.fromtimestamp(end_ts).strftime('%B %d, %Y at %I:%M %p')}"
|
time_range = f"{datetime.datetime.fromtimestamp(start_ts).strftime('%B %d, %Y at %I:%M %p')} to {datetime.datetime.fromtimestamp(end_ts).strftime('%B %d, %Y at %I:%M %p')}"
|
||||||
timeline_summary_prompt = f"""
|
timeline_summary_prompt = f"""
|
||||||
You are a security officer writing a concise security report.
|
You are a security officer.
|
||||||
|
Time range: {time_range}.
|
||||||
|
Input: JSON list with "title", "scene", "confidence", "potential_threat_level" (0-2), "other_concerns", "_is_primary", "_camera".
|
||||||
|
|
||||||
Time range: {time_range}
|
Task: Write a concise, human-presentable security report in markdown format.
|
||||||
|
|
||||||
Input format: Each event is a JSON object with:
|
CRITICAL - Understanding Primary vs Contextual Items:
|
||||||
- "title", "scene", "confidence", "potential_threat_level" (0-2), "other_concerns", "camera", "time", "start_time", "end_time"
|
- Items with "_is_primary": true are events that REQUIRE REVIEW and MUST be included in the report
|
||||||
- "context": array of related events from other cameras that occurred during overlapping time periods
|
- Items with "_is_primary": false are additional context from other camera perspectives that overlap in time
|
||||||
|
- **DO NOT create separate bullet points or sections for contextual items**
|
||||||
|
- **ONLY use contextual items to enrich and inform the description of primary items**
|
||||||
|
- The "_camera" field indicates which camera captured each event
|
||||||
|
- **When a contextual item provides relevant background, you MUST incorporate it directly into the primary event's bullet point**
|
||||||
|
- Contextual information often explains or de-escalates seemingly suspicious primary events
|
||||||
|
|
||||||
Report Structure - Use this EXACT format:
|
Rules for the report:
|
||||||
|
|
||||||
|
- Title & overview
|
||||||
|
- Start with:
|
||||||
# Security Summary - {time_range}
|
# Security Summary - {time_range}
|
||||||
|
- Write a 1-2 sentence situational overview capturing the general pattern of the period.
|
||||||
|
- Keep the overview high-level; specific details will be in the event bullets below.
|
||||||
|
|
||||||
## Overview
|
- Event details
|
||||||
[Write 1-2 sentences summarizing the overall activity pattern during this period.]
|
- **ONLY create bullet points for PRIMARY items (_is_primary: true)**
|
||||||
|
- **Do NOT create sections or bullets for events that don't exist**
|
||||||
|
- Do NOT create separate bullets for contextual items
|
||||||
|
- Present primary events in chronological order as a bullet list.
|
||||||
|
- **CRITICAL: When contextual items overlap with a primary event, you MUST weave that information directly into the same bullet point**
|
||||||
|
- Format: **[Timestamp]** - [Description incorporating any contextual information]. [Camera info]. (threat level: X)
|
||||||
|
- If contextual information provides an explanation (e.g., delivery truck → person is likely delivery driver), reflect this understanding in your description and potentially adjust the perceived threat level
|
||||||
|
- If multiple PRIMARY events occur within the same minute, combine them into a single bullet with sub-points.
|
||||||
|
- Use bold timestamps for clarity.
|
||||||
|
- Camera format: "Camera: [camera name]" or mention contextual cameras inline when relevant
|
||||||
|
- Group bullets under subheadings ONLY when you have actual PRIMARY events to list (e.g., Porch Activity, Unusual Behavior).
|
||||||
|
|
||||||
---
|
- Threat levels
|
||||||
|
- Show the threat level for PRIMARY events using these labels:
|
||||||
|
- Threat level 0: "Normal"
|
||||||
|
- Threat level 1: "Needs review"
|
||||||
|
- Threat level 2: "Security concern"
|
||||||
|
- Format as (threat level: Normal), (threat level: Needs review), or (threat level: Security concern).
|
||||||
|
- **When contextual items clearly explain a primary event (e.g., delivery truck explains person at door), you should describe it as normal activity and note the explanation**
|
||||||
|
- **Your description and tone should reflect the fuller understanding provided by contextual information**
|
||||||
|
- Example: Primary event says "unidentified person with face covering" but context shows delivery truck → describe as "delivery person (truck visible on Front Driveway Cam)" rather than emphasizing suspicious elements
|
||||||
|
- The stored threat level remains as originally classified, but your narrative should reflect the contextual understanding
|
||||||
|
- If multiple PRIMARY events at the same time share the same threat level, only state it once.
|
||||||
|
|
||||||
## Timeline
|
- Final assessment
|
||||||
|
- End with a Final Assessment section.
|
||||||
|
- If all primary events are threat level 0 or explained by contextual items:
|
||||||
|
Final assessment: Only normal residential activity observed during this period.
|
||||||
|
- If threat level 1 events are present:
|
||||||
|
Final assessment: Some activity requires review but no security concerns identified.
|
||||||
|
- If threat level 2 events are present, clearly summarize them as Security concerns requiring immediate attention.
|
||||||
|
- Keep this section brief - do not repeat details from the event descriptions above.
|
||||||
|
|
||||||
[Group events by time periods (e.g., "Morning (6:00 AM - 12:00 PM)", "Afternoon (12:00 PM - 5:00 PM)", "Evening (5:00 PM - 9:00 PM)", "Night (9:00 PM - 6:00 AM)"). Use appropriate time blocks based on when events occurred.]
|
- Conciseness
|
||||||
|
- Do not repeat benign clothing/appearance details unless they distinguish individuals.
|
||||||
### [Time Block Name]
|
- Summarize similar routine events instead of restating full scene descriptions.
|
||||||
|
- When incorporating contextual information, do so briefly and naturally within the primary event description.
|
||||||
**HH:MM AM/PM** | [Camera Name] | [Threat Level Indicator]
|
- Avoid lengthy explanatory notes - integrate context seamlessly into the narrative.
|
||||||
- [Event title]: [Clear description incorporating contextual information from the "context" array]
|
|
||||||
- Context: [If context array has items, mention them here, e.g., "Delivery truck present on Front Driveway Cam (HH:MM AM/PM)"]
|
|
||||||
- Assessment: [Brief assessment incorporating context - if context explains the event, note it here]
|
|
||||||
|
|
||||||
[Repeat for each event in chronological order within the time block]
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
[One sentence summarizing the period. If all events are normal/explained: "Routine activity observed." If review needed: "Some activity requires review but no security concerns." If security concerns: "Security concerns requiring immediate attention."]
|
|
||||||
|
|
||||||
Guidelines:
|
|
||||||
- List ALL events in chronological order, grouped by time blocks
|
|
||||||
- Threat level indicators: ✓ Normal, ⚠️ Needs review, 🔴 Security concern
|
|
||||||
- Integrate contextual information naturally - use the "context" array to enrich each event's description
|
|
||||||
- If context explains the event (e.g., delivery truck explains person at door), describe it accordingly (e.g., "delivery person" not "unidentified person")
|
|
||||||
- Be concise but informative - focus on what happened and what it means
|
|
||||||
- If contextual information makes an event clearly normal, reflect that in your assessment
|
|
||||||
- Only create time blocks that have events - don't create empty sections
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
timeline_summary_prompt += "\n\nEvents:\n"
|
for item in segments:
|
||||||
for event in events:
|
timeline_summary_prompt += f"\n{item}"
|
||||||
timeline_summary_prompt += f"\n{event}\n"
|
|
||||||
|
|
||||||
if debug_save:
|
if debug_save:
|
||||||
with open(
|
with open(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user