Architecture
PoseFlow runs the same five-stage pipeline on every surface that consumes the SDK. This page explains those stages and how they hand off.
The pipeline
βββββββββββββββββββββββββββββββββ 1. CAMERA β PoseCameraView (native) β CameraTrackingView (web) β CameraImage stream β HTMLVideoElement + Worker ββββββββββββββ¬ββββββββββββββββββββ β raw frames v βββββββββββββββββββββββββββββββββ 2. POSE β Native pose engine β Web Worker (the pose engine WASM) β pure-C FFI β same model, different host ββββββββββββββ¬ββββββββββββββββββββ β Pose (33 landmarks + worldZ + vis) β, display-space, [0, 1] normalised v βββββββββββββββββββββββββββββββββ 3. TRACK β MovementTracker β β - PhaseStateMachine β phase transitions β - rep counter + scoring gate β β - form-rule evaluator β β - CameraAngleDetector β 16-bucket orientation β - frame validator β visibility / distance gates ββββββββββββββ¬ββββββββββββββββββββ β TrackingResult (per frame) β + RepCompletedEvent stream (on rep) β + FormFeedbackEvent stream (on cue) v βββββββββββββββββββββββββββββββββ 4. STATE β Your app state (BLoC, etc.) β - rep count β β UI counter β - form score β β UI score badge β - feedback events β β toast deck / haptics β - detected phase β β highlighted phase tile β - detected bucket β β angle indicator ββββββββββββββ¬ββββββββββββββββββββ β v βββββββββββββββββββββββββββββββββ 5. RENDER β Your widgets β βββββββββββββββββββββββββββββββββThe contract between stages
Each stage talks to the next via a small, well-typed surface:
| Stage | Output | Type |
|---|---|---|
| Camera | Raw frame | CameraImage (native) / ImageBitmap (web) |
| Pose | Detected pose | Pose |
| Track (per frame) | Tracking result | TrackingResult |
| Track (events) | Rep + feedback events | RepCompletedEvent, FormFeedbackEvent |
Your app never reaches into the tracker; it consumes the two streams and the per-frame result and renders.
The canonical pose coordinate space
PoseFlow exposes one pose space across the whole pipeline:
display-space, [0, 1] normalised against the post-rotation
buffer dimensions, selfie-mirrored on the front camera.
- The skeleton overlay paints in display space.
MovementTrackerevaluates tracking points (angle, distance, ratio, position, velocity, stability) in display space.- PoseFlow Studio authors
.posethresholds against the same display-space values its preview tracker sees.
Authoring (Studio) and playback (your app) agree on coordinate scale by construction, distance / position / ratio thresholds resolve against the same numerical values on both sides.
The canonical entry point
Load movements through one call:
final tracker = MovementTracker.withPreset(MovementTrackerPreset.standard);tracker.load( movement, // a Movement decoded from .pose configOverride: cfg, // optional published MovementConfig overlay);If you use TrackedMovementView,
the widget handles this for you, pass the movement and any optional
config, the widget loads them.
Rep-counting modes
MovementTracker runs in one of two modes depending on how the
Movement was authored:
- Rule-based phases (
phaseConfigspopulated,positionsempty) , the default, and the only mode PoseFlow Studio emits. ThePhaseStateMachineadvances when each phaseβs authored conditions (membership gates) evaluate to true against the current per-frame tracking values; reps complete when the phase machine cycles through the authored sequence. - Vector matching (
Movement.positions.isNotEmpty), for movements built from a recorded marker pass. A small PCA index classifies the current pose against named reference positions. ThePhaseStateMachineticks when the user traverses the authored sequence of positions.
PoseFlow Studio always emits the rule-based shape, declarative phase conditions, no recorded reference frames. The vector-matching mode is available for movements built outside Studio against a recorded marker pass.
Camera-angle bucketing
The 16-bucket CameraAngleDetector
is a sidecar that classifies the userβs body orientation every frame
into one of {front, behind, Β±45Β°, Β±90Β°} Γ {hip, floor, overhead}.
Its output gates the form service: when an movement has multiple
AngleBands (one set of ranges per camera bucket), the tracker uses
the detected bucket to pick the right reference. Read more in
camera buckets.
Where the SDK ends and the Studio starts
The Studio is purely an authoring tool, it never participates in
the runtime tracking path. The Studio uses the same MovementTracker
(via its ShowcaseTracker facade) to
drive its live preview, so βwhat you author is what the user getsβ is
enforced by construction: any movement that ticks reps in the Studio
will tick reps in your app.
When the Studio saves, it serialises the in-memory Movement to JSON
via Movement.toJson(). Loading is the inverse ,
Movement.fromJson(). No special βstudio fileβ format exists; the
.pose file is the canonical artifact and any SDK consumer can read
it without involving the Studio at all.
Read next
- Tracking pipeline, what each stage does per frame, with timings.
- Rep counting, the two rep-counting modes in detail.
- Form analysis, how
FormRules flow through the form service. - Camera angle buckets, the 16-bucket model.
- .pose file spec, the on-disk format every consumer reads.