Prepare the example app environment
main/node_modules/react-native-vision-camera-face-detector/node_modules directory, but do not delete the .bin folder.repository·main·Indexed 43 days ago
https://github.com/luicfrr/react-native-vision-camera-face-detectorA Frame Processor Plugin for React Native Vision Camera that provides real-time and static image face detection by integrating Google MLKit. Version 2.1.0 supports facial landmarks, contours, and classifications via the <Camera /> component, useFaceDetectorOutput hook, or useFaceDetector for advanced frame processor usage.
/node_modules/react-native-vision-camera-face-detector/node_modules directory, but do not delete the .bin folder.To set up the face-detector-example project, first install the necessary dependencies using npm or yarn.
npm install
# or
yarnTo use this library, you must first install react-native-vision-camera. Then, install the face detector package using yarn:
yarn add react-native-vision-camera-face-detectorImportant: You must add the react-native-worklets plugin to your babel.config.js file to ensure proper functionality.
Once dependencies are installed and the nested node_modules are cleaned, you can launch the app using the following commands.
# Development mode
npm run android
# or
npm run ios
# or
yarn android
# or
yarn ios
# Production mode
npm run android:prod
# or
npm run ios:prod
# or
yarn android:prod
# or
yarn ios:prodCommon issues and solutions:
Regular javascript function cannot be shared. Try decorating the function with the 'worklet' keyword...react-native-reanimated, ensure you have completed the necessary setup steps for worklets.Execution failed for task ':react-native-vision-camera-face-detector:compileDebugKotlin'...If you encounter build issues or need to reset the project state, use the provided cleaning command.
npm run prebuild:clean
# or
yarn prebuild:cleanThe simplest way to implement face detection is by using the provided <Camera /> component from react-native-vision-camera-face-detector. This component accepts props like runClassifications, runContours, and runLandmarks to enable specific detection features, and an onFacesDetected callback to handle the results.
Note: You must request camera permissions using Camera.requestCameraPermission() before using the component.
import { StyleSheet, Text, View } from 'react-native'
import { useEffect } from 'react'
import { useCameraDevice } from 'react-native-vision-camera'
import { Camera, Face } from 'react-native-vision-camera-face-detector'
export default function App() {
const device = useCameraDevice('front')
useEffect(() => {
(async () => {
const status = await Camera.requestCameraPermission()
console.log({ status })
})()
}, [device])
function handleFacesDetected(faces: Face[]) {
console.log('faces', faces.length)
}
return (
<View style={{ flex: 1 }}>
{!!device ? (
<Camera
runClassifications
runContours
runLandmarks
performanceMode={'fast'}
onFacesDetected={handleFacesDetected}
style={StyleSheet.absoluteFill}
device={device}
/>
) : (
<Text>No Device</Text>
)}
</View>
)
}For advanced usage, you can use useFaceDetector within a Vision Camera Frame Processor. It is highly recommended to run face detection asynchronously using an asyncRunner to avoid blocking the camera preview.
Warning: Do not destructure hybrid objects returned by the hooks (e.g., avoid const { detectFaces } = useFaceDetector(...)).
When using this method, you are responsible for calling frame.dispose() to prevent memory leaks.
import { StyleSheet, Text, View } from 'react-native'
import { useEffect } from 'react'
import { Camera, useCameraDevice, useFrameProcessor } from 'react-native-vision-camera'
import { useFaceDetector } from 'react-native-vision-camera-face-detector'
import { Worklets } from 'react-native-worklets-core'
export default function App() {
const device = useCameraDevice('front')
const faceDetector = useFaceDetector({
// detection options
})
const asyncRunner = useAsyncRunner()
const frameOutput = useFrameOutput({
onFrame: (frame) => {
'worklet'
const wasHandled = asyncRunner.runAsync(() => {
'worklet'
const faces = faceDetector.detectFaces(frame)
// ... do something with detected faces
frame.dispose()
})
if (!wasHandled) {
frame.dispose()
}
}
})
useEffect(() => {
(async () => {
const status = await Camera.requestCameraPermission()
console.log({ status })
})()
}, [device])
return (
<View style={{ flex: 1 }}>
{!!device ? (
<Camera
style={StyleSheet.absoluteFill}
device={device}
isActive={true}
outputs={[frameOutput]}
/>
) : (
<Text>No Device</Text>
)}
</View>
)
}You can perform face detection on static images (e.g., from a gallery or local assets) using the useImageFaceDetector hook. The detectFaces method accepts several types of input:
require('./path/to/image.jpg')file://, content://, or http(s)://{ uri: string }Warning: Do not destructure hybrid objects returned by the hook.
import { useImageFaceDetector } from 'react-native-vision-camera-face-detector'
// ❌ don't destruct hybrid objects ❌
const faceDetector = useImageFaceDetector({
// detection options
})
// Using a bundled asset
const faces1 = await faceDetector.detectFaces(
require('./assets/photo.jpg')
)
// Using a local file path or content URI
const faces2 = await faceDetector.detectFaces(
'file:///storage/emulated/0/Download/pic.jpg'
)
// Using an object
const faces3 = await faceDetector.detectFaces({
uri: 'content://media/external/images/media/12345'
})
console.log({ faces1, faces2, faces3 })You can connect face detection to a camera session using the useFaceDetectorOutput hook. This hook returns an output object that you pass to the outputs prop of the <Camera /> component. This is useful when following the Vision Camera 'Camera Outputs' pattern.
import { StyleSheet, Text, View } from 'react-native'
import { useEffect } from 'react'
import { Camera, useCameraDevice } from 'react-native-vision-camera'
import { useFaceDetectorOutput } from 'react-native-vision-camera-face-detector'
export default function App() {
const device = useCameraDevice('front')
const faceDetectorOutput = useFaceDetectorOutput({
// detection options
})
useEffect(() => {
(async () => {
const status = await Camera.requestCameraPermission()
console.log({ status })
})()
}, [device])
return (
<View style={{ flex: 1 }}>
{!!device ? (
<Camera
style={StyleSheet.absoluteFill}
device={device}
isActive={true}
outputs={[faceDetectorOutput]}
/>
) : (
<Text>No Device</Text>
)}
</View>
)
}The metro.config.js in the face-detector-example directory is configured to handle peer dependencies correctly within a monorepo-like structure. It prevents multiple versions of the same peer dependency from being loaded by blacklisting the versions located in the project root and aliasing them to the versions found in the example's local node_modules via extraNodeModules.
const { getDefaultConfig } = require( 'expo/metro-config' )
const path = require( 'path' )
const escape = require( 'escape-string-regexp' )
const pak = require( '../package.json' )
const root = path.resolve( __dirname, '..' )
const defaultConfig = getDefaultConfig( __dirname )
const modules = Object.keys( { ...pak.peerDependencies } )
module.exports = {
...defaultConfig,
projectRoot: __dirname,
watchFolders: [ root ],
resolver: {
...defaultConfig.resolver,
blockList: modules.map( ( m ) => (
new RegExp( `^${ escape( path.join( root, 'node_modules', m ) ) }\/.*$` )
) ),
extraNodeModules: modules.reduce( ( acc, name ) => {
acc[ name ] = path.join( __dirname, 'node_modules', name )
return acc
}, {} )
},
transformer: {
...defaultConfig.transformer,
getTransformOptions: async () => ( {
transform: {
experimentalImportSupport: false,
inlineRequires: true
}
} )
}
}Use the expo-build-properties plugin to set specific SDK versions and deployment targets required for the face detector to function correctly.
Android Requirements:
minSdkVersion: 26 (Android 8)compileSdkVersion: 36targetSdkVersion: 36buildToolsVersion: '36.0.0'iOS Requirements:
deploymentTarget: '16.4'Example configuration:
plugins: [
[
'expo-build-properties',
{
android: {
minSdkVersion: 26,
compileSdkVersion: 36,
targetSdkVersion: 36,
buildToolsVersion: '36.0.0'
},
ios: {
deploymentTarget: '16.4'
}
}
]
]plugins: [
[ 'expo-image-picker', {
photosPermission: 'The app accesses your photos to let you share them with your friends.'
} ],
[ 'expo-build-properties', {
android: {
minSdkVersion: 26,
compileSdkVersion: 36,
targetSdkVersion: 36,
buildToolsVersion: '36.0.0'
},
ios: {
deploymentTarget: '16.4'
}
} ]
]