npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ugx-face-liveness-react

v3.0.0

Published

React face-liveness component: on-device MediaPipe FaceLandmarker with a randomized head-turn challenge. Framework-agnostic detection core shared with ugx-face-liveness (Angular).

Readme

ugx-face-liveness-react

React face-liveness widget with an on-device MediaPipe FaceLandmarker and a randomized head-turn challenge. No server, no cloud, no cost — all detection runs in a Web Worker in the browser. It is the React counterpart to the Angular ugx-face-liveness library and shares the same detection core (liveness-challenge.ts + the MediaPipe worker), though the two are tuned independently — see the changelog for differences.

  • 🎯 Randomized anti-spoofing challenge (turn left / turn right) — a static photo can't pass it.
  • 🧠 Runs fully client-side (WASM + Web Worker). Nothing leaves the device.
  • 📦 Ships a <FaceLiveness> component and a headless useFaceLiveness() hook for custom UIs.
  • 🖼️ Returns a JPEG snapshot + an optional WebM recording of the challenge.

Installation

npm install ugx-face-liveness-react

react and react-dom (17–19) are peer dependencies.

Serve the static assets (required)

The model, WASM runtime and detection worker are shipped as static files, not bundled — they must be served by your app and reachable at a base URL (default /assets/face-liveness).

Copy the package's assets/ folder into your public/static directory:

# Vite / CRA (public/) — run once, or add to a "postinstall"/build step
cp -R node_modules/ugx-face-liveness-react/assets public/assets/face-liveness

That yields:

public/assets/face-liveness/
  worker/face-landmarker.worker.js
  mediapipe-wasm/…                    (~21 MB, SIMD + no-SIMD)
  models-v2/face_landmarker.task      (~3.6 MB)
  models-v2/efficientdet_lite0.tflite (~4.6 MB, phone/screen detection)

If you serve them somewhere else, pass options={{ assetBaseUrl: '/your/path' }}.

Upgrading: re-run the asset copy after bumping the package — a new version may add files (e.g. the phone-detection model above). If that model is missing, device detection is silently skipped; core liveness keeps working.

HTTPS + permissions: camera access requires a secure context (https:// or localhost).


Usage — the ready-made component

import { FaceLiveness, type LivenessResult } from 'ugx-face-liveness-react';

export function Verify() {
  const handleCompleted = (result: LivenessResult) => {
    // result.snapshot -> Blob (image/jpeg)
    // result.video    -> Blob (video/webm) | null
    upload(result.snapshot, result.video);
  };

  return (
    <FaceLiveness
      onCompleted={handleCompleted}
      onError={(message) => console.warn(message)}
    />
  );
}

Styles are injected automatically — no CSS import needed.

Props

| Prop | Type | Description | | --- | --- | --- | | options | FaceLivenessOptions | Tunables (see below). | | onCompleted | (r: LivenessResult) => void | Fired once the challenge is passed. | | onError | (message: string) => void | Camera denied, timeout, model error, … | | onFaceDetectionStatusChange | (isValid: boolean) => void | Alignment status flips. | | showDebug | boolean | Show the on-screen stage/yaw/inference readout. | | className | string | Extra class on the root element. |


Usage — headless hook (custom UI)

Want your own markup? Drive everything from the hook and render whatever you like:

import { useFaceLiveness } from 'ugx-face-liveness-react';

export function CustomVerify() {
  const { state, videoRef, canvasRef, start, stop } = useFaceLiveness({
    onCompleted: (r) => upload(r.snapshot, r.video),
    onError: (m) => alert(m),
  });

  return (
    <div>
      <video ref={videoRef} autoPlay muted playsInline style={{ transform: 'scaleX(-1)' }} />
      <canvas ref={canvasRef} hidden />
      <p>{state.instruction}</p>
      <progress value={state.progress} max={100} />
      {state.stage === 'idle'
        ? <button onClick={start}>Start</button>
        : <button onClick={stop}>Cancel</button>}
    </div>
  );
}

state (FaceLivenessState) exposes stage, instruction, status, progress, currentAction, isValidFaceDetected, lastDetectionResult, and more — enough to render any UI.

For non-React or fully manual control, the same logic is available as the framework-agnostic FaceLivenessEngine class (attach(), start(), stop(), subscribe()).


Options

| Option | Default | Description | | --- | --- | --- | | assetBaseUrl | /assets/face-liveness | Where the worker/wasm/model are served. | | detectionIntervalMs | 140 | Min ms between inferences. | | maxDetectionIntervalMs | 280 | Cap when the device is slow (auto-throttles). | | minDetectionConfidence | 0.55 | MediaPipe detection/presence threshold. | | timeoutMs | 25000 | Abort the flow if not completed in time. | | captureWidth / captureHeight | 640 / 480 | Requested camera resolution. | | videoBitsPerSecond | 600000 | Challenge recording bitrate. | | thresholds | {} | Partial<ChallengeThresholds> overriding the challenge tuning (e.g. { minFaceHeight: 0.4 }). Merged over the defaults; also drives the size of the on-screen alignment oval. | | deviceDetection | { enabled: true, scoreThreshold: 0.4, minFramesToFlag: 2, minFramesToClear: 2 } | Phone/screen presentation-attack layer (see below). Set enabled: false to skip loading the extra model. |

Phone / screen detection

When deviceDetection.enabled is on (the default), the worker also runs a small object detector (assets/models-v2/efficientdet_lite0.tflite). If a phone, tablet or monitor is held up in front of the camera — overlapping the face — the flow pauses and shows "Remove any phone or screen from view.", then auto-resumes once the device is gone. A phone lying in the background does not trip it (the device must overlap the face or dominate the frame).

Limitations — this raises the bar, it is not KYC-grade on its own:

  • It catches a device only when its body/bezel is visible. A screen cropped to fill the entire frame (no edges) looks like a bare face and can slip through.
  • Detection is client-side, so a determined attacker can still bypass it by injecting a fake video stream (a virtual camera). For high-stakes identity checks, verify liveness server-side as well.

Local development

npm install
npm run build        # builds the worker (esbuild) + the library (tsup)

cd example           # a Vite React demo that consumes the built library
npm install
npm run dev          # http://localhost:5173

How it relates to the Angular library

src/liveness-challenge.ts and src/face-landmarker.worker.ts are copied verbatim from ugx-face-liveness. The camera / worker / recorder / snapshot logic lives in a framework-agnostic FaceLivenessEngine; the React hook and component are thin shells over it, mirroring the Angular component's outputs (livenessCompleted, errorOccurred, faceDetectionStatusChange).