Inspiration
CCTV is everywhere, but most cameras operate in isolation. Each sees a small part of the world and loses the story when someone leaves the frame. When violence or a medical emergency occurs, response still depends on a person watching dozens of screens, making a phone call, and relaying details that become less accurate with every handoff. Meanwhile, a suspect may simply move from one camera’s view into another. We asked: What if the incident moved through the camera network with them? Clarity turns separate camera feeds into one continuous incident. Evidence, suspect descriptions, risk level, and route predictions accumulate across cameras while responders receive live updates.
What it does
Clarity connects CCTV cameras as nodes in a Jac graph across Fort Mason and the Marina District in San Francisco. When a camera detects a violent incident or medical emergency, Clarity performs four steps:
- Detection Gemini analyzes the footage, classifies the incident, and returns structured evidence. Nothing is hardcoded. The dashboard remains empty until the model determines what occurred. A five-level policy then assigns risk. In our staged stabbing scenario, the incident is classified as: Level 5: Immediate Threat to Life
- Escalation Clarity uses Vapi to place a real outbound call to a configured responder. The call reports the incident, location, victim condition, and current evidence: “This is a simulated emergency exercise. A possible stabbing was detected near Marina Boulevard and Safeway. The victim is conscious and holding their abdomen on the ground. Do you acknowledge?” Every detail is generated from the video analysis. Clarity polls the live call status, and the dashboard updates to Responder Acknowledged when the call ends.
- Pursuit As the suspect enters another camera’s view, Clarity passes the accumulated description through the graph. Each camera: • Searches for the same person • Adds a new observation • Refines the suspect description • Updates the direction of travel • Reinforces the route taken • Predicts the next likely camera Four sightings remain part of one incident instead of producing four disconnected alerts.
- Live mode A phone can become a new camera node. It streams frames to the backend, Gemini analyzes a rolling window every four seconds, and a staged incident can turn the node red and trigger the responder call in roughly 20 seconds. All footage was staged by consenting participants. Calls only go to our configured demo number. The system blocks numbers ending in 911, and every call clearly identifies itself as a simulation.
How we built it
Jac is the core backend and orchestration layer, not a wrapper. There is no traditional incidents table. Each incident is represented as a connected subgraph: Incident → Suspect → Observation → Evidence → Risk Assessment → Predicted Route → Escalation Jac walkers such as DetectIncident, PropagateContext, and SelectNextCamera traverse and update this graph. Reading the case file means walking the graph. Jac represents 57% of the backend by line count.
Challenges we ran into
Gemini Live limitations We originally planned to stream video through Gemini’s Live API. Testing showed that the available Live models were designed for voice conversations and did not support the text output our pipeline required. We rebuilt the system around full-video generateContent requests and used rolling video windows for the live phone camera. Removing hidden hardcoding Our fallback system was silently merging scripted values into live model results. We removed that path and verified that the suspect description spoken during the call matched the clothing and appearance captured in the footage. Misaligned camera markers Camera markers appeared progressively farther from their correct positions, with CAM-04 nearly 90 pixels away. The issue came from a CSS position: relative rule overriding Mapbox’s required position: absolute. We confirmed the projected coordinates in the browser and corrected the styling. Telephony constraints We also handled E.164 phone formatting, prevented the Vapi agent from calling itself, and worked around account rate limits during the hackathon. Accomplishments we are proud of • Maintained one incident across four cameras without creating duplicates • Re-identified the suspect with match scores of 0.84, 0.73, and 0.79 • Expanded the suspect description as new evidence appeared, including recognizing short dark hair after the hood came down • Generated a phone call using the incident type, location, and victim condition extracted seconds earlier • Reinforced graph edges after confirmed routes, improving future movement predictions • Turned a phone into a live camera node • Triggered a real responder call within 20 seconds of a staged incident
Accomplishments that we're proud of
What we learned
What's next for Clarity
Medical emergency response The graph already supports incidents such as collapse and unresponsiveness through an EMS escalation policy. The next step is a complete medical-response demonstration with dispatch-ready information. Stronger re-identification We plan to replace description-based matching with visual embeddings while keeping the same Jac graph traversal and context propagation. Concurrent incidents Clarity should support several incidents moving through the graph simultaneously without mixing their evidence or predictions. Two-way responder calls Vapi webhooks could allow responders to ask questions such as: “Which direction is the suspect moving now?” Clarity could answer directly from the latest graph state. Privacy by architecture Future versions will prioritize on-device analysis, strict retention limits for observation nodes, and policies that prohibit identity inference. Clarity should demonstrate that public-safety systems can preserve continuity of context without enabling unrestricted surveillance.
Log in or sign up for Devpost to join the conversation.