td_liveliness_detection
Face liveness detection for Flutter. The user is asked to perform simple challenges (blink, smile, turn head) in front of the front camera, and a selfie is returned once every challenge passes. Detection runs on-device with Google ML Kit, so no paid API or network call is needed.
Features
- Blink, smile, and left/right head-turn challenges, asked in random order
- Waits for a neutral face between challenges, so one expression can't pass two steps
- Arch-shaped camera frame with a ring that changes colour as the user progresses
- Step indicator, live instructions below the frame, and a success animation
- Returns the captured selfie as an
XFile - Android and iOS
Installation
dependencies:
td_liveliness_detection: ^1.0.0
Android
In android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
Set minSdk to at least 21 in android/app/build.gradle(.kts) (ML Kit requirement).
iOS setup
-
Minimum iOS 16.0. In
ios/Podfile:platform :ios, '16.0'Also set iOS Deployment Target to 16.0 for the Runner target in Xcode.
-
Camera usage description in
ios/Runner/Info.plist:<key>NSCameraUsageDescription</key> <string>The camera is used to confirm you are a real person.</string> -
If your app uses
permission_handler, enable the camera permission in thepost_installblock ofios/Podfile:post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', 'PERMISSION_CAMERA=1', ] end end end -
Test on a real iPhone. The iOS Simulator has no front camera.
Usage
import 'package:camera/camera.dart';
import 'package:td_liveliness_detection/td_liveliness_detection.dart';
final XFile? selfie = await FlutterLivenessDetection().start(
context: context,
expressions: [
Expression.eyeblink,
Expression.smile,
// Expression.leftPose,
// Expression.rightPose,
],
);
if (selfie != null) {
// Liveness passed – use selfie.path
} else {
// User cancelled
}
Request camera permission before calling start (for example with permission_handler). See the example/ app for a complete flow.
Expressions
| Expression | Passes when |
|---|---|
Expression.eyeblink |
Either eye is closed (open probability < 0.3) |
Expression.smile |
Smiling probability > 0.5 |
Expression.leftPose |
Head turned left (yaw > 10°) |
Expression.rightPose |
Head turned right (yaw < -10°) |
License
MIT