Skip to content
All work

Case study · 01 / 08

PPE Safety Platform

A local-first, offline-capable PPE compliance platform that runs on one on-site server — it watches existing RTSP cameras, tracks every person, checks the PPE their zone requires over seconds rather than single frames, keeps snapshot-and-clip evidence for every confirmed miss, and learns from what the safety team reviews.

Missing before a violation opens — never one frame
3 s
Video, evidence and models stay on the site server
0 cloud
Helmet to harness, plus custom site types
10 PPE types
No model goes live without a golden-set check
Human-gated
Screenshot of PPE Safety Monitoring Platform

Context

Industrial sites need to know who is on the floor without a helmet or vest, but cloud video analytics means streaming CCTV off-site, and naive detectors raise an alarm on every flickering frame until people stop looking. Off-the-shelf PPE models also confuse cloth caps with helmets and miss small items seen from high, wide camera angles. The brief: run entirely on one local server, never decide from a single frame, attach proof to every event, and get better on each site's own footage — without a model ever being swapped in behind a person's back.

I lead the platform at Alta Vision as its architect and decision-maker — I set the product brief and requirements, signed off the architecture (Python vision and trainer services, a Bun + Hono API, a Next.js console, one-server deployment), and I make the product calls and own the milestone roadmap from the first client go-live to a white-label product.

01

Tracks, not frames — violations confirmed over seconds

Each camera's light sub-stream runs person detection, ByteTrack tracking, then a PPE detector on batched person crops; an associator assigns every item to the right body region of the right track. Presence is smoothed per track and PPE type, and a person is judged by the smallest zone their feet stand in, after an entry grace period. A violation opens only after an item stays missing for 3 seconds and clears after 2 seconds of being seen, with one event per episode, a 60-second cooldown and an 80 px minimum person height — so a flicker never raises an alarm. Rules are a matrix of zone × PPE type, each with a severity and optional hours and weekdays.

02

Evidence with every event

The main stream is recorded continuously to local SSD as 60-second ffmpeg segments, stream-copied and never re-encoded. When an event closes, the recorder cuts a clip from 5 seconds before to 5 seconds after it, and annotated and raw snapshots come from a per-camera ring buffer of the last 3 seconds. Reviewers mark each event true or false positive, and false positives flow straight into the training queue. If the API is unreachable, events spool to disk and replay when it is back — detection never stops.

03

A learning loop with a human at the gate

The miner saves hard examples — PPE probabilities stuck in the uncertain band, low-confidence people, unusual-looking frames — rate-limited per person and camera. Reviewers correct boxes in a label editor and approve samples into immutable dataset versions. Training fine-tunes the active model during configured idle windows and pauses whenever live cameras need the GPU. Every candidate is scored against a permanent golden set it is never trained on, and activation stays manual: a passing score or a written reason, with one-click rollback.

04

People across cameras, privacy by default

Each confirmed track gets an appearance embedding, which re-attaches people after occlusion on the same camera and links them across cameras into a stable id such as P-1A2B3C4D with a journey of where they were seen. Face recognition is opt-in and matches only people an admin has named; face data of unnamed people is deleted after 7 days by default. PPE checking can be switched off per camera, which unloads the model and frees the GPU for security-only use.

05

One codebase from a MacBook to a GPU server

An InferenceProvider abstraction hides the backend behind one Detections contract — PyTorch on Apple Silicon MPS or CUDA, ONNX Runtime on CPU, CUDA or TensorRT — so it is developed on a Mac and deployed on Linux + NVIDIA with no code changes. Class maps let any model's vocabulary drive the configured PPE types, including "no helmet" classes counted as evidence of absence. Rule and setting changes hot-reload to every camera within 15 seconds, and go2rtc gives sub-second WebRTC live view with an annotated MJPEG fallback.

Stack & architecture

  • Next.js 16 operator console: monitor wall with kiosk mode, zone editor, rules matrix, events, datasets, training, models, analytics, ⌘K palette
  • Bun + Hono + Drizzle API: auth, four-role RBAC, audit log, WebSocket events, WebRTC signalling proxy, idle-training scheduler
  • Zod contract package shared by the web app and the API
  • Python vision service: decode → detect → ByteTrack → PPE association → temporal rules → events, plus recorder and hard-example miner
  • Python trainer service: immutable dataset versions, idle-aware fine-tuning, golden-set evaluation, candidate registration
  • Inference providers: PyTorch (MPS / CUDA), ONNX Runtime (CPU / CUDA / TensorRT), and a DeepStream integration point
  • PostgreSQL 17 — or embedded, file-backed PGlite for single-box installs — with Redis for heartbeats, live frames and the training queue
  • go2rtc for sub-second WebRTC live view; ffmpeg stream-copy recording to local SSD with retention by free space and age
  • Caddy HTTPS (Let's Encrypt or an internal CA for offline sites), Docker Compose with the NVIDIA runtime, systemd units, one-click Windows and macOS installers
  • Python
  • PyTorch
  • ONNX Runtime
  • TensorRT
  • ByteTrack
  • Next.js 16
  • Bun + Hono
  • PostgreSQL
  • Redis
  • go2rtc
  • Docker

What's next

  1. 01 · In progress

    Accounts

    Request access from the sign-in page with admin approval, password reset that works offline through one-time admin links, invitations and change password. The server side is done; the screens are being built.

  2. 02 · Next

    Client go-live

    Camera presets, NVR bulk add and areas; one event for a person seen by overlapping cameras; visits and incidents with evidence packs; a storage view with disk forecast and 90-day retention; Test bench A/B compare; branded PDF and CSV reports; a load test and handover documents.

  3. 03 · Planned

    Sell-ready white label

    Signed licences with modules and camera limits, an Apps page that switches products on and off, and compiled releases with a licence server. The default model stack moves to licence-safe Apache-2.0 detectors such as RF-DETR, with every model's licence and provenance on record, plus a hygiene and food-safety PPE preset.

  4. 04 · Later

    Security system

    No-go zones with schedules, watchlist alerts, camera tamper, alarms and a site map — plus safety checks: fire and smoke early warning, person down, phone use, forklift proximity, safe corridors and occupancy limits.

  5. 05 · Later

    More apps

    A CCTV playback timeline with export and PTZ; people counting and area analytics with line counts, occupancy, heatmaps and dwell; vehicles and number plates; video search by text description; and time and attendance.

Where it stands