Skip to main content
The zone_dwell_violation_snapshot data action prepares annotated full-frame attachments for loitering violations. It reads records from the zone_dwell_reader, finds full-frame attachments, annotates them with bounding boxes and dwell time, and prepares them for the create_violation action.

What it does

The zone dwell violation snapshot action:
  1. Reads records from the previous zone_dwell_reader action result
  2. Checks for duplicates using violated_branch_rules tracking
  3. Finds full-frame attachments in each record’s attachments field
  4. Annotates frames with red bounding boxes and “Loitering [MM:SS]” labels
  5. Falls back to live capture if no full-frame attachments are available
  6. Marks records as violated to prevent duplicate violations
  7. Outputs attachments ready for create_violation to consume

Requirements

RequirementDescription
Previous zone_dwell_readerMust have executed with records in results
Records with attachmentsRecords should have full_frame category attachments
Branch rule IDRequired for duplicate violation tracking

How it works

Attachment processing

1

Extract records

The action retrieves records from the previous zone_dwell_reader action’s extras.records.
2

Check for duplicates

For each record, check if the current branch_rule_id is already in the record’s extra_info.violated_branch_rules list. Skip if already processed.
3

Find full-frame attachments

Look through each record’s attachments array for entries with category: 'full_frame'.
4

Annotate frame

Decode the base64 image, draw a red bounding box using the bbox from metadata, and add a “Loitering [MM:SS]” label showing the dwell duration.
5

Create output attachment

Re-encode the annotated image as a new ResultAttachment with metadata including record_id, dwell_seconds, zone_name, and camera_name.
6

Mark as violated

After successful processing, add the branch_rule_id to the record’s violated_branch_rules list in the database.

Fallback live capture

If no full-frame attachments are found in the records, the action falls back to live stream capture:
  1. Gets the stream_id from the first non-violated record
  2. Loads the stream configuration to get the RTSP URL
  3. Attempts capture using multiple methods (GStreamer, OpenCV, Jetson)
  4. Saves the captured frame as the violation attachment

Duplicate violation prevention

The action implements duplicate tracking at the record level:
FieldLocationDescription
violated_branch_ruleszone_dwell_events.extra_infoArray of branch rule IDs that have created violations for this record
How it works:
  • Before processing a record, check if the current branch_rule_id is in violated_branch_rules
  • If present, skip the record (already processed by this rule)
  • After successfully creating attachments, add the branch_rule_id to the list
  • Different rules can still create violations from the same record
This allows multiple rules to create violations from the same dwell event while preventing a single rule from creating duplicate violations.

Result format

Success with attachments

FieldValue
is_successtrue
feature_resultattachments_prepared
note”Prepared X annotated attachments from Y records”
extras.attachmentsArray of ResultAttachment dicts (for create_violation)
extras.recordsOriginal records (for ANPR or other downstream actions)
extras.branch_rule_idThe branch rule ID used for tracking
extras.records_marked_violatedArray of record IDs that were marked

All duplicates

FieldValue
is_successtrue
feature_resultall_duplicates
note”All X records already violated by branch_rule Y”
extras.attachmentsEmpty array
extras.records_skipped_duplicateCount of skipped records

No records

FieldValue
is_successtrue
feature_resultno_records
note”No records from zone_dwell_reader”
extras.attachmentsEmpty array

Fallback capture success

FieldValue
is_successtrue
feature_resultfallback_snapshot_captured
note”Fallback snapshot captured for stream X”
extras.attachmentsArray with single fallback attachment
detection_attachment_pathLocal file path of captured image

Annotation details

The annotation draws:
ElementStyle
Bounding boxRed rectangle, 2px line width
Label backgroundSolid red fill
Label textWhite text: “Loitering [MM:SS]“
FontHERSHEY_SIMPLEX, 0.7 scale, 2px thickness
The dwell time is calculated from duration_seconds in the record, formatted as MM:SS.

Possible errors

What happened: Records don’t have full_frame category attachments.How to fix:
  • Ensure the zone dwell engine is configured to capture full frames
  • Check full_frame_capture_interval setting
  • The action will attempt fallback live capture
What happened: Full-frame attachment doesn’t have bbox in metadata.How to fix:
  • Ensure zone dwell engine includes bbox when capturing frames
  • Check that detection_result is being stored with bounding box data
What happened: Live stream capture failed using all methods.How to fix:
  • Check stream connectivity
  • Verify RTSP URL is correct
  • Ensure camera is accessible from the RES server

Workflow integration

This action is the middle step in a loitering violation workflow:
1

Query dwell events

zone_dwell_reader queries for long-duration dwell events matching violation criteria.
2

Prepare attachments

zone_dwell_violation_snapshot annotates frames and prepares attachments.
3

Create violations

create_violation uploads attachments and creates violation records.
Example workflow configuration:
NodeActionPurpose
1zone_dwell_readerQuery events with duration > threshold
2zone_dwell_violation_snapshotAnnotate frames, skip duplicates
3create_violationCreate violations from attachments
The duplicate tracking ensures that even if the workflow runs frequently, each record only produces one violation per branch rule. Different rules can still create separate violations from the same event.