@pose-tracker/react-native-pose-estimation-light 0.1.0
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/LICENSE +45 -0
- package/PoseTrackerVision.podspec +28 -0
- package/README.md +161 -0
- package/THIRD_PARTY_NOTICES.md +19 -0
- package/ios/PoseTrackerVision/PoseTrackerBodyPosePlugin.m +18 -0
- package/ios/PoseTrackerVision/PoseTrackerBodyPosePlugin.swift +108 -0
- package/lib/PoseTrackerProvider.d.ts +102 -0
- package/lib/PoseTrackerProvider.js +204 -0
- package/lib/api/configure.d.ts +29 -0
- package/lib/api/configure.js +64 -0
- package/lib/api/skeleton.d.ts +17 -0
- package/lib/api/skeleton.js +53 -0
- package/lib/api/track.d.ts +61 -0
- package/lib/api/track.js +146 -0
- package/lib/backends/PoseBackend.d.ts +50 -0
- package/lib/backends/PoseBackend.js +11 -0
- package/lib/backends/vision/VisionPoseBackend.d.ts +72 -0
- package/lib/backends/vision/VisionPoseBackend.js +177 -0
- package/lib/backends/vision/mapVisionJoints.d.ts +35 -0
- package/lib/backends/vision/mapVisionJoints.js +162 -0
- package/lib/backends/vision/optionalVision.d.ts +32 -0
- package/lib/backends/vision/optionalVision.js +76 -0
- package/lib/backends/webview/WebViewPoseBackend.d.ts +223 -0
- package/lib/backends/webview/WebViewPoseBackend.js +382 -0
- package/lib/backends/webview/brandAssets.d.ts +5 -0
- package/lib/backends/webview/brandAssets.js +8 -0
- package/lib/backends/webview/onlineRuntime.d.ts +45 -0
- package/lib/backends/webview/onlineRuntime.js +57 -0
- package/lib/backends/webview/poseHtml.d.ts +71 -0
- package/lib/backends/webview/poseHtml.js +188 -0
- package/lib/backends/webview/poseRuntimeSource.d.ts +3 -0
- package/lib/backends/webview/poseRuntimeSource.js +4 -0
- package/lib/cache/obfuscate.d.ts +18 -0
- package/lib/cache/obfuscate.js +90 -0
- package/lib/camera/PoseCameraView.d.ts +51 -0
- package/lib/camera/PoseCameraView.js +99 -0
- package/lib/camera/WebViewPoseView.d.ts +81 -0
- package/lib/camera/WebViewPoseView.js +312 -0
- package/lib/client.d.ts +361 -0
- package/lib/client.js +1046 -0
- package/lib/diagnostics/logReport.d.ts +23 -0
- package/lib/diagnostics/logReport.js +102 -0
- package/lib/engine/EngineLoader.d.ts +95 -0
- package/lib/engine/EngineLoader.js +347 -0
- package/lib/engine/types.d.ts +83 -0
- package/lib/engine/types.js +11 -0
- package/lib/events/classicMessage.d.ts +31 -0
- package/lib/events/classicMessage.js +259 -0
- package/lib/exercises/aliases.d.ts +18 -0
- package/lib/exercises/aliases.js +48 -0
- package/lib/index.d.ts +72 -0
- package/lib/index.js +170 -0
- package/lib/models/poseModels.d.ts +39 -0
- package/lib/models/poseModels.js +63 -0
- package/lib/quality/AdaptiveQualityController.d.ts +120 -0
- package/lib/quality/AdaptiveQualityController.js +423 -0
- package/lib/quality/RuntimeGuard.d.ts +34 -0
- package/lib/quality/RuntimeGuard.js +105 -0
- package/lib/quality/captureMode.d.ts +82 -0
- package/lib/quality/captureMode.js +75 -0
- package/lib/quality/deviceCapability.d.ts +37 -0
- package/lib/quality/deviceCapability.js +177 -0
- package/lib/quality/profiles.d.ts +125 -0
- package/lib/quality/profiles.js +202 -0
- package/lib/runtime/RuntimeCache.d.ts +75 -0
- package/lib/runtime/RuntimeCache.js +230 -0
- package/lib/sdkVersion.d.ts +2 -0
- package/lib/sdkVersion.js +5 -0
- package/lib/support/optionalModules.d.ts +46 -0
- package/lib/support/optionalModules.js +82 -0
- package/lib/types/acceleration.d.ts +86 -0
- package/lib/types/acceleration.js +15 -0
- package/lib/types/events.d.ts +345 -0
- package/lib/types/events.js +10 -0
- package/lib/types/features.d.ts +90 -0
- package/lib/types/features.js +122 -0
- package/lib/types/manifest.d.ts +197 -0
- package/lib/types/manifest.js +10 -0
- package/lib/types/pose.d.ts +36 -0
- package/lib/types/pose.js +41 -0
- package/lib/types/preload.d.ts +17 -0
- package/lib/types/preload.js +10 -0
- package/lib/types/skeleton.d.ts +29 -0
- package/lib/types/skeleton.js +52 -0
- package/package.json +92 -0
- package/react-native.config.js +12 -0
- package/src/PoseTrackerProvider.tsx +332 -0
- package/src/api/configure.ts +82 -0
- package/src/api/skeleton.ts +60 -0
- package/src/api/track.ts +182 -0
- package/src/backends/PoseBackend.ts +59 -0
- package/src/backends/vision/VisionPoseBackend.ts +238 -0
- package/src/backends/vision/mapVisionJoints.ts +185 -0
- package/src/backends/vision/optionalVision.ts +94 -0
- package/src/backends/webview/WebViewPoseBackend.ts +582 -0
- package/src/backends/webview/brandAssets.ts +5 -0
- package/src/backends/webview/onlineRuntime.ts +94 -0
- package/src/backends/webview/poseHtml.ts +259 -0
- package/src/backends/webview/poseRuntimeSource.d.ts +3 -0
- package/src/cache/obfuscate.ts +94 -0
- package/src/camera/PoseCameraView.tsx +223 -0
- package/src/camera/WebViewPoseView.tsx +466 -0
- package/src/client.ts +1295 -0
- package/src/diagnostics/logReport.ts +131 -0
- package/src/engine/EngineLoader.ts +428 -0
- package/src/engine/types.ts +93 -0
- package/src/events/classicMessage.ts +271 -0
- package/src/exercises/aliases.ts +50 -0
- package/src/index.ts +243 -0
- package/src/models/poseModels.ts +93 -0
- package/src/quality/AdaptiveQualityController.ts +579 -0
- package/src/quality/RuntimeGuard.ts +119 -0
- package/src/quality/captureMode.ts +97 -0
- package/src/quality/deviceCapability.ts +187 -0
- package/src/quality/profiles.ts +253 -0
- package/src/runtime/RuntimeCache.ts +300 -0
- package/src/sdkVersion.ts +2 -0
- package/src/support/optionalModules.ts +114 -0
- package/src/types/acceleration.ts +94 -0
- package/src/types/events.ts +437 -0
- package/src/types/features.ts +176 -0
- package/src/types/manifest.ts +230 -0
- package/src/types/pose.ts +85 -0
- package/src/types/preload.ts +19 -0
- package/src/types/skeleton.ts +77 -0
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK event types.
|
|
3
|
+
*
|
|
4
|
+
* These mirror the postMessage payloads of the existing PoseTracker WebView
|
|
5
|
+
* API (keypoints, angles, counter, posture, progression, recommendations,
|
|
6
|
+
* form_score, exercise_summary) so existing integrations can migrate with
|
|
7
|
+
* minimal changes: the WebView `onMessage` JSON becomes a typed callback.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Keypoint } from './pose';
|
|
11
|
+
import type { AccelerationState } from './acceleration';
|
|
12
|
+
import type { QualityProfile, QualityProfileId } from '../quality/profiles';
|
|
13
|
+
|
|
14
|
+
export type PoseTrackerStatus =
|
|
15
|
+
| 'idle'
|
|
16
|
+
| 'configuring'
|
|
17
|
+
| 'downloading'
|
|
18
|
+
| 'warming'
|
|
19
|
+
| 'ready'
|
|
20
|
+
| 'error';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Operating mode (commercial boundary):
|
|
24
|
+
* - 'keypoints-only': no validated API key/session — the SDK provides its
|
|
25
|
+
* core value only (bundled MoveNet, warm-up, camera pipeline) and streams
|
|
26
|
+
* raw `keypoints` events. No business events (counter, angles, posture,
|
|
27
|
+
* progression, recommendations, form_score, exercise_summary).
|
|
28
|
+
* - 'full-engine': a handshake succeeded (live or from the encrypted local
|
|
29
|
+
* session cache) and the engine bundle is loaded — all events available.
|
|
30
|
+
*
|
|
31
|
+
* The mode can upgrade at runtime (keypoints-only → full-engine) without
|
|
32
|
+
* restarting the camera pipeline, via `configure()` or a preload retry.
|
|
33
|
+
*/
|
|
34
|
+
export type PoseTrackerMode = 'keypoints-only' | 'full-engine';
|
|
35
|
+
|
|
36
|
+
export type InitializationStep =
|
|
37
|
+
| 'configuring'
|
|
38
|
+
| 'downloading'
|
|
39
|
+
| 'warming'
|
|
40
|
+
| 'accessing_webcam'
|
|
41
|
+
| 'loading_pose_model'
|
|
42
|
+
| 'ready';
|
|
43
|
+
|
|
44
|
+
export interface InitializationEvent {
|
|
45
|
+
type: 'initialization';
|
|
46
|
+
/**
|
|
47
|
+
* Machine step. Classic PoseTracker used free-form `message` strings
|
|
48
|
+
* ("accessing webcam", "loading pose model", "running"); both are set.
|
|
49
|
+
*/
|
|
50
|
+
step: InitializationStep;
|
|
51
|
+
/** Human-readable status (PoseTracker WebView parity). */
|
|
52
|
+
message: string;
|
|
53
|
+
ready: boolean;
|
|
54
|
+
/** Present on the `ready` step. */
|
|
55
|
+
mode?: PoseTrackerMode;
|
|
56
|
+
/**
|
|
57
|
+
* Present on the `ready` step: GPU-acceleration verdict from the warm-up
|
|
58
|
+
* health check ('gpu' | 'cpu-fallback' | 'unavailable'). See
|
|
59
|
+
* docs/ANDROID_GL_ACCELERATION.md.
|
|
60
|
+
*/
|
|
61
|
+
acceleration?: AccelerationState;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface ErrorEvent {
|
|
65
|
+
type: 'error';
|
|
66
|
+
code:
|
|
67
|
+
| 'invalid_token'
|
|
68
|
+
| 'quota_exceeded'
|
|
69
|
+
| 'network'
|
|
70
|
+
/**
|
|
71
|
+
* First launch, no network, empty runtime cache: the pose runtime cannot
|
|
72
|
+
* be initialized without downloading the payload once. Fatal.
|
|
73
|
+
*/
|
|
74
|
+
| 'network_required'
|
|
75
|
+
/**
|
|
76
|
+
* Offline with an API key: metered features (engine/exercises) are
|
|
77
|
+
* refused because PoseTracker cannot count their usage. Non-fatal —
|
|
78
|
+
* keypoints-only keeps running from the cache.
|
|
79
|
+
*/
|
|
80
|
+
| 'offline_metered'
|
|
81
|
+
/**
|
|
82
|
+
* The `free` plan requested developer features (angles, recommendations,
|
|
83
|
+
* progression, or keypoints combined with an exercise). Same message as
|
|
84
|
+
* the PoseTracker WebView (`TrackingAppV3`). Non-fatal: keypoints-only
|
|
85
|
+
* pose estimation keeps running.
|
|
86
|
+
*/
|
|
87
|
+
| 'free_plan_feature_blocked'
|
|
88
|
+
/**
|
|
89
|
+
* A WebView-only option was requested (blazepose, poseEngine,
|
|
90
|
+
* mediapipeModel, …): this SDK ships MoveNet Lightning only.
|
|
91
|
+
*/
|
|
92
|
+
| 'feature_not_supported'
|
|
93
|
+
/** Unknown exercise id (WebView parity: `invalid_exercise`). */
|
|
94
|
+
| 'invalid_exercise'
|
|
95
|
+
/** jump_analysis requires `userHeightCm` (WebView parity). */
|
|
96
|
+
| 'jump_analysis_missing_height'
|
|
97
|
+
| 'model_load_failed'
|
|
98
|
+
| 'engine_load_failed'
|
|
99
|
+
| 'integrity_check_failed'
|
|
100
|
+
| 'webview_error'
|
|
101
|
+
| 'device_too_slow'
|
|
102
|
+
| 'backend_fallback_wasm'
|
|
103
|
+
| 'internal';
|
|
104
|
+
message: string;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Non-fatal warning the host can surface (telemetry / soft UX).
|
|
109
|
+
* Classic WebView sometimes used `type: "warning"`; V3 degradations often
|
|
110
|
+
* reuse `type: "error"` with a code — see {@link PerformanceWarningEvent}.
|
|
111
|
+
*/
|
|
112
|
+
export interface WarningEvent {
|
|
113
|
+
type: 'warning';
|
|
114
|
+
code:
|
|
115
|
+
| 'quality_downgraded'
|
|
116
|
+
| 'backend_fallback_wasm'
|
|
117
|
+
| 'webview'
|
|
118
|
+
| 'internal';
|
|
119
|
+
message: string;
|
|
120
|
+
timestampMs: number;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface KeypointsEvent {
|
|
124
|
+
type: 'keypoints';
|
|
125
|
+
keypoints: Keypoint[];
|
|
126
|
+
/** Mean confidence of the pose. */
|
|
127
|
+
score: number;
|
|
128
|
+
timestampMs: number;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface AngleValue {
|
|
132
|
+
/** Angle id from the exercise config, e.g. "left_knee". */
|
|
133
|
+
id: string;
|
|
134
|
+
side: 'left' | 'right' | 'center';
|
|
135
|
+
degrees: number;
|
|
136
|
+
/** Min confidence of the three keypoints defining the angle. */
|
|
137
|
+
score: number;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface AnglesEvent {
|
|
141
|
+
type: 'angles';
|
|
142
|
+
angles: AngleValue[];
|
|
143
|
+
timestampMs: number;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Letter grade for a 0–100 form score (GitBook / Front BaseExercise):
|
|
148
|
+
* A ≥ 90, B ≥ 80, C ≥ 70, D ≥ 60, F < 60.
|
|
149
|
+
*/
|
|
150
|
+
export type FormGrade = 'A' | 'B' | 'C' | 'D' | 'F';
|
|
151
|
+
|
|
152
|
+
/** Valid `minGrade` filter values (F is not a valid minGrade config). */
|
|
153
|
+
export type MinGrade = 'A' | 'B' | 'C' | 'D';
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Nested form score on a counted rep — GitBook / WebView V3
|
|
157
|
+
* `counter.form_score` (authoritative grade for that rep).
|
|
158
|
+
*/
|
|
159
|
+
export interface CounterFormScore {
|
|
160
|
+
/** Score of the rep that was just counted, 0–100. */
|
|
161
|
+
score: number;
|
|
162
|
+
/** Running average across counted reps, 0–100. */
|
|
163
|
+
average: number;
|
|
164
|
+
grade: FormGrade;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export interface CounterEvent {
|
|
168
|
+
type: 'counter';
|
|
169
|
+
count: number;
|
|
170
|
+
/**
|
|
171
|
+
* Authoritative form score for the counted rep (WebView
|
|
172
|
+
* `counter.form_score`). Prefer this over a standalone `form_score` event
|
|
173
|
+
* when mirroring the tracking endpoint.
|
|
174
|
+
*/
|
|
175
|
+
formScore?: CounterFormScore;
|
|
176
|
+
/** Similarity score vs. reference movement for the last rep, when a reference is active. */
|
|
177
|
+
referenceScore?: number;
|
|
178
|
+
timestampMs: number;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface PostureEvent {
|
|
182
|
+
type: 'posture';
|
|
183
|
+
/** True when the user placement satisfies the exercise posture requirements. */
|
|
184
|
+
ready: boolean;
|
|
185
|
+
/** Localized human hint ("Face the camera", "Get ready…"). */
|
|
186
|
+
hint: string;
|
|
187
|
+
/** WebView parity: placement direction hint ("in-frame", "face-camera", "profile-camera"). */
|
|
188
|
+
direction?: string;
|
|
189
|
+
missingKeypoints: string[];
|
|
190
|
+
timestampMs: number;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface ProgressionEvent {
|
|
194
|
+
type: 'progression';
|
|
195
|
+
/** Movement progression within the current rep, 0–100. */
|
|
196
|
+
value: number;
|
|
197
|
+
timestampMs: number;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export interface RecommendationsEvent {
|
|
201
|
+
type: 'recommendations';
|
|
202
|
+
/** Localized form advice strings. */
|
|
203
|
+
recommendations: string[];
|
|
204
|
+
timestampMs: number;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface FormScoreEvent {
|
|
208
|
+
type: 'form_score';
|
|
209
|
+
/** Score of the last completed rep, 0–100. */
|
|
210
|
+
score: number;
|
|
211
|
+
/** Running average across the session, 0–100. */
|
|
212
|
+
average: number;
|
|
213
|
+
grade: FormGrade;
|
|
214
|
+
timestampMs: number;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export interface RepSummary {
|
|
218
|
+
index: number;
|
|
219
|
+
formScore: number;
|
|
220
|
+
durationMs: number;
|
|
221
|
+
referenceScore?: number;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export interface ExerciseSummaryEvent {
|
|
225
|
+
type: 'exercise_summary';
|
|
226
|
+
exercise: string;
|
|
227
|
+
counter: number;
|
|
228
|
+
averageFormScore: number;
|
|
229
|
+
averageSimilarity?: number;
|
|
230
|
+
grade: FormGrade;
|
|
231
|
+
history: RepSummary[];
|
|
232
|
+
durationMs: number;
|
|
233
|
+
timestampMs: number;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// ---------------------------------------------------------------------------
|
|
237
|
+
// Custom jump exercises (jump_analysis / air_time_jump) — WebView parity:
|
|
238
|
+
// same event `type` strings and field names as the front's sendDataToNative
|
|
239
|
+
// payloads (CameraFeedV3 runCustomHandlerCompute).
|
|
240
|
+
// ---------------------------------------------------------------------------
|
|
241
|
+
|
|
242
|
+
export interface VisibleHipsInfo {
|
|
243
|
+
left: boolean;
|
|
244
|
+
right: boolean;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** jump_analysis only: cm/pixel calibration established from userHeightCm. */
|
|
248
|
+
export interface JumpCalibrationEvent {
|
|
249
|
+
type: 'jump_calibration';
|
|
250
|
+
calibrated: true;
|
|
251
|
+
cmPerPixel: number;
|
|
252
|
+
baselineY: number | null;
|
|
253
|
+
visibleHips: VisibleHipsInfo;
|
|
254
|
+
/** WebView literal: "Calibration complete - ready to jump". */
|
|
255
|
+
message: string;
|
|
256
|
+
timestampMs: number;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** Push-off detected — measurement in progress. */
|
|
260
|
+
export interface JumpStartedEvent {
|
|
261
|
+
type: 'jump_started';
|
|
262
|
+
/** WebView literal: "Jump detected - measuring height". */
|
|
263
|
+
message: string;
|
|
264
|
+
timestampMs: number;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Live/final jump height. `final: true` closes the jump (see JumpResultEvent). */
|
|
268
|
+
export interface JumpHeightEvent {
|
|
269
|
+
type: 'jump_height';
|
|
270
|
+
jumpHeightCm: number;
|
|
271
|
+
baselineY?: number | null;
|
|
272
|
+
minY?: number | null;
|
|
273
|
+
measuring: boolean;
|
|
274
|
+
landed: boolean;
|
|
275
|
+
final?: boolean;
|
|
276
|
+
deltaPixels?: number;
|
|
277
|
+
sideUsed?: string | null;
|
|
278
|
+
airTimeMs?: number;
|
|
279
|
+
airTimeSeconds?: number;
|
|
280
|
+
visibleHips?: VisibleHipsInfo;
|
|
281
|
+
timestampMs: number;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/** Detection aborted (approach toward camera, timeout, tracking lost…). */
|
|
285
|
+
export interface JumpDiscardedEvent {
|
|
286
|
+
type: 'jump_discarded';
|
|
287
|
+
reason: string;
|
|
288
|
+
userMessage: string;
|
|
289
|
+
timestampMs: number;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/** One completed jump (final height for jump N). */
|
|
293
|
+
export interface JumpResultEvent {
|
|
294
|
+
type: 'jump_result';
|
|
295
|
+
jumpNumber: number;
|
|
296
|
+
jumpHeightCm: number;
|
|
297
|
+
airTimeMs?: number;
|
|
298
|
+
airTimeSeconds?: number;
|
|
299
|
+
baselineY?: number | null;
|
|
300
|
+
minY?: number | null;
|
|
301
|
+
deltaPixels?: number;
|
|
302
|
+
sideUsed?: string | null;
|
|
303
|
+
visibleHips?: VisibleHipsInfo;
|
|
304
|
+
timestampMs: number;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export interface JumpSummaryEntry {
|
|
308
|
+
jumpNumber: number;
|
|
309
|
+
jumpHeightCm: number;
|
|
310
|
+
airTimeMs?: number;
|
|
311
|
+
airTimeSeconds?: number;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** Running summary of all completed jumps (emitted after each jump_result). */
|
|
315
|
+
export interface JumpSummaryEvent {
|
|
316
|
+
type: 'jump_summary';
|
|
317
|
+
totalJumps: number;
|
|
318
|
+
avgJumpHeight: number;
|
|
319
|
+
maxJumpHeight: number;
|
|
320
|
+
minJumpHeight: number;
|
|
321
|
+
avgAirTimeSeconds?: number;
|
|
322
|
+
jumps: JumpSummaryEntry[];
|
|
323
|
+
timestampMs: number;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Camera / preprocess quality tier changed (AdaptiveChoice auto-downgrade,
|
|
328
|
+
* crash-guard recovery, or GL capability hint). English, for app developers.
|
|
329
|
+
*/
|
|
330
|
+
export interface QualityChangedEvent {
|
|
331
|
+
type: 'quality_changed';
|
|
332
|
+
previousProfile: QualityProfileId;
|
|
333
|
+
activeProfile: QualityProfileId;
|
|
334
|
+
reason:
|
|
335
|
+
| 'low_fps'
|
|
336
|
+
| 'device_capability'
|
|
337
|
+
| 'crash_guard'
|
|
338
|
+
| 'warmup_estimate'
|
|
339
|
+
| 'manual';
|
|
340
|
+
detail: string;
|
|
341
|
+
profile: QualityProfile;
|
|
342
|
+
/** Present when reason is warmup_estimate / low_fps. */
|
|
343
|
+
estimatedFps?: number | null;
|
|
344
|
+
medianInferenceMs?: number | null;
|
|
345
|
+
timestampMs: number;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Fired when mean inference FPS stays critically low. English developer alert —
|
|
350
|
+
* surface in your own telemetry / support tooling; do not show raw to end users
|
|
351
|
+
* unless you localize it.
|
|
352
|
+
*/
|
|
353
|
+
export interface PerformanceWarningEvent {
|
|
354
|
+
type: 'performance_warning';
|
|
355
|
+
code: 'device_too_slow';
|
|
356
|
+
message: string;
|
|
357
|
+
meanFps: number;
|
|
358
|
+
thresholdFps: number;
|
|
359
|
+
activeProfile: QualityProfileId;
|
|
360
|
+
medianInferenceMs: number | null;
|
|
361
|
+
videoSize?: string;
|
|
362
|
+
timestampMs: number;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Download progress of the pose-runtime payload (first preload, or version
|
|
367
|
+
* update). Lets the host app show a loader/progress bar during the initial
|
|
368
|
+
* ~9 MB download; never fired when the cache is already up-to-date.
|
|
369
|
+
*/
|
|
370
|
+
export interface RuntimeDownloadProgressEvent {
|
|
371
|
+
type: 'runtime_download_progress';
|
|
372
|
+
/** Part being downloaded (tfjs, tfjs-wasm, model, weights, pipeline, runtime). */
|
|
373
|
+
part: string;
|
|
374
|
+
completedParts: number;
|
|
375
|
+
totalParts: number;
|
|
376
|
+
/** Size of the current part, from the signed manifest. */
|
|
377
|
+
partBytes: number;
|
|
378
|
+
timestampMs: number;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export type PoseTrackerEvent =
|
|
382
|
+
| InitializationEvent
|
|
383
|
+
| ErrorEvent
|
|
384
|
+
| WarningEvent
|
|
385
|
+
| RuntimeDownloadProgressEvent
|
|
386
|
+
| KeypointsEvent
|
|
387
|
+
| AnglesEvent
|
|
388
|
+
| CounterEvent
|
|
389
|
+
| PostureEvent
|
|
390
|
+
| ProgressionEvent
|
|
391
|
+
| RecommendationsEvent
|
|
392
|
+
| FormScoreEvent
|
|
393
|
+
| ExerciseSummaryEvent
|
|
394
|
+
| JumpCalibrationEvent
|
|
395
|
+
| JumpStartedEvent
|
|
396
|
+
| JumpHeightEvent
|
|
397
|
+
| JumpDiscardedEvent
|
|
398
|
+
| JumpResultEvent
|
|
399
|
+
| JumpSummaryEvent
|
|
400
|
+
| QualityChangedEvent
|
|
401
|
+
| PerformanceWarningEvent;
|
|
402
|
+
|
|
403
|
+
export type PoseTrackerEventType = PoseTrackerEvent['type'];
|
|
404
|
+
|
|
405
|
+
export type PoseTrackerEventListener = (event: PoseTrackerEvent) => void;
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Typed per-event callbacks, convenient for `usePoseTracker({ onCounter, ... })`.
|
|
409
|
+
* Also accepts {@link onMessage} for classic PoseTracker WebView JSON parity.
|
|
410
|
+
*/
|
|
411
|
+
export interface PoseTrackerCallbacks {
|
|
412
|
+
onInitialization?: (event: InitializationEvent) => void;
|
|
413
|
+
onError?: (event: ErrorEvent) => void;
|
|
414
|
+
onWarning?: (event: WarningEvent) => void;
|
|
415
|
+
onKeypoints?: (event: KeypointsEvent) => void;
|
|
416
|
+
onAngles?: (event: AnglesEvent) => void;
|
|
417
|
+
onCounter?: (event: CounterEvent) => void;
|
|
418
|
+
onPosture?: (event: PostureEvent) => void;
|
|
419
|
+
onProgression?: (event: ProgressionEvent) => void;
|
|
420
|
+
onRecommendations?: (event: RecommendationsEvent) => void;
|
|
421
|
+
onFormScore?: (event: FormScoreEvent) => void;
|
|
422
|
+
onExerciseSummary?: (event: ExerciseSummaryEvent) => void;
|
|
423
|
+
onJumpCalibration?: (event: JumpCalibrationEvent) => void;
|
|
424
|
+
onJumpStarted?: (event: JumpStartedEvent) => void;
|
|
425
|
+
onJumpHeight?: (event: JumpHeightEvent) => void;
|
|
426
|
+
onJumpDiscarded?: (event: JumpDiscardedEvent) => void;
|
|
427
|
+
onJumpResult?: (event: JumpResultEvent) => void;
|
|
428
|
+
onJumpSummary?: (event: JumpSummaryEvent) => void;
|
|
429
|
+
onQualityChanged?: (event: QualityChangedEvent) => void;
|
|
430
|
+
onPerformanceWarning?: (event: PerformanceWarningEvent) => void;
|
|
431
|
+
onRuntimeDownloadProgress?: (event: RuntimeDownloadProgressEvent) => void;
|
|
432
|
+
/**
|
|
433
|
+
* Classic PoseTracker `sendDataToNative` JSON stream (same `type` / field
|
|
434
|
+
* names as the WebView product). Fires for every typed event.
|
|
435
|
+
*/
|
|
436
|
+
onMessage?: (message: import('../events/classicMessage').ClassicNativeMessage) => void;
|
|
437
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-selectable tracking features — SDK port of the PoseTracker WebView
|
|
3
|
+
* query params (`/pose_tracker/tracking?angles=true&…`) with the SAME plan
|
|
4
|
+
* gating and the SAME error messages as `TrackingAppV3`.
|
|
5
|
+
*
|
|
6
|
+
* Rules (mirroring the WebView product):
|
|
7
|
+
* - Without an API key the SDK always runs keypoints-only (offline, free,
|
|
8
|
+
* no gating) — pose-only mode streams `keypoints` unconditionally.
|
|
9
|
+
* - `angles`, `recommendations`, `progression` require a PAID plan
|
|
10
|
+
* (anything but `free`).
|
|
11
|
+
* - `keypoints` DURING an exercise session requires a paid plan too
|
|
12
|
+
* (free may stream keypoints only in pose-only mode, i.e. no exercise).
|
|
13
|
+
* - `blazepose` / `poseEngine` / `mediapipeModel` / `poseBackend` /
|
|
14
|
+
* `runInWorker` are NOT part of this SDK (MoveNet Lightning only) and are
|
|
15
|
+
* rejected with a clear error.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { MinGrade } from './events';
|
|
19
|
+
|
|
20
|
+
export interface PoseTrackerFeatures {
|
|
21
|
+
/**
|
|
22
|
+
* Stream `angles` events during an exercise session. Default `false`
|
|
23
|
+
* (WebView parity: `angles="false"`). Paid plans only.
|
|
24
|
+
*/
|
|
25
|
+
angles?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Stream `recommendations` events (form advice) during an exercise
|
|
28
|
+
* session. Default `false`. Paid plans only.
|
|
29
|
+
*/
|
|
30
|
+
recommendations?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Stream `progression` events (0–100 within the rep) during an exercise
|
|
33
|
+
* session. Default `false`. Paid plans only.
|
|
34
|
+
*/
|
|
35
|
+
progression?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Stream raw `keypoints` events DURING an exercise session. Default
|
|
38
|
+
* `false` (WebView parity: free plans cannot combine keypoints with an
|
|
39
|
+
* exercise). Outside a session (pose-only mode) keypoints always stream —
|
|
40
|
+
* that is the SDK's free offline base and is never gated.
|
|
41
|
+
*/
|
|
42
|
+
keypoints?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Only count reps whose form grade is at or above this letter (`A` best).
|
|
45
|
+
* WebView parity: `minGrade` query param (`A`…`D` only). Works on all
|
|
46
|
+
* plans that can run the exercise.
|
|
47
|
+
*/
|
|
48
|
+
minGrade?: MinGrade;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Feature keys after defaults are applied. */
|
|
52
|
+
export interface ResolvedFeatures {
|
|
53
|
+
angles: boolean;
|
|
54
|
+
recommendations: boolean;
|
|
55
|
+
progression: boolean;
|
|
56
|
+
keypoints: boolean;
|
|
57
|
+
minGrade: MinGrade | null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** WebView-parity defaults: everything opt-in, like the query params. */
|
|
61
|
+
export const DEFAULT_FEATURES: ResolvedFeatures = {
|
|
62
|
+
angles: false,
|
|
63
|
+
recommendations: false,
|
|
64
|
+
progression: false,
|
|
65
|
+
keypoints: false,
|
|
66
|
+
minGrade: null,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const KNOWN_FEATURE_KEYS = new Set<string>([
|
|
70
|
+
'angles',
|
|
71
|
+
'recommendations',
|
|
72
|
+
'progression',
|
|
73
|
+
'keypoints',
|
|
74
|
+
'minGrade',
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* WebView params that this SDK deliberately does NOT ship (one SDK, one
|
|
79
|
+
* model: MoveNet Lightning). Passing them (possible from untyped JS hosts)
|
|
80
|
+
* produces a clear `feature_not_supported` error.
|
|
81
|
+
*/
|
|
82
|
+
const UNSUPPORTED_FEATURE_HINTS: Record<string, string> = {
|
|
83
|
+
blazepose: 'BlazePose',
|
|
84
|
+
poseEngine: 'pose engine selection (MediaPipe/PoseLandmarker)',
|
|
85
|
+
mediapipeModel: 'MediaPipe model selection',
|
|
86
|
+
poseBackend: 'pose backend selection',
|
|
87
|
+
runInWorker: 'worker thread selection',
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Error messages — EXACT copies of PoseTrackerFront/components/v3/TrackingAppV3.js
|
|
92
|
+
// so hosts migrating from the WebView see identical strings.
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
/** Free plan requested developer features (angles/recommendations/progression/keypoints+exercise). */
|
|
96
|
+
export const FREE_PLAN_FEATURES_MESSAGE =
|
|
97
|
+
'You cannot use developer features. (visit: https://posetracker.gitbook.io/posetracker-api/tracking-endpoint)';
|
|
98
|
+
|
|
99
|
+
/** Missing/invalid API token when key-gated features are requested. */
|
|
100
|
+
export const INVALID_TOKEN_MESSAGE =
|
|
101
|
+
'Invalid params. Please refer to the documentation and set token=YOUR API_KEY et exercise=A correct exercise. (visit: https://posetracker.gitbook.io/posetracker-api/tracking-endpoint)';
|
|
102
|
+
|
|
103
|
+
/** Reference movement and exercise are mutually exclusive (Phase 2 surface). */
|
|
104
|
+
export const COMBINED_REFERENCE_EXERCISE_MESSAGE =
|
|
105
|
+
'You cannot combine reference & exercise. Please check the documentation.';
|
|
106
|
+
|
|
107
|
+
/** SDK-specific: the requested WebView feature does not exist in this SDK. */
|
|
108
|
+
export function featureNotSupportedMessage(key: string): string {
|
|
109
|
+
const hint = UNSUPPORTED_FEATURE_HINTS[key] ?? `'${key}'`;
|
|
110
|
+
return (
|
|
111
|
+
`The '${key}' option (${hint}) is not available in this SDK. ` +
|
|
112
|
+
'This SDK ships MoveNet Lightning only — pose engine and model cannot be changed. ' +
|
|
113
|
+
'Remove the option, or use the PoseTracker WebView product if you need it. ' +
|
|
114
|
+
'(visit: https://posetracker.gitbook.io/posetracker-api/tracking-endpoint)'
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// Helpers
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Apply WebView-parity defaults and detect unsupported keys passed by
|
|
124
|
+
* untyped JS hosts (e.g. `{ blazepose: true }`).
|
|
125
|
+
*/
|
|
126
|
+
export function resolveFeatures(input: PoseTrackerFeatures | undefined): {
|
|
127
|
+
features: ResolvedFeatures;
|
|
128
|
+
unsupportedKeys: string[];
|
|
129
|
+
} {
|
|
130
|
+
if (!input) {
|
|
131
|
+
return { features: { ...DEFAULT_FEATURES }, unsupportedKeys: [] };
|
|
132
|
+
}
|
|
133
|
+
const unsupportedKeys = Object.keys(input).filter((k) => !KNOWN_FEATURE_KEYS.has(k));
|
|
134
|
+
return {
|
|
135
|
+
features: {
|
|
136
|
+
angles: input.angles === true,
|
|
137
|
+
recommendations: input.recommendations === true,
|
|
138
|
+
progression: input.progression === true,
|
|
139
|
+
keypoints: input.keypoints === true,
|
|
140
|
+
minGrade: input.minGrade ?? null,
|
|
141
|
+
},
|
|
142
|
+
unsupportedKeys,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Which requested features a `free` plan is NOT allowed to use — exact port
|
|
148
|
+
* of the TrackingAppV3 condition (keypoints only blocked when an exercise
|
|
149
|
+
* is involved; pose-only keypoints stay free).
|
|
150
|
+
*/
|
|
151
|
+
export function freeBlockedFeatures(
|
|
152
|
+
features: ResolvedFeatures,
|
|
153
|
+
options: { withExercise: boolean },
|
|
154
|
+
): string[] {
|
|
155
|
+
const blocked: string[] = [];
|
|
156
|
+
if (features.angles) blocked.push('angles');
|
|
157
|
+
if (features.recommendations) blocked.push('recommendations');
|
|
158
|
+
if (features.progression) blocked.push('progression');
|
|
159
|
+
if (features.keypoints && options.withExercise) blocked.push('keypoints');
|
|
160
|
+
return blocked;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** True for every plan type except `free` (developer / company / custom). */
|
|
164
|
+
export function isPaidPlan(planType: string | null | undefined): boolean {
|
|
165
|
+
return typeof planType === 'string' && planType.length > 0 && planType !== 'free';
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Whether the live camera overlay should show the PoseTracker watermark.
|
|
170
|
+
* Shown for keyless (null), `free`, and any non-paid plan. Hidden for paid
|
|
171
|
+
* plans (`developer`, `company`, `enterprise`, custom, …) — same rule as
|
|
172
|
+
* {@link isPaidPlan}.
|
|
173
|
+
*/
|
|
174
|
+
export function shouldShowWatermark(planType: string | null | undefined): boolean {
|
|
175
|
+
return !isPaidPlan(planType);
|
|
176
|
+
}
|