facecore

A self-contained Flutter plugin that runs a camera-based face liveness flow natively on Android and iOS, then returns a captured JPEG to Dart. The platform side handles camera permission, preview, face detection, motion and depth anti-spoof checks, and image capture — your Dart code just calls one method.

Features

  • Native liveness UI on Android (CameraX + ML Kit Face Detection) and iOS (AVFoundation + Vision).
  • Configurable challenge actions: blink, turn left, turn right.
  • Motion standard-deviation check to reject static photos / replays.
  • Optional depth-based anti-spoof check.
  • Returns the saved JPEG path plus telemetry (dimensions, motion, depth).

Platform support

Platform Minimum version
Android API 21
iOS 13.0

Installation

dependencies:
  facecore: ^0.1.0

Android

Camera permission is declared by the plugin. No additional setup required.

iOS

Add a usage description to your app's ios/Runner/Info.plist:

<key>NSCameraUsageDescription</key>
<string>This app uses the camera to verify your identity.</string>

Usage

import 'package:facecore/facecore.dart';

final facecore = Facecore();

final result = await facecore.captureWithLiveness(
  config: const LivenessConfig(
    actions: [
      LivenessAction.blink,
      LivenessAction.turnLeft,
      LivenessAction.turnRight,
    ],
    requireDepth: false,
    title: 'Verify your identity',
    subtitle: 'Follow the prompts to confirm you are present.',
  ),
);

if (result == null) {
  // User cancelled.
  return;
}

print('Saved to: ${result.imagePath}');
print('Size: ${result.width}x${result.height}');
print('Motion stddev: ${result.motionStdDev}');
print('Depth range: ${result.depthRange}');

captureWithLiveness returns null when the user cancels and throws a FaceCaptureException if the native flow fails (e.g. permission denied, camera unavailable, anti-spoof rejection).

See example/ for a runnable demo.

Configuration

LivenessConfig exposes the knobs that drive the native flow:

Field Default Purpose
actions [blink, turnLeft, turnRight] Ordered list of liveness challenges to run.
requireDepth false Require depth data; rejects flat-image spoofs on supported devices.
minFaceFraction 0.18 Minimum face area as a fraction of the frame.
maxFaceFraction 0.85 Maximum face area (too close).
minMotionStdDev 1.5 Minimum motion variance to accept the capture.
minDepthRange 6.0 Minimum depth range when requireDepth is true.
holdFrames 6 Frames the user must hold the target pose.
jpegQuality 90 JPEG quality (1–100) for the saved capture.
title null Optional title shown on the native screen.
subtitle null Optional subtitle shown on the native screen.

License

MIT — see LICENSE.