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

react-native-liveness-kit

v0.1.0

Published

On-device face liveness, gesture verification and age estimation for React Native using ONNX Runtime

Readme

react-native-liveness-kit

npm version license platform

On-device face liveness detection, gesture verification and age estimation for React Native, powered by ONNX Runtime.

100% offline. Every model ships inside the package and is loaded straight from the app bundle. There are no backend servers, no cloud APIs, no network calls, and no model downloads at runtime — the library works with the device in airplane mode. The only network use is optional, one-time, and at build time: when you clone this repo for development you fetch the .onnx files once (see Getting the models); end users who npm install the package get the models pre-bundled and never download anything.

Features

  • 100% on-device & offline — no backend, no APIs, no internet at runtime
  • Models bundled in the package (loaded from the app bundle, never downloaded)
  • ✅ Three components: Liveness, Gesture Verification, Age Estimation
  • TypeScript first (strict: true)
  • Pure React Native CLI — no Expo

Installation

npm install react-native-liveness-kit \
  onnxruntime-react-native \
  react-native-vision-camera \
  react-native-fs \
  @react-native-community/image-editor \
  react-native-image-picker

All of these are peer dependencies — install them in your app. Then, on iOS:

cd ios && pod install && cd ..

No Expo, no Expo modules. The library uses only community React Native CLI packages: react-native-fs (read/copy files), @react-native-community/image-editor (crop/resize) and react-native-image-picker (camera/gallery for age estimation).

Required metro.config.js change

This is the only mandatory configuration step. Add 'onnx' to resolver.assetExts so Metro bundles the models as assets:

// metro.config.js
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');

const config = {
  resolver: {
    assetExts: [...getDefaultConfig(__dirname).resolver.assetExts, 'onnx'],
  },
};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);

You also need camera (and, for age estimation, photo-library) permissions:

  • iOS (Info.plist): NSCameraUsageDescription, NSPhotoLibraryUsageDescription.
  • Android (AndroidManifest.xml): android.permission.CAMERA.

See example/ios/LivenessKitExample/Info.plist and example/android/app/src/main/AndroidManifest.xml for working values.

Usage

Liveness Detection

import { LivenessCheck } from 'react-native-liveness-kit';

<LivenessCheck
  onSuccess={(r) => console.log('Live!', r.confidence)}
  onFailure={(e) => console.warn(e.code, e.message)}
  threshold={0.75}
  requiredFrames={8}
  timeoutMs={30000}
/>;

Gesture Verification

import { GestureVerification, GestureType } from 'react-native-liveness-kit';

<GestureVerification
  referenceImageBase64={enrollmentPhotoBase64}
  gestures={[GestureType.SMILE, GestureType.BLINK, GestureType.OPEN_MOUTH]}
  onSuccess={(r) => console.log('Identity confidence', r.identityConfidence)}
  onFailure={(e) => console.warn(e.code, e.message)}
  onGestureComplete={(g, i) => console.log('done', g, i)}
  identityThreshold={0.7}
/>;

Age Estimation

import { AgeEstimation } from 'react-native-liveness-kit';

<AgeEstimation
  mode="both"
  onResult={(results) => console.log(results)}
  onError={(e) => console.warn(e.code, e.message)}
  onNoFaceDetected={() => console.log('no face')}
/>;

API Reference

<LivenessCheck />

| Prop | Type | Default | Description | | ---------------- | ---------------------------------- | ------- | ------------------------------------ | | onSuccess | (r: LivenessResult) => void | — | Called when liveness is confirmed. | | onFailure | (e: LivenessError) => void | — | Timeout / permission / no-face / load error. | | onProgress | (p: number) => void | — | Progress 0..1. | | threshold | number | 0.75 | Min combined "real" score per frame. | | requiredFrames | number | 8 | Consecutive passing frames needed. | | timeoutMs | number | 30000 | Overall timeout. | | style | ViewStyle | — | Container style. |

<GestureVerification />

| Prop | Type | Default | | --------------------- | --------------------------------------------- | -------------------------------- | | referenceImageBase64| string | — | | gestures | GestureType[] | [SMILE, BLINK, OPEN_MOUTH] | | onSuccess | (r: GestureVerificationResult) => void | — | | onFailure | (e: GestureVerificationError) => void | — | | onGestureComplete | (g: GestureType, index: number) => void | — | | onProgress | (completed: number, total: number) => void | — | | identityThreshold | number | 0.70 | | gestureHoldFrames | number | 4 | | timeoutPerGestureMs | number | 15000 | | randomizeOrder | boolean | false | | style | ViewStyle | — |

GestureType: SMILE, BLINK, OPEN_MOUTH, TURN_LEFT, TURN_RIGHT, NOD, RAISE_HAND, THUMBS_UP, PEACE_SIGN. The last three have no embedded hand model and fall back to a motion heuristic (a console warning is emitted); treat them as optional.

<AgeEstimation />

| Prop | Type | Default | | --------------------- | ------------------------------------------ | -------- | | mode | 'camera' \| 'gallery' \| 'both' | 'both' | | onResult | (r: AgeEstimationResult[]) => void | — | | onError | (e: AgeEstimationError) => void | — | | onNoFaceDetected | () => void | — | | confidenceThreshold | number | 0.55 | | maxFaces | number | 5 | | showPreview | boolean | true | | style | ViewStyle | — |

How it works

Every model runs through ONNX Runtime on the device. Camera frames (or a gallery image) are cropped/resized with @react-native-community/image-editor (to PNG), decoded to raw pixels by a small built-in PNG decoder, and normalized to a Float32Array in JavaScript, then fed to the bundled .onnx models. No image, frame, embedding or result ever leaves the phone — there is no network call in the inference path.

Liveness combines two FASNet anti-spoofing models on two crop scales (score = 0.6·model1 + 0.4·model2) and requires several consecutive passing frames. Gesture verification combines geometric landmark analysis (EAR/MAR/head pose) with ArcFace embeddings + cosine similarity to confirm it is the same person from the enrollment photo. Age estimation runs a face detector then the SSR-Net age regressor on a margin-padded square crop of each face.

Models

The bundled set (~118 MB total) actually used by this package:

| Model | Real source | Size | I/O | | --------------------- | -------------------------------------------------------------------- | ------- | -------------------------------------------- | | face_detector.onnx | YOLOv8n-face (deepghs/yolo-face) | 11.6 MB | [1,3,640,640][1,5,8400] | | face_landmarks.onnx | MediaPipe Face Mesh V2 with attention (face_landmarker.task) | 4.7 MB | [1,256,256,3] NHWC → 478×(x,y,z) | | face_embedding.onnx | ArcFace MobileFaceNet (immich-app/buffalo_s) | 13 MB | [1,3,112,112][1,512] | | age.onnx | FairFace ViT (onnx-community/fairface_age, int8) | 83 MB | [1,3,224,224][1,9] age buckets | | gender.onnx | InsightFace genderage (buffalo_l) | 1.3 MB | [1,3,96,96][1,3] (gender + age) | | liveness_1.onnx | MiniFASNetV2 (minivision-ai/Silent-Face-Anti-Spoofing) | 1.7 MB | [1,3,80,80][1,3] | | liveness_2.onnx | MiniFASNetV1SE (minivision-ai/Silent-Face-Anti-Spoofing) | 1.7 MB | [1,3,80,80][1,3] |

Getting the models

The .onnx binaries are not committed to git (they total ~118 MB; age.onnx alone is 83 MB). How you obtain them depends on how you consume the package:

  • Installing from npm (npm install react-native-liveness-kit): nothing to do. The models are bundled inside the npm tarball, so the package works fully offline right after install — no runtime downloads.

  • Cloning this repo (to run the example or contribute): the models/ folder ships only with a README.md — you must place the seven .onnx files there yourself before building. The easiest way:

    node scripts/download-models.js

    It downloads the four ready-made models straight into models/ (with the correct names) and prints the conversion recipe for the other three.

    Each file must live in models/ with this EXACT name (the package loads them by these paths via require('../../models/<name>.onnx')):

    | Save as (in models/) | Where to get it | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | models/face_detector.onnx | ⬇️ deepghs/yolo-face — rename model.onnx | | models/face_embedding.onnx | ⬇️ immich-app/buffalo_s — rename model.onnx | | models/age.onnx | ⬇️ onnx-community/fairface_age — rename model_quantized.onnx | | models/gender.onnx | ⬇️ public-data/insightface — rename genderage.onnx | | models/face_landmarks.onnx | 🛠️ No public ONNX — generate it: python scripts/generate_face_landmarks.py (see below) | | models/liveness_1.onnx | 🛠️ No public ONNX — generate it: python scripts/generate_liveness.py (see below) | | models/liveness_2.onnx | 🛠️ No public ONNX — generate it: python scripts/generate_liveness.py (see below) |

Generating the converted models (face_landmarks, liveness_*)

These three have no ready-made ONNX, so two Python scripts build them from their official sources straight into models/. Use Python 3.10–3.12 (TensorFlow and torch have no 3.13 wheels), and a separate venv per script (their deps pin conflicting onnx/numpy versions):

# Face Mesh "with attention" → models/face_landmarks.onnx
#   (downloads MediaPipe's face_landmarker.task and converts tflite → ONNX)
python3.12 -m venv venv-tf
./venv-tf/bin/pip install tensorflow tf2onnx "onnx==1.16.2"
./venv-tf/bin/python scripts/generate_face_landmarks.py

# MiniFASNet anti-spoofing → models/liveness_1.onnx + liveness_2.onnx
#   (clones Silent-Face-Anti-Spoofing and exports its .pth weights → ONNX)
python3.12 -m venv venv-torch
./venv-torch/bin/pip install "numpy<2" torch onnx
./venv-torch/bin/python scripts/generate_liveness.py

💡 Tip: to give contributors a one-click download instead of running the scripts, attach the seven prebuilt .onnx files to a GitHub Release of your fork — Releases hold large binaries without bloating git history.

Maintainers: make sure all seven files are in models/ before npm publishnpm publish packs them from the working dir, so the tarball ships them and end users get everything offline.

Example app

A pure React Native CLI app (no Expo) lives in example/. From the repo root:

npm install
node scripts/download-models.js   # populate models/
npm run build

cd example
npm install
# iOS:
cd ios && pod install && cd ..
npm run android                   # or: npm run ios

See example/README.md for full details. It contains a dark-themed home screen plus dedicated screens for each feature.

License

MIT