@viji-dev/core 0.2.7 → 0.2.9

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/dist/index.d.ts CHANGED
@@ -61,7 +61,12 @@ declare interface CoreCapabilities {
61
61
  hasGeneral: boolean;
62
62
  }
63
63
 
64
+ declare type CVFeature = 'faceDetection' | 'faceMesh' | 'handTracking' | 'poseDetection' | 'bodySegmentation';
65
+
66
+ declare type CVFrameRateMode = 'full' | 'half' | 'quarter' | 'eighth';
67
+
64
68
  export declare interface FaceData {
69
+ id: number;
65
70
  bounds: {
66
71
  x: number;
67
72
  y: number;
@@ -69,11 +74,25 @@ export declare interface FaceData {
69
74
  height: number;
70
75
  };
71
76
  confidence: number;
72
- landmarks: {
77
+ landmarks?: {
73
78
  x: number;
74
79
  y: number;
80
+ z?: number;
75
81
  }[];
76
- expressions: Record<string, number>;
82
+ expressions: {
83
+ neutral: number;
84
+ happy: number;
85
+ sad: number;
86
+ angry: number;
87
+ surprised: number;
88
+ disgusted: number;
89
+ fearful: number;
90
+ };
91
+ headPose: {
92
+ pitch: number;
93
+ yaw: number;
94
+ roll: number;
95
+ };
77
96
  }
78
97
 
79
98
  declare interface FrameRateInfo {
@@ -91,15 +110,89 @@ export declare interface FrequencyBand {
91
110
  }
92
111
 
93
112
  export declare interface HandData {
94
- palm: {
113
+ id: number;
114
+ handedness: 'left' | 'right';
115
+ confidence: number;
116
+ bounds: {
95
117
  x: number;
96
118
  y: number;
119
+ width: number;
120
+ height: number;
97
121
  };
98
- fingers: {
122
+ landmarks: {
99
123
  x: number;
100
124
  y: number;
125
+ z: number;
101
126
  }[];
102
- gestures: Record<string, boolean>;
127
+ palm: {
128
+ x: number;
129
+ y: number;
130
+ z: number;
131
+ };
132
+ fingers: {
133
+ thumb: {
134
+ tip: {
135
+ x: number;
136
+ y: number;
137
+ z: number;
138
+ };
139
+ extended: boolean;
140
+ };
141
+ index: {
142
+ tip: {
143
+ x: number;
144
+ y: number;
145
+ z: number;
146
+ };
147
+ extended: boolean;
148
+ };
149
+ middle: {
150
+ tip: {
151
+ x: number;
152
+ y: number;
153
+ z: number;
154
+ };
155
+ extended: boolean;
156
+ };
157
+ ring: {
158
+ tip: {
159
+ x: number;
160
+ y: number;
161
+ z: number;
162
+ };
163
+ extended: boolean;
164
+ };
165
+ pinky: {
166
+ tip: {
167
+ x: number;
168
+ y: number;
169
+ z: number;
170
+ };
171
+ extended: boolean;
172
+ };
173
+ };
174
+ gestures: {
175
+ fist: number;
176
+ openPalm: number;
177
+ peace: number;
178
+ thumbsUp: number;
179
+ pointing: number;
180
+ };
181
+ }
182
+
183
+ declare interface ImageConfig {
184
+ label: string;
185
+ description?: string;
186
+ group?: string;
187
+ category?: ParameterCategory;
188
+ }
189
+
190
+ declare interface ImageParameter {
191
+ value: ImageBitmap | OffscreenCanvas | null;
192
+ label: string;
193
+ description?: string;
194
+ group: string;
195
+ category: ParameterCategory;
103
196
  }
104
197
 
105
198
  export declare interface KeyboardAPI {
@@ -180,7 +273,7 @@ export declare interface ParameterConfig {
180
273
  }
181
274
 
182
275
  export declare interface ParameterDefinition {
183
- type: 'slider' | 'color' | 'toggle' | 'select' | 'text' | 'number';
276
+ type: 'slider' | 'color' | 'toggle' | 'select' | 'text' | 'number' | 'image';
184
277
  defaultValue: any;
185
278
  label?: string;
186
279
  description?: string;
@@ -199,23 +292,73 @@ export declare interface ParameterGroup {
199
292
  parameters: Record<string, ParameterDefinition>;
200
293
  }
201
294
 
202
- declare type ParameterValue = string | number | boolean;
295
+ declare type ParameterValue = string | number | boolean | ImageBitmap | OffscreenCanvas | null;
203
296
 
204
297
  export declare interface PerformanceStats {
205
298
  frameTime: number;
206
299
  resolution: Resolution;
207
300
  scale: number;
208
301
  frameRate: FrameRateInfo;
302
+ rendererType: RendererType;
209
303
  memoryUsage?: number;
210
304
  activeStreams?: number;
211
305
  parameterCount?: number;
306
+ cv?: {
307
+ activeFeatures: CVFeature[];
308
+ processingTime: number;
309
+ targetFPS: number;
310
+ actualFPS: number;
311
+ isProcessing: boolean;
312
+ };
212
313
  }
213
314
 
315
+ declare interface PoseData {
316
+ confidence: number;
317
+ landmarks: {
318
+ x: number;
319
+ y: number;
320
+ z: number;
321
+ visibility: number;
322
+ }[];
323
+ face: {
324
+ x: number;
325
+ y: number;
326
+ }[];
327
+ torso: {
328
+ x: number;
329
+ y: number;
330
+ }[];
331
+ leftArm: {
332
+ x: number;
333
+ y: number;
334
+ }[];
335
+ rightArm: {
336
+ x: number;
337
+ y: number;
338
+ }[];
339
+ leftLeg: {
340
+ x: number;
341
+ y: number;
342
+ }[];
343
+ rightLeg: {
344
+ x: number;
345
+ y: number;
346
+ }[];
347
+ }
348
+
349
+ declare type RendererType = 'native' | 'p5' | 'shader';
350
+
214
351
  export declare type Resolution = {
215
352
  width: number;
216
353
  height: number;
217
354
  };
218
355
 
356
+ declare interface SegmentationData {
357
+ mask: Uint8Array;
358
+ width: number;
359
+ height: number;
360
+ }
361
+
219
362
  declare interface SelectConfig {
220
363
  options: string[] | number[];
221
364
  label: string;
@@ -338,7 +481,7 @@ declare interface TouchPoint {
338
481
  isEnding: boolean;
339
482
  }
340
483
 
341
- export declare const VERSION = "0.2.4";
484
+ export declare const VERSION = "0.2.9";
342
485
 
343
486
  export declare interface VideoAPI {
344
487
  isConnected: boolean;
@@ -349,6 +492,17 @@ export declare interface VideoAPI {
349
492
  getFrameData: () => ImageData | null;
350
493
  faces: FaceData[];
351
494
  hands: HandData[];
495
+ pose: PoseData | null;
496
+ segmentation: SegmentationData | null;
497
+ cv: {
498
+ enableFaceDetection(enabled: boolean): Promise<void>;
499
+ enableFaceMesh(enabled: boolean): Promise<void>;
500
+ enableHandTracking(enabled: boolean): Promise<void>;
501
+ enablePoseDetection(enabled: boolean): Promise<void>;
502
+ enableBodySegmentation(enabled: boolean): Promise<void>;
503
+ getActiveFeatures(): CVFeature[];
504
+ isProcessing(): boolean;
505
+ };
352
506
  }
353
507
 
354
508
  export declare interface VijiAPI {
@@ -373,6 +527,7 @@ export declare interface VijiAPI {
373
527
  select: (defaultValue: string | number, config: SelectConfig) => SelectParameter;
374
528
  text: (defaultValue: string, config: TextConfig) => TextParameter;
375
529
  number: (defaultValue: number, config: NumberConfig) => NumberParameter;
530
+ image: (defaultValue: null, config: ImageConfig) => ImageParameter;
376
531
  useContext(type: '2d' | 'webgl'): OffscreenCanvasRenderingContext2D | WebGLRenderingContext | WebGL2RenderingContext | null;
377
532
  }
378
533
 
@@ -448,10 +603,22 @@ export declare class VijiCore {
448
603
  * Handle parameter validation errors
449
604
  */
450
605
  private handleParameterError;
606
+ /**
607
+ * Get parameter definition by name
608
+ */
609
+ private getParameterDefinition;
451
610
  /**
452
611
  * Set a single parameter value
612
+ * Handles all parameter types including images intelligently
613
+ */
614
+ setParameter(name: string, value: ParameterValue | File | Blob): Promise<void>;
615
+ /**
616
+ * Internal method to handle image parameter loading and transfer
617
+ * Loads the image on the host side and creates TWO ImageBitmaps:
618
+ * - One for the host (listeners, previews)
619
+ * - One to transfer to the worker
453
620
  */
454
- setParameter(name: string, value: ParameterValue): Promise<void>;
621
+ private handleImageParameter;
455
622
  /**
456
623
  * Set multiple parameter values efficiently
457
624
  */
@@ -540,13 +707,15 @@ export declare class VijiCore {
540
707
  */
541
708
  private notifyParameterListeners;
542
709
  /**
543
- * Sets the frame rate to full speed (every animation frame)
710
+ * Sets the scene frame rate mode
711
+ * @param mode - 'full' for every animation frame, 'half' for every second frame
544
712
  */
545
- setFullFrameRate(): Promise<void>;
713
+ setFrameRate(mode: FrameRateMode): Promise<void>;
546
714
  /**
547
- * Sets the frame rate to half speed (every second animation frame)
715
+ * Sets the CV processing frame rate mode (relative to scene frame rate)
716
+ * @param mode - CV processing rate: 'full', 'half', 'quarter', or 'eighth' of scene rate
548
717
  */
549
- setHalfFrameRate(): Promise<void>;
718
+ setCVFrameRate(mode: CVFrameRateMode): Promise<void>;
550
719
  /**
551
720
  * Updates the canvas resolution by sending effective dimensions to the worker
552
721
  */
package/dist/index.js CHANGED
@@ -434,8 +434,9 @@ class IFrameManager {
434
434
  }
435
435
  function WorkerWrapper(options) {
436
436
  return new Worker(
437
- "" + new URL("assets/viji.worker-BKsgIT1d.js", import.meta.url).href,
437
+ "" + new URL("assets/viji.worker-Cbdf1a6N.js", import.meta.url).href,
438
438
  {
439
+ type: "module",
439
440
  name: options?.name
440
441
  }
441
442
  );
@@ -460,7 +461,6 @@ class WorkerManager {
460
461
  this.postMessage("set-scene-code", { sceneCode: this.sceneCode });
461
462
  await this.initializeWorker();
462
463
  this.isInitialized = true;
463
- return this.worker;
464
464
  } catch (error) {
465
465
  throw new VijiCoreError(
466
466
  `Failed to create worker: ${error}`,
@@ -599,6 +599,7 @@ class WorkerManager {
599
599
  }
600
600
  /**
601
601
  * Initializes the worker with canvas and basic setup
602
+ * Waits for init-response message (worker will also send separate 'ready' event)
602
603
  */
603
604
  async initializeWorker() {
604
605
  if (!this.worker) {
@@ -1695,6 +1696,7 @@ class VijiCore {
1695
1696
  screenRefreshRate: 60,
1696
1697
  effectiveRefreshRate: 60
1697
1698
  },
1699
+ rendererType: "native",
1698
1700
  parameterCount: 0
1699
1701
  };
1700
1702
  constructor(config) {
@@ -1894,6 +1896,9 @@ class VijiCore {
1894
1896
  if (!this.workerManager) return;
1895
1897
  this.workerManager.onMessage("ready", (data) => {
1896
1898
  this.debugLog("Worker ready:", data);
1899
+ if (data.rendererType !== void 0) {
1900
+ this.stats.rendererType = data.rendererType;
1901
+ }
1897
1902
  });
1898
1903
  this.workerManager.onMessage("error", (data) => {
1899
1904
  console.error("Worker error:", data);
@@ -1907,9 +1912,15 @@ class VijiCore {
1907
1912
  this.stats.frameRate.mode = data.frameRateMode;
1908
1913
  this.stats.frameRate.screenRefreshRate = data.screenRefreshRate;
1909
1914
  }
1915
+ if (data.rendererType !== void 0) {
1916
+ this.stats.rendererType = data.rendererType;
1917
+ }
1910
1918
  if (data.parameterCount !== void 0) {
1911
1919
  this.stats.parameterCount = data.parameterCount;
1912
1920
  }
1921
+ if (data.cv !== void 0) {
1922
+ this.stats.cv = data.cv;
1923
+ }
1913
1924
  });
1914
1925
  this.workerManager.onMessage("parameters-defined", (data) => {
1915
1926
  this.handleParametersDefined(data);
@@ -1963,8 +1974,20 @@ class VijiCore {
1963
1974
  }
1964
1975
  }
1965
1976
  }
1977
+ /**
1978
+ * Get parameter definition by name
1979
+ */
1980
+ getParameterDefinition(name) {
1981
+ for (const group of this.parameterGroups.values()) {
1982
+ if (group.parameters[name]) {
1983
+ return group.parameters[name];
1984
+ }
1985
+ }
1986
+ return void 0;
1987
+ }
1966
1988
  /**
1967
1989
  * Set a single parameter value
1990
+ * Handles all parameter types including images intelligently
1968
1991
  */
1969
1992
  async setParameter(name, value) {
1970
1993
  this.validateReady();
@@ -1974,6 +1997,11 @@ class VijiCore {
1974
1997
  if (!this.parameterValues.has(name)) {
1975
1998
  throw new VijiCoreError(`Unknown parameter: ${name}`, "UNKNOWN_PARAMETER");
1976
1999
  }
2000
+ const paramDef = this.getParameterDefinition(name);
2001
+ if (paramDef?.type === "image") {
2002
+ await this.handleImageParameter(name, value);
2003
+ return;
2004
+ }
1977
2005
  const oldValue = this.parameterValues.get(name);
1978
2006
  this.parameterValues.set(name, value);
1979
2007
  if (this.workerManager) {
@@ -1986,6 +2014,64 @@ class VijiCore {
1986
2014
  this.notifyParameterListeners(name, value);
1987
2015
  }
1988
2016
  }
2017
+ /**
2018
+ * Internal method to handle image parameter loading and transfer
2019
+ * Loads the image on the host side and creates TWO ImageBitmaps:
2020
+ * - One for the host (listeners, previews)
2021
+ * - One to transfer to the worker
2022
+ */
2023
+ async handleImageParameter(name, value) {
2024
+ try {
2025
+ let hostImageBitmap = null;
2026
+ let workerImageBitmap = null;
2027
+ if (value === null || value === void 0) {
2028
+ hostImageBitmap = null;
2029
+ workerImageBitmap = null;
2030
+ } else if (typeof value === "string") {
2031
+ const response = await fetch(value);
2032
+ const blob = await response.blob();
2033
+ [hostImageBitmap, workerImageBitmap] = await Promise.all([
2034
+ createImageBitmap(blob),
2035
+ createImageBitmap(blob)
2036
+ ]);
2037
+ } else if (value instanceof File || value instanceof Blob) {
2038
+ [hostImageBitmap, workerImageBitmap] = await Promise.all([
2039
+ createImageBitmap(value),
2040
+ createImageBitmap(value)
2041
+ ]);
2042
+ } else if (value instanceof ImageBitmap) {
2043
+ const canvas = document.createElement("canvas");
2044
+ canvas.width = value.width;
2045
+ canvas.height = value.height;
2046
+ const ctx = canvas.getContext("2d");
2047
+ ctx.drawImage(value, 0, 0);
2048
+ hostImageBitmap = value;
2049
+ workerImageBitmap = await createImageBitmap(canvas);
2050
+ } else {
2051
+ throw new Error(`Invalid value type for image parameter. Expected File, Blob, string (URL), or null.`);
2052
+ }
2053
+ const oldValue = this.parameterValues.get(name);
2054
+ this.parameterValues.set(name, hostImageBitmap);
2055
+ if (this.workerManager) {
2056
+ const messageData = {
2057
+ name,
2058
+ value: workerImageBitmap
2059
+ };
2060
+ const transferList = workerImageBitmap ? [workerImageBitmap] : [];
2061
+ this.workerManager.postMessage("parameter-update", messageData, transferList);
2062
+ }
2063
+ if (oldValue !== hostImageBitmap) {
2064
+ this.notifyParameterListeners(name, hostImageBitmap);
2065
+ }
2066
+ this.debugLog(`Image parameter '${name}' ${hostImageBitmap ? "loaded" : "cleared"} (${this.instanceId})`);
2067
+ } catch (error) {
2068
+ throw new VijiCoreError(
2069
+ `Failed to load image for parameter '${name}': ${error}`,
2070
+ "IMAGE_LOAD_ERROR",
2071
+ { error, name }
2072
+ );
2073
+ }
2074
+ }
1989
2075
  /**
1990
2076
  * Set multiple parameter values efficiently
1991
2077
  */
@@ -2005,8 +2091,7 @@ class VijiCore {
2005
2091
  this.parameterValues.set(name, value);
2006
2092
  updates.push({
2007
2093
  name,
2008
- value,
2009
- timestamp: performance.now()
2094
+ value
2010
2095
  });
2011
2096
  if (oldValue !== value) {
2012
2097
  changedParams.push({ name, value });
@@ -2014,8 +2099,7 @@ class VijiCore {
2014
2099
  }
2015
2100
  if (updates.length > 0 && this.workerManager) {
2016
2101
  this.workerManager.postMessage("parameter-batch-update", {
2017
- updates,
2018
- timestamp: performance.now()
2102
+ updates
2019
2103
  });
2020
2104
  }
2021
2105
  for (const { name, value } of changedParams) {
@@ -2147,13 +2231,11 @@ class VijiCore {
2147
2231
  for (const [name, value] of this.parameterValues) {
2148
2232
  updates.push({
2149
2233
  name,
2150
- value,
2151
- timestamp: performance.now()
2234
+ value
2152
2235
  });
2153
2236
  }
2154
2237
  this.workerManager.postMessage("parameter-batch-update", {
2155
- updates,
2156
- timestamp: performance.now()
2238
+ updates
2157
2239
  });
2158
2240
  this.debugLog(`Synced ${updates.length} parameter values to worker`);
2159
2241
  }
@@ -2243,28 +2325,28 @@ class VijiCore {
2243
2325
  }
2244
2326
  }
2245
2327
  /**
2246
- * Sets the frame rate to full speed (every animation frame)
2328
+ * Sets the scene frame rate mode
2329
+ * @param mode - 'full' for every animation frame, 'half' for every second frame
2247
2330
  */
2248
- async setFullFrameRate() {
2331
+ async setFrameRate(mode) {
2249
2332
  this.validateReady();
2250
- this.config.frameRateMode = "full";
2333
+ this.config.frameRateMode = mode;
2251
2334
  if (this.workerManager) {
2252
- this.workerManager.postMessage("frame-rate-update", { mode: "full" });
2335
+ this.workerManager.postMessage("frame-rate-update", { mode });
2253
2336
  }
2254
2337
  this.updateFrameRateStats();
2255
- this.debugLog(`Frame rate set to full (${this.instanceId})`);
2338
+ this.debugLog(`Scene frame rate set to ${mode} (${this.instanceId})`);
2256
2339
  }
2257
2340
  /**
2258
- * Sets the frame rate to half speed (every second animation frame)
2341
+ * Sets the CV processing frame rate mode (relative to scene frame rate)
2342
+ * @param mode - CV processing rate: 'full', 'half', 'quarter', or 'eighth' of scene rate
2259
2343
  */
2260
- async setHalfFrameRate() {
2344
+ async setCVFrameRate(mode) {
2261
2345
  this.validateReady();
2262
- this.config.frameRateMode = "half";
2263
2346
  if (this.workerManager) {
2264
- this.workerManager.postMessage("frame-rate-update", { mode: "half" });
2347
+ this.workerManager.postMessage("cv-frame-rate-update", { mode });
2265
2348
  }
2266
- this.updateFrameRateStats();
2267
- this.debugLog(`Frame rate set to half (${this.instanceId})`);
2349
+ this.debugLog(`CV frame rate set to ${mode} of scene rate (${this.instanceId})`);
2268
2350
  }
2269
2351
  /**
2270
2352
  * Updates the canvas resolution by sending effective dimensions to the worker
@@ -2525,7 +2607,7 @@ class VijiCore {
2525
2607
  }
2526
2608
  }
2527
2609
  }
2528
- const VERSION = "0.2.4";
2610
+ const VERSION = "0.2.9";
2529
2611
  export {
2530
2612
  VERSION,
2531
2613
  VijiCore,