An event alert is only useful if its payload is triageable from a lock screen.
Most guides on security camera event alerts walk through the same checklist: pick your sensitivity, draw your zones, set a notification schedule. That checklist configures the trigger, not the payload. The trigger is the easy half. The hard half is what lands on the recipient's phone at 2 AM. This guide is about the nine fields an event alert has to carry for a recipient to decide, from the lock screen, whether to dispatch or dismiss. No login, no app, no scrub bar.
See a live event alert land on a phoneThe lock-screen test
Every event alert has a single job: to be acted on. Acted on means the recipient, reading a notification preview on a locked phone at 2:04 AM, can tell what happened, where it happened, and whether anyone needs to be dispatched. If the alert does not pass this test, it has failed, regardless of how many triggers, zones, and schedules were configured upstream. The full video, the desktop dashboard, the deep-linked clip, all of that is a fallback. The common case is a phone.
Most alert-configuration guides assume the recipient will always open the full app to get context. That assumption is what creates alert fatigue. A recipient who has to tap into an app to see what triggered the alert will eventually stop tapping. The payload itself has to be enough. Nine fields is the minimum. Fewer than that, and the recipient is forced back into the app. More than that, and the notification preview gets truncated.
Two alert bodies at 2:04 AM
Camera 7 motion detected. Tap to view live feed. 02:04:22.
- Channel number, not the camera's actual name
- No event class, only a pixel-change flag
- No thumbnail preview, only a text string
- Forces a tap into the app to learn anything
The alert body the phone actually shows
The iOS and Android notification previews truncate past roughly 100 characters on the lock screen. So the alert body has to front-load the fields that decide the dispatch. Order matters. First the tile label so the recipient knows where. Then the event class and duration so they know what. Then the property name so a regional manager can disambiguate across sites. The thumbnail is the attachment. Everything else stays in the JSON for the webhook consumers.
The same record that powers the notification preview also powers the webhook POST to a vendor, the row in the review dashboard, and the deep link to the underlying DVR clip. Write the nine fields once at capture, reuse on every delivery surface. That is why an event alert is a record, not a string. A string is what every other alert system in the category emits, and a string is why everyone with a camera system has muted their alerts at some point this year. 0 to 0 second median lag from incident to phone is only useful if what arrives on the phone is already enough to act on.
One record, many delivery surfaces
The edge box runs classification once per composite frame. That single inference pass produces one event record per tile that crossed a threshold. From there, the record fans out. WhatsApp for the on-call property manager. Webhook POST for the central-station operator. A row on the review dashboard for the morning triage. A push to the Cyrano iOS app if installed. Every surface reads the same nine fields.
One event record in, every alert channel out
What the payload actually looks like on the wire
This is one event record as it leaves the edge box. Flat JSON, nine scalars plus one small object for the tile, plus two helper fields (dwell_seconds and dvr_deeplink). The thumbnail is a URL to a 480x270 JPEG that renders in the notification preview without re-decoding the DVR blob. The WhatsApp message body is rendered from these fields. The webhook POST is these fields. The dashboard row is these fields. One shape, three surfaces.
What the notification preview looks like
Front-loading tile.label plus event_class plus dwell or zone info produces alert bodies that pass the lock-screen test. A sample strip from a busy overnight shift across a 25-camera property:
Compare to the default output of a DVR motion push, which reads Camera 7 motion detected on every tile. The difference is not aesthetic. It is operational. A property manager can triage the top strip in ninety seconds. The default DVR push cannot be triaged at all without opening the app.
The delivery pipeline, end to end
A phone-triageable event alert is the output of a chain that starts at the HDMI output of the DVR. The important property of this chain is that the classification happens before the payload is ever assembled. Every field in the alert body exists at the moment of capture, not at the moment of delivery.
Event alert sequence, capture to lock screen
The webhook POST
For integrators routing event alerts to a central station, a CRM, or a downstream automation, the delivery surface is an HTTP webhook. Same nine-field record, wrapped in a POST body. The receiving service gets the same shape the WhatsApp body is rendered from. No separate schema for human versus machine.
The four places the nine-field record shows up
Writing the record once at capture and reusing it on every surface means the property manager, the central station operator, the vendor CRM, and the morning reviewer all see the same language for the same incident. That consistency is what makes escalation possible without re-describing the event.
WhatsApp body
Message body: 'Loading Dock NE, loiter 62s, Maple Ridge'. Thumbnail attached. Tap-through deep links to the DVR clip. Fits the lock screen preview without truncation.
Webhook POST
JSON body with nine scalars plus tile, overlay_mask, thumbnail URL, and dvr_deeplink. Signed with X-Cyrano-Signature. Same schema as the WhatsApp source.
Dashboard row
Review table: tile.label column, event_class column, iso8601_ts column, thumbnail thumbnail column, dvr_deeplink action column. Filters hit the exact fields the alert body carries.
iOS push (Cyrano app)
APNS payload: alert body front-loads tile.label plus event_class. Rich notification attaches the 480x270 thumbnail. Long-press preview renders without opening the app.
DVR deep link
dvr_deeplink resolves to a browser-playable clip on the recorder, seeked to iso8601_ts minus a small buffer. Shared with law enforcement or insurance without extracting a file.
Portfolio CSV export
Filter the event table across a portfolio of mixed-brand recorders, export. Same nine fields per row. Audit evidence in one file.
Event alert vs. motion alert, field by field
The comparison that matters is not Cyrano versus another camera brand. It is the shape of an event alert versus the shape of a motion alert. Every DVR and NVR on the market can emit the second. A smaller set emits the first.
| Feature | DVR motion alert | Cyrano event alert |
|---|---|---|
| What the alert body says | channel number + 'motion detected' | tile.label + event_class + duration + property |
| Camera identifier in the body | CH7 or Camera 7 (channel assigned by the DVR) | Loading Dock NE (OCR'd from the DVR multiview strip) |
| What the classifier knows | pixel-difference threshold, no object label | person_in_zone, loiter, vehicle_dwell, tamper, package_tamper |
| Thumbnail preview | text only, or a full-composite thumb with every tile | 480x270 JPEG attached, renders on the lock screen |
| Capture-to-delivery latency | variable, unmeasured, reported only in app logs | 7 to 8 second median, measured per event in latency_ms |
| Dedup across a dwelling incident | one alert per motion-active segment, or continuous | one alert per dedup key within a cooldown window |
| Survives DVR multiview layout change | no, keyed on channel number | yes, keyed on tile.label |
| Same record on WhatsApp, webhook, dashboard | three separate formats | yes, one shape |
| Deep link back to DVR clip | open the DVR app, pick the channel, scrub | dvr_deeplink field resolves to a seeked clip |
The lock-screen checklist
A delivered event alert is lock-screen-triageable when the notification preview carries all of the following fields. Drop any one of them, and the recipient is forced back into the app, which is exactly the failure mode alert fatigue is made of.
Fields that must be in the alert body, not behind a tap
- tile.label: the OCR'd camera name, identical to what the monitor shows. First word in the alert body.
- event_class: person_in_zone, loiter, vehicle_dwell, tamper, or package_tamper. Semantic, not pixel-based.
- dwell_seconds or similar duration: turns a binary 'something happened' into a magnitude the recipient can weigh.
- thumbnail: 480x270 JPEG attached to the notification, rendered in the lock-screen preview.
- property: site identifier for regional managers covering multiple sites from one phone.
- iso8601_ts: recorder clock time, not delivery time. Separates 'this just happened' from 'this happened an hour ago and queued'.
- latency_ms: measured per event, so the phone shows when the alert is stale without needing a separate monitoring dashboard.
- dvr_deeplink: one-tap to the underlying DVR clip, seeked. No re-scrub, no separate login.
- overlay_mask: the DVR chrome regions blanked before inference. Audit field proving the classifier did not fire on a clock glyph.
From incident to decision, step by step
This is what the pipeline looks like from the moment a person steps into the alcove to the moment the on-call manager decides to dispatch or dismiss. The key property is that every decision-relevant field is frozen by the time the record leaves the edge box. Nothing is enriched at the phone.
HDMI composite frame enters the edge box
One frame carrying all 25 tiles of the multiview, 30 fps, 38 ms per frame budget. Recorder clock painted in the corner, camera name strips painted on each tile.
Overlay mask blanks the DVR chrome
clock, cam_name_strip, and channel_bug pixels are masked before the classifier sees them. overlay_mask value is captured into the event record for audit.
Per-tile person and vehicle classification
One inference pass on the composite produces bounding boxes, each mapped back to a tile.index via the layout_id. Persistence filter requires the box to survive 3 to 5 frames.
Event class written with duration
Tile-local timers turn a sustained detection into a specific class: loiter with dwell_seconds, vehicle_dwell with dwell_seconds, person_in_zone, or tamper if the tile goes dark or fuzzy.
Record materialises with all nine fields
tile.label (from OCR), tile.index, tile.coords, property, layout_id, overlay_mask, event_class, iso8601_ts, latency_ms. Thumbnail cropped from the triggering tile only.
Fan-out to WhatsApp, webhook, dashboard
Same record on every surface. Alert body front-loads tile.label + event_class + duration + property. Latency budget is 7 to 8 seconds median, 5 to 15 second envelope.
Lock-screen triage
Recipient reads the body on a locked phone. Dispatch or dismiss from the notification without opening the app. If context is needed, dvr_deeplink opens the clip.
What still goes to the DVR, and what does not
Nothing on the recorder changes. The DVR keeps doing whatever motion-triggered recording it was doing before. Cyrano reads the HDMI output of the recorder via an HDMI tap, does not touch the DVR config, and does not need RTSP credentials. The event-alert channel runs in parallel with the recorder, which means the original footage is still there for any window the classifier did not flag.
What goes away is the DVR motion push. Property managers with Cyrano event alerts flowing to WhatsApp typically mute or disable the DVR's own motion push rules within the first week. Not because the DVR push was wrong, but because it was redundant and noisier. The DVR keeps its motion-triggered recording segments for fallback retrieval, and the event alert channel carries the triage layer.
Want a live event alert to land on your own phone?
15-minute call. We plug Cyrano into a running DVR and walk you through one real alert from incident to lock-screen preview to dvr_deeplink.
Frequently asked questions
What is a security camera event alert, as opposed to a motion alert or a notification?
An event alert is a notification whose payload carries a classified incident, not just a pixel-change flag. The alert body contains an event class (person_in_zone, loiter, vehicle_dwell, tamper, package_tamper), the camera name the incident fired on, a cropped thumbnail, a timestamp on the recorder clock, and a deep link back to the underlying DVR clip. A motion alert, by contrast, is a one-bit signal that some set of pixels changed. The difference is whether a recipient can act on the alert from their phone without logging into anything. An event alert can. A motion alert cannot.
Why does the camera name inside the alert body matter so much?
Because at 2 AM, on a locked phone, the first word a recipient reads decides whether they act or dismiss. "Loading Dock NE, loiter 62s" is an action. "Camera 7, motion detected" is a dismissal. The name Loading Dock NE came off the DVR itself: Cyrano OCR's the cam_name_strip overlay painted by the recorder on the multiview, writes it into the tile.label field of the event record, and reuses that exact string in the WhatsApp message body. The camera name in the alert matches the camera name on the monitor matches the camera name in the filter chip on the dashboard. One label, three surfaces.
What are the nine fields inside one event alert payload?
tile.label (the OCR'd camera name), tile.index (row-major grid position), tile.coords (x, y, w, h in the composite frame), property (site identifier), layout_id (recorder multiview template), overlay_mask (DVR chrome regions blanked before inference), event_class (person_in_zone, loiter, vehicle_dwell, tamper, package_tamper), iso8601_ts (recorder clock time), and latency_ms (capture-to-delivery time). Plus a 480x270 JPEG thumbnail. Every Cyrano event alert carries all nine on the wire. The dashboard, the WhatsApp body, and the webhook POST all share the same record.
How fast does an event alert land on a phone from the moment the incident happens?
Median capture-to-delivery is 7 to 8 seconds on a 25-tile multiview, with a 5 to 15 second envelope across the portfolio. That includes HDMI capture, overlay masking, batched inference on the composite frame, multi-frame persistence, dedup, thumbnail crop, and WhatsApp or webhook delivery. The number is recorded as latency_ms on every event so you can chart p50 and p95 per property without waiting for staff to notice missed alerts.
What goes in an event alert body when the delivery channel is a webhook POST?
A JSON body with the same nine fields plus the thumbnail as a URL. Tile.label, event_class, iso8601_ts, latency_ms are scalars on the root. tile.index, tile.coords are nested under tile. property and layout_id identify the site and recorder layout. overlay_mask is a string array like ["clock", "cam_name_strip", "channel_bug"] so a downstream consumer knows which DVR chrome regions got blanked before classification. The thumbnail field is an https URL to a 480x270 JPEG crop of the triggering tile so a recipient's notification preview renders without decoding the full composite.
How does event dedup work when the same person is in frame for ten minutes?
Every candidate alert gets a dedup key of property + tile.label + event_class. If that key has fired within a configurable cooldown window (5 minutes for loiter, 30 seconds for person_in_zone), the new detection is suppressed instead of emitted. One person standing at a mailbox for ten minutes produces one WhatsApp alert, not 18,000 frames of alerts. A second person walking into the same tile while the first is still dwelling still fires, because the tracked object identity changes.
Can event alerts survive the DVR switching multiview layouts or a maintenance team re-cabling channels?
Yes. The alert payload is keyed on tile.label, not tile.index. Tile.label comes from OCR of the camera-name strip the DVR paints on the composite, which is stable across layout switches and channel swaps because the property manager wrote "Loading Dock NE" into the DVR config months ago. When the recorder switches from 4x4 to 5x5, tile.index shifts and tile.coords shift, but tile.label does not. An alert rule like "tamper on Loading Dock NE" keeps firing on the right camera through firmware updates, coax swaps, and layout changes. Alerts keyed on channel number break the first time maintenance touches the wiring.
Which event classes actually fire in production on a multifamily property?
Five classes cover about 99% of what property managers ask about: person_in_zone (someone crossed into a defined area), loiter (dwell time exceeds a threshold in a tile), vehicle_dwell (vehicle parked past a threshold in a tile), tamper (camera occlusion, spray, or frame drop), and package_tamper (object pickup from a detected package region). Every class writes the same nine-field record. The only difference is the event_class scalar, which downstream routing uses to decide whether to WhatsApp the property manager, webhook the vendor, or just log the row to the dashboard.
Does Cyrano replace motion alerts entirely, or do they still fire alongside event alerts?
The DVR keeps doing whatever motion-trigger recording it was already doing. Cyrano does not touch the recorder's config. What Cyrano adds is a second channel: the event alert, delivered over WhatsApp or webhook, keyed on classified incidents with 7 to 8 second latency. In practice, property managers mute or delete the DVR motion alert rules once event alerts are flowing, because the event alert is self-contained and the motion alert is not. The motion-triggered recording segments on the DVR disk stay available as a fallback archive.
What is the single thing to check if an event alert is not actionable from a phone?
Look at the alert body and ask whether a recipient with zero context could make a dispatch-or-dismiss decision without tapping through to anything. If the body is missing the camera name (tile.label), the event class, or a thumbnail preview, the alert is not actionable. Those three fields are the floor. Everything else is nice to have. A raw motion alert with a channel number and no thumbnail fails this test on every property.
Comments (••)
Leave a comment to see what others are saying.Public and anonymous. No signup.