MeeeetupSDK documentationJA

React Native

@meeeetup/camera-react-native runs detection on the native thread through a Vision Camera frame processor backed by ML Kit. There is no JavaScript inference and no per-frame JPEG encode, so the pipeline costs a few milliseconds per frame on mid-range Android hardware.

pnpm add @meeeetup/camera-react-native

Peer dependencies, all of which you install yourself:

Package Minimum
react-native-vision-camera 4.0.0
react-native-vision-camera-face-detector 1.10.0
react-native-worklets-core 1.5.0
react-native-fs 2.20.0

Passive capture

import { useRef } from "react";
import { Camera, useCameraDevice } from "react-native-vision-camera";
import { useFaceCaptureSession } from "@meeeetup/camera-react-native";

export function Kiosk({ width, height }: { width: number; height: number }) {
  const camera = useRef<Camera>(null);
  const device = useCameraDevice("front");

  const conf = {
    cameraRef: camera,
    sessionType: "passive",
    minFaceHeight: 0.18,
    minFrontalness: 55,
    captureWindowMs: 2_000,
    cooldownMs: 30_000,
    detectionFps: 15,
    windowWidth: width,
    windowHeight: height,
    cameraFacing: "front",
    onBatchCapture: async (faces) => {
      await upload(faces);
    },
  } as const;

  const { frameProcessor, trackedCount, ready, error } = useFaceCaptureSession(conf);

  if (!device) return null;

  return (
    <Camera
      ref={camera}
      device={device}
      isActive={ready && !error}
      photo
      frameProcessor={frameProcessor}
      style={{ flex: 1 }}
    />
  );
}

Every capture gate from Configuration applies here unchanged — the hook forwards them straight to the same FaceCaptureSession the web SDK uses, so a deployment can tune thresholds once and use them on both platforms.

Native-only options

Option Default What it does
cameraRef required Ref to the Vision Camera <Camera>, used to snapshot the JPEG the tracker crops from.
detectionFps 15 Frame-processor throttle. Vision Camera 4 removed frameProcessorFps, so throttling lives inside the worklet.
photoCadenceMs 1000 How often the cached snapshot is refreshed. Lower means committed crops match the peak frame more closely, at more GPU cost.
snapshotQuality 60 JPEG quality of that snapshot.
windowWidth / windowHeight — Preview size in px. Pass these. They switch the detector into autoMode, which rotates, mirrors and scales landmarks into window coordinates so your overlays line up with the preview.
cameraFacing "front" Required for correct mirroring in autoMode.

What the hook returns

Field Meaning
frameProcessor Attach to <Camera frameProcessor={…} />.
ready / error Session status.
trackedCount Faces currently tracked.
lastDetections Normalised detections for drawing your own overlay.
lastSnapshot file:// URI of the cached preview snapshot, plus its size and timestamp.
lastTimings Per-stage latency — native detect time and the worklet-to-JS hop.
flushBatch() Send buffered faces now; call it when the app backgrounds.

Nose landmark

ML Kit exposes noseBase, not noseTip. The hook sets noseLandmark: "noseBase" on the session for you, which shifts the vertical-tilt reference so scores stay comparable with MediaPipe on web. That is also why UseFaceCaptureSessionOptions omits noseLandmark — setting it by hand would break cross-platform parity.

Android build notes