Earlier this week, an investor paused mid-call and said, “You’re processing biometrics in the browser with sub-50ms latency. But what stops someone from holding up a photo?” I didn’t have a real-time answer. I had assumptions—about spoofing being low-effort, about enterprise buyers layering in their own liveness—but not a technical one. The call ended. I opened a new tab, pulled the last 18 sessions from our internal logs, and started writing.
Most people think spoof detection requires machine learning, specialized hardware, or cloud-heavy inference. That’s true if you’re building a turnkey identity platform. But we’re not. EmoPulse is a behavioral perception layer. We don’t own the final decision—we feed signals. So when the gap was flagged, the real question wasn’t “How do we build a liveness model?” It was “What can we derive now from signals we’re already emitting?” That shift—away from prediction, toward deterministic signal logic—changed everything. It’s not flashy. But it’s fast. And it works.
Our /state vector already carries 47 biometric and behavioral signals: rPPG-derived heart rate, 52 ARKit blendshapes, blink frequency, gaze vector, facial action units, voice prosody. All extracted on-device via WebAssembly from a standard RGB camera. No cloud inference. No data exfiltration. Sub-50ms round-trip from frame to server. That means the raw material for anti-spoofing was already in flight—we just weren’t using it. The insight: liveness isn’t a new model. It’s a state machine over existing signals.
So I built a server-side scorer that runs on the Flask endpoint, analyzing a sliding window of the last five ticks per session. Three deterministic penalties:
BPM instability: If rPPG shows heart rate standard deviation >12 BPM across five ticks, it fails. Real faces have micro-variations, but not chaos. Synthetic surfaces, especially replays, cause rPPG to hunt—color shifts don’t map to physiology. This penalty catches phone screen replays.
Gaze and blink freeze: Gaze stability >95% (per MediaPipe normalized vectors) plus zero blinks over five ticks. Humans glance. Humans blink. Photos don’t. This is the printed photo signature.
Micro-expression burst: If micro-expression count >8 or Duchenne smile count >20 in the first tick, it triggers. Why? Because spoofers often start a video replay mid-laugh. Real onboarding ramps up. Replay starts peak.
Each penalty scores 0.3. Base liveness = 1.0. Threshold for live: 0.5. The validation set: 18 real human sessions (3 subjects), 2 spoof attempts (1 photo, 1 phone replay). Real sessions scored 0.6–1.0. Spoofs: 0.2–0.4. 100% separation. Margin: 0.2. Not perfect. But enough to close the easy gap.
We’re not replacing FaceTec or iProov. We’re preventing the lazy attack. And we did it in four hours—no new models, no cloud scaling, no client-side bloat. Just deterministic logic on signals we already compute.
This is the EmoPulse pattern: extract, derive, deliver. We implement peer-reviewed methods—Giannakakis et al., IEEE, MDPI—not train our own. Our stress classifier? Published path. Our HRV proxy? RMSSD-like, short-window, fixed weights. No ML training. No weights to drift. The stack runs on a $0/month Oracle ARM box in Chicago (4 OCPU, 24 GB RAM). The perception is in the browser. The intelligence is in the composition.
Shipping this liveness scorer didn’t just patch a gap. It proved the model: lightweight, deterministic, signal-native scoring beats waiting for “perfect” AI. It forces the next step—layering in ethical validation (Dr. Vasina is reviewing the penalty logic for consent implications) and preparing for real integration traffic. SLC Digital is in due diligence. The pre-seed round is open: EUR 2M at EUR 6M pre-money. But we still have zero deployed customers. Zero production partners. This is still ground zero.
But now, when an investor asks about spoofing, I don’t deflect. I show them the logs. I show them the 0.2 vs 0.7 gap. I say: “It’s not bulletproof. But it’s running. And it’s simple.”
What’s the simplest thing you’ve shipped that changed the conversation?
Top comments (0)