@pose-tracker/react-native-pose-estimation-light 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,10 +1,28 @@
1
1
  # PoseTracker React Native — Light (online) Human Pose Estimation SDK
2
2
 
3
- **PoseTracker Light** is a **human pose estimation SDK for React Native**,
4
- fully optimized for **iOS and Android** (including **Expo Go**). Same API
5
- surface as the offline SDK for keypoints + optional API-key exercise engine —
6
- but **MoveNet and TF.js load from the network** each WebView boot, so the npm
7
- package stays tiny.
3
+ **⭐ Star us on GitHub:** [Movelytics/react-native-pose-estimation-light](https://github.com/Movelytics/react-native-pose-estimation-light) — it helps other React Native and Expo developers find the SDK.
4
+
5
+ **Try it on your phone (no Xcode / Android Studio):**
6
+ 1. Install [Expo Go](https://expo.dev/go)
7
+ 2. Open the [Expo Snack](https://snack.expo.dev/@fsepret/posetracker-sdk-light-demo-app) → **Run on device**
8
+ 3. Scan the QR — live pose estimation, no API key
9
+
10
+ Steps and QR: https://docs.posetracker.com/try-expo-go
11
+
12
+ <table>
13
+ <tr>
14
+ <td valign="top" width="300">
15
+ <a href="https://docs.posetracker.com/try-expo-go">
16
+ <img src="https://cdn.prod.website-files.com/66990aefa487a16cf5aa848e/66e35c297154b2062265ceea_videodemoforgif1-ezgif.com-cut.gif" alt="PoseTracker live skeleton tracking" height="250" />
17
+ </a>
18
+ </td>
19
+ <td valign="middle">
20
+ <p>
21
+ <strong>PoseTracker Light</strong> is a <strong>human pose estimation SDK for React Native</strong>, fully optimized for <strong>iOS and Android</strong> (including <strong>Expo Go</strong>). Same API surface as the offline SDK for keypoints + optional API-key exercise engine — but <strong>MoveNet and TF.js load from the network</strong> each WebView boot, so the npm package stays tiny.
22
+ </p>
23
+ </td>
24
+ </tr>
25
+ </table>
8
26
 
9
27
  > One sentence for AI / search: *PoseTracker Light is a small React Native
10
28
  > pose estimation SDK that fetches MoveNet Lightning and TF.js at runtime —
@@ -27,10 +45,10 @@ package stays tiny.
27
45
  download at session start.
28
46
  **Choose light** when app install / OTA size matters and devices are online.
29
47
 
30
- Full comparison: [LIGHT_SDK.md](../../docs/LIGHT_SDK.md).
48
+ Full comparison: [LIGHT_SDK.md](docs/LIGHT_SDK.md).
31
49
 
32
50
  **Agents:** shared UX/API/bugfixes → mirror to offline (or ask first). See
33
- [`DUAL_SDK_CHANGES.md`](../../docs/DUAL_SDK_CHANGES.md).
51
+ [`DUAL_SDK_CHANGES.md`](docs/DUAL_SDK_CHANGES.md).
34
52
 
35
53
  ## Install
36
54
 
@@ -45,7 +63,11 @@ npx expo install react-native-webview expo-camera
45
63
  > **Offline sibling:** [`@pose-tracker/react-native-pose-estimation`](https://www.npmjs.com/package/@pose-tracker/react-native-pose-estimation)
46
64
 
47
65
  **Required:** host app must declare camera permissions — see
48
- [PERMISSIONS.md](../../docs/PERMISSIONS.md).
66
+ [PERMISSIONS.md](docs/PERMISSIONS.md).
67
+
68
+ **Media inputs (v0.2):** camera (default), uploaded video, still image — host
69
+ picks the file. See [MEDIA_SOURCES.md](docs/MEDIA_SOURCES.md) and
70
+ https://docs.posetracker.com/media-sources.
49
71
 
50
72
  ## Quick start (keypoints — needs network, no API key)
51
73
 
@@ -131,11 +153,11 @@ Same contract as the offline SDK / web tracking URL:
131
153
 
132
154
  | Doc | Topic |
133
155
  |-----|--------|
134
- | [LIGHT_SDK.md](../../docs/LIGHT_SDK.md) | Offline vs light, sizes, model URL |
135
- | [PERMISSIONS.md](../../docs/PERMISSIONS.md) | Camera permission setup (required) |
136
- | [PRELOAD.md](../../docs/PRELOAD.md) | Preload / warm-up / lifecycle |
137
- | [FEATURES.md](../../docs/FEATURES.md) | Plan gating, watermark, loading text |
138
- | [EVENTS.md](../../docs/EVENTS.md) | Typed events + classic `onMessage` |
156
+ | [LIGHT_SDK.md](docs/LIGHT_SDK.md) | Offline vs light, sizes, model URL |
157
+ | [PERMISSIONS.md](docs/PERMISSIONS.md) | Camera permission setup (required) |
158
+ | [PRELOAD.md](docs/PRELOAD.md) | Preload / warm-up / lifecycle |
159
+ | [FEATURES.md](docs/FEATURES.md) | Plan gating, watermark, loading text |
160
+ | [EVENTS.md](docs/EVENTS.md) | Typed events + classic `onMessage` |
139
161
 
140
162
  ## FAQ
141
163
 
@@ -164,6 +186,8 @@ see [`THIRD_PARTY_NOTICES.md`](./THIRD_PARTY_NOTICES.md).
164
186
  ## Links
165
187
 
166
188
  - Product: https://www.posetracker.com
167
- - API docs: https://posetracker.gitbook.io/posetracker-api
168
- - Offline SDK: https://github.com/Movelytics/react-native-pose-estimation
189
+ - Docs: https://docs.posetracker.com
190
+ - Try on your phone: https://docs.posetracker.com/try-expo-go
191
+ - Expo Snack: https://snack.expo.dev/@fsepret/posetracker-sdk-light-demo-app
169
192
  - Light demo: https://github.com/Movelytics/react-native-pose-estimation-light-demo
193
+ - Offline SDK: https://github.com/Movelytics/react-native-pose-estimation
@@ -154,6 +154,9 @@ function usePoseTracker(callbacks = {}) {
154
154
  case 'progression':
155
155
  cb.onProgression?.(event);
156
156
  break;
157
+ case 'engine_debug':
158
+ cb.onEngineDebug?.(event);
159
+ break;
157
160
  case 'recommendations':
158
161
  cb.onRecommendations?.(event);
159
162
  break;
package/lib/client.d.ts CHANGED
@@ -102,6 +102,11 @@ export interface PoseTrackerClientOptions extends ConfigureOptions {
102
102
  * triaging Android GPU issues in the field.
103
103
  */
104
104
  onDiagnostic?: (message: string) => void;
105
+ /**
106
+ * @internal PoseTracker QA only — not a supported public API.
107
+ * See `.private/ENGINE_DEBUG_QA.md` (do not document in Mintlify).
108
+ */
109
+ debugEngine?: boolean;
105
110
  }
106
111
  /**
107
112
  * Per-session options for {@link PoseTrackerClient.startExercise} — the SDK
@@ -118,6 +123,11 @@ export interface StartExerciseOptions {
118
123
  userHeightCm?: number;
119
124
  /** Device pitch in degrees — jump exercises compensate camera tilt. */
120
125
  devicePitchDeg?: number;
126
+ /**
127
+ * @internal PoseTracker QA only — not a supported public API.
128
+ * Defaults to {@link PoseTrackerClientOptions.debugEngine}.
129
+ */
130
+ debug?: boolean;
121
131
  }
122
132
  export declare class PoseTrackerClient {
123
133
  private status;
package/lib/client.js CHANGED
@@ -818,17 +818,21 @@ class PoseTrackerClient {
818
818
  this.stopExercise();
819
819
  this.currentExerciseId = exerciseId;
820
820
  this.keypointsSuppressionLogged = false;
821
+ const debug = options.debug ?? this.options.debugEngine === true;
821
822
  this.session = this.engine.createSession({
822
823
  exercise,
823
824
  locale: this.options.locale ?? 'en',
824
825
  difficulty: options.difficulty,
825
826
  minGrade: this.features.minGrade ?? undefined,
827
+ debug,
826
828
  features: {
827
829
  angles: this.features.angles,
828
830
  recommendations: this.features.recommendations,
829
831
  progression: this.features.progression,
830
832
  },
831
833
  }, (event) => this.emitFromSession(event));
834
+ this.options.onDiagnostic?.(`[posetracker] startExercise id=${exercise.id} difficulty=${options.difficulty ?? 'medium'} ` +
835
+ `debug=${debug} engine=${this.engine.version} minGrade=${this.features.minGrade ?? 'off'}`);
832
836
  }
833
837
  /** Custom engine session (jump_analysis / air_time_jump). */
834
838
  startCustomExercise(custom, options) {
@@ -1032,6 +1036,10 @@ class PoseTrackerClient {
1032
1036
  return;
1033
1037
  }
1034
1038
  const classic = (0, classicMessage_1.toClassicNativeMessage)(event);
1039
+ if (classic == null) {
1040
+ // SDK-only events (e.g. engine_debug) have no classic equivalent.
1041
+ return;
1042
+ }
1035
1043
  this.messageListeners.forEach((l) => {
1036
1044
  try {
1037
1045
  l(classic);
@@ -36,6 +36,11 @@ export interface EngineSessionOptions {
36
36
  minGrade?: MinGrade;
37
37
  /** Emission flags — engines older than 1.1.0 ignore them (client re-filters). */
38
38
  features?: EngineSessionFeatures;
39
+ /**
40
+ * @internal PoseTracker QA only — not a supported public API.
41
+ * Ignored by older engines.
42
+ */
43
+ debug?: boolean;
39
44
  }
40
45
  export interface EngineSession {
41
46
  /** Feed one estimated pose; the session emits events through the sink. */
@@ -26,6 +26,6 @@ export declare function anglesToClassicTree(angles: AngleValue[]): {
26
26
  /**
27
27
  * Map a typed SDK event to a classic PoseTracker `sendDataToNative` payload.
28
28
  * Returns null for SDK-only events that have no classic equivalent and should
29
- * not be mirrored (none today — quality/performance map to error/warning).
29
+ * not be mirrored (e.g. `engine_debug` QA snapshots).
30
30
  */
31
- export declare function toClassicNativeMessage(event: PoseTrackerEvent): ClassicNativeMessage;
31
+ export declare function toClassicNativeMessage(event: PoseTrackerEvent): ClassicNativeMessage | null;
@@ -49,7 +49,7 @@ function anglesToClassicTree(angles) {
49
49
  /**
50
50
  * Map a typed SDK event to a classic PoseTracker `sendDataToNative` payload.
51
51
  * Returns null for SDK-only events that have no classic equivalent and should
52
- * not be mirrored (none today — quality/performance map to error/warning).
52
+ * not be mirrored (e.g. `engine_debug` QA snapshots).
53
53
  */
54
54
  function toClassicNativeMessage(event) {
55
55
  switch (event.type) {
@@ -236,6 +236,9 @@ function toClassicNativeMessage(event) {
236
236
  totalParts: event.totalParts,
237
237
  timestampMs: event.timestampMs,
238
238
  };
239
+ case 'engine_debug':
240
+ // SDK-only QA stream — no classic WebView equivalent; skip onMessage.
241
+ return null;
239
242
  default: {
240
243
  const _exhaustive = event;
241
244
  return { type: 'unknown', event: _exhaustive };
@@ -1,2 +1,2 @@
1
1
  /** AUTO-GENERATED by scripts/sync-sdk-version.mjs — do not edit. */
2
- export declare const SDK_VERSION = "0.2.0";
2
+ export declare const SDK_VERSION = "0.2.2";
package/lib/sdkVersion.js CHANGED
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SDK_VERSION = void 0;
4
4
  /** AUTO-GENERATED by scripts/sync-sdk-version.mjs — do not edit. */
5
- exports.SDK_VERSION = '0.2.0';
5
+ exports.SDK_VERSION = '0.2.2';
@@ -154,6 +154,40 @@ export interface ProgressionEvent {
154
154
  value: number;
155
155
  timestampMs: number;
156
156
  }
157
+ /**
158
+ * @internal PoseTracker QA only — not a supported public API (do not document in Mintlify).
159
+ * Throttled movement / rep-FSM snapshot. See `.private/ENGINE_DEBUG_QA.md`.
160
+ */
161
+ export interface EngineDebugEvent {
162
+ type: 'engine_debug';
163
+ exerciseId: string;
164
+ engineVersion: string;
165
+ ready: boolean;
166
+ postureHint: string;
167
+ direction?: string;
168
+ missingKeypoints: string[];
169
+ stepIndex: number;
170
+ stepCount: number;
171
+ stepPosition: number | null;
172
+ stepProgression: number;
173
+ progression: number;
174
+ /** Raw FSM rep count (before minGrade gate). */
175
+ rawCount: number;
176
+ /** Public counter after minGrade gate. */
177
+ publicCount: number;
178
+ difficulty: string;
179
+ minGrade: MinGrade | null;
180
+ pointOfView: 'low' | 'up';
181
+ computeError?: string;
182
+ lastSkipReason: string | null;
183
+ posesProcessed: number;
184
+ visibleKeypoints: number;
185
+ knees: {
186
+ left: number | null;
187
+ right: number | null;
188
+ };
189
+ timestampMs: number;
190
+ }
157
191
  export interface RecommendationsEvent {
158
192
  type: 'recommendations';
159
193
  /** Localized form advice strings. */
@@ -309,7 +343,7 @@ export interface RuntimeDownloadProgressEvent {
309
343
  partBytes: number;
310
344
  timestampMs: number;
311
345
  }
312
- export type PoseTrackerEvent = InitializationEvent | ErrorEvent | WarningEvent | RuntimeDownloadProgressEvent | KeypointsEvent | AnglesEvent | CounterEvent | PostureEvent | ProgressionEvent | RecommendationsEvent | FormScoreEvent | ExerciseSummaryEvent | JumpCalibrationEvent | JumpStartedEvent | JumpHeightEvent | JumpDiscardedEvent | JumpResultEvent | JumpSummaryEvent | QualityChangedEvent | PerformanceWarningEvent;
346
+ export type PoseTrackerEvent = InitializationEvent | ErrorEvent | WarningEvent | RuntimeDownloadProgressEvent | KeypointsEvent | AnglesEvent | CounterEvent | PostureEvent | ProgressionEvent | EngineDebugEvent | RecommendationsEvent | FormScoreEvent | ExerciseSummaryEvent | JumpCalibrationEvent | JumpStartedEvent | JumpHeightEvent | JumpDiscardedEvent | JumpResultEvent | JumpSummaryEvent | QualityChangedEvent | PerformanceWarningEvent;
313
347
  export type PoseTrackerEventType = PoseTrackerEvent['type'];
314
348
  export type PoseTrackerEventListener = (event: PoseTrackerEvent) => void;
315
349
  /**
@@ -325,6 +359,7 @@ export interface PoseTrackerCallbacks {
325
359
  onCounter?: (event: CounterEvent) => void;
326
360
  onPosture?: (event: PostureEvent) => void;
327
361
  onProgression?: (event: ProgressionEvent) => void;
362
+ onEngineDebug?: (event: EngineDebugEvent) => void;
328
363
  onRecommendations?: (event: RecommendationsEvent) => void;
329
364
  onFormScore?: (event: FormScoreEvent) => void;
330
365
  onExerciseSummary?: (event: ExerciseSummaryEvent) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pose-tracker/react-native-pose-estimation-light",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Human pose estimation SDK for React Native (light / online) — MoveNet Lightning via CDN + model URL each session, no bundled weights. iOS & Android (Expo Go). Optional API-key exercise engine.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -281,6 +281,9 @@ export function usePoseTracker(callbacks: PoseTrackerCallbacks = {}): PoseTracke
281
281
  case 'progression':
282
282
  cb.onProgression?.(event);
283
283
  break;
284
+ case 'engine_debug':
285
+ cb.onEngineDebug?.(event);
286
+ break;
284
287
  case 'recommendations':
285
288
  cb.onRecommendations?.(event);
286
289
  break;
package/src/client.ts CHANGED
@@ -69,7 +69,6 @@ import {
69
69
  import {
70
70
  toClassicNativeMessage,
71
71
  type ClassicMessageListener,
72
- type ClassicNativeMessage,
73
72
  } from './events/classicMessage';
74
73
  import {
75
74
  FREE_PLAN_FEATURES_MESSAGE,
@@ -164,6 +163,11 @@ export interface PoseTrackerClientOptions extends ConfigureOptions {
164
163
  * triaging Android GPU issues in the field.
165
164
  */
166
165
  onDiagnostic?: (message: string) => void;
166
+ /**
167
+ * @internal PoseTracker QA only — not a supported public API.
168
+ * See `.private/ENGINE_DEBUG_QA.md` (do not document in Mintlify).
169
+ */
170
+ debugEngine?: boolean;
167
171
  }
168
172
 
169
173
  /**
@@ -181,6 +185,11 @@ export interface StartExerciseOptions {
181
185
  userHeightCm?: number;
182
186
  /** Device pitch in degrees — jump exercises compensate camera tilt. */
183
187
  devicePitchDeg?: number;
188
+ /**
189
+ * @internal PoseTracker QA only — not a supported public API.
190
+ * Defaults to {@link PoseTrackerClientOptions.debugEngine}.
191
+ */
192
+ debug?: boolean;
184
193
  }
185
194
 
186
195
  export class PoseTrackerClient {
@@ -1040,12 +1049,14 @@ export class PoseTrackerClient {
1040
1049
  this.stopExercise();
1041
1050
  this.currentExerciseId = exerciseId;
1042
1051
  this.keypointsSuppressionLogged = false;
1052
+ const debug = options.debug ?? this.options.debugEngine === true;
1043
1053
  this.session = this.engine.createSession(
1044
1054
  {
1045
1055
  exercise,
1046
1056
  locale: this.options.locale ?? 'en',
1047
1057
  difficulty: options.difficulty,
1048
1058
  minGrade: this.features.minGrade ?? undefined,
1059
+ debug,
1049
1060
  features: {
1050
1061
  angles: this.features.angles,
1051
1062
  recommendations: this.features.recommendations,
@@ -1054,6 +1065,10 @@ export class PoseTrackerClient {
1054
1065
  },
1055
1066
  (event) => this.emitFromSession(event),
1056
1067
  );
1068
+ this.options.onDiagnostic?.(
1069
+ `[posetracker] startExercise id=${exercise.id} difficulty=${options.difficulty ?? 'medium'} ` +
1070
+ `debug=${debug} engine=${this.engine.version} minGrade=${this.features.minGrade ?? 'off'}`,
1071
+ );
1057
1072
  }
1058
1073
 
1059
1074
  /** Custom engine session (jump_analysis / air_time_jump). */
@@ -1280,7 +1295,11 @@ export class PoseTrackerClient {
1280
1295
  // Skip the classic-message conversion entirely (per-frame allocation).
1281
1296
  return;
1282
1297
  }
1283
- const classic: ClassicNativeMessage = toClassicNativeMessage(event);
1298
+ const classic = toClassicNativeMessage(event);
1299
+ if (classic == null) {
1300
+ // SDK-only events (e.g. engine_debug) have no classic equivalent.
1301
+ return;
1302
+ }
1284
1303
  this.messageListeners.forEach((l) => {
1285
1304
  try {
1286
1305
  l(classic);
@@ -39,6 +39,11 @@ export interface EngineSessionOptions {
39
39
  minGrade?: MinGrade;
40
40
  /** Emission flags — engines older than 1.1.0 ignore them (client re-filters). */
41
41
  features?: EngineSessionFeatures;
42
+ /**
43
+ * @internal PoseTracker QA only — not a supported public API.
44
+ * Ignored by older engines.
45
+ */
46
+ debug?: boolean;
42
47
  }
43
48
 
44
49
  export interface EngineSession {
@@ -59,9 +59,11 @@ export function anglesToClassicTree(angles: AngleValue[]): {
59
59
  /**
60
60
  * Map a typed SDK event to a classic PoseTracker `sendDataToNative` payload.
61
61
  * Returns null for SDK-only events that have no classic equivalent and should
62
- * not be mirrored (none today — quality/performance map to error/warning).
62
+ * not be mirrored (e.g. `engine_debug` QA snapshots).
63
63
  */
64
- export function toClassicNativeMessage(event: PoseTrackerEvent): ClassicNativeMessage {
64
+ export function toClassicNativeMessage(
65
+ event: PoseTrackerEvent,
66
+ ): ClassicNativeMessage | null {
65
67
  switch (event.type) {
66
68
  case 'initialization':
67
69
  return {
@@ -247,6 +249,9 @@ export function toClassicNativeMessage(event: PoseTrackerEvent): ClassicNativeMe
247
249
  totalParts: event.totalParts,
248
250
  timestampMs: event.timestampMs,
249
251
  };
252
+ case 'engine_debug':
253
+ // SDK-only QA stream — no classic WebView equivalent; skip onMessage.
254
+ return null;
250
255
  default: {
251
256
  const _exhaustive: never = event;
252
257
  return { type: 'unknown', event: _exhaustive };
package/src/sdkVersion.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** AUTO-GENERATED by scripts/sync-sdk-version.mjs — do not edit. */
2
- export const SDK_VERSION = '0.2.0';
2
+ export const SDK_VERSION = '0.2.2';
@@ -198,6 +198,38 @@ export interface ProgressionEvent {
198
198
  timestampMs: number;
199
199
  }
200
200
 
201
+ /**
202
+ * @internal PoseTracker QA only — not a supported public API (do not document in Mintlify).
203
+ * Throttled movement / rep-FSM snapshot. See `.private/ENGINE_DEBUG_QA.md`.
204
+ */
205
+ export interface EngineDebugEvent {
206
+ type: 'engine_debug';
207
+ exerciseId: string;
208
+ engineVersion: string;
209
+ ready: boolean;
210
+ postureHint: string;
211
+ direction?: string;
212
+ missingKeypoints: string[];
213
+ stepIndex: number;
214
+ stepCount: number;
215
+ stepPosition: number | null;
216
+ stepProgression: number;
217
+ progression: number;
218
+ /** Raw FSM rep count (before minGrade gate). */
219
+ rawCount: number;
220
+ /** Public counter after minGrade gate. */
221
+ publicCount: number;
222
+ difficulty: string;
223
+ minGrade: MinGrade | null;
224
+ pointOfView: 'low' | 'up';
225
+ computeError?: string;
226
+ lastSkipReason: string | null;
227
+ posesProcessed: number;
228
+ visibleKeypoints: number;
229
+ knees: { left: number | null; right: number | null };
230
+ timestampMs: number;
231
+ }
232
+
201
233
  export interface RecommendationsEvent {
202
234
  type: 'recommendations';
203
235
  /** Localized form advice strings. */
@@ -389,6 +421,7 @@ export type PoseTrackerEvent =
389
421
  | CounterEvent
390
422
  | PostureEvent
391
423
  | ProgressionEvent
424
+ | EngineDebugEvent
392
425
  | RecommendationsEvent
393
426
  | FormScoreEvent
394
427
  | ExerciseSummaryEvent
@@ -418,6 +451,7 @@ export interface PoseTrackerCallbacks {
418
451
  onCounter?: (event: CounterEvent) => void;
419
452
  onPosture?: (event: PostureEvent) => void;
420
453
  onProgression?: (event: ProgressionEvent) => void;
454
+ onEngineDebug?: (event: EngineDebugEvent) => void;
421
455
  onRecommendations?: (event: RecommendationsEvent) => void;
422
456
  onFormScore?: (event: FormScoreEvent) => void;
423
457
  onExerciseSummary?: (event: ExerciseSummaryEvent) => void;