High-performance pose detection for React Native using Google's MediaPipe models with optimized frame processing for smooth real-time tracking.
You can find the package on npm: react-native-mediapipe-posedetection
📖 Read the full documentation →
⚠️ New Architecture RequiredThis library only supports React Native's New Architecture (Turbo Modules). You must enable the New Architecture in your app to use this library.
- ✨ Real-time pose detection via
react-native-vision-camera - 🎯 33 pose landmarks per detected person
- 🚀 Optimized for performance (configurable FPS limit, built-in event throttling on iOS)
- 📱 iOS & Android support
- 🔥 GPU acceleration support
- 🎨 Static image detection support
- 🪝 Easy-to-use React hooks
- React Native: 0.74.0 or higher
- New Architecture: Must be enabled
- iOS: the minimum iOS version supported by your React Native version
- Android: API 24+
- Dependencies:
react-native-vision-camera^4.0.0 (for real-time detection)react-native-worklets-core^1.0.0 (for frame processing)
npm install react-native-mediapipe-posedetection react-native-vision-camera react-native-worklets-core
# or
yarn add react-native-mediapipe-posedetection react-native-vision-camera react-native-worklets-coreIf you are using Expo, you can use the built-in config plugin to automatically copy your MediaPipe model files to the native Android and iOS projects during prebuild.
- Add your model files (e.g.,
pose_landmarker_lite.task) to a directory in your project (e.g.,./assets/models/). - Update your
app.jsonorapp.config.js:
{
"expo": {
"plugins": [
[
"react-native-mediapipe-posedetection",
{
"assetsPaths": ["./assets/models/"]
}
]
]
}
}This plugin will copy all files from the specified assetsPaths to:
- Android:
android/app/src/main/assets/ - iOS: The root of the Xcode project (and add them to the build resources).
Note: The
assetsPathsare relative to your project root. You can also passignoredPattern(a regex string) to skip files, e.g."\\.md$".
If you haven't already enabled the New Architecture in your React Native app:
In your android/gradle.properties:
newArchEnabled=trueIn your ios/Podfile:
use_frameworks! :linkage => :static
$RNNewArchEnabled = trueThen reinstall pods:
cd ios && pod install- Download the MediaPipe pose landmarker model (e.g.,
pose_landmarker_lite.task) - Add it to your Xcode project
- Ensure it's included in "Copy Bundle Resources" build phase
The MediaPipe dependencies are automatically included. Place your model file in android/app/src/main/assets/.
import {
usePoseDetection,
RunningMode,
Delegate,
KnownPoseLandmarks,
} from 'react-native-mediapipe-posedetection';
import { Camera, useCameraDevice } from 'react-native-vision-camera';
function PoseDetectionScreen() {
const device = useCameraDevice('back');
const poseDetection = usePoseDetection(
{
onResults: (result) => {
// result.results[0].landmarks is an array of people, each with 33 landmarks
const people = result.results[0]?.landmarks ?? [];
console.log('Number of poses:', people.length);
const firstPerson = people[0];
if (firstPerson) {
const nose = firstPerson[KnownPoseLandmarks.nose];
console.log('Nose position:', nose.x, nose.y);
}
},
onError: (error) => {
console.error('Detection error:', error.message);
},
},
RunningMode.LIVE_STREAM,
'pose_landmarker_lite.task',
{
numPoses: 1,
minPoseDetectionConfidence: 0.5,
minPosePresenceConfidence: 0.5,
minTrackingConfidence: 0.5,
delegate: Delegate.GPU,
}
);
if (!device) return null;
return (
<Camera
style={{ flex: 1 }}
device={device}
isActive={true}
pixelFormat="rgb"
frameProcessor={poseDetection.frameProcessor}
onLayout={poseDetection.cameraViewLayoutChangeHandler}
onOutputOrientationChanged={poseDetection.cameraOrientationChangedHandler}
/>
);
}import {
PoseDetectionOnImage,
Delegate,
} from 'react-native-mediapipe-posedetection';
async function detectPoseInImage(imagePath: string) {
const result = await PoseDetectionOnImage(
imagePath,
'pose_landmarker_lite.task',
{
numPoses: 2, // Detect up to 2 people
minPoseDetectionConfidence: 0.5,
delegate: Delegate.GPU,
}
);
console.log('Detected poses:', result.results[0]?.landmarks.length ?? 0);
console.log('Inference time:', result.inferenceTime, 'ms');
}For a simpler setup, pass the result of usePoseDetection to the provided MediapipeCamera component. It wires up the frame processor, layout, orientation and camera device handlers for you:
import {
MediapipeCamera,
usePoseDetection,
RunningMode,
} from 'react-native-mediapipe-posedetection';
function App() {
const solution = usePoseDetection(
{
onResults: (result) => {
console.log('Pose detected:', result.results[0]?.landmarks);
},
onError: (error) => console.warn(error.message),
},
RunningMode.LIVE_STREAM,
'pose_landmarker_lite.task',
{ numPoses: 1, minPoseDetectionConfidence: 0.5 }
);
return (
<MediapipeCamera
style={{ flex: 1 }}
solution={solution}
activeCamera="back" // 'front' (default) | 'back'
resizeMode="cover" // 'cover' (default) | 'contain'
/>
);
}Hook for real-time pose detection.
Parameters:
-
callbacks:DetectionCallbacks<PoseDetectionResultBundle>onResults: (result: PoseDetectionResultBundle, viewCoordinator: ViewCoordinator) => void- Called when poses are detected.viewCoordinatorconverts normalized landmarks to screen coordinatesonError: (error: DetectionError) => void- Called on detection errors
-
runningMode:RunningModeRunningMode.LIVE_STREAM- For camera/video inputRunningMode.VIDEO- For video file processingRunningMode.IMAGE- For static images (usePoseDetectionOnImageinstead)
-
model:string- Path to MediaPipe model file (e.g.,'pose_landmarker_lite.task') -
options:Partial<PoseDetectionOptions>(optional)numPoses:number- Maximum number of poses to detect (default: 1)minPoseDetectionConfidence:number- min confidence threshold (default: 0.5)minPosePresenceConfidence:number- min presence threshold (default: 0.5)minTrackingConfidence:number- min tracking threshold (default: 0.5)shouldOutputSegmentationMasks:boolean- Include segmentation masks (default: false)delegate:Delegate.CPU | Delegate.GPU- Processing delegate (default: GPU)mirrorMode:'no-mirror' | 'mirror' | 'mirror-front-only'- Camera mirroring (default:'mirror-front-only'on Android,'no-mirror'on iOS)forceCameraOrientation/forceOutputOrientation:ImageOrientation- Override detected orientationsfpsMode:'none' | number- Additional FPS throttling (default: 'none')
Returns: MediaPipeSolution
frameProcessor: VisionCamera frame processorcameraViewLayoutChangeHandler: Layout change handlercameraDeviceChangeHandler: Camera device change handlercameraOrientationChangedHandler: Orientation change handlerresizeModeChangeHandler: Resize mode handlercameraViewDimensions: Current camera view dimensions
Detect poses in a static image.
Parameters:
imagePath:string- Path to the image filemodel:string- Path to MediaPipe model fileoptions: Same asusePoseDetectionoptions
Returns: Promise<PoseDetectionResultBundle>
interface PoseDetectionResultBundle {
results: PoseLandmarkerResult[]; // One entry for live camera frames and single images
inferenceTime: number; // Milliseconds
inputImageWidth: number;
inputImageHeight: number;
}
interface PoseLandmarkerResult {
landmarks: Landmark[][]; // [person][landmarkIndex], 33 landmarks per person, normalized
worldLandmarks: Landmark[][]; // [person][landmarkIndex], 3D world coordinates in meters
segmentationMasks: Mask[];
}
interface Landmark {
x: number; // Normalized 0-1
y: number; // Normalized 0-1
z: number; // Depth (relative)
visibility?: number; // Confidence 0-1
presence?: number; // Presence confidence 0-1
}Use KnownPoseLandmarks for easy landmark access:
import { KnownPoseLandmarks } from 'react-native-mediapipe-posedetection';
const landmarks = result.results[0]?.landmarks[0]; // first person
const nose = landmarks[KnownPoseLandmarks.nose];
const leftShoulder = landmarks[KnownPoseLandmarks.leftShoulder];
const rightWrist = landmarks[KnownPoseLandmarks.rightWrist];Available landmarks:
- Face:
nose,leftEye,rightEye,leftEar,rightEar,mouthLeft,mouthRight - Upper body:
leftShoulder,rightShoulder,leftElbow,rightElbow,leftWrist,rightWrist - Hands:
leftPinky,rightPinky,leftIndex,rightIndex,leftThumb,rightThumb - Lower body:
leftHip,rightHip,leftKnee,rightKnee,leftAnkle,rightAnkle - Feet:
leftHeel,rightHeel,leftFootIndex,rightFootIndex
This library includes critical performance optimizations for React Native's new architecture:
On iOS, the native module caps result events sent to JavaScript at ~15 per second to keep memory stable during long sessions. This needs no configuration. Android delivers every result, so setting fpsMode (below) matters more there.
Limit how many frames are sent to MediaPipe with the fpsMode option. 10–15 FPS is enough for smooth tracking in most apps and saves battery:
usePoseDetection(callbacks, RunningMode.LIVE_STREAM, 'model.task', {
fpsMode: 10, // Process frames at 10 FPS
});If you were using a previous version that supported the Bridge architecture:
-
Upgrade React Native to 0.74.0 or higher
-
Enable New Architecture (see installation instructions)
-
Rebuild your app completely:
# iOS cd ios && pod install && cd .. # Android cd android && ./gradlew clean && cd ..
The API remains the same, so your application code shouldn't need changes.
Cause: New Architecture is not enabled or not properly configured.
Solution:
- Verify
newArchEnabled=trueinandroid/gradle.properties - Verify
$RNNewArchEnabled = trueinios/Podfile - Clean and rebuild your app
- Ensure you're using React Native 0.74.0+
Cause: Model file not found or invalid configuration.
Solution:
- Verify the model file path is correct
- Ensure the model file is included in your app bundle
- Check that the model file is a valid MediaPipe pose landmarker model
Solution:
- Ensure you're on the latest version
- Set
fpsMode: 15(or lower) - Reduce
numPosesto 1 - Set
shouldOutputSegmentationMasks: false - Use
Delegate.CPUinstead ofDelegate.GPUif GPU memory is limited
Solutions:
- Use
pose_landmarker_lite.taskinstead ofpose_landmarker_full.task - Set
fpsMode: 10for lower frame processing - Reduce
numPosesif you don't need to detect multiple people - Enable GPU acceleration:
delegate: Delegate.GPU
Check out the example directory for a complete working app demonstrating:
- Real-time pose detection
- Pose landmark visualization
- Camera controls
- Performance optimization
Run the example:
cd example
yarn install
yarn ios # or yarn androidSee the contributing guide to learn how to contribute to the repository and the development workflow.
This library is based on the work from react-native-mediapipe by cdiddy77. The pose detection module codes were taken from this repository and upgraded to support React Native's New Architecture (Turbo Modules).
MIT © EndLess728
Made with create-react-native-library