@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,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classic PoseTracker WebView → native message parity.
|
|
3
|
+
*
|
|
4
|
+
* Host apps that already parse `sendDataToNative` JSON
|
|
5
|
+
* (`PoseTrackerFront/lib/v3/sendDataToNativeContract.js`) can subscribe via
|
|
6
|
+
* `addMessageListener` / `usePoseTracker({ onMessage })` and keep the same
|
|
7
|
+
* `type` + payload field names (`data`, `current_count`, `message`, …).
|
|
8
|
+
*
|
|
9
|
+
* Typed {@link PoseTrackerEvent} remains the preferred API for new apps.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { AngleValue, PoseTrackerEvent } from '../types/events';
|
|
13
|
+
|
|
14
|
+
/** Loose JSON envelope matching the frozen WebView → native contract. */
|
|
15
|
+
export type ClassicNativeMessage = {
|
|
16
|
+
type: string;
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type ClassicMessageListener = (message: ClassicNativeMessage) => void;
|
|
21
|
+
|
|
22
|
+
/** Relation keys matching engine `PUBLIC_ANGLES` / Front `computeAngles`. */
|
|
23
|
+
const ANGLE_RELATIONS: Record<string, string> = {
|
|
24
|
+
left_knee: 'from_hip_to_ankle',
|
|
25
|
+
right_knee: 'from_hip_to_ankle',
|
|
26
|
+
left_hip: 'from_knee_to_shoulder',
|
|
27
|
+
right_hip: 'from_knee_to_shoulder',
|
|
28
|
+
left_shoulder: 'from_hip_to_elbow',
|
|
29
|
+
right_shoulder: 'from_hip_to_elbow',
|
|
30
|
+
left_elbow: 'from_shoulder_to_wrist',
|
|
31
|
+
right_elbow: 'from_shoulder_to_wrist',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Rebuild the WebView `angles.data` tree (`left_side` / `right_side`) from
|
|
36
|
+
* the typed flat `AngleValue[]` list.
|
|
37
|
+
*/
|
|
38
|
+
export function anglesToClassicTree(angles: AngleValue[]): {
|
|
39
|
+
left_side: Record<string, Record<string, number>>;
|
|
40
|
+
right_side: Record<string, Record<string, number>>;
|
|
41
|
+
} {
|
|
42
|
+
const data = {
|
|
43
|
+
left_side: {} as Record<string, Record<string, number>>,
|
|
44
|
+
right_side: {} as Record<string, Record<string, number>>,
|
|
45
|
+
};
|
|
46
|
+
for (const a of angles) {
|
|
47
|
+
if (a.side !== 'left' && a.side !== 'right') continue;
|
|
48
|
+
const side = a.side === 'left' ? data.left_side : data.right_side;
|
|
49
|
+
const joint = a.id.replace(/^(left_|right_)/, '');
|
|
50
|
+
const angleType = `${joint}_angle`;
|
|
51
|
+
const relation = ANGLE_RELATIONS[a.id] ?? 'value';
|
|
52
|
+
if (!side[angleType]) side[angleType] = {};
|
|
53
|
+
side[angleType]![relation] = a.degrees;
|
|
54
|
+
side[angleType]![`score_${relation}`] = a.score;
|
|
55
|
+
}
|
|
56
|
+
return data;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Map a typed SDK event to a classic PoseTracker `sendDataToNative` payload.
|
|
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).
|
|
63
|
+
*/
|
|
64
|
+
export function toClassicNativeMessage(event: PoseTrackerEvent): ClassicNativeMessage {
|
|
65
|
+
switch (event.type) {
|
|
66
|
+
case 'initialization':
|
|
67
|
+
return {
|
|
68
|
+
type: 'initialization',
|
|
69
|
+
// WebView-literal parity: TrackingAppV3 emits exactly
|
|
70
|
+
// "checking you plan and access" (sic) while the plan loads — hosts
|
|
71
|
+
// migrating from the WebView may string-match it.
|
|
72
|
+
message:
|
|
73
|
+
event.step === 'configuring'
|
|
74
|
+
? 'checking you plan and access'
|
|
75
|
+
: event.message ?? humanInitStep(event.step),
|
|
76
|
+
ready: event.ready,
|
|
77
|
+
step: event.step,
|
|
78
|
+
...(event.mode != null ? { mode: event.mode } : {}),
|
|
79
|
+
...(event.acceleration != null ? { acceleration: event.acceleration } : {}),
|
|
80
|
+
};
|
|
81
|
+
case 'error':
|
|
82
|
+
return {
|
|
83
|
+
type: 'error',
|
|
84
|
+
error: event.code,
|
|
85
|
+
message: event.message,
|
|
86
|
+
};
|
|
87
|
+
case 'warning':
|
|
88
|
+
return {
|
|
89
|
+
type: 'warning',
|
|
90
|
+
error: event.code,
|
|
91
|
+
message: event.message,
|
|
92
|
+
};
|
|
93
|
+
case 'keypoints':
|
|
94
|
+
return {
|
|
95
|
+
type: 'keypoints',
|
|
96
|
+
data: event.keypoints.map((k) => ({
|
|
97
|
+
name: k.name,
|
|
98
|
+
x: k.x,
|
|
99
|
+
y: k.y,
|
|
100
|
+
...(k.z != null ? { z: k.z } : {}),
|
|
101
|
+
score: k.score,
|
|
102
|
+
})),
|
|
103
|
+
score: event.score,
|
|
104
|
+
timestampMs: event.timestampMs,
|
|
105
|
+
};
|
|
106
|
+
case 'angles':
|
|
107
|
+
return {
|
|
108
|
+
type: 'angles',
|
|
109
|
+
// WebView V3 shape: nested left_side / right_side tree (not the typed flat array).
|
|
110
|
+
data: anglesToClassicTree(event.angles),
|
|
111
|
+
timestampMs: event.timestampMs,
|
|
112
|
+
};
|
|
113
|
+
case 'counter':
|
|
114
|
+
return {
|
|
115
|
+
type: 'counter',
|
|
116
|
+
current_count: event.count,
|
|
117
|
+
// GitBook: authoritative grade for a counted rep lives on counter.form_score.
|
|
118
|
+
...(event.formScore != null
|
|
119
|
+
? {
|
|
120
|
+
form_score: {
|
|
121
|
+
score: event.formScore.score,
|
|
122
|
+
avg_score: event.formScore.average,
|
|
123
|
+
grade: event.formScore.grade,
|
|
124
|
+
},
|
|
125
|
+
}
|
|
126
|
+
: {}),
|
|
127
|
+
...(event.referenceScore != null
|
|
128
|
+
? { reference_score: { overallScore: event.referenceScore } }
|
|
129
|
+
: {}),
|
|
130
|
+
timestampMs: event.timestampMs,
|
|
131
|
+
};
|
|
132
|
+
case 'posture':
|
|
133
|
+
return {
|
|
134
|
+
type: 'posture',
|
|
135
|
+
message: event.hint,
|
|
136
|
+
ready: event.ready,
|
|
137
|
+
direction: event.direction ?? '',
|
|
138
|
+
requirements: { missingKeypoints: event.missingKeypoints },
|
|
139
|
+
timestampMs: event.timestampMs,
|
|
140
|
+
};
|
|
141
|
+
case 'progression':
|
|
142
|
+
return {
|
|
143
|
+
type: 'progression',
|
|
144
|
+
value: event.value,
|
|
145
|
+
timestampMs: event.timestampMs,
|
|
146
|
+
};
|
|
147
|
+
case 'recommendations':
|
|
148
|
+
return {
|
|
149
|
+
type: 'recommendations',
|
|
150
|
+
data: event.recommendations,
|
|
151
|
+
timestampMs: event.timestampMs,
|
|
152
|
+
};
|
|
153
|
+
case 'form_score':
|
|
154
|
+
// Optional live / convenience stream — do not treat as authoritative
|
|
155
|
+
// for the counted rep (prefer counter.form_score). Kept for hosts that
|
|
156
|
+
// already subscribe to a standalone form_score type.
|
|
157
|
+
return {
|
|
158
|
+
type: 'form_score',
|
|
159
|
+
score: event.score,
|
|
160
|
+
avg_score: event.average,
|
|
161
|
+
grade: event.grade,
|
|
162
|
+
timestampMs: event.timestampMs,
|
|
163
|
+
};
|
|
164
|
+
case 'exercise_summary':
|
|
165
|
+
return {
|
|
166
|
+
type: 'exercise_summary',
|
|
167
|
+
exercise: event.exercise,
|
|
168
|
+
counter: event.counter,
|
|
169
|
+
avg_rep_score: event.averageFormScore,
|
|
170
|
+
avg_similarity: event.averageSimilarity,
|
|
171
|
+
grade: event.grade,
|
|
172
|
+
history: event.history,
|
|
173
|
+
durationMs: event.durationMs,
|
|
174
|
+
timestampMs: event.timestampMs,
|
|
175
|
+
};
|
|
176
|
+
// Custom jump exercises: the classic contract already uses these exact
|
|
177
|
+
// type strings and camelCase field names — pass through minus timestampMs
|
|
178
|
+
// restructuring (front payloads have no timestampMs, but extra fields are
|
|
179
|
+
// harmless for string-matching hosts).
|
|
180
|
+
case 'jump_calibration':
|
|
181
|
+
return {
|
|
182
|
+
type: 'jump_calibration',
|
|
183
|
+
calibrated: event.calibrated,
|
|
184
|
+
cmPerPixel: event.cmPerPixel,
|
|
185
|
+
baselineY: event.baselineY,
|
|
186
|
+
visibleHips: event.visibleHips,
|
|
187
|
+
message: event.message,
|
|
188
|
+
timestampMs: event.timestampMs,
|
|
189
|
+
};
|
|
190
|
+
case 'jump_started':
|
|
191
|
+
return {
|
|
192
|
+
type: 'jump_started',
|
|
193
|
+
message: event.message,
|
|
194
|
+
timestampMs: event.timestampMs,
|
|
195
|
+
};
|
|
196
|
+
case 'jump_height': {
|
|
197
|
+
const { type, timestampMs, ...rest } = event;
|
|
198
|
+
return { type, ...rest, timestampMs };
|
|
199
|
+
}
|
|
200
|
+
case 'jump_discarded':
|
|
201
|
+
return {
|
|
202
|
+
type: 'jump_discarded',
|
|
203
|
+
reason: event.reason,
|
|
204
|
+
userMessage: event.userMessage,
|
|
205
|
+
timestampMs: event.timestampMs,
|
|
206
|
+
};
|
|
207
|
+
case 'jump_result': {
|
|
208
|
+
const { type, timestampMs, ...rest } = event;
|
|
209
|
+
return { type, ...rest, timestampMs };
|
|
210
|
+
}
|
|
211
|
+
case 'jump_summary': {
|
|
212
|
+
const { type, timestampMs, ...rest } = event;
|
|
213
|
+
return { type, ...rest, timestampMs };
|
|
214
|
+
}
|
|
215
|
+
case 'performance_warning':
|
|
216
|
+
// Classic V3 uses type "error" with degradation codes for device capability.
|
|
217
|
+
return {
|
|
218
|
+
type: 'error',
|
|
219
|
+
error: event.code,
|
|
220
|
+
message: event.message,
|
|
221
|
+
meanFps: event.meanFps,
|
|
222
|
+
thresholdFps: event.thresholdFps,
|
|
223
|
+
activeProfile: event.activeProfile,
|
|
224
|
+
medianInferenceMs: event.medianInferenceMs,
|
|
225
|
+
videoSize: event.videoSize,
|
|
226
|
+
timestampMs: event.timestampMs,
|
|
227
|
+
};
|
|
228
|
+
case 'quality_changed':
|
|
229
|
+
return {
|
|
230
|
+
type: 'warning',
|
|
231
|
+
error: 'quality_downgraded',
|
|
232
|
+
message: event.detail,
|
|
233
|
+
previousProfile: event.previousProfile,
|
|
234
|
+
activeProfile: event.activeProfile,
|
|
235
|
+
reason: event.reason,
|
|
236
|
+
timestampMs: event.timestampMs,
|
|
237
|
+
};
|
|
238
|
+
case 'runtime_download_progress':
|
|
239
|
+
// Classic contract has no download event — mirror as initialization.
|
|
240
|
+
return {
|
|
241
|
+
type: 'initialization',
|
|
242
|
+
message: `downloading pose runtime ${event.completedParts + 1}/${event.totalParts}`,
|
|
243
|
+
ready: false,
|
|
244
|
+
step: 'downloading',
|
|
245
|
+
part: event.part,
|
|
246
|
+
completedParts: event.completedParts,
|
|
247
|
+
totalParts: event.totalParts,
|
|
248
|
+
timestampMs: event.timestampMs,
|
|
249
|
+
};
|
|
250
|
+
default: {
|
|
251
|
+
const _exhaustive: never = event;
|
|
252
|
+
return { type: 'unknown', event: _exhaustive };
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function humanInitStep(step: string): string {
|
|
258
|
+
switch (step) {
|
|
259
|
+
case 'configuring':
|
|
260
|
+
// Front literal (sic) — TrackingAppV3.js.
|
|
261
|
+
return 'checking you plan and access';
|
|
262
|
+
case 'downloading':
|
|
263
|
+
return 'downloading engine';
|
|
264
|
+
case 'warming':
|
|
265
|
+
return 'loading pose model';
|
|
266
|
+
case 'ready':
|
|
267
|
+
return 'running';
|
|
268
|
+
default:
|
|
269
|
+
return step;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V2 Strapi movement names → canonical V3 exercise keys.
|
|
3
|
+
* Mirrors PoseTrackerFront/lib/v3/exercises/index.js `EXERCISE_ALIASES`.
|
|
4
|
+
*
|
|
5
|
+
* The RN SDK manifest still often ships legacy `face_*` ids from Strapi while
|
|
6
|
+
* host apps / demos call V3 keys (`squat`, `push_up`, …).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export const EXERCISE_ALIASES: Readonly<Record<string, string>> = {
|
|
10
|
+
face_squat: 'squat',
|
|
11
|
+
face_pushup: 'push_up',
|
|
12
|
+
face_plank: 'plank',
|
|
13
|
+
face_lunge: 'lunge',
|
|
14
|
+
face_jumping_jack: 'jumping_jack',
|
|
15
|
+
face_low_impact_jack: 'low_impact_jack',
|
|
16
|
+
face_balance_leg: 'balance_leg',
|
|
17
|
+
face_balance_leg_left: 'balance_leg_left',
|
|
18
|
+
face_balance_leg_right: 'balance_leg_right',
|
|
19
|
+
jump: 'air_time_jump',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** Resolve a legacy or V3 id to the canonical V3 key. */
|
|
23
|
+
export function resolveExerciseName(name: string): string {
|
|
24
|
+
return EXERCISE_ALIASES[name] ?? name;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Pick the best matching exercise config for a requested id.
|
|
29
|
+
* Tries exact id, then any legacy alias that maps to the same V3 key,
|
|
30
|
+
* then any config whose id resolves to the same V3 key.
|
|
31
|
+
*/
|
|
32
|
+
export function findExerciseByIdOrAlias<T extends { id: string }>(
|
|
33
|
+
exerciseId: string,
|
|
34
|
+
exercises: readonly T[],
|
|
35
|
+
): T | undefined {
|
|
36
|
+
const exact = exercises.find((e) => e.id === exerciseId);
|
|
37
|
+
if (exact) return exact;
|
|
38
|
+
|
|
39
|
+
const canonical = resolveExerciseName(exerciseId);
|
|
40
|
+
const legacyIds = Object.entries(EXERCISE_ALIASES)
|
|
41
|
+
.filter(([, v3]) => v3 === canonical)
|
|
42
|
+
.map(([legacy]) => legacy);
|
|
43
|
+
|
|
44
|
+
for (const legacy of legacyIds) {
|
|
45
|
+
const hit = exercises.find((e) => e.id === legacy);
|
|
46
|
+
if (hit) return hit;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return exercises.find((e) => resolveExerciseName(e.id) === canonical);
|
|
50
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @pose-tracker/react-native-pose-estimation-light — public API surface.
|
|
3
|
+
*
|
|
4
|
+
* Light / fully online variant: TF.js loads from CDN and MoveNet (default)
|
|
5
|
+
* from a remote URL each WebView boot. The movement engine is still
|
|
6
|
+
* downloaded from the PoseTracker API after an authenticated handshake.
|
|
7
|
+
*
|
|
8
|
+
* Runtime model:
|
|
9
|
+
* - Default (both platforms, incl. Expo Go): MoveNet SinglePose Lightning
|
|
10
|
+
* (17 keypoints, 192×192) inside a Chromium/WKWebView — TF.js WebGL.
|
|
11
|
+
* Mount {@link WebViewPoseView}. Requires network for TF.js + model.
|
|
12
|
+
* - Opt-in (`preferredBackend: 'vision'`, iOS native builds): Apple Vision
|
|
13
|
+
* `VNDetectHumanBodyPoseRequest` via {@link PoseCameraView}.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// Handshake + usage tracking
|
|
17
|
+
export { configure, ConfigureError, DEFAULT_BASE_URL, SDK_NAME, SDK_VERSION } from './api/configure';
|
|
18
|
+
export type { ConfigureOptions } from './api/configure';
|
|
19
|
+
export {
|
|
20
|
+
EXERCISE_ALIASES,
|
|
21
|
+
findExerciseByIdOrAlias,
|
|
22
|
+
resolveExerciseName,
|
|
23
|
+
} from './exercises/aliases';
|
|
24
|
+
export { UsageTracker, TrackError } from './api/track';
|
|
25
|
+
export type { TrackRequest, TrackResponse, UsageTrackerOptions } from './api/track';
|
|
26
|
+
|
|
27
|
+
// Online pose-runtime
|
|
28
|
+
export { RuntimeCache } from './runtime/RuntimeCache';
|
|
29
|
+
export type {
|
|
30
|
+
PoseRuntimeParts,
|
|
31
|
+
RuntimeCacheOptions,
|
|
32
|
+
RuntimeCacheProgress,
|
|
33
|
+
} from './runtime/RuntimeCache';
|
|
34
|
+
export {
|
|
35
|
+
getOnlineRuntimeParts,
|
|
36
|
+
getOnlineRuntimeVersion,
|
|
37
|
+
defaultOnlineRuntimeUrls,
|
|
38
|
+
ONLINE_TFJS_VERSION,
|
|
39
|
+
} from './backends/webview/onlineRuntime';
|
|
40
|
+
export type {
|
|
41
|
+
GetOnlineRuntimeOptions,
|
|
42
|
+
OnlineRuntimeParts,
|
|
43
|
+
OnlineRuntimeUrls,
|
|
44
|
+
} from './backends/webview/onlineRuntime';
|
|
45
|
+
export {
|
|
46
|
+
DEFAULT_MOVENET_LIGHTNING_URL,
|
|
47
|
+
originFromModelUrl,
|
|
48
|
+
resolvePoseModel,
|
|
49
|
+
} from './models/poseModels';
|
|
50
|
+
export type {
|
|
51
|
+
PoseModelAlias,
|
|
52
|
+
ResolvePoseModelOptions,
|
|
53
|
+
ResolvedPoseModel,
|
|
54
|
+
} from './models/poseModels';
|
|
55
|
+
|
|
56
|
+
// Orchestrator + React layer
|
|
57
|
+
export { PoseTrackerClient } from './client';
|
|
58
|
+
export type { PoseTrackerClientOptions, PreferredBackend, StartExerciseOptions } from './client';
|
|
59
|
+
export type { ColdStartMode, PreloadOptions } from './types/preload';
|
|
60
|
+
export type {
|
|
61
|
+
SkeletonAnglesStyle,
|
|
62
|
+
SkeletonCirclesStyle,
|
|
63
|
+
SkeletonDefinition,
|
|
64
|
+
SkeletonLinesStyle,
|
|
65
|
+
} from './types/skeleton';
|
|
66
|
+
export { DEFAULT_SKELETON_DEFINITION } from './types/skeleton';
|
|
67
|
+
export { fetchSkeletonDefinition, SkeletonFetchError } from './api/skeleton';
|
|
68
|
+
export type { FetchSkeletonOptions } from './api/skeleton';
|
|
69
|
+
export { PoseTrackerProvider, usePoseTracker } from './PoseTrackerProvider';
|
|
70
|
+
export type { PoseTrackerContextValue, PoseTrackerProviderProps } from './PoseTrackerProvider';
|
|
71
|
+
|
|
72
|
+
// Inference backends
|
|
73
|
+
export type { PoseBackend, PoseBackendInitOptions, PoseInputFrame } from './backends/PoseBackend';
|
|
74
|
+
|
|
75
|
+
// WebView MoveNet — light online runtime (both platforms)
|
|
76
|
+
export { WebViewPoseBackend, isWebViewPoseBackend } from './backends/webview/WebViewPoseBackend';
|
|
77
|
+
export type { WebViewPoseBackendOptions, WebViewPoseMessage } from './backends/webview/WebViewPoseBackend';
|
|
78
|
+
export { WebViewPoseView } from './camera/WebViewPoseView';
|
|
79
|
+
export type { WebViewPoseViewProps } from './camera/WebViewPoseView';
|
|
80
|
+
export {
|
|
81
|
+
buildPoseHtml,
|
|
82
|
+
DEFAULT_LOADING_TEXT,
|
|
83
|
+
POSE_HTML_BUILD,
|
|
84
|
+
} from './backends/webview/poseHtml';
|
|
85
|
+
export type { PoseHtmlOptions } from './backends/webview/poseHtml';
|
|
86
|
+
export { POSETRACKER_LOGO_DATA_URL } from './backends/webview/brandAssets';
|
|
87
|
+
|
|
88
|
+
// Apple Vision (iOS native builds, opt-in via preferredBackend: 'vision')
|
|
89
|
+
export { VisionPoseBackend, VisionUnavailableError } from './backends/vision/VisionPoseBackend';
|
|
90
|
+
export type { VisionPoseBackendOptions } from './backends/vision/VisionPoseBackend';
|
|
91
|
+
export {
|
|
92
|
+
isVisionBackendAvailable,
|
|
93
|
+
isVisionPoseCameraAvailable,
|
|
94
|
+
VISION_BODY_POSE_PLUGIN_NAME,
|
|
95
|
+
} from './backends/vision/optionalVision';
|
|
96
|
+
export {
|
|
97
|
+
poseFromVisionPluginResult,
|
|
98
|
+
VISION_JOINT_TO_SDK,
|
|
99
|
+
} from './backends/vision/mapVisionJoints';
|
|
100
|
+
export type { VisionPluginJoint, VisionPluginResult } from './backends/vision/mapVisionJoints';
|
|
101
|
+
export { PoseCameraView } from './camera/PoseCameraView';
|
|
102
|
+
export type {
|
|
103
|
+
PoseCameraStats,
|
|
104
|
+
PoseCameraUnavailableReason,
|
|
105
|
+
PoseCameraViewProps,
|
|
106
|
+
} from './camera/PoseCameraView';
|
|
107
|
+
|
|
108
|
+
// Environment probes
|
|
109
|
+
export { isExpoGo } from './support/optionalModules';
|
|
110
|
+
|
|
111
|
+
// Acceleration / diagnostics types
|
|
112
|
+
export type {
|
|
113
|
+
AccelerationDiagnostics,
|
|
114
|
+
AccelerationState,
|
|
115
|
+
DiagnosticListener,
|
|
116
|
+
GlCapabilities,
|
|
117
|
+
InferenceRuntime,
|
|
118
|
+
NativeDelegateLabel,
|
|
119
|
+
TfjsFlagSnapshot,
|
|
120
|
+
VisionDelegateLabel,
|
|
121
|
+
} from './types/acceleration';
|
|
122
|
+
|
|
123
|
+
// Engine
|
|
124
|
+
export {
|
|
125
|
+
EngineLoader,
|
|
126
|
+
createExpoFileStore,
|
|
127
|
+
createRnfsFileStore,
|
|
128
|
+
createBlobUtilFileStore,
|
|
129
|
+
createMemoryFileStore,
|
|
130
|
+
createNativeFileStore,
|
|
131
|
+
} from './engine/EngineLoader';
|
|
132
|
+
export type { EngineLoadResult, EngineLoaderOptions, FileStore, KeyValueStore } from './engine/EngineLoader';
|
|
133
|
+
export type {
|
|
134
|
+
CustomExerciseDescriptor,
|
|
135
|
+
CustomSessionOptions,
|
|
136
|
+
EngineModuleExports,
|
|
137
|
+
EngineSession,
|
|
138
|
+
EngineSessionFeatures,
|
|
139
|
+
EngineSessionOptions,
|
|
140
|
+
EventSink,
|
|
141
|
+
PoseTrackerEngine,
|
|
142
|
+
} from './engine/types';
|
|
143
|
+
|
|
144
|
+
// Metro / logcat diagnostic helpers
|
|
145
|
+
export {
|
|
146
|
+
defaultDiagnosticLogger,
|
|
147
|
+
logAccelerationReport,
|
|
148
|
+
logFrameStats,
|
|
149
|
+
logPlatformBanner,
|
|
150
|
+
} from './diagnostics/logReport';
|
|
151
|
+
|
|
152
|
+
// Classic PoseTracker WebView message parity (sendDataToNative JSON)
|
|
153
|
+
export {
|
|
154
|
+
toClassicNativeMessage,
|
|
155
|
+
} from './events/classicMessage';
|
|
156
|
+
export type {
|
|
157
|
+
ClassicMessageListener,
|
|
158
|
+
ClassicNativeMessage,
|
|
159
|
+
} from './events/classicMessage';
|
|
160
|
+
|
|
161
|
+
// Adaptive camera quality (AdaptiveChoice + crash-loop guard + FPS downgrade)
|
|
162
|
+
export {
|
|
163
|
+
AdaptiveQualityController,
|
|
164
|
+
} from './quality/AdaptiveQualityController';
|
|
165
|
+
export type {
|
|
166
|
+
AdaptiveQualityControllerOptions,
|
|
167
|
+
QualityState,
|
|
168
|
+
QualityStatsSample,
|
|
169
|
+
} from './quality/AdaptiveQualityController';
|
|
170
|
+
export {
|
|
171
|
+
CRITICAL_FPS_THRESHOLD,
|
|
172
|
+
IDEAL_FPS_RANGE_ANDROID,
|
|
173
|
+
IDEAL_FPS_RANGE_IOS,
|
|
174
|
+
LOW_FPS_STREAK_BEFORE_DOWNGRADE,
|
|
175
|
+
QUALITY_SETTLE_MS,
|
|
176
|
+
MIN_TARGET_FPS_ANDROID,
|
|
177
|
+
MIN_TARGET_FPS_DEFAULT,
|
|
178
|
+
MIN_TARGET_FPS_IOS,
|
|
179
|
+
QUALITY_LADDER,
|
|
180
|
+
QUALITY_PROFILES,
|
|
181
|
+
TARGET_FPS,
|
|
182
|
+
TARGET_MEDIAN_MS,
|
|
183
|
+
currentQualityPlatform,
|
|
184
|
+
estimatedFpsFromMedianMs,
|
|
185
|
+
getCriticalFpsThreshold,
|
|
186
|
+
getIdealFpsRange,
|
|
187
|
+
getMinTargetFps,
|
|
188
|
+
getQualityProfile,
|
|
189
|
+
isQualityProfileId,
|
|
190
|
+
lowerQualityProfile,
|
|
191
|
+
minMedianMsForMinTarget,
|
|
192
|
+
nextLowerQualityProfile,
|
|
193
|
+
profileFromWarmupMedianMs,
|
|
194
|
+
} from './quality/profiles';
|
|
195
|
+
export {
|
|
196
|
+
ANDROID_INFER_FRAME_SKIP,
|
|
197
|
+
ANDROID_MIN_TARGET_FPS,
|
|
198
|
+
ANDROID_PERF_DEBUG,
|
|
199
|
+
ANDROID_PREPROCESS_PATH,
|
|
200
|
+
ANDROID_SOFT_CAP_PROFILE,
|
|
201
|
+
CAPTURE_CONSTRAINT_MODE,
|
|
202
|
+
ENABLE_MALI_HARD_CAP,
|
|
203
|
+
} from './quality/captureMode';
|
|
204
|
+
export type {
|
|
205
|
+
AndroidPreprocessPath,
|
|
206
|
+
AndroidSoftCapProfile,
|
|
207
|
+
CaptureConstraintMode,
|
|
208
|
+
} from './quality/captureMode';
|
|
209
|
+
export type {
|
|
210
|
+
FpsRange,
|
|
211
|
+
CapturePriority,
|
|
212
|
+
QualityChoice,
|
|
213
|
+
QualityPlatform,
|
|
214
|
+
QualityProfile,
|
|
215
|
+
QualityProfileId,
|
|
216
|
+
} from './quality/profiles';
|
|
217
|
+
export {
|
|
218
|
+
isMaliRenderer,
|
|
219
|
+
profileFromScore,
|
|
220
|
+
scoreDeviceCapability,
|
|
221
|
+
} from './quality/deviceCapability';
|
|
222
|
+
export type { DeviceCapabilitySnapshot } from './quality/deviceCapability';
|
|
223
|
+
export { RuntimeGuard } from './quality/RuntimeGuard';
|
|
224
|
+
export type { GuardState } from './quality/RuntimeGuard';
|
|
225
|
+
|
|
226
|
+
// Tracking features (WebView query-param parity + plan gating)
|
|
227
|
+
export {
|
|
228
|
+
DEFAULT_FEATURES,
|
|
229
|
+
FREE_PLAN_FEATURES_MESSAGE,
|
|
230
|
+
INVALID_TOKEN_MESSAGE,
|
|
231
|
+
COMBINED_REFERENCE_EXERCISE_MESSAGE,
|
|
232
|
+
featureNotSupportedMessage,
|
|
233
|
+
freeBlockedFeatures,
|
|
234
|
+
isPaidPlan,
|
|
235
|
+
shouldShowWatermark,
|
|
236
|
+
resolveFeatures,
|
|
237
|
+
} from './types/features';
|
|
238
|
+
export type { PoseTrackerFeatures, ResolvedFeatures } from './types/features';
|
|
239
|
+
|
|
240
|
+
// Types
|
|
241
|
+
export * from './types/events';
|
|
242
|
+
export * from './types/manifest';
|
|
243
|
+
export * from './types/pose';
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Online pose-model catalog for the light SDK.
|
|
3
|
+
*
|
|
4
|
+
* Defaults match the PoseTracker Front / Docs API product path:
|
|
5
|
+
* MoveNet SinglePose Lightning hosted at app.posetracker.com (same URL as
|
|
6
|
+
* `usePoseDetection` / tracking WebView `modelUrl`).
|
|
7
|
+
*
|
|
8
|
+
* BlazePose is accepted as a `model` alias for API parity but is not wired
|
|
9
|
+
* in the RN WebView yet (needs MediaPipe). Pass a TF.js `modelUrl` for any
|
|
10
|
+
* custom graph model.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Production MoveNet SinglePose Lightning topology (Front default). */
|
|
14
|
+
export const DEFAULT_MOVENET_LIGHTNING_URL =
|
|
15
|
+
'https://app.posetracker.com/scripts/tmp_model_to_remove.json';
|
|
16
|
+
|
|
17
|
+
/** Docs API / Front `model` query aliases. */
|
|
18
|
+
export type PoseModelAlias =
|
|
19
|
+
| 'movenet'
|
|
20
|
+
| 'movenet-singlepose-lightning'
|
|
21
|
+
| 'lightning'
|
|
22
|
+
| 'blazepose'
|
|
23
|
+
| (string & {});
|
|
24
|
+
|
|
25
|
+
export interface ResolvePoseModelOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Docs API `model` query parity (`movenet` default, `blazepose`, …).
|
|
28
|
+
* Ignored when {@link modelUrl} is set.
|
|
29
|
+
*/
|
|
30
|
+
model?: PoseModelAlias;
|
|
31
|
+
/** Explicit TF.js graph-model topology URL (weights resolve as siblings). */
|
|
32
|
+
modelUrl?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ResolvedPoseModel {
|
|
36
|
+
/** Stable id reported in diagnostics / track params. */
|
|
37
|
+
modelId: string;
|
|
38
|
+
/** TF.js `loadGraphModel` URL, or null when unsupported without override. */
|
|
39
|
+
modelUrl: string | null;
|
|
40
|
+
/** Human-readable reason when {@link modelUrl} is null. */
|
|
41
|
+
unsupportedReason?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Resolve which TF.js graph model the light WebView should fetch.
|
|
46
|
+
* Default: MoveNet SinglePose Lightning (product URL).
|
|
47
|
+
*/
|
|
48
|
+
export function resolvePoseModel(options: ResolvePoseModelOptions = {}): ResolvedPoseModel {
|
|
49
|
+
const explicit =
|
|
50
|
+
typeof options.modelUrl === 'string' && options.modelUrl.trim().length > 0
|
|
51
|
+
? options.modelUrl.trim()
|
|
52
|
+
: null;
|
|
53
|
+
if (explicit) {
|
|
54
|
+
const alias =
|
|
55
|
+
typeof options.model === 'string' && options.model.trim().length > 0
|
|
56
|
+
? options.model.trim()
|
|
57
|
+
: 'custom';
|
|
58
|
+
return { modelId: alias, modelUrl: explicit };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const key = (options.model ?? 'movenet').trim().toLowerCase();
|
|
62
|
+
if (key === 'movenet' || key === 'movenet-singlepose-lightning' || key === 'lightning') {
|
|
63
|
+
return {
|
|
64
|
+
modelId: 'movenet-singlepose-lightning',
|
|
65
|
+
modelUrl: DEFAULT_MOVENET_LIGHTNING_URL,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (key === 'blazepose') {
|
|
69
|
+
return {
|
|
70
|
+
modelId: 'blazepose',
|
|
71
|
+
modelUrl: null,
|
|
72
|
+
unsupportedReason:
|
|
73
|
+
'BlazePose is not wired in the light RN WebView yet (needs MediaPipe). ' +
|
|
74
|
+
'Use model="movenet" or pass a TF.js graph modelUrl.',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
modelId: key,
|
|
79
|
+
modelUrl: null,
|
|
80
|
+
unsupportedReason:
|
|
81
|
+
`Unknown model "${options.model}". Use "movenet" (default) or pass modelUrl.`,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Origin used as WebView `baseUrl` so model fetches are same-origin when possible. */
|
|
86
|
+
export function originFromModelUrl(modelUrl: string): string {
|
|
87
|
+
try {
|
|
88
|
+
const u = new URL(modelUrl);
|
|
89
|
+
return `${u.protocol}//${u.host}/`;
|
|
90
|
+
} catch {
|
|
91
|
+
return 'https://app.posetracker.com/';
|
|
92
|
+
}
|
|
93
|
+
}
|