@framefind/coreDetect eyewear presence with confidence score
Glasses, head pose, blink — running fully local in the browser or Node.js via ONNX. Zero backend. Zero tracking.
import { useRef } from 'react';
import {
useGlassesDetector,
useHeadPoseDetector,
useBlinkDetector,
} from '@framefind/react';
export function App() {
const videoRef = useRef(null);
const glasses = useGlassesDetector({ videoRef });
const headPose = useHeadPoseDetector({ videoRef });
const blink = useBlinkDetector({
videoRef,
onBlink: (ear) => console.log('blink!', ear),
onFaceLost: () => console.log('face lost'),
});
return (
<div>
<video ref={videoRef} autoPlay playsInline muted />
{glasses.loading && <p>Loading…</p>}
{glasses.result && <p>Glasses: {glasses.result.glasses ? 'yes' : 'no'}</p>}
{headPose.result && <p>Yaw: {headPose.result.yaw.toFixed(1)}°</p>}
{blink.result && <p>Blinking: {blink.result.isBlinking ? 'yes' : 'no'}</p>}
</div>
);
}npm install @framefind/core @framefind/reactAll detectors live in @framefind/core with React hooks in @framefind/react. Models stream from CDN — zero bundle cost.
@framefind/coreDetect eyewear presence with confidence score
@framefind/coreReal-time yaw, pitch, and roll estimation
@framefind/coreMulti-signal blink detection with per-eye self-calibration
@framefind/coreThree-way face-mask classifier with on-device inference
@framefind/coreIris-based gaze direction with 3×3 screen region mapping
@framefind/coreAnti-spoof challenge for KYC and onboarding flows
@framefind/coreMouth-open detector for meeting UX and speaker indicators
@framefind/coreFatigue scoring from blink rate, yawns, and eye closure
@framefind/coreEngagement score from head pose and eye state
@framefind/coreHeart-rate estimation from facial micro-color changes
How it works
Everything runs locally. No cloud round-trip. No raw video ever leaves the browser.
Video Frame
Camera · Image · Node
MediaPipe
468 facial landmarks
ROI / Features
Eye · Face bbox · EAR
ONNX · Geometry
WASM · WebGPU · solvePnP
Result
Class · Angles · Event
Video Frame
Camera · Image · Node
MediaPipe
468 facial landmarks
ROI / Features
Eye · Face bbox · EAR
ONNX · Geometry
WASM · WebGPU · solvePnP
Result
Class · Angles · Event
5
live detectors
0 bytes
data sent to server
<30ms
typical inference
Sending 30fps over the network to cloud APIs causes severe lag. On-device inference delivers sub-100ms feedback with zero round-trips.
Transmitting user face data to servers creates GDPR/CCPA overhead and erodes user trust. FrameFind guarantees data never leaves the browser.
ONNX Runtime and MediaPipe are peer dependencies — loaded only when the detector needs them. Browser and Node builds ship as separate subpath exports, so your bundle stays minimal.
Weights and WASM runtimes are hosted on cdn.framefind.moraxh.dev (Cloudflare R2) — version-pinned, immutable cache, no jsdelivr/Google Storage dependency. ONNX Runtime stays a peer dep so your bundle stays lean.
Use cases
Face signals unlock new interactions across industries — without sending data to a cloud.
EdTech
Attention monitoring
Detect when a student looks away from the screen to flag disengagement.
Telemedicine
Fatigue detection
Monitor blink rate and head drooping to alert fatigued healthcare workers.
Gaming
Gaze & head tracking
Use head pose as a no-controller input for hands-free interaction.
Accessibility
Eye tracking UI
Navigate interfaces by gaze for users with limited motor control.
Automotive
Drowsiness alerts
Detect microsleeps and distraction in driver-assistance systems.
Video Conferencing
Engagement scoring
Surface attention signals to meeting software without uploading video.
Three steps from install to first detection result.
Install packages
npm install @framefind/core @framefind/react onnxruntime-webnpm install @framefind/core onnxruntime-nodeInitialize a detector
const { videoRef, result, loading } = useGlassesDetector();Or use the vanilla API: new GlassesDetector()
Read results in your render loop
if (result?.glasses) {
console.log(`Glasses! ${(result.probability * 100).toFixed(1)}% confidence`);
}import { useRef, useEffect } from 'react';
import { useGlassesDetector, useBlinkDetector } from '@framefind/react';
export default function App() {
const videoRef = useRef<HTMLVideoElement>(null);
const { result: glasses, loading } = useGlassesDetector({
videoRef,
threshold: 0.35,
});
const { result: blink } = useBlinkDetector({
videoRef,
onBlink: (ear) => console.log('blink!', ear),
onFaceLost: () => console.log('face lost'),
onEARChange: (ear) => console.log('ear:', ear),
});
useEffect(() => {
let stream: MediaStream;
navigator.mediaDevices
.getUserMedia({ video: true })
.then((s) => {
stream = s;
if (videoRef.current) videoRef.current.srcObject = s;
});
return () => stream?.getTracks().forEach((t) => t.stop());
}, []);
return (
<div className="max-w-sm p-4">
<video ref={videoRef} autoPlay playsInline muted className="w-full" />
{loading && <p>Loading model…</p>}
{glasses && (
<p>Glasses: {glasses.glasses ? 'Yes' : 'No'} ({(glasses.probability * 100).toFixed(1)}%)</p>
)}
{blink && (
<>
<p>State: {blink.isBlinking ? 'closed' : 'open'}</p>
<p>EAR: {blink.smoothedEar?.toFixed(3) ?? '—'}</p>
<p>Baseline: {blink.baselineEar?.toFixed(3) ?? '—'}</p>
</>
)}
</div>
);
}