expo-vision-face-detector
v1.0.0
Published
Face detection using Apple Vision on iOS and ML Kit on Android. Native arm64 simulator support.
Downloads
166
Maintainers
Readme
expo-vision-face-detector
Face detection for React Native using Apple Vision on iOS and Google ML Kit on Android.
Why this package exists
Every other React Native face detection library routes both platforms through Google's ML Kit iOS SDK. That SDK ships its core framework (MLImage.framework) as a prebuilt fat binary containing only an arm64 device slice — not an arm64 simulator slice. On Apple Silicon Macs (M1/M2/M3), the iOS Simulator runs natively as arm64, so the linker rejects the device binary:
Building for 'iOS-simulator', but linking in object file
(.../MLImage.framework/MLImage[arm64](GMLImage.o)) built for 'iOS'
Linker command failed with exit code 1The usual workaround — adding EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64 — hides the simulator from Xcode's device picker entirely on Apple Silicon, making local development painful.
This package sidesteps the problem entirely on iOS by using Apple's built-in Vision framework (VNDetectFaceRectanglesRequest), which is part of the OS SDK and compiles natively for every target including arm64 simulator. On Android, where ML Kit has no architecture issues, it uses com.google.mlkit:face-detection as normal.
| | iOS | Android |
|---|---|---|
| Engine | Apple Vision (VNDetectFaceRectanglesRequest) | Google ML Kit |
| Extra pods | None — Vision is a system framework | mlkit:face-detection:16.1.5 |
| arm64 simulator | ✅ Native | ✅ Native |
| x86_64 simulator | ✅ | ✅ |
| Physical device | ✅ | ✅ |
Installation
npm install expo-vision-face-detectorExpo
Add the plugin to your app.json / app.config.js:
{
"plugins": ["expo-vision-face-detector"]
}Then rebuild:
npx expo prebuildBare React Native
# iOS
cd ios && pod install
# Android — nothing extra, Gradle autolinking handles itAPI
detectFaces(uri: string): Promise<number>
Returns the number of faces detected in the image at the given URI.
import { detectFaces } from 'expo-vision-face-detector';
const count = await detectFaces(imageUri);
console.log(`${count} face(s) detected`);validateFaceInImage(uri: string): Promise<FaceValidationResult>
Convenience wrapper that validates a profile-photo upload — expects exactly one face.
import { validateFaceInImage } from 'expo-vision-face-detector';
const result = await validateFaceInImage(imageUri);
if (!result.valid) {
Alert.alert('Invalid photo', result.reason);
}FaceValidationResult
interface FaceValidationResult {
valid: boolean;
reason?: string; // set when valid is false
}reason values:
"no face detected — please use a photo of yourself""multiple faces detected — please use a solo photo"
Notes
- Simulator accuracy — Apple Vision on simulator uses software rendering without the Neural Engine, so accuracy may be lower than on a real device. The library fails open (returns
valid: true) if detection throws, so simulator testing is never blocked. - URI formats — Both
file://paths and content URIs are supported. Pass the URI directly fromexpo-image-pickerorreact-native-image-picker. - Web — Not supported.
detectFacesreturns0on web.
License
MIT © Noel Portugal
