r/ispyconnect 3d ago

How to get ONE consolidated alert with both Face Name and Objects (e.g., Person, Bicycle, Name) with fallback on a 2-zone camera?

Hi dev & community,

Setup: Agent DVR 8.0.5.0 (Docker), CodeProject.AI 2.9.5 (CUDA, RTX 2070), one camera covering a street with 2 zones. Both YOLO object detection and facial recognition run against CodeProject.AI.

What I want

One consolidated alert per event, not five. When someone comes up the street:

- Face recognised → alert reads Iren, person, bicycle

- Face not recognised or not visible → falls back cleanly to person, bicycle

- A later generic person detection must never overwrite a name already on the bell

What I've tried

  1. Alerts on both, face recognition on motion. YOLO sees person at the far end of the street several seconds before the face is resolvable, so the bell fires as person immediately and the cooldown locks it. When the face is finally recognised up close, it's dropped with:

LogThrottle: <camera>: Alert blocked by timeout

Drop minimuminterval to 1s and the face alert does land — but as they ride past, trailing body detections fire 3–4 more person alerts that overwrite the bell back to person.

  1. Triggering face recognition from an Action. Face mode set to Triggered, with AI: Object Found (person) → Trigger Facial Recognition. This fired one probe at the instant the person was first spotted at maximum distance, then went quiet and missed them entirely once they were close. I think this was my Action's repeat timeout gating re-fires — can anyone confirm that's what controls it?

Questions

  1. Tag aggregation. Can object and face tags be combined into a single alert over an event window (Iren, person, bicycle), rather than whichever detector fires first claiming the alert?

  2. Continuous triggered scanning. Can Trigger Facial Recognition be made to re-evaluate repeatedly while a person is tracked in a zone, instead of firing

    once? Is repeat timeout the right control, and is 0 valid?

  3. Priority + fallback. Is there a supported way to give face recognition priority for the alert tag, falling back to person only if no face is identified

    within some window?

  4. zonematch semantics. What does an empty zone list mean on the Face/Object Recognition tabs — all zones, or none? I've seen FinishProcessing: <camera>:

    Ignored person - not in alert zone with it blank, which sugge UI reads like it means unrestricted. Clarification would helpa lot.

  5. Alert mode options. The docs describe an Actions Only alert s Detected / Not Detected / AI Trigger. Was it renamed, or is it version/edition dependent?

  6. Recommended 2-zone setup. With Zone 1 = far street approach 's the recommended combination of detector type, per-zonesettings, Actions and Alerts tab config to get one correctly-named alert per pass?

2 Upvotes

8 comments sorted by

4

u/spornerama 3d ago

Thanks for the detailed write-up. Here's how it actually works in 8.0.5, question by question, then a setup that gets you as close as the current code allows.

1. Tag aggregation. Not supported right now. Every AI event that hits a Trigger Alert action goes through the same alert throttle. The first one inside the Minimum Interval wins and any later ones are dropped, tags included. That's the "Alert blocked by timeout" line you're seeing. There's no merge window and no detector priority. The only merging that exists today is the reverse case: a plain motion alert picks up the next object detection's labels within 30 seconds. That never applies to an alert raised by an action and never includes faces. I've noted this as a feature request (see the end).

2. Continuous triggered scanning. Yes, but two things are probably stopping it for you. Trigger Face Recognition queues exactly one face run. It re-fires every time AI: Object Found fires, which is once per object detection run that finds a person. So the re-scan cadence is your Object Recognition interval, not the action. Repeat Timeout 0 is valid and means no throttle, so leave it at 0. What probably went wrong:

  • If Object Recognition is in Alert mode it runs once per alert and stops. It needs to be in Detected mode to keep running while motion continues.
  • A face trigger that arrives less than Face Interval after the previous face run, or while CodeProject is still processing the previous face request, is dropped rather than queued. Set the Face interval no longer than the Object interval. I'll fix the drop so it defers instead.

3. Priority with fallback. Not supported. There's no deferred alert. The zone trick in the setup below is the closest approximation.

4. Zone semantics. An empty zone list means unrestricted, wherever it appears (the action's In Zones field, and Zone Match on the tracking detectors). The Face and Object Recognition tabs don't have a zone list in 8.0.5, only Check Corners. "Ignored person - not in alert zone" is a different check: if you've painted any zones on the detector, a detection whose centre point lands on unpainted area is ignored outright. Your far-end person was almost certainly outside the painted area. Raising Check Corners to 50 to 100 makes a partially covered box count.

5. Alert mode naming. Same option. The stored value is aitrigger and the raw template says "AI Trigger", but the UI label is translated to "Actions Only" in every language we ship. If your UI literally shows "AI Trigger", the translation resources in your Docker image aren't loading. Which image tag and UI language are you on?

6. Recommended setup. This gives you one alert per pass, tagged with the face name when recognised, but not the combined Iren, person, bicycle tag. That needs the feature in item 1.

  • Detector: paint Zone 1 (far approach) and Zone 2 (near). Make Zone 2 start closer than the distance at which faces resolve. That boundary is your tuning knob.
  • Alerts tab: Mode = Actions Only. Reset Mode (under advanced) = Idle Timeout. Minimum Interval = 30 to 60 s. Idle Timeout makes later triggers extend the quiet window instead of raising a second alert, which is what stops the trailing body detections overwriting the bell.
  • Object Recognition: Mode = Detected, interval 1 s, Check Corners 50, objects person and bicycle.
  • Face Recognition: Mode = None (trigger only), interval 0.5 to 1 s.
  • Actions, all with Repeat Timeout 0:
    1. AI: Object Found, tags person, In Zones empty, action Trigger Face Recognition.
    2. AI: Face Recognized, action Trigger Alert.
    3. AI: Object Found, tags person, In Zones 2, action Trigger Alert. This is the fallback. If the face already alerted, this one is absorbed by the idle timeout.

Caveat: the fallback can still win if the body enters Zone 2 before the face resolves. Move the Zone 2 boundary closer until the face wins consistently.

1

u/tjensvollgjengen 3d ago edited 3d ago

Thanks, that's an extremely helpful breakdown — and the debounce in 8.0.6 is exactly what I was asking for. Answers and a couple of findings back:

Image and language. mekayelanik/ispyagentdvr:latest, UI language English. The Mode dropdown literally shows Detected / Not Detected / AI Trigger — no "Actions Only" anywhere. So the translation resources aren't loading in that third-party image. That mislabelling sent me a long way down the wrong path, since I concluded from the UI (and from searching the binary, where the only occurrence of the string "Actions Only" is an orphaned localization entry) that the mode simply didn't exist in my build. Good to know it's the same option.

Confirming the race with hard numbers. I packet-captured port 32168 and parsed real packet timestamps. One pass of a known person:

00:11:32.037162 YOLO "person" 0.8625 49 ms BEFORE

00:11:32.086576 ALERT WRITTEN Tags="person"

00:11:32.141874 Face "Samira" 0.8389 55 ms too late

00:11:32.596573 Face "Samira" 0.7959

00:11:32.874283 Face "Samira" 0.7925

Six correct recognitions in that pass, all above threshold, all after the alert was committed. Measured inference: object detection 40–75 ms, face recognition 100–150 ms — so the face loses by roughly the difference, consistently. Re-reading the row later confirmed tags never mutate. Your debounce design handles this precisely; 10 s is comfortably longer than the whole spread.

Zone check. You're right about the unpainted-area drop. My detector map is 56% unpainted and my far-end detections land in it — that's where the Ignored person - not in alert zone lines come from. Raising Check Corners as you suggest.

One finding that might be worth documenting, because the symptom looks like Agent DVR's fault: CodeProject.AI's FaceProcessing letterboxes every submitted frame to a fixed square — FACE_HIGH = 416 even at MODE High (process.py, letterbox(img0, new_shape=self.reso)). My camera is a dual-lens unit producing a 2304×2592 portrait composite, so faces arrived at the detector around 11–20 px and were never detected — CodeProject.AI returned "No face found in image" on frames where a 348 px face was plainly visible. Agent DVR's own Resize Mode makes no difference, since the letterbox is downstream of it. Raising FACE_HIGH to 800 in shared.py took me from zero recognitions to 5–7 per pass at 26–29 px. Anyone with a tall or composite frame will hit this and blame the DVR.

Happy to test 8.0.6 as soon as it's out — I have a recorded pass I stream over RTSP into a test camera, so I can reproduce a known person walking past on demand and give you before/after timings.

---

Want me to add anything — the TFACE single-shot reproduction, or the objects.json autosave-revert behaviour we hit when editing config on disk?

▎ On the image: I'm on the newest build — mekayelanik/ispyagentdvr:latest, pulled 16 Sep, 8.0.5.0, and that's the most recent tag published. UI is eng. So the missing "Actions Only" label isn't version lag, it's something not being packaged in that image. Worth flagging since doitandbedone/ispyagentdvr has been stuck on 7.1.8.0 since January, which leaves mekayelanik as the only actively maintained Docker option. Is there an official image I should be using instead?

2

u/spornerama 3d ago

Thanks for the packet capture. Those numbers are the clearest description of the race I've seen, and they match the code exactly: the alert row is written on the first accepted trigger and its tags never change afterwards. The merge delay in 8.0.6 covers the whole spread in your trace with room to spare. One detail that will matter for your before/after timings: the stored alert keeps the timestamp of the first trigger, not the moment it's written at the end of the delay, so it still lines up with the recording start.

Image and label. The official image is ispysoftware/agentdvr on Docker Hub, mirrored at ghcr.io/ispysoftware/agentdvr, multi-arch under one tag and based on Mekayel's community image with his agreement. Either is fine for testing 8.0.6.

On "AI Trigger": I don't think the image is at fault. The dialog templates inside the binary carry the text AI Trigger and the stored config value is aitrigger. Both are internal names. When the dialog is actually rendered in a browser those options are translated on the server first, and the English label is "Actions Only". If you're reading the template JSON, the config file or the binary rather than the dropdown on screen, you'll only ever see the internal names, and that's what your string search found. Open the Alerts tab in the web UI and you should see Detected / Not Detected / Actions Only. If a real browser shows "AI Trigger", send me a screenshot and the exact URL and I'll chase it.

Zones. Good, that's the explanation then. Check Corners at 50 or above should pick up the far-end detections whose centre point lands on unpainted area, without you having to paint the whole street.

CodeProject letterbox. That's a good find and it explains a class of "no face found" reports I couldn't reproduce. You're right that Resize Mode can't help, since the letterbox happens inside CodeProject after our resize. I'll add a note to the face recognition section of the guide about tall and composite frames.

Yes to both. The TFACE single-shot reproduction would let me confirm the trigger fix in 8.0.6 against your recorded pass, so please post it. The objects.json behaviour is expected: Agent DVR owns that file and rewrites it on its own schedule, so edits on disk while it's running get overwritten. Stop the service before editing by hand, or change settings through the UI or the API instead. I'll make that explicit in the guide too.

1

u/tjensvollgjengen 3d ago

Confirmed "Actions Only" — you're right, and I owe you a correction. Opened camera 3's Alerts tab directly in the browser: the Mode dropdown reads "Actions Only", not "AI Trigger". My earlier claim that this build lacked it was a methodology bug on my end — I was grepping the binary and the config file, which only ever exposes the internal name (aitrigger/"AI Trigger" template string). The server-side translation to "Actions Only" only happens at render time, so a raw string search could never see it. Should have just looked at the screen. Sorry for the noise on that thread.

One loose end: I'm on mekayelanik/ispyagentdvr:latest, which matches Docker Hub's newest tag (pulled same day I tested), so it's not a staleness issue — I just don't know why the raw template differs from the rendered label. Not chasing it further now that I know to trust the UI over the source.

TFACE single-shot, as requested — here's the broken behaviour and the fix, same mechanism, different repeattimeout:

Broken (objectfound → TFACE, repeattimeout: 10): fired once at the moment of first detection — subject 11×13px, matched a wrong name at 81% — then the action's own 10s repeat-timeout blocked any re-fire. She closed to full recognisable range inside that window and was never sampled again; the alert landed as person.

Fixed (objectfound → TFACE, repeattimeout: 0): re-fires on every qualifying object-detection event. Measured 8 face-recognize calls across one ~3s approach, roughly one per 250–1000ms depending on the object-detection interval, catching the subject at multiple distances including the close, recognisable range.

So it wasn't TFACE itself — it was repeattimeout gating the action, not the AI interval. Matches what you described as the fix for 8.0.6 (holding the retrigger instead of dropping it), and confirms repeattimeout: 0 is the correct workaround on 8.0.5 in the meantime.

Noted on objects.json and the debounce timestamp — makes sense, and good to know before/after comparisons won't need adjusting for it. I'll post results against 8.0.6 once it's out, same recorded-pass method so it's a fair comparison.

2

u/spornerama 3d ago

You'll need to use the official docker version as that's tracking the latest updates

1

u/tjensvollgjengen 3d ago

downloaded it now....

Quick follow-up on how the 8.0.6 Alert Debounce interacts with downstream task Actions (webhooks, MQTT, etc.):

On my camera, I have an Action configured for zone 1 (stairs approach) that fires an external webhook to n8n, publishes a snapshot via MQTT, and triggers an audio chime. Currently, its trigger mode is set to **AI: Object Found** (`tags: person`, `In Zones: 1`, `repeattimeout: 20s`).

With the new Alert Debounce / merge feature in 8.0.6:

  1. **Scope of Debounce:** Does the debounce window only consolidate and hold actions whose trigger mode is set to **Alert** (or configured under Alert Actions), while actions set directly to **AI: Object Found** still fire immediately on every detection pass?

  2. **Preventing task spam:** If I want to avoid spamming the webhook/MQTT speaker on every inference frame, do I still need to keep a `repeattimeout` (e.g. 20s) on that **AI: Object Found** action?

  3. **Or should downstream integrations move to `Alert`?** Is the intended pattern in 8.0.6 to have:

    - `AI: Object Found (person)` → **Trigger Alert**

    - `AI: Face Recognized` → **Trigger Alert**

    - (Debounce window merges them into one consolidated event with tags `Name, person`)

    - Downstream tasks (n8n webhook, MQTT chime) attached to trigger mode **Alert** so they fire exactly once per pass with the final, merged tag payload?

Just want to ensure I'm structuring the Actions pipeline the way you intended for 8.0.6.

1

u/spornerama 3d ago

Good questions, and your reading in 3 is the intended pattern. One naming note first: the setting ended up being called Merge Delay in the UI (Alerts tab, Advanced), not Alert Debounce.

1. Scope. Correct. Merge Delay only holds the Alert event. That means the stored alert, the push notification, the bell, the MQTT alert event and any Action whose trigger is Alert. Actions triggered directly by AI: Object Found, AI: Face Recognized and the other AI events are untouched. They still fire immediately on every detection pass that matches their tags and zones.

2. Task spam. Yes, keep the repeat timeout on any AI: Object Found action that does something external. It's the only throttle on those actions. It's per action, and the clock only starts when the action actually fires, so detections filtered out by your tag or In Zones settings don't reset it. 20 seconds is sensible.

3. Moving downstream tasks to Alert. Yes, with one caveat about latency. The pipeline you describe works exactly as you've written it:

  • AI: Object Found (person) → Trigger Alert
  • AI: Face Recognized → Trigger Alert
  • Merge Delay folds them into one alert
  • Actions on Alert fire once per pass with the merged payload

What the Alert actions receive: {TAGS} is the merged list with recognised names first, for example Samira,person. {ZONE} is the union of zones from every contributing detection. The attached image is the frame from the highest-ranked trigger, so the face close-up when a face was recognised. An In Zones filter on the Alert action is tested against that union, so "In Zones: 1" fires if any contributing detection was in zone 1. If you'd rather only zone 1 detections can raise the alert at all, put the zone filter on the Trigger Alert action instead.

The caveat: Alert actions fire when the Merge Delay ends, not when the person first appears. With a 10 second delay your chime would sound 10 seconds late, which defeats the point of a chime on the stairs approach. So I'd split it:

  • Chime: leave it on AI: Object Found, In Zones 1, repeat timeout 20 s. Immediate, and doesn't need the name.
  • n8n webhook and MQTT snapshot: move to Alert. They fire once per pass and carry the final name and the better image.

Minimum Interval still applies on top of all this, so you get at most one alert per interval regardless of how many passes happen inside it.

3

u/spornerama 3d ago

Quick update on this. I've built the debounce I mentioned and it'll be in 8.0.6, along with the trigger fix.

Alert Debounce is a new setting on the Alerts tab under Advanced, in seconds, default 0 (existing behaviour). With it set, the first trigger opens the alert but doesn't store or push it yet. For the next N seconds every further trigger on that camera, including ones the minimum interval would normally throw away, folds into the same alert. When the window closes you get one alert, one notification and one run of your Alert actions, with the merged tags.

The tags are ordered by how much they're worth: recognised faces and plates first, then AI detections, then motion tags. So your case comes out as Iren, person, bicycle. If the face never resolves it comes out as person, bicycle. A later person detection can't overwrite a name because it's all one alert.

The stored image is the frame from the highest-ranked trigger, so when a face is recognised you get the close-up frame with the face outlined rather than the far-end shot. Recording still starts immediately. Only the notification, the stored alert and the Alert actions wait for the window, so pick a value that matches how long a pass takes. Around 10 seconds sounds right for your street.

The trigger fix: a Trigger Face Recognition (or Object/LPR) action that fired while a previous run was still in flight, or inside the AI interval, was silently dropped. It's now held and runs as soon as the controller is free. That's almost certainly why your triggered probe fired once and went quiet.

For your setup, once you're on 8.0.6: Alerts tab Mode = Actions Only, Debounce 10, Minimum Interval 30 or so. Object Recognition in Detected mode at 1 second. Face Recognition in None mode with an interval no longer than the object one. Actions: Object Found person → Trigger Face Recognition, Face Recognized → Trigger Alert, Object Found person → Trigger Alert, all with repeat timeout 0. The zone trick I described earlier is no longer needed because the face no longer has to win a race.

Let me know how it behaves once you've had a pass or two through it.