aliveness 1.0.0
aliveness: ^1.0.0 copied to clipboard
A Flutter package for face liveness detection — verifies that a user is a real, live person by guiding them through a sequence of randomized facial expression challenges captured via the front camera.
aliveness #
A Flutter package for face liveness detection — verifies that a user is a real, live person by guiding them through a sequence of randomized facial expression challenges captured via the front camera.
Built on top of Google ML Kit Face Detection.
Features #
- 11 built-in challenge expressions — blink, smile, head turns, nods, tilts, open mouth, and per-eye winks
- Randomized challenge order — shuffled on every session to prevent replay attacks
- Wrong gesture detection — real-time feedback when the user performs the incorrect expression
- Low-light detection — pauses detection and prompts the user when ambient light is insufficient
- Per-challenge photo capture — returns one cropped face image per completed challenge
- Haptic feedback — vibration on success and wrong gesture
- Cross-platform — supports iOS (BGRA8888) and Android (YUV420) camera formats
Platform Setup #
Android #
Add the camera permission to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
Set the minimum SDK version in android/app/build.gradle:
minSdkVersion 21
iOS #
Add the camera usage description to ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Camera is required for face liveness detection.</string>
Installation #
Add to your pubspec.yaml:
dependencies:
aliveness: ^0.0.1
Then run:
flutter pub get
Usage #
Basic #
import 'package:aliveness/aliveness.dart';
final FaceLivenessData? result = await Aliveness().start(
context: context,
expressions: [
ChallengeExpression.smile,
ChallengeExpression.eyeblink,
ChallengeExpression.leftPose,
ChallengeExpression.rightPose,
ChallengeExpression.nodUp,
ChallengeExpression.nodDown,
ChallengeExpression.tiltLeft,
ChallengeExpression.tiltRight,
ChallengeExpression.openMouth,
ChallengeExpression.winkLeft,
ChallengeExpression.winkRight,
],
);
if (result != null) {
final List<img.Image> photos = result.photos;
// photos[0] → cropped face from challenge 1
// photos[1] → cropped face from challenge 2
// ...
}
The challenge order is automatically shuffled on every call — you do not need to shuffle the list yourself.
Handling Cancellation #
start() returns null if the user exits the screen before completing all challenges:
final result = await Aliveness().start(
context: context,
expressions: [ChallengeExpression.smile, ChallengeExpression.eyeblink],
);
if (result == null) {
// User cancelled or exited early
return;
}
// Proceed with result.photos
Converting Photos to Bytes #
The returned images are img.Image objects from the image package. To convert to raw bytes (e.g. for upload):
import 'package:image/image.dart' as img;
for (final photo in result.photos) {
final Uint8List bytes = Uint8List.fromList(img.encodeJpg(photo));
// Upload or display bytes
}
Available Expressions #
| Expression | Description | Detection Basis |
|---|---|---|
ChallengeExpression.smile |
Smile for the camera | smilingProbability > 0.5 |
ChallengeExpression.eyeblink |
Blink both eyes | Either eye openProbability < 0.3 |
ChallengeExpression.leftPose |
Turn head to the left | headEulerAngleY > 10° ¹ |
ChallengeExpression.rightPose |
Turn head to the right | headEulerAngleY < -10° ¹ |
ChallengeExpression.nodUp |
Look up | headEulerAngleX > 15° |
ChallengeExpression.nodDown |
Look down | headEulerAngleX < -15° |
ChallengeExpression.tiltLeft |
Tilt head to the left | headEulerAngleZ < -20° ¹ |
ChallengeExpression.tiltRight |
Tilt head to the right | headEulerAngleZ > 20° ¹ |
ChallengeExpression.openMouth |
Open mouth wide | Lip contour gap / face height > 5% |
ChallengeExpression.winkLeft |
Wink left eye only | Subject's left eye closed, right open ² |
ChallengeExpression.winkRight |
Wink right eye only | Subject's right eye closed, left open ² |
¹ iOS mirror correction — ML Kit reports raw (unmirrored) euler angles. The package negates Y and Z on iOS so the detected direction matches the mirrored camera preview the user sees.
² Android eye coordinate correction — Android ML Kit uses image-space coordinates for eye landmarks (
leftEye= camera-left = subject's right). The package swaps the probabilities on Android sowinkLeft/winkRightconsistently refer to the subject's own eye.
You can pass any subset or combination. At least one expression is required — passing an empty list throws an exception.
Return Value #
start() returns a FaceLivenessData? object:
class FaceLivenessData {
final List<img.Image> photos; // one cropped face image per completed challenge
}
The list length equals the number of expressions passed. Each image is a square-cropped face photo captured at the moment the challenge was completed.
Assets #
This package requires icon assets to display challenge instructions. Add the following files to your app's asset bundle under assets/icons/:
| File | Used for |
|---|---|
icon_face_liveness_smile.png |
Smile challenge |
icon_face_liveness_blink.png |
Eyeblink challenge |
icon_face_liveness_look_left.png |
Left pose challenge |
icon_face_liveness_look_right.png |
Right pose challenge |
icon_face_liveness_nod_up.png |
Nod up challenge |
icon_face_liveness_nod_down.png |
Nod down challenge |
icon_face_liveness_tilt_left.png |
Tilt left challenge |
icon_face_liveness_tilt_right.png |
Tilt right challenge |
icon_face_liveness_open_mouth.png |
Open mouth challenge |
icon_face_liveness_wink_left.png |
Wink left challenge |
icon_face_liveness_wink_right.png |
Wink right challenge |
Declare them in your pubspec.yaml:
flutter:
assets:
- assets/icons/
Dependencies #
| Package | Version | Purpose |
|---|---|---|
camera |
^0.12.0+1 |
Camera stream access |
google_mlkit_face_detection |
^0.13.2 |
Face metrics and contour detection |
image |
^4.9.1 |
Image conversion and cropping |
License #
MIT