🎬 Kiddometer — What age is this video actually for?

The world's first 100% client-side engine that quantifies sensory overload, hyper-pacing and flashing in children's media — and turns it into a science-backed age rating, without a single byte leaving the device.

Machine Learning / AI · Built solo by Daniyal Khan · Build window: October 13–15, 2026

🧭 Inspiration — the blind spot hiding in plain sight

Every parent has done this: you hand a toddler a tablet, a video autoplays, and you think "it's a cartoon, it must be fine."

Then you check the rating. TV-Y. All ages. PG.

Here's the uncomfortable truth I couldn't stop thinking about: those ratings judge plot and profanity. They are completely blind to the thing that actually reshapes a developing brain in real time — how the video is built:

  • 🔪 A new shot every 1–3 seconds
  • 🔊 Jumpscares and sound stings 15 dB over the rest of the track
  • ⚡ Strobing and flashing that breaches the seizure-safety limit
  • 🌈 Extreme saturation and edge density that overloads a young visual system

In 2011, Lillard & Peterson showed that a fast-paced cartoon (~5.5 cuts/min) produced measurable executive-function deficits in 4-year-olds — immediately after watching, compared to a slow-paced one. A 2025 meta-analysis (Hinten et al., Developmental Science) confirmed the pattern across the literature.

And yet, in 2026, no consumer tool tells a parent the pacing, the loudness spikes, or the flash rate of the video in front of them.

I wanted to build the tool that answers the question parents actually ask: "Is this right for my kid?" — with data, not vibes.

💡 What it does

Current age ratings judge plot and profanity. Kiddometer quantifies the sensory signals that hijack early cognitive development.

Drop in a video — a local file, a direct URL, or a YouTube/Vimeo/TikTok link. In roughly ¼ of the video's runtime, Kiddometer decodes the audio-visual stream entirely inside the browser and returns:

Output What it is
🎯 A recommended age 0–3 · 4–6 · 7–12 · 13+ — driven by the strictest signal present
📊 Six quantified metrics Cuts/min, flashes/s, loudness peaks, sound-event density, on-screen motion, visual complexity
⚠️ A photosensitivity alert Raised automatically if the video exceeds 3 flashes/s (WCAG 2.3.1)
🕐 An intensity timeline Minute-by-minute color-coded breakdown of where the video gets hard
🔥 "Most intense moments" The exact segments to skip, in mm:ss ranges
💬 Plain-language advice "Turn the volume down, watch it with them, skip 4:12–5:00"
📄 A downloadable report Self-contained HTML with the full per-segment table

The verdict is not a black box: every number is traceable to a published standard, and the UI explicitly labels which thresholds are peer-reviewed and which are calibrated heuristics. The system performs automated feature extraction and classification across two modalities (vision + audio), replacing what a human rater would otherwise do manually — the same pattern used in modern content-moderation pipelines.

🔬 How it works — the science and the signal processing

The six metrics, and exactly how each is computed

Metric Technique (real implementation) Scientific basis
Visual cuts / min Frames downsampled to 160×90, converted to luminance, binned into a 32-bin histogram, and compared frame-to-frame with Pearson correlation; a correlation below 0.6 is a shot change Lillard & Peterson (2011) — ~5.5 cuts/min impaired executive function in 4-year-olds; Hinten et al. (2025) meta-analysis
Flashes / s Luminance tracked in 3×3 zones; a transition is a swing ≥ 0.1 in relative luminance that reverses direction with a dark side < 0.8; a flash = 2 opposing transitions; max counted in any sliding 1-second window, per zone (so one full-frame cut can't be miscounted as nine flashes) WCAG 2.3.1 / ITU-R BT.1702 — 3 flashes/s is the photosensitive-seizure limit at any age
Loudness peaks Audio decoded, downmixed to mono @ 22 050 Hz, K-weighted with highpass (38 Hz) + highshelf (1681 Hz, +4 dB) biquads per ITU-R BT.1770, measured in 400 ms short-term windows (EBU R128 style) ITU-R BT.1770 / EBU R128; WHO safe-listening (< 75 dB)
Sound-event density Onset detection via energy-flux peaks over a 50 ms envelope, with an adaptive threshold (median + 1.5 × (p90 − median)) and a 3 %-of-peak floor; events deduplicated at 1 s Christakis et al., PNAS (2018) — early audiovisual overstimulation and later attention problems
On-screen motion Mean absolute luminance change within shots (0–100 index) Calibrated heuristic
Visual complexity Sobel edge density per frame (0–100 index) Calibrated heuristic

The aggregation engine — where most "AI rating" tools quietly go wrong

  1. The video is split into 60-second segments.
  2. Each segment receives the age band demanded by its strictest metric.
  3. The global rating is the 90th percentile across segments — sustained intensity decides, so a single outlier minute can neither inflate nor deflate the verdict. Outliers are surfaced separately as intense moments.
  4. Any breach of the 3 flashes/s limit escalates to an explicit ⚠️ photosensitivity warning, regardless of the percentile.

🔍 Why this matters: the legacy version of Kiddometer used the mode (most common band) across segments. That meant a video with a few toddler-safe minutes and a majority of hyper-paced minutes could be rated toddler-safe. The 90th-percentile rollup was a deliberate correctness fix — and it's the kind of subtle scoring bug that separates a demo from a tool.

🔐 Privacy by architecture — not a policy, a physics fact

The video never leaves the device. Decoding, frame inspection, signal analysis and scoring all execute 100 % locally in the browser using native platform APIs.

This isn't a checkbox — it's the core design decision, and it solves the hardest problem in child-safety tooling:

Typical approach Kiddometer
Upload the child's media to a cloud server ❌ Nothing is uploaded — there is no server to breach
Store analysis history tied to an account ❌ No accounts, no tracking, no database
COPPA / GDPR-K exposure by design ✅ Compliance risk eliminated by construction
Parents must trust a privacy policy ✅ Parents can read the source and verify it

The optional backend exists for one reason: streaming platforms don't allow cross-origin video fetches. It relays bytes and stores nothing — no disk write, no log of content, no retention. And without it, everything else still works.

🏗️ Technical execution

Zero-build, zero-dependency vanilla JavaScript (ES modules). No frameworks, no bundlers, no WebAssembly blobs. ~2 600 lines of hand-written code that does real DSP on the client.

Kiddometer
├── docs/                          # 🌐 Static web app
│   ├── index.html                 #    Home · analysis · methodology · references
│   ├── css/styles.css             #    Design-token system (from design/desgin.pen)
│   └── js/
│       ├── video-analyzer.js      # 🎞️ Histogram cuts · Sobel edges · per-zone WCAG flashes
│       ├── audio-analyzer.js      # 🔊 BT.1770 K-weighting · short-term loudness · onsets
│       ├── scoring.js             # 📐 Age thresholds · 90th-percentile aggregation
│       ├── insights.js            # 🧠 Data-driven verdict, advice, tips, moments
│       ├── main.js                # 🎛️ Orchestration, rendering, report export
│       └── config.js              # ⚙️ Optional backend URL
├── backend/                       # ☁️ Optional FastAPI + yt-dlp byte relay (HF Space)
├── design/                        # 🎨 Pencil design source
└── app.py / core.py               # 🕰️ Legacy Streamlit reference

Engineering details I'm proud of

  • requestVideoFrameCallback fast path — the video plays muted at 4× speed in a tiny off-screen element, sampling every presented frame for accurate flash detection.
  • Deterministic seek fallback — if the browser presents too few frames (headless, throttled, exotic codecs), the analyzer detects it via a pair-coverage check and re-runs a seek-based pass at fixed ⅓-second steps. That pass can't sample fast enough for WCAG flash detection, so flashes is honestly reported as "not evaluated" rather than faked.
  • Background-throttling resistance — Chrome pauses muted media in occluded tabs, stalling long analyses. The analyzer force-resumes playback on pause and requests a Screen Wake Lock so the OS doesn't suspend the tab.
  • Audio/video bucketing parity — both analyzers independently merge a degenerate tail interval (< 5 s) into the previous segment, so the two pipelines produce index-aligned interval arrays that can be zipped safely.
  • Multi-layer anti-blocking backend — PO Token provider sidecar, Chrome TLS impersonation, a 4-client fallback chain, ffmpeg merge fallback for DASH-only streams, and 12-hourly yt-dlp self-updates.
  • Graceful degradation everywhere — no audio track? Say so. Degraded video path? Say so. No backend configured? Explain how to proceed manually instead of failing silently.

🎨 Design and usability

  • 🧒 Basic / Expert modes — a plain, warm verdict for a tired parent at 9 p.m.; full charts, sparklines, a distribution donut and a per-segment table for the curious.
  • ♿ Accessible by construction — semantic roles, aria-labels, keyboard-focusable dropzone, color-blind-safe band palette.
  • 🎯 Copy generated from the data — the verdict, the advice and the tips are assembled from the actual measurements and drivers, never hardcoded.
  • 📱 Responsive — works on the phone in a parent's hand.
  • 🌍 Free, open source, MIT-licensed, with an explicit disclaimer that it's an orientation tool, not a medical device.

🧩 Which challenge areas does Kiddometer address?

The brief asked for solutions to the sociotechnical challenges of protecting children in an age of AI. Kiddometer tackles three head-on:

Challenge area from the brief How Kiddometer delivers
✅ AI-powered content safety — detect or filter harmful / age-inappropriate content Automated computer-vision + audio-signal analysis flags sensory-toxic content that human ratings structurally miss
✅ Parental and educator tools — support safety without excessive surveillance Fully client-side; guidance comes from the parent's own file. No accounts, no tracking, no data collection, no monitoring of the child
✅ Trustworthy AI systems — evaluate, audit, or improve the safety of AI products used by children An auditable, open-source, standards-cited scoring engine anyone can inspect, re-run and challenge — including honest flagging of heuristic thresholds

🌍 Impact — measurable, scalable, lasting

  • Immediate: a parent gets an actionable verdict before the child watches — no account, no upload, no waiting.
  • Scalable to zero marginal cost: static files on any CDN. One video or ten million, the server bill is the same: $0.
  • Embeds anywhere: the same engine can drop into a browser extension, a smart-TV firmware layer, a school LMS, or a streaming platform's "watch with kids" mode — because it's dependency-free and runs on the client.
  • Compounding value: every heuristic threshold is a tunable parameter with a documented evidence: flag, and the repo explicitly invites calibration data and studies. The tool is designed to get more correct over time, in public.

Why it's a real "AI for child safety" contribution: it doesn't add another chatbot between a child and the world. It audits the media itself — using computer vision and audio signal processing — and hands the judgement back to the adult who knows the child.

⚙️ Built with

HTML5 Canvas · Web Audio API (OfflineAudioContext) · requestVideoFrameCallback · Screen Wake Lock API · Vanilla JS ES Modules · CSS design tokens · Python · FastAPI · yt-dlp · Docker · Hugging Face Spaces · GitHub Pages · Pencil (design)

🚀 Try it

git clone https://github.com/digiflowhelp-stack/Kiddometer
cd Kiddometer/docs
python -m http.server 8000
# → http://localhost:8000

No build step. No dependencies. Just a browser (Chromium-based recommended for full requestVideoFrameCallback support). Drop a video, wait ~¼ of its duration.

🏅 Judging criteria — where Kiddometer scores

Criterion Weight Where Kiddometer delivers
Technical Execution 25 % Real client-side DSP: histogram-correlation cut detection, per-zone WCAG flash analysis, BT.1770 K-weighted loudness, Sobel edge density — all in dependency-free vanilla JS, with a self-healing degraded path and an anti-blocking streaming backend
AI Relevance 20 % Automated computer-vision and audio-feature extraction replace manual human review; the system classifies content the way a human rater cannot — at scale and in milliseconds
Usefulness 15 % Answers the exact question a parent has, before the child watches, with concrete "skip this segment" guidance
Impact 15 % Zero-cost, zero-data, standards-cited, and portable into extensions, TV firmware and school platforms
Creativity 15 % Reframes content rating from subjective human opinion and text tags to quantitative sensory-signal telemetry — and fixes the aggregation flaw that made the naive version unsafe
Presentation 10 % Dual-mode UI, rich diagnostics, downloadable report, and a demo that shows the verdict changing on real footage

🎥 Demo

▶ Watch the 2-minute demo — drop a hyper-paced cartoon, watch the flash warning fire, then drop a calm documentary and see the verdict flip to 0–3.

Code: https://github.com/digiflowhelp-stack/Kiddometer

🙏 What I learned

That the most important safety signal in children's media was never measured — not because it's hard, but because nobody thought to look at the pixels and the waveform instead of the script. That client-side compute is now powerful enough to run broadcast-grade loudness standards in a browser tab. And that "privacy by design" is far more convincing when it's architecturally impossible to leak data than when it's a paragraph in a policy.


Built with ❤️ and a lot of ☕ by Daniyal Khan for the Child Safety in AI hackathon.

🛡️ 100% local · 🚫 0 bytes uploaded · 📖 peer-reviewed methodology · 🌍 built for every child's browser

Built With

  • audio-analysis
  • canvas-api
  • client-side
  • computer-vision
  • css3
  • docker
  • es-modules
  • fastapi
  • github
  • html5
  • hugging-face-spaces
  • javascript
  • mit
  • offlineaudiocontext
  • open-source
  • pencil
  • privacy
  • python
  • requestvideoframecallback
  • screen-wake-lock-api
  • signal-processing
  • vanilla-js
  • web-apis
  • web-audio-api
  • yt-dlp
Share this project:

Updates

Submission history