Quintrix ITSO: My Final-Year Project — 60% Less CCTV Storage by Scoring What Happens
Our 2nd-place InOrbit research project: 15-second segments, a MOG2 motion gate, fine-tuned YOLOv8s, R3D-18 on UCF-Crime, an auditable fusion score and three storage tiers — plus the seven defects we only found by measuring.

Final-year undergraduate research project · Department of Computing, Rajarata University of Sri Lanka · ICT 3411 & COM 3405 · Supervisor: Ms. A.K.N.L. Aththanagoda · 2nd place at InOrbit among all technology projects. Built by a team of five — my part was the upload pipeline, 15-second segmentation, tiered storage and the review queue.
A surveillance camera records 24 hours a day. An operator usually needs a few minutes of it. In between sit hours of static corridors and routine movement, all stored at the same quality, all making the one important moment harder to find.
Storage lifecycle rules don't help: they move video to colder storage by age, not by content, so last night's robbery and last night's empty car park expire on the same schedule. Motion-based recording doesn't help much either: it tells you something changed, not that it mattered.
Our research question was simple to say and hard to answer: can content-aware tiering reduce storage while prioritising important footage?

The operator dashboard: 60.0% of uploaded footage size saved across 255 analysed segments.
From upload to searchable archive
Upload footage
→ 15-second segments
→ Motion filter (MOG2) ── little or no motion ──► LOW route
→ Activity: object + action + scene-risk analysis
→ Context-aware significance score (S_sig)
→ Configured thresholds
HIGH full-quality video + metadata
MEDIUM compressed video + metadata
LOW keyframes + metadata
→ SQLite metadata + files on disk → timelines, playback, alerts, forensic searchThe 15-second segment is the unit everything reasons about. The MOG2 motion gate is cheap, and with frame sampling it cut the frames sent to the models by 91.7%.

The models — and why they changed
| Signal | Model | What it answers | Result |
|---|---|---|---|
| Motion | MOG2 | Is anything happening? | Static segments skip deep analysis |
| Objects | YOLOv8s, fine-tuned on 8 threat classes | What is visible? | Precision 0.936 · Recall 0.900 · mAP@0.5 0.954 · mAP@0.5:0.95 0.736 |
| Context objects | YOLO11m | People, bags, crowd | Second detection track |
| Actions | R3D-18 on UCF-Crime (14 classes, 4,200 clips) | What happens over time? | 95.71% test accuracy on 630 held-out clips · macro F1 0.96 |
| Scene risk | 16-feature MLP (16→64→32→1) | How risky is this scene? | MAE 0.0567 · RMSE 0.0753 · R² 0.9375 |
Earlier versions used pretrained COCO and Kinetics models. Two problems pushed us to train: generic COCO YOLO has no gun or knife class, and Kinetics actions ("playing guitar") carry no security meaning. The YOLOv8s threat detector was fine-tuned for 80 epochs at 640 px (batch 16, 4.6 h on a Colab GPU) on gun, knife, rifle, fire, smoke, unattended bag, mask and broken glass. R3D-18 used a 70/15/15 split (2,940 / 630 / 630); its weakest class is robbery at 84.44%.

Image Lab: the fine-tuned detector finds a gun at 71% on real robbery CCTV in 631 ms on the M2 GPU.
Fusion: one auditable score per segment
S_sig = 0.40·A + 0.35·O + 0.25·S + ΣΔctx − U
A action severity × (0.5 + 0.5 · confidence)
O max threat × (0.6 + 0.4 · persistence)
S scene-risk MLP output
Δctx context modifiers: weapon, fire, crowd, night, unattended
U penalty when the action model is undecidedA critical hazard — gun, knife, fire — floors the tier to HIGH whatever the sum says. This is weighted-sum late fusion in the style of Atrey et al. (2010); the weights are the team's own and live in engine/fusion.py.
On a real gun-point robbery the player shows the reasoning: a gun detected at 74% over 9 frames adds the weapon modifier, three people add the crowd modifier, the hazard floor applies, and the segment scores S_sig 1.000 → HIGH, kept lossless.

S_sig is a decision aid, not a probability that a crime occurred. A wrong LOW decision loses the full sequence — which is why calibration and the review queue exist.
Calibrating against the worst mistake
The dangerous error isn't a false alarm. It's a critical event stored LOW. We simulated four score distributions (6,000 samples each) and measured the worst-case critical-to-LOW miss rate:
| Low / high thresholds | Worst-case critical → LOW |
|---|---|
| 0.40 / 0.70 | 6.43% |
| 0.30 / 0.90 | 1.27% |
0.30/0.90 also lowered the mean storage index from 0.269 to 0.227. These trade-offs ship as five operating-mode presets — Forensic Hold, High Security, Balanced, Storage Economy and Edge / Low Power. They're simulations, not real-world safety validation, and we say so.
And because LOW-tier degradation is irreversible, segments wait 72 hours in a degradation review queue where an operator can restore them.

Results
Storage: 60.0% reduction. 17 videos, 62.9 minutes, 443.3 MB uploaded → 177.4 MB retained, across 255 segments (46 HIGH, 143 MEDIUM, 66 LOW). That beats the proposal's >50% target.
saving = (1 − retained / uploaded) × 100 = (1 − 177.4 / 443.3) × 100 ≈ 60.0%Savings depend on what the footage shows — which is the whole point:
| Footage | Saved | Why |
|---|---|---|
| Mall gun-point robbery | ~25% | Most of it correctly kept HIGH |
| Static scene | ~95% | Almost nothing happens |
Speed. 1.43× real-time on an Apple M2. Per 15-second segment: CPU 6.6 s vs GPU 1.3 s — the GPU was 3.4× to 6× faster for every model (same machine, same script, 3 warm-up and 20 timed runs).
Software. API P95 15.2 ms (target < 80 ms); P99 ≤ 18 ms on every endpoint; 15,576 of 15,576 load-test requests answered; 173 regression tests pass in 19 seconds. Reviewers rated it 4.15/5 (4 reviewers, 10 criteria).
Defects we only found by measuring
This list is my favourite slide in the deck. Every one has a named regression test.
- Segmentation inflated storage 3.7× → switched to ffmpeg stream copy.
- The savings baseline was self-generated — a reported 78% saving was really −3%.
- The motion gate never filtered → warm-up frames plus a sustain window.
- Detectors only saw the first second of each segment.
- 100 concurrent uploads all got stuck (0/100) — one thread and one ffmpeg per upload. A bounded worker pool and queue fixed it: 100/100 in 551 s.
- Orphaned alerts after deletes → foreign-key cascades.
- Playback popup blocked → inline player.
Earlier documents described Flask, Next.js, X3D-S and an 84.6% saving. The built system is FastAPI, vanilla JS, R3D-18 and a measured 60.0%. Correcting our own numbers was part of the work.
Engineering choices
- FastAPI + bounded job queue, Python services, OpenCV, PyTorch, YOLO and FFmpeg.
- SQLite in WAL mode, 12 normalised tables (project → footage → segment → events / alerts), FK cascades with
foreign_keys = ON, indexed search P95 5.2 ms. Video files stay on disk. - Three roles enforced server-side (403 tested), random session tokens, a 57,263-entry audit log.
- Device layer: CUDA, then MPS, then CPU, automatically.
- CI/CD on Ubuntu, macOS and Windows with GCP and Hugging Face deploy targets. The pipeline is in How I Ship 23 Projects.
- Honest hardware reporting: every inference result was measured on a physical M2 (
hv_vmm_present = 0); training ran on a Colab CUDA VM; Docker on macOS is CPU-only because it runs in a Linux VM.

My part
I owned the path from file to storage: upload, 15-second segmentation, the tiered storage writers (HIGH / MEDIUM / LOW) and the degradation review queue. That's where two of the defects above lived — the 3.7× segmentation inflation and the 0/100 concurrency failure — and fixing them taught me more than building the first version.
Limitations and what's next
The integrated storage evaluation uses 17 videos on one test platform; the scoring rubric is expert-made rather than annotated video; there's no audio yet; and session tokens don't expire. Next: live RTSP streams at the edge, multi-camera processing, an audio branch (gunshot, scream, glass), validation on independently labelled local CCTV, and expiring tokens.
Contribution: an integrated significance-scoring, three-tier storage and searchable-metadata workflow. The results support prototype feasibility; wider validation comes before broader claims.
Finished this one?
Progress is saved in this browser.


