face-validator-sdk
v1.3.0
Published
Real-time selfie validation SDK with face detection, i18n (pt-BR, en, es). Built on MediaPipe.
Maintainers
Readme
Face Validator SDK
Real-time selfie validation SDK with face detection, powered by MediaPipe. Detects faces, hands, and validates pose, lighting, and occlusions in real-time.
✨ Features
Face Detection (478 landmarks)
- ✅ Distance validation: TOO_CLOSE / TOO_FAR
- ✅ Centering: Face must be centered in oval guide
- ✅ Head pose: Detects tilted or turned head
- ✅ Illumination: Validates proper lighting
- ✅ Stability: Ensures user stays still before capture
- ✅ Multiple faces: Rejects when more than one face detected
Hand Detection (NEW! 🎉)
- ✅ Hand near face detection: Prevents hand covering face (obstructions)
- ✅ 21 landmarks per hand: High precision tracking
- ✅ Real-time validation: Instant feedback
Additional Features
- 🌐 i18n: Portuguese (pt-BR), English (en), Spanish (es)
- 🎨 Visual feedback: Oval guide with color-coded status
- 🐛 Debug mode: Visualize landmarks and bounding boxes
- 📦 Multiple builds: ESM, CJS, UMD
- 🚀 GPU accelerated: Powered by MediaPipe with GPU support
📦 Installation (Core SDK)
For any web application (React, Angular, Vue, vanilla JS, Java backend with JS frontend, etc.) that wants to use the core validator:
npm install face-validator-sdkThe SDK declares
@mediapipe/tasks-vision(^0.10.15) as a regular dependency, so it is installed automatically when you installface-validator-sdk.
🚀 Quick Start (Core API)
import { FaceValidator, ValidationStatus } from 'face-validator-sdk';
const video = document.querySelector('video');
const canvas = document.querySelector('canvas');
const validator = new FaceValidator({
videoElement: video,
overlayCanvasElement: canvas,
locale: 'pt-BR', // 'pt-BR' | 'en' | 'es'
debugMode: false,
onStatusUpdate: (status, message) => {
console.log(status, message);
// Update UI with validation status
},
onCaptureSuccess: (blob) => {
// Upload or preview the captured selfie
const url = URL.createObjectURL(blob);
document.querySelector('img').src = url;
},
onError: (errorType, error) => {
console.error(errorType, error);
}
});
// Validator starts automatically
// To stop: validator.stop();📊 Validation Status
| Status | Description |
|--------|-------------|
| INITIALIZING | Loading MediaPipe models |
| NO_FACE_DETECTED | No face found in frame |
| FACE_DETECTED | Face detected, validating... |
| TOO_CLOSE | Face too close to camera |
| TOO_FAR | Face too far from camera |
| OFF_CENTER | Face not centered in oval |
| FACE_OBSTRUCTED | Hand covering face or low visibility |
| HEAD_NOT_STRAIGHT | Head tilted or turned |
| MULTIPLE_FACES | More than one face detected |
| POOR_ILLUMINATION | Insufficient lighting |
| STAY_STILL | Hold still for capture |
| CAPTURING | Taking photo... |
| SUCCESS | Capture successful! |
| ERROR | An error occurred |
⚙️ Configuration Options
interface FaceValidatorOptions {
// Required
videoElement: HTMLVideoElement;
onStatusUpdate: (status: ValidationStatus, message: string) => void;
onCaptureSuccess: (imageBlob: Blob) => void;
onError: (errorType: ValidationStatus, error: Error) => void;
// Optional
overlayCanvasElement?: HTMLCanvasElement;
locale?: 'pt-BR' | 'en' | 'es'; // Default: 'en'
debugMode?: boolean; // Default: false
// Validation thresholds
minDetectionConfidence?: number; // Default: 0.5
minIlluminationThreshold?: number; // Default: 70 (0-255)
minFaceSizeFactor?: number; // Default: 0.25
maxFaceSizeFactor?: number; // Default: 0.65
stabilizationTimeThreshold?: number; // Default: 1000ms
stabilityMovementThreshold?: number; // Default: 5px
minFaceVisibilityScore?: number; // Default: 0.5
maxHeadTiltDegrees?: number; // Default: 28°
maxHandFaceDistance?: number; // Default: 0.15 (normalized)
// Advanced
modelPath?: string; // MediaPipe WASM path (auto-detected from CDN)
customMessages?: Partial<Record<ValidationStatus, string>>;
}🧩 React Component: ReactSelfieCapture
If you are building a React application and want a ready‑to‑use selfie capture UI, the SDK exposes an optional React component that encapsulates:
- Camera access (
getUserMedia) - Validation loop (
FaceValidator) - Overlay drawing (oval + feedback)
- Preview step (photo + buttons)
- i18n for pt-BR, en, es
Installation (React project)
Your React app should already have react and react-dom installed. Then:
npm install face-validator-sdk
@mediapipe/tasks-visionis installed automatically as a dependency of the SDK.reactandreact-domare declared as peerDependencies – they are not bundled inside the package.
Non‑React applications should use the coreFaceValidatorAPI shown above instead ofReactSelfieCapture.
Basic usage
import { ReactSelfieCapture } from 'face-validator-sdk';
function SelfieExample() {
const handleCapture = (imageBase64: string | null) => {
if (imageBase64) {
// send to API, store, etc.
}
};
return (
<ReactSelfieCapture
locale={navigator.language} // 'pt-BR' | 'en' | 'es' (auto-normalized)
onCapture={handleCapture}
onDismiss={() => console.log('Modal closed')}
/>
);
}Props
type SupportedLocale = 'pt-BR' | 'en' | 'es';
type SelfieCaptureStyles = {
container?: React.CSSProperties;
media?: React.CSSProperties;
messageBanner?: React.CSSProperties;
primaryButton?: React.CSSProperties;
secondaryButton?: React.CSSProperties;
};
type SelfieCaptureUILabelOverrides = Partial<{
previewQuestion: string;
savePhoto: string;
tryAgain: string;
cancel: string;
}>;
interface ReactSelfieCaptureProps {
onCapture: (image: string | null) => void; // base64 data URL or null on cancel
onDismiss?: () => void;
// Behaviour
locale?: SupportedLocale | string; // Default: 'pt-BR' (auto-normalized)
videoWidth?: number; // Default: 512
videoHeight?: number; // Default: 384
debugMode?: boolean; // Default: false
modelPath?: string; // Optional MediaPipe WASM path; if omitted, uses internal CDN default
// Visual customization (inline styles)
styles?: SelfieCaptureStyles;
// Optional UI labels override (per-locale defaults exist)
labels?: SelfieCaptureUILabelOverrides;
}Labels and i18n
By default, the component renders UI labels in Portuguese (pt-BR), English (en) or Spanish (es):
- Preview question (“O que você achou?” / “What do you think?” / “¿Qué te pareció?”)
- Buttons (“Salvar foto”, “Tentar novamente”, “Cancelar”, etc.)
You can override any of these without having to set up an external i18n layer:
<ReactSelfieCapture
locale="pt-BR"
onCapture={handleCapture}
labels={{
previewQuestion: 'Confira sua selfie antes de salvar',
savePhoto: 'Confirmar selfie',
}}
/>Styling
The component ships with a sensible default layout, but you can tweak it via the styles prop:
<ReactSelfieCapture
onCapture={handleCapture}
styles={{
container: { borderRadius: 24 },
media: { borderRadius: 16 },
messageBanner: { backgroundColor: '#f0f9ff', color: '#0369a1' },
primaryButton: { backgroundColor: '#2563eb', borderColor: '#2563eb' },
secondaryButton: { borderRadius: 9999 },
}}
/>;Tip: you can wrap
ReactSelfieCapturein your own modal/dialog and passonDismissto close it from the Cancel button.
🏗️ Architecture
MediaPipe Integration
The SDK uses two MediaPipe models running in parallel:
- FaceLandmarker: 478 facial landmarks + face detection
- HandLandmarker: 21 hand landmarks per hand
📚 Why MediaPipe?
Migrated from face-api.js (discontinued 2021) to MediaPipe (Google):
| Feature | face-api.js | MediaPipe | |---------|-------------|-----------| | Landmarks | 68 points | 478 points | | Hand detection | ❌ None | ✅ 21 pts/hand | | Maintenance | ❌ Discontinued | ✅ Active (Google) | | Performance | CPU only | ✅ GPU accelerated | | Accuracy | ~60-70% | ✅ ~90-95% | | Model size | ~8MB | ~15MB |
🤝 Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit changes:
git commit -m 'feat: add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
📄 License
MIT License - see LICENSE file for details.
🙏 Acknowledgments
- MediaPipe by Google
- face-api.js (original inspiration)
📞 Support
- 🐛 Report Bug
- 💡 Request Feature
- 📧 Contact: GitHub Profile
