Inspiration
Light is everywhere, and almost everyone carries a camera. I wanted to know: can an ordinary phone reveal something hidden about the energy systems around us? The idea of extracting electrical network frequency (ENF) from video is established research, but existing tools are either lab-grade, platform-locked, or opaque. I saw an opportunity to build something different: a browser-local, privacy-preserving optical lab that makes the measurement process transparent—and, just as importantly, knows when to say “I’m not sure.”
The real inspiration came from a failure. Early versions averaged large areas of the frame, and dark backgrounds or mixed light sources would dilute or cancel the signal. I realized that honest rejection is harder—and more valuable—than a plausible-looking number. That principle now drives every design decision.
What it does
GridLens turns ordinary video into transparent, browser-local optical evidence. It:
- Decodes video frames directly (no reliance on playback callbacks) and extracts timestamped brightness time series from nine independent regions.
- Searches each region for periodic signals using sinusoidal least-squares fitting.
- Checks for competing signals, clipping, dropped frames, and temporal consistency across time blocks.
- Refuses to report a single-frequency result when evidence is ambiguous, and explains exactly why a scan is inconclusive.
- Presents results with acquisition method, frame count, assumptions, and calibration limits—no black box, no overclaims.
- Works entirely in the browser. No video is uploaded.
It does not claim to measure electrical grid frequency. It reports optical periodicity with explicit boundaries. Any electrical interpretation is conditional and clearly labeled.
How we built it
The pipeline is entirely client-side:
- Acquisition — A dedicated decode worker extracts frames sequentially using browser video/canvas APIs. A frame sampler builds a precise timestamped brightness series.
- Regional analysis — The frame is divided into nine fixed regions. Each region is analyzed independently to avoid phase cancellation and to localize the signal.
- Signal engine — For each region, a sinusoidal least-squares fit scans a frequency range. Peaks are validated against noise floor, harmonic structure, and temporal persistence.
- Cross-checks — Independent regions must agree. Temporal blocks must agree. Clipping and frame-drop fractions are computed and thresholds are enforced.
- UI — A Web Worker keeps the interface responsive. Results show evidence tabs, regional grids, rejection reasons, and a validation page that runs known test videos through the exact same pipeline as uploads.
The codebase includes 54 automated tests covering phase cancellation, dark backgrounds, competing lights, drifting frequencies, dropped frames, and rounding errors. All tests pass.
Challenges we ran into
- Dropped frames. Early versions relied on
requestVideoFrameCallbackand playback timing. The latest browser test failed because frames were silently dropped. I replaced this with direct sequential decoding, which recovered all 540 frames from each control video. - Phase cancellation. Averaging a large central area could cancel out the very signal we wanted. Independent regional analysis solved this.
- Aliasing and exposure. Camera exposure can suppress flicker; different lights can alias to the same apparent frequency. We added explicit checks and refuse to report when aliases are plausible.
- Competing signals. Two light sources with different rhythms would previously be merged into one bogus peak. Now they are detected and reported as competing signals.
- Rounding errors. Accumulated clipping fractions could round slightly above 100%, causing valid video to be rejected. Fixed at capture time with a regression test.
- Over-strict checks. A slowly drifting frequency was initially treated as two competing signals. We distinguished real change over time from genuinely different rhythms.
Accomplishments that we're proud of
- Complete acquisition: 540/540 frames decoded for all three encoded control videos.
- Browser validation passed 3/3: detected the intended 8.000 Hz signal, correctly rejected steady light, and correctly rejected competing rhythms.
- Honest rejection logic: the app frequently returns “inconclusive” and explains why—this is a feature, not a bug.
- Privacy-preserving: all processing is local; no raw video leaves the device.
- Reproducible validation: a public validation page runs the same pipeline on known fixtures, so anyone can inspect the results.
- 54 passing automated tests and a clean browser upload-to-result workflow with no console errors.
- Clear scope: the product is framed around optical measurement, not unsupported grid identification.
What we learned
- Measurement validity is the hard part, not the UI.
- Camera exposure, scene content, and codec behavior can silently break a naive detector.
- A correct system sometimes must refuse to produce a number.
- Direct frame decoding is essential for reliable timing; playback callbacks are not enough.
- Independent regional analysis is more robust than global averaging.
- AI-assisted development can accelerate progress, but the engineering decisions must be understood and defensible. I can explain every threshold, failure mode, and design choice.
What's next for GridLens
- Physical validation: record controlled clips with a known light source and an independent reference (oscilloscope + photodiode, or a calibrated ENF logger). Publish all results, including failures.
- Real stakeholder: partner with an energy researcher or community-energy organization to identify a concrete decision that optical measurements could inform.
- Broader format support: investigate full-frame decoding on additional codecs and devices.
- User-selectable regions: let users preview and choose the analyzed area.
- Acquisition preflight: warn about clipping, unusable area, and timing suitability before analysis.
- Environmental impact measurement: only after a real partner and a measurable outcome exist. Until then, we explicitly state that environmental impact is not yet measured.

Log in or sign up for Devpost to join the conversation.