@webex/ladon-ts 4.5.0 → 5.0.1

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/build/module/config.json.js +26 -0
  3. package/build/module/config.json.js.map +1 -0
  4. package/build/module/index.d.ts +3 -0
  5. package/build/module/index.js +41 -8
  6. package/build/module/index.js.map +1 -0
  7. package/build/module/lib/config-builder.d.ts +180 -0
  8. package/build/module/lib/config-builder.js +336 -0
  9. package/build/module/lib/config-builder.js.map +1 -0
  10. package/build/module/lib/config-types.d.ts +98 -0
  11. package/build/module/lib/config-types.js +6 -0
  12. package/build/module/lib/config-types.js.map +1 -0
  13. package/build/module/lib/config.d.ts +30 -105
  14. package/build/module/lib/config.js +22 -151
  15. package/build/module/lib/config.js.map +1 -0
  16. package/build/module/lib/generator.d.ts +3 -1
  17. package/build/module/lib/generator.js +212 -273
  18. package/build/module/lib/generator.js.map +1 -0
  19. package/build/module/lib/pipeline.d.ts +11 -8
  20. package/build/module/lib/pipeline.js +158 -213
  21. package/build/module/lib/pipeline.js.map +1 -0
  22. package/build/module/lib/preload.d.ts +9 -0
  23. package/build/module/lib/preload.js +8 -0
  24. package/build/module/lib/preload.js.map +1 -0
  25. package/build/module/lib/renderer/blur-renderer.d.ts +6 -5
  26. package/build/module/lib/renderer/blur-renderer.js +102 -126
  27. package/build/module/lib/renderer/blur-renderer.js.map +1 -0
  28. package/build/module/lib/renderer/ladon-renderer.d.ts +3 -2
  29. package/build/module/lib/renderer/passthrough-renderer.d.ts +6 -5
  30. package/build/module/lib/renderer/passthrough-renderer.js +25 -44
  31. package/build/module/lib/renderer/passthrough-renderer.js.map +1 -0
  32. package/build/module/lib/renderer/replacement-renderer.d.ts +9 -6
  33. package/build/module/lib/renderer/replacement-renderer.js +84 -99
  34. package/build/module/lib/renderer/replacement-renderer.js.map +1 -0
  35. package/build/module/lib/renderer/webgl-renderer.d.ts +12 -3
  36. package/build/module/lib/renderer/webgl-renderer.js +168 -115
  37. package/build/module/lib/renderer/webgl-renderer.js.map +1 -0
  38. package/build/module/lib/shared-resource-manager.d.ts +40 -31
  39. package/build/module/lib/shared-resource-manager.js +151 -189
  40. package/build/module/lib/shared-resource-manager.js.map +1 -0
  41. package/build/module/lib/util.d.ts +10 -0
  42. package/build/module/lib/util.js +92 -179
  43. package/build/module/lib/util.js.map +1 -0
  44. package/build/module/lib/version.d.ts +1 -1
  45. package/build/module/lib/version.js +5 -2
  46. package/build/module/lib/version.js.map +1 -0
  47. package/package.json +21 -5
  48. package/build/module/lib/renderer/ladon-renderer.js +0 -2
  49. package/build/module/lib/renderer.js +0 -6
@@ -1,213 +1,158 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import { LocalGenerator, NullGenerator, WorkerGenerator, } from './generator';
11
- import { BlurRenderer, PassthroughRenderer, ReplacementRenderer } from './renderer';
12
- import { resizeImage } from './util';
13
- export class Pipeline {
14
- constructor(inputCanvas, outputCanvas, config, videoElement) {
15
- this.inputCanvas = inputCanvas;
16
- this.outputCanvas = outputCanvas;
17
- this.config = config;
18
- this.videoElement = videoElement;
19
- this.loaded = false;
20
- this.frameQueue = [];
21
- this.maskQueue = [];
22
- const inputCanvasCtx = this.inputCanvas.getContext('2d', {
23
- alpha: false,
24
- willReadFrequently: true,
25
- });
26
- if (!inputCanvasCtx) {
27
- throw new Error('[ladon-ts] - error getting input context 2d');
28
- }
29
- this.inputCanvasCtx = inputCanvasCtx;
30
- }
31
- /**
32
- * Gets the raw image data from the input canvas context.
33
- *
34
- * @returns The raw image data.
35
- */
36
- getRawImageDataFromInputCanvas() {
37
- return this.inputCanvasCtx.getImageData(0, 0, this.config.input.width, this.config.input.height).data;
38
- }
39
- /**
40
- * Processes a single frame and returns the inference result.
41
- *
42
- * @param timestamp - The timestamp of the frame.
43
- * @param [performInference=true] - Flag to perform mask inference.
44
- * @returns The result of the frame processing.
45
- * @throws If the pipeline (generator or renderer) is not loaded.
46
- */
47
- onFrame(timestamp, performInference = true) {
48
- var _a, _b;
49
- return __awaiter(this, void 0, void 0, function* () {
50
- if (!this.generator || !this.renderer) {
51
- throw new Error('[ladon-ts] - pipeline is not loaded.');
52
- }
53
- const maskNeeded = performInference || !this.lastMaskResult;
54
- // Generate the mask if needed.
55
- if (maskNeeded) {
56
- const rawImageData = this.getRawImageDataFromInputCanvas();
57
- const maskImageData = this.getMaskImageData(rawImageData);
58
- // Add the frame to the queue. Perform inference and get the mask result and add it to the queue.
59
- this.frameQueue.push({ timestamp, rawImageData });
60
- this.lastMaskResult = yield this.generator.getLadonOutput(maskImageData, timestamp);
61
- this.maskQueue.push(this.lastMaskResult);
62
- // Sync frames and masks to render together.
63
- yield this.renderSyncedFrameAndMask();
64
- // Post-process the mask after rendering.
65
- yield this.generator.postRender(maskImageData, timestamp);
66
- }
67
- else if (this.lastMaskResult) {
68
- // Render the current image with the last mask when inference is skipped. Use the video element if
69
- // available to avoid an uneeeded copy from GPU to CPU.
70
- const videoOrImageData = (_a = this.videoElement) !== null && _a !== void 0 ? _a : this.getRawImageDataFromInputCanvas();
71
- yield ((_b = this.renderer) === null || _b === void 0 ? void 0 : _b.render(videoOrImageData));
72
- // Empty queues when inference is skipped to avoid jitter when switching back to inference.
73
- this.resetQueues();
74
- }
75
- // Return the inference result.
76
- return this.createInferenceResult(timestamp, performInference);
77
- });
78
- }
79
- /**
80
- * Synchronizes frames and masks to ensure they are rendered together.
81
- */
82
- renderSyncedFrameAndMask() {
83
- var _a, _b;
84
- return __awaiter(this, void 0, void 0, function* () {
85
- while (this.frameQueue.length > 0 && this.maskQueue.length > 0) {
86
- const frame = this.frameQueue[0];
87
- const mask = this.maskQueue[0];
88
- // Render the frame and mask together if they match.
89
- if (frame.timestamp === mask.timestamp) {
90
- yield ((_a = this.renderer) === null || _a === void 0 ? void 0 : _a.render((_b = this.videoElement) !== null && _b !== void 0 ? _b : frame.rawImageData, mask));
91
- this.frameQueue.shift();
92
- this.maskQueue.shift();
93
- }
94
- else if (frame.timestamp < mask.timestamp) {
95
- // If the frame is older than the mask, discard the frame.
96
- this.frameQueue.shift();
97
- }
98
- else {
99
- // If the mask is older than the frame, discard the mask.
100
- this.maskQueue.shift();
101
- }
102
- }
103
- });
104
- }
105
- /**
106
- * Resizes the image data if the model expects a fixed size input.
107
- *
108
- * @param {Uint8ClampedArray} rawImageData - The raw image data.
109
- * @returns {Uint8ClampedArray} - The processed mask image data.
110
- */
111
- getMaskImageData(rawImageData) {
112
- // Check if resizing is needed based on configuration.
113
- if (this.config.mask.input_size.width === this.config.input.width) {
114
- return rawImageData;
115
- }
116
- // Resize the image data.
117
- return resizeImage(rawImageData, this.config.input.width, this.config.input.height, this.config.mask.input_size.width, this.config.mask.input_size.height);
118
- }
119
- /**
120
- * Creates the inference result object.
121
- *
122
- * @param {number} timestamp - The timestamp of the frame.
123
- * @param {boolean} performedInference - Indicates if the inference was performed.
124
- * @returns {IFrameInferenceResult} - The result object containing inference details.
125
- */
126
- createInferenceResult(timestamp, performedInference) {
127
- if (!this.lastMaskResult) {
128
- return {
129
- facesAndLandmarks: { data: new Float32Array(0), dims: [] },
130
- gesture: new Float32Array(0),
131
- motion: 0,
132
- skipped: true,
133
- timestamp,
134
- };
135
- }
136
- return {
137
- facesAndLandmarks: this.lastMaskResult.facesAndLandmarks,
138
- gesture: this.lastMaskResult.gesture,
139
- motion: this.lastMaskResult.motion,
140
- skipped: !performedInference,
141
- timestamp,
142
- };
143
- }
144
- /**
145
- * Checks if the pipeline is loaded.
146
- *
147
- * @returns True if the pipeline is loaded, false otherwise.
148
- */
149
- isLoaded() {
150
- return this.loaded;
151
- }
152
- /**
153
- * Loads the pipeline components such as the generator and renderer.
154
- */
155
- load() {
156
- return __awaiter(this, void 0, void 0, function* () {
157
- switch (this.config.render.type) {
158
- case 'blur':
159
- this.renderer = new BlurRenderer(this.outputCanvas, this.config);
160
- break;
161
- case 'passthrough':
162
- this.renderer = new PassthroughRenderer(this.outputCanvas, this.config);
163
- break;
164
- case 'replacement':
165
- this.renderer = new ReplacementRenderer(this.outputCanvas, this.config);
166
- break;
167
- default:
168
- throw new Error('[ladon-ts] - renderer not implemented.');
169
- }
170
- yield this.renderer.load();
171
- if (this.config.render.type === 'passthrough') {
172
- // automatically disable model evaluation when the renderer is set to passthrough
173
- // Note: this may change when gestures are detected (model eval will be a dependency for more than rendering)
174
- this.generator = new NullGenerator(this.config);
175
- }
176
- else {
177
- switch (this.config.mask.generator) {
178
- case 'local':
179
- this.generator = new LocalGenerator(this.config);
180
- break;
181
- case 'worker':
182
- this.generator = new WorkerGenerator(this.config);
183
- break;
184
- default:
185
- throw new Error('[ladon-ts] - generator not implemented.');
186
- }
187
- }
188
- yield this.generator.load();
189
- this.loaded = true;
190
- });
191
- }
192
- /**
193
- * Resets the frame and mask queues.
194
- */
195
- resetQueues() {
196
- this.frameQueue = [];
197
- this.maskQueue = [];
198
- }
199
- reset() {
200
- this.resetQueues();
201
- this.lastMaskResult = undefined;
202
- }
203
- /**
204
- * Destroys the pipeline and cleans up resources.
205
- */
206
- destroy() {
207
- var _a, _b;
208
- this.reset();
209
- (_a = this.generator) === null || _a === void 0 ? void 0 : _a.destroy();
210
- (_b = this.renderer) === null || _b === void 0 ? void 0 : _b.destroy();
211
- }
212
- }
213
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGlwZWxpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3BpcGVsaW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUNBLE9BQU8sRUFHSCxjQUFjLEVBRWQsYUFBYSxFQUNiLGVBQWUsR0FDbEIsTUFBTSxhQUFhLENBQUM7QUFDckIsT0FBTyxFQUFFLFlBQVksRUFBaUIsbUJBQW1CLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDbkcsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQXFCckMsTUFBTSxPQUFPLFFBQVE7SUFXakIsWUFDWSxXQUE4QixFQUM5QixZQUErQixFQUN2QixNQUFzQixFQUNyQixZQUErQjtRQUh4QyxnQkFBVyxHQUFYLFdBQVcsQ0FBbUI7UUFDOUIsaUJBQVksR0FBWixZQUFZLENBQW1CO1FBQ3ZCLFdBQU0sR0FBTixNQUFNLENBQWdCO1FBQ3JCLGlCQUFZLEdBQVosWUFBWSxDQUFtQjtRQVo1QyxXQUFNLEdBQUcsS0FBSyxDQUFDO1FBS2YsZUFBVSxHQUFrRSxFQUFFLENBQUM7UUFDL0UsY0FBUyxHQUF1QixFQUFFLENBQUM7UUFRdkMsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFO1lBQ3JELEtBQUssRUFBRSxLQUFLO1lBQ1osa0JBQWtCLEVBQUUsSUFBSTtTQUMzQixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsY0FBYyxFQUFFO1lBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMsNkNBQTZDLENBQUMsQ0FBQztTQUNsRTtRQUNELElBQUksQ0FBQyxjQUFjLEdBQUcsY0FBYyxDQUFDO0lBQ3pDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssOEJBQThCO1FBQ2xDLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxZQUFZLENBQ25DLENBQUMsRUFDRCxDQUFDLEVBQ0QsSUFBSSxDQUFDLE1BQU0s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
1
+ import { NullGenerator as n, WorkerGenerator as h, LocalGenerator as o } from "./generator.js";
2
+ import { BlurRenderer as u } from "./renderer/blur-renderer.js";
3
+ import { PassthroughRenderer as d } from "./renderer/passthrough-renderer.js";
4
+ import { ReplacementRenderer as l } from "./renderer/replacement-renderer.js";
5
+ import { resizeImage as m } from "./util.js";
6
+ class R {
7
+ constructor(e, t, s, i) {
8
+ this.inputCanvas = e, this.outputCanvas = t, this.config = s, this.videoElement = i, this.loaded = !1, this.frameQueue = [], this.maskQueue = [];
9
+ const a = this.inputCanvas.getContext("2d", {
10
+ alpha: !1,
11
+ willReadFrequently: !0
12
+ });
13
+ if (!a)
14
+ throw new Error("[ladon-ts] - error getting input context 2d");
15
+ this.inputCanvasCtx = a;
16
+ }
17
+ /**
18
+ * Processes a single frame and returns the inference result.
19
+ *
20
+ * @param timestamp - The timestamp of the frame.
21
+ * @param [performInference=true] - Flag to perform mask inference.
22
+ * @returns The result of the frame processing.
23
+ * @throws If the pipeline (generator or renderer) is not loaded.
24
+ */
25
+ async onFrame(e, t = !0) {
26
+ if (!this.generator || !this.renderer)
27
+ throw new Error("[ladon-ts] - pipeline is not loaded.");
28
+ const s = this.getInputFrameData(t);
29
+ if (this.frameQueue.push({ timestamp: e, frameData: s }), t || !this.lastMaskResult) {
30
+ const i = s, a = this.getMaskImageData(i), r = await this.generator.getLadonOutput(a, e);
31
+ this.maskQueue.push({ timestamp: r.timestamp, maskResult: r }), this.lastMaskResult = r, await this.renderSyncedFrameAndMask(), await this.generator.postRender(a, e);
32
+ } else
33
+ this.maskQueue.push({ timestamp: e, maskResult: this.lastMaskResult }), await this.renderSyncedFrameAndMask();
34
+ return this.createInferenceResult(e, t);
35
+ }
36
+ /**
37
+ * Synchronizes frames and masks to ensure they are rendered together.
38
+ */
39
+ async renderSyncedFrameAndMask() {
40
+ var e;
41
+ for (; this.frameQueue.length > 0 && this.maskQueue.length > 0; ) {
42
+ const t = this.frameQueue[0], s = this.maskQueue[0];
43
+ t.timestamp === s.timestamp ? (await ((e = this.renderer) == null ? void 0 : e.render(t.frameData, s.maskResult)), this.frameQueue.shift(), this.maskQueue.shift()) : t.timestamp < s.timestamp ? this.frameQueue.shift() : this.maskQueue.shift();
44
+ }
45
+ }
46
+ /**
47
+ * Gets the raw image data from the input canvas context.
48
+ *
49
+ * @param needFreshImageData - Flag to indicate if fresh image data is needed.
50
+ *
51
+ * @returns The raw image data.
52
+ */
53
+ getInputFrameData(e) {
54
+ return e || !this.videoElement ? this.inputCanvasCtx.getImageData(
55
+ 0,
56
+ 0,
57
+ this.config.input.width,
58
+ this.config.input.height
59
+ ).data : this.videoElement;
60
+ }
61
+ /**
62
+ * Resizes the image data if the model expects a fixed size input.
63
+ *
64
+ * @param {Uint8ClampedArray} rawImageData - The raw image data.
65
+ * @returns {Uint8ClampedArray} - The processed mask image data.
66
+ */
67
+ getMaskImageData(e) {
68
+ return this.config.mask.inputSize.width === this.config.input.width ? e : m(
69
+ e,
70
+ this.config.input.width,
71
+ this.config.input.height,
72
+ this.config.mask.inputSize.width,
73
+ this.config.mask.inputSize.height
74
+ );
75
+ }
76
+ /**
77
+ * Creates the inference result object.
78
+ *
79
+ * @param {number} timestamp - The timestamp of the frame.
80
+ * @param {boolean} performedInference - Indicates if the inference was performed.
81
+ * @returns {IFrameInferenceResult} - The result object containing inference details.
82
+ */
83
+ createInferenceResult(e, t) {
84
+ return this.lastMaskResult ? {
85
+ facesAndLandmarks: this.lastMaskResult.facesAndLandmarks,
86
+ gesture: this.lastMaskResult.gesture,
87
+ motion: this.lastMaskResult.motion,
88
+ skipped: !t,
89
+ timestamp: e
90
+ } : {
91
+ facesAndLandmarks: { data: new Float32Array(0), dims: [] },
92
+ gesture: new Float32Array(0),
93
+ motion: 0,
94
+ skipped: !0,
95
+ timestamp: e
96
+ };
97
+ }
98
+ /**
99
+ * Checks if the pipeline is loaded.
100
+ *
101
+ * @returns True if the pipeline is loaded, false otherwise.
102
+ */
103
+ isLoaded() {
104
+ return this.loaded;
105
+ }
106
+ /**
107
+ * Loads the pipeline components such as the generator and renderer.
108
+ */
109
+ async load() {
110
+ switch (this.config.render.type) {
111
+ case "blur":
112
+ this.renderer = new u(this.outputCanvas, this.config);
113
+ break;
114
+ case "passthrough":
115
+ this.renderer = new d(this.outputCanvas, this.config);
116
+ break;
117
+ case "replacement":
118
+ this.renderer = new l(this.outputCanvas, this.config);
119
+ break;
120
+ default:
121
+ throw new Error("[ladon-ts] - renderer not implemented.");
122
+ }
123
+ if (await this.renderer.load(), this.config.render.type === "passthrough")
124
+ this.generator = new n(this.config);
125
+ else
126
+ switch (this.config.mask.generator) {
127
+ case "local":
128
+ this.generator = new o(this.config);
129
+ break;
130
+ case "worker":
131
+ this.generator = new h(this.config);
132
+ break;
133
+ default:
134
+ throw new Error("[ladon-ts] - generator not implemented.");
135
+ }
136
+ await this.generator.load(), this.loaded = !0;
137
+ }
138
+ /**
139
+ * Resets the frame and mask queues.
140
+ */
141
+ resetQueues() {
142
+ this.frameQueue = [], this.maskQueue = [];
143
+ }
144
+ reset() {
145
+ this.resetQueues(), this.lastMaskResult = void 0;
146
+ }
147
+ /**
148
+ * Destroys the pipeline and cleans up resources.
149
+ */
150
+ destroy() {
151
+ var e, t;
152
+ this.reset(), (e = this.generator) == null || e.destroy(), (t = this.renderer) == null || t.destroy();
153
+ }
154
+ }
155
+ export {
156
+ R as Pipeline
157
+ };
158
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sources":["../../../src/lib/pipeline.ts"],"sourcesContent":["import { PipelineConfig } from './config-types';\nimport {\n FacesAndLandmarks,\n FrameData,\n LadonOutput,\n LocalGenerator,\n MaskGenerator,\n NullGenerator,\n WorkerGenerator,\n} from './generator';\nimport { BlurRenderer, LadonRenderer, PassthroughRenderer, ReplacementRenderer } from './renderer';\nimport { resizeImage } from './util';\n\nexport interface IFrameInferenceResult {\n facesAndLandmarks: FacesAndLandmarks;\n gesture: Float32Array;\n motion: number;\n skipped: boolean;\n timestamp: number;\n}\n\nexport interface IPipeline {\n onFrame(\n timestamp: number,\n maskNeeded?: boolean,\n videoElement?: HTMLVideoElement\n ): Promise<IFrameInferenceResult>;\n isLoaded(): boolean;\n load(): Promise<void>;\n destroy(): void;\n}\n\nexport class Pipeline implements IPipeline {\n private generator?: MaskGenerator;\n private renderer?: LadonRenderer;\n private loaded = false;\n\n private inputCanvasCtx: CanvasRenderingContext2D;\n private lastMaskResult?: LadonOutput;\n\n private frameQueue: Array<{ timestamp: number; frameData: FrameData }> = [];\n private maskQueue: Array<{ timestamp: number; maskResult: LadonOutput }> = [];\n\n constructor(\n private inputCanvas: HTMLCanvasElement,\n private outputCanvas: HTMLCanvasElement,\n public readonly config: PipelineConfig,\n private readonly videoElement?: HTMLVideoElement\n ) {\n const inputCanvasCtx = this.inputCanvas.getContext('2d', {\n alpha: false,\n willReadFrequently: true,\n });\n\n if (!inputCanvasCtx) {\n throw new Error('[ladon-ts] - error getting input context 2d');\n }\n this.inputCanvasCtx = inputCanvasCtx;\n }\n\n /**\n * Processes a single frame and returns the inference result.\n *\n * @param timestamp - The timestamp of the frame.\n * @param [performInference=true] - Flag to perform mask inference.\n * @returns The result of the frame processing.\n * @throws If the pipeline (generator or renderer) is not loaded.\n */\n public async onFrame(\n timestamp: number,\n performInference = true\n ): Promise<IFrameInferenceResult> {\n if (!this.generator || !this.renderer) {\n throw new Error('[ladon-ts] - pipeline is not loaded.');\n }\n\n // Get the current frame (raw image data or video element)\n const frameData = this.getInputFrameData(performInference);\n\n // Add the frame to the queue with its timestamp\n this.frameQueue.push({ timestamp, frameData });\n\n if (performInference || !this.lastMaskResult) {\n // Perform inference and add the new mask to the mask queue\n const rawImageData = frameData as Uint8ClampedArray;\n const maskImageData = this.getMaskImageData(rawImageData);\n const maskResult = await this.generator.getLadonOutput(maskImageData, timestamp);\n // Add the mask to the queue and use the mask timestamp to sync frames and masks.\n this.maskQueue.push({ timestamp: maskResult.timestamp, maskResult });\n this.lastMaskResult = maskResult;\n\n // Sync frames and masks to render together\n await this.renderSyncedFrameAndMask();\n\n // Post-process the mask after rendering\n await this.generator.postRender(maskImageData, timestamp);\n } else {\n // Skipping inference. Update the last mask result's timestamp to match the current frame.\n this.maskQueue.push({ timestamp, maskResult: this.lastMaskResult });\n // Sync frames and masks to render together\n await this.renderSyncedFrameAndMask();\n }\n\n // Return the inference result\n return this.createInferenceResult(timestamp, performInference);\n }\n\n /**\n * Synchronizes frames and masks to ensure they are rendered together.\n */\n private async renderSyncedFrameAndMask(): Promise<void> {\n while (this.frameQueue.length > 0 && this.maskQueue.length > 0) {\n const frame = this.frameQueue[0];\n const maskEntry = this.maskQueue[0];\n\n if (frame.timestamp === maskEntry.timestamp) {\n // Render the frame and mask together\n await this.renderer?.render(frame.frameData, maskEntry.maskResult);\n this.frameQueue.shift();\n this.maskQueue.shift();\n } else if (frame.timestamp < maskEntry.timestamp) {\n // Discard the older frame\n this.frameQueue.shift();\n } else {\n // Discard the older mask\n this.maskQueue.shift();\n }\n }\n }\n\n /**\n * Gets the raw image data from the input canvas context.\n *\n * @param needFreshImageData - Flag to indicate if fresh image data is needed.\n *\n * @returns The raw image data.\n */\n private getInputFrameData(needFreshImageData: boolean): FrameData {\n if (needFreshImageData || !this.videoElement) {\n return this.inputCanvasCtx.getImageData(\n 0,\n 0,\n this.config.input.width,\n this.config.input.height\n ).data;\n }\n\n return this.videoElement;\n }\n\n /**\n * Resizes the image data if the model expects a fixed size input.\n *\n * @param {Uint8ClampedArray} rawImageData - The raw image data.\n * @returns {Uint8ClampedArray} - The processed mask image data.\n */\n private getMaskImageData(rawImageData: Uint8ClampedArray): Uint8ClampedArray {\n // Check if resizing is needed based on configuration.\n if (this.config.mask.inputSize.width === this.config.input.width) {\n return rawImageData;\n }\n\n // Resize the image data.\n return resizeImage(\n rawImageData,\n this.config.input.width,\n this.config.input.height,\n this.config.mask.inputSize.width,\n this.config.mask.inputSize.height\n );\n }\n\n /**\n * Creates the inference result object.\n *\n * @param {number} timestamp - The timestamp of the frame.\n * @param {boolean} performedInference - Indicates if the inference was performed.\n * @returns {IFrameInferenceResult} - The result object containing inference details.\n */\n private createInferenceResult(\n timestamp: number,\n performedInference: boolean\n ): IFrameInferenceResult {\n if (!this.lastMaskResult) {\n return {\n facesAndLandmarks: { data: new Float32Array(0), dims: [] },\n gesture: new Float32Array(0),\n motion: 0,\n skipped: true,\n timestamp,\n };\n }\n\n return {\n facesAndLandmarks: this.lastMaskResult.facesAndLandmarks,\n gesture: this.lastMaskResult.gesture,\n motion: this.lastMaskResult.motion,\n skipped: !performedInference,\n timestamp,\n };\n }\n\n /**\n * Checks if the pipeline is loaded.\n *\n * @returns True if the pipeline is loaded, false otherwise.\n */\n public isLoaded(): boolean {\n return this.loaded;\n }\n\n /**\n * Loads the pipeline components such as the generator and renderer.\n */\n public async load(): Promise<void> {\n switch (this.config.render.type) {\n case 'blur':\n this.renderer = new BlurRenderer(this.outputCanvas, this.config);\n break;\n case 'passthrough':\n this.renderer = new PassthroughRenderer(this.outputCanvas, this.config);\n break;\n case 'replacement':\n this.renderer = new ReplacementRenderer(this.outputCanvas, this.config);\n break;\n default:\n throw new Error('[ladon-ts] - renderer not implemented.');\n }\n\n await this.renderer.load();\n\n if (this.config.render.type === 'passthrough') {\n // automatically disable model evaluation when the renderer is set to passthrough\n // Note: this may change when gestures are detected (model eval will be a dependency for more than rendering)\n this.generator = new NullGenerator(this.config);\n } else {\n switch (this.config.mask.generator) {\n case 'local':\n this.generator = new LocalGenerator(this.config);\n break;\n case 'worker':\n this.generator = new WorkerGenerator(this.config);\n break;\n default:\n throw new Error('[ladon-ts] - generator not implemented.');\n }\n }\n\n await this.generator.load();\n\n this.loaded = true;\n }\n\n /**\n * Resets the frame and mask queues.\n */\n private resetQueues(): void {\n this.frameQueue = [];\n this.maskQueue = [];\n }\n\n public reset(): void {\n this.resetQueues();\n this.lastMaskResult = undefined;\n }\n\n /**\n * Destroys the pipeline and cleans up resources.\n */\n public destroy(): void {\n this.reset();\n this.generator?.destroy();\n this.renderer?.destroy();\n }\n}\n"],"names":["Pipeline","inputCanvas","outputCanvas","config","videoElement","inputCanvasCtx","timestamp","performInference","frameData","rawImageData","maskImageData","maskResult","frame","maskEntry","_a","needFreshImageData","resizeImage","performedInference","BlurRenderer","PassthroughRenderer","ReplacementRenderer","NullGenerator","LocalGenerator","WorkerGenerator","_b"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { PreloadConfig } from './config-types';
2
+
3
+ /**
4
+ * Preload the resources using the provided configuration. This function is used to preload the model
5
+ * and the worker before creating the pipeline.
6
+ *
7
+ * @param config - The configuration object.
8
+ */
9
+ export declare const preload: (config: PreloadConfig) => Promise<void>;
@@ -0,0 +1,8 @@
1
+ import { sharedResourceManager as r } from "./shared-resource-manager.js";
2
+ const o = async (e) => {
3
+ e.mask.generator === "worker" ? await r.preloadWorker(e) : await r.loadModel(e);
4
+ };
5
+ export {
6
+ o as preload
7
+ };
8
+ //# sourceMappingURL=preload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preload.js","sources":["../../../src/lib/preload.ts"],"sourcesContent":["import { PreloadConfig } from './config-types';\nimport { sharedResourceManager } from './shared-resource-manager';\n\n/**\n * Preload the resources using the provided configuration. This function is used to preload the model\n * and the worker before creating the pipeline.\n *\n * @param config - The configuration object.\n */\nexport const preload = async (config: PreloadConfig) => {\n if (config.mask.generator === 'worker') {\n await sharedResourceManager.preloadWorker(config);\n } else {\n await sharedResourceManager.loadModel(config);\n }\n};\n"],"names":["preload","config","sharedResourceManager"],"mappings":";AASa,MAAAA,IAAU,OAAOC,MAA0B;AAChD,EAAAA,EAAO,KAAK,cAAc,WACpB,MAAAC,EAAsB,cAAcD,CAAM,IAE1C,MAAAC,EAAsB,UAAUD,CAAM;AAEpD;"}
@@ -1,7 +1,8 @@
1
- import { PipelineConfig } from '../config';
2
- import { LadonOutput } from '../generator';
3
- import { LadonRenderer } from './ladon-renderer';
4
- import { WebGLRenderer } from './webgl-renderer';
1
+ import { PipelineConfig } from '../config-types';
2
+ import { FrameData, LadonOutput } from '../generator';
3
+ import { LadonRenderer } from './ladon-renderer';
4
+ import { WebGLRenderer } from './webgl-renderer';
5
+
5
6
  export declare class BlurRenderer extends WebGLRenderer implements LadonRenderer {
6
7
  output_canvas: HTMLCanvasElement;
7
8
  readonly config: PipelineConfig;
@@ -14,7 +15,7 @@ export declare class BlurRenderer extends WebGLRenderer implements LadonRenderer
14
15
  private fragment_shader_pass_1_src;
15
16
  fragment_shader_pass_2_src: string;
16
17
  constructor(output_canvas: HTMLCanvasElement, config: PipelineConfig);
17
- render(input: Uint8ClampedArray | HTMLVideoElement, mask?: LadonOutput): Promise<void>;
18
+ render(input: FrameData, mask?: LadonOutput): Promise<void>;
18
19
  load(): Promise<void>;
19
20
  destroy(): void;
20
21
  private getBlurKernel;