MoveNet Lightning, Thunder and MultiPose: Inputs, Outputs and Licence
Last verified October 17, 2026 · 5 min read
Sources checked (7) · October 17, 2026
- github.com/tensorflow/tfjs-models/blob/master/pose-detection/src/movenet/README.md — The three model types and their descriptions, detector options, the WebGL and WASM backends, the FPS table and the MultiPose speed and accuracy note.
- github.com/tensorflow/tfjs-models/blob/master/pose-detection/src/movenet/constants.ts — 192 and 256 input resolutions, the MultiPose default maximum dimension of 256, the tfhub.dev URLs, the valid models and DEFAULT_MIN_POSE_SCORE 0.25.
- github.com/tensorflow/tfjs-models/blob/master/pose-detection/src/movenet/detector.ts — minPoseScore falls back to DEFAULT_MIN_POSE_SCORE when it is not set.
- github.com/tensorflow/tfjs-models/blob/master/pose-detection/README.md — Keypoint fields x, y, score and name in image coordinates, keypointsToNormalizedKeypoints, and the sentence that only PoseNet supports multi-pose estimation.
- storage.googleapis.com/movenet/MoveNet.SinglePose%20Model%20Card.pdf — Architecture and depth multipliers, 192x192 and 256x256 int32 inputs, the 1x1x17x3 yx output, TF.js and TF Lite, 3 to 6 feet, the person closest to the image center, the 0.3 threshold and the Apache-2.0 license line.
- storage.googleapis.com/movenet/MoveNet.MultiPose%20Model%20Card.pdf — Up to 6 people, depth multiplier 1.5, dynamic input in multiples of 32 with 256 recommended, int32 for TF.js and uint8 for TF Lite, the 1x6x56 output; no license line in the extracted text.
- github.com/tensorflow/tfjs-models/blob/master/LICENSE — Apache License, Version 2.0.
This page is about MoveNet alone. The choice between it and MediaPipe is made in MediaPipe vs MoveNet, and the licence layers are read in full in pose estimation model licenses. Everything below was read from Google's two MoveNet model cards and the tensorflow/tfjs-models repository on October 17, 2026.
The three models#
| Model | modelType in TF.js | Input | People | How the source describes it |
|---|---|---|---|---|
| SinglePose Lightning | SINGLEPOSE_LIGHTNING (the default) | 192x192x3, int32, RGB 0 to 255 | 1 | "intended for latency-critical applications" |
| SinglePose Thunder | SINGLEPOSE_THUNDER | 256x256x3, int32, RGB 0 to 255 | 1 | "intended for applications that require high accuracy" |
| MultiPose Lightning | MULTIPOSE_LIGHTNING | 1xHxWx3, H and W multiples of 32 set at run time | Up to 6 | "detects up to 6 poses" |
The SinglePose card describes both single-person models as a MobileNetV2 feature extractor with a Feature Pyramid Network decoder and CenterNet prediction heads, Lightning at depth multiplier 1.0 and Thunder at 1.75. The MultiPose card gives the same architecture at depth multiplier 1.5 and recommends resizing the image so its larger side is 256 pixels, keeping the aspect ratio. In the TF.js package that size is multiPoseMaxDimension: a multiple of 32, 256 by default, with 128 to 512 recommended.
What comes out#
Read the coordinate order before writing any code. Per the SinglePose card, the raw model returns a float32 tensor of shape [1, 1, 17, 3]: for each keypoint, y and x normalized to the image frame (0.0 to 1.0), then a confidence score. The MultiPose card's output is [1, 6, 56]: six instance slots, each holding 17 groups of y, x and score, then a bounding box (ymin, xmin, ymax, xmax) in normalized coordinates and an instance score.
The TF.js pose-detection package converts this for you. Its README says each keypoint "contains x, y, score and name", that x and y "represent the actual keypoint position in the image", and that poseDetection.calculators.keypointsToNormalizedKeypoints converts them to the 0 to 1 range. With MultiPose, each returned pose also carries a box, and an id when tracking is on.
The 17 keypoints follow the COCO order, from 0 nose to 16 right_ankle. The full table, and the other models that share it, are in the COCO 17 keypoint map.
Confidence thresholds#
The SinglePose card says the model "predicts 17 human keypoints of the full body even when they are occluded", gives keypoints outside the frame low confidence scores, and recommends a default threshold of 0.3 to filter them. The TF.js package has a separate, pose-level threshold: minPoseScore, which falls back to DEFAULT_MIN_POSE_SCORE, 0.25 in the MoveNet constants file, when you do not set it.
Runtimes and where the weights come from#
In the browser, the MoveNet README pairs the package with a TF.js backend: WebGL, or WebAssembly, which it calls "the typical backend for devices with lower-end or no GPUs". By default the package loads weights from tfhub.dev, and the constants file names the three model URLs:
https://tfhub.dev/google/tfjs-model/movenet/singlepose/lightning/4
https://tfhub.dev/google/tfjs-model/movenet/singlepose/thunder/4
https://tfhub.dev/google/tfjs-model/movenet/multipose/lightning/1
The modelUrl option points the package at your own copy instead; the README calls it useful "for area/countries that don't have access to the model hosted on tf.hub", and it also accepts an io.IOHandler such as tfjs-react-native's bundleResourceIO to load from an app bundle. Outside the browser, both cards name TensorFlow Lite for on-device use, and the MultiPose card gives its input as int32 for TF.js and uint8 for TF Lite.
The published speed numbers#
The MoveNet README publishes frames per second for its three models, in the order SinglePose Lightning, SinglePose Thunder, MultiPose Lightning:
| Backend | MacBook Pro 15-inch 2019 | iPhone 12 | Pixel 5 | Desktop, i9-10900K with GTX 1070 |
|---|---|---|---|---|
| WebGL | 104, 77, 54 | 51, 43, 24 | 34, 12, 8 | 87, 82, 62 |
| WASM with SIMD and multithreading | 42, 21, N/A | N/A | N/A | 71, 30, N/A |
These are the TF.js team's figures on its own hardware. The README adds that for MultiPose "the number of detected persons does not impact inference speed and the accuracy of detections is similar to that of SinglePose Lightning". The cards' millisecond benchmarks are set against MediaPipe's on the comparison page; measure on your own target devices before you choose.
Licence#
The tensorflow/tfjs-models LICENSE is the Apache License, Version 2.0, and the SinglePose card says "Licensed Under Apache License, Version 2.0". The text of the MultiPose card has no license line. That gap, and what Apache-2.0 asks of you when you ship, are covered in pose estimation model licenses.
Two statements that disagree#
The pose-detection package README still says "Currently, only PoseNet supports multi-pose estimation." The MoveNet README in the same repository documents MULTIPOSE_LIGHTNING, and the MoveNet constants file lists it among the valid models. We go by the MoveNet README and the code.
Which one to load#
Our reading of Google's own descriptions: SinglePose Lightning for live rep counting where latency matters most, Thunder when you can spend more compute for a cleaner pose, and MultiPose Lightning only when more than one person must be tracked. The SinglePose card is explicit that it focuses "on detecting the pose of the person who is closest to the image center" and ignores the rest. What you then compute from the keypoints is covered in how rep counting works.
Frequently asked questions
- What input size do MoveNet Lightning and Thunder expect?
- Google's MoveNet.SinglePose card gives an int32 tensor of 192x192x3 for Lightning and 256x256x3 for Thunder, RGB with values from 0 to 255, and the TF.js MoveNet constants file uses the same 192 and 256 resolutions. MultiPose Lightning differs: its input is 1xHxWx3 with H and W multiples of 32 chosen at run time, and its card recommends resizing so the larger side is 256 pixels.
- In what order does MoveNet's output tensor store coordinates?
- y first, then x, then the score. The SinglePose card describes a 1x1x17x3 float32 tensor whose last dimension holds the yx coordinates normalized to the image frame followed by the confidence, and the MultiPose card lays out each person as y, x and score for all 17 keypoints followed by a bounding box and an instance score. The TF.js pose-detection package converts this into keypoints with x, y, score and name, with x and y in image pixels.
- How many people can MoveNet MultiPose track?
- Up to 6. The MoveNet README describes MULTIPOSE_LIGHTNING as a multi-pose detector that detects up to 6 poses, the MultiPose card says the same, and each returned pose carries a bounding box. Setting enableTracking gives each pose an id that identifies the person across frames. The README also says the number of detected people does not change inference speed and that accuracy is similar to SinglePose Lightning's.
- Where does the TF.js pose-detection package load MoveNet weights from?
- From tfhub.dev by default: the MoveNet constants file points at movenet/singlepose/lightning/4, movenet/singlepose/thunder/4 and movenet/multipose/lightning/1 under tfhub.dev/google/tfjs-model. The modelUrl option loads your own copy instead and also accepts an io.IOHandler, which the README pairs with tfjs-react-native's bundleResourceIO to load a model from the app bundle.
- What confidence threshold does Google suggest for MoveNet keypoints?
- 0.3. The MoveNet.SinglePose card says the model predicts all 17 keypoints even when they are occluded, gives keypoints outside the frame low confidence scores, and recommends a default threshold of 0.3 to filter out unconfident predictions. That is per keypoint; the TF.js package's minPoseScore is a separate threshold on the whole pose, which defaults to 0.25.
Keep reading
Elsewhere on the site
Pages that share this one’s concepts and sources, from other sections.
Next steps
Was this page useful?
Independent comparison, last reviewed October 17, 2026. Pricing, rate limits, and feature availability change often — confirm current details in each provider’s official documentation before you commit. Product and company names are trademarks of their respective owners; AIFitnessAPI is not affiliated with, endorsed by, or sponsored by any product listed here.
← All ai motion · by AIFitnessAPI