@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,5 +1,5 @@
1
+ import { PreloadConfig, ResolutionConfig, WorkerConfig } from './config-types';
1
2
  import * as ort from 'onnxruntime-web';
2
- import { PipelineConfig, PreloadConfig, SizeConfig } from './config';
3
3
  /**
4
4
  * Shared resource manager used to preload and share resources across different pipelines.
5
5
  * This is useful when multiple pipelines are using the same model or when the model needs
@@ -9,49 +9,45 @@ declare class SharedResourceManager {
9
9
  private modelSessions;
10
10
  private worker?;
11
11
  private workerUrl?;
12
+ private resolvedUriCache;
12
13
  /**
13
14
  * Initialize the worker using the provided configuration.
14
15
  *
15
- * @param {PreloadConfig} config The configuration object.
16
- * @returns {Promise<Worker>} A promise that resolves when the worker is initialized.
17
- * @example
18
- * await initializeWorker(config);
16
+ * @param config - The configuration object.
17
+ * @returns A promise that resolves when the worker is initialized.
19
18
  */
20
- initializeWorker(config: PreloadConfig): Promise<Worker>;
19
+ initializeWorker(config: WorkerConfig): Promise<Worker>;
21
20
  /**
22
21
  * Terminate the worker.
23
22
  */
24
23
  terminateWorker(): void;
25
24
  /**
26
- * Preload the model using the provided configuration.
25
+ * Load the model using the provided configuration. This gets called by the worker when using
26
+ * the worker generator.
27
27
  *
28
- * @param {PreloadConfig} config The configuration object.
29
- * @returns {Promise<void>} A promise that resolves when the model is preloaded.
30
- * @example
31
- * await preloadModel(config);
28
+ * @param config - The configuration object.
29
+ * @returns A promise that resolves when the model is preloaded.
32
30
  */
33
- preloadModel(config: PreloadConfig): Promise<ort.InferenceSession>;
31
+ loadModel(config: PreloadConfig): Promise<ort.InferenceSession>;
34
32
  /**
35
33
  * Preload the worker using the provided configuration.
36
34
  *
37
- * @param {PreloadConfig} config The configuration object.
38
- * @returns {Promise<void>} A promise that resolves when the worker is preloaded.
39
- * @example
40
- * await preloadWorker(config);
35
+ * @param config - The configuration object.
36
+ * @returns A promise that resolves when the worker is preloaded.
41
37
  */
42
38
  preloadWorker(config: PreloadConfig): Promise<void>;
43
39
  /**
44
40
  * Warmup the model session with a dummy input to avoid latency when running the model for the first time.
45
41
  *
46
42
  * @param {ort.InferenceSession} session The model session.
47
- * @param {SizeConfig} inputSize The input size of the model.
43
+ * @param {ResolutionConfig} inputSize The input size of the model.
48
44
  * @param {number} inputChannels The number of input channels (e.g., RGB is 3).
49
45
  * @param {ort.Tensor.Type} inputType The input tensor type.
50
46
  * @returns {Promise<void>} A promise that resolves when the model is warmed up.
51
47
  * @example
52
48
  * await warmupModel(session, inputSize, inputChannels, inputType);
53
49
  */
54
- warmupModel(session: ort.InferenceSession, inputSize?: SizeConfig, inputChannels?: number, inputType?: ort.Tensor.Type): Promise<void>;
50
+ warmupModel(session: ort.InferenceSession, inputSize?: ResolutionConfig, inputChannels?: number, inputType?: ort.Tensor.Type): Promise<void>;
55
51
  /**
56
52
  * Get the model session for the provided model URL.
57
53
  *
@@ -62,23 +58,36 @@ declare class SharedResourceManager {
62
58
  */
63
59
  getModelSession(modelUrl: string): ort.InferenceSession;
64
60
  /**
65
- * Resolves the model URL based on the configuration.
61
+ * Resolves the full URL for a given asset. Non-file URIs are treated as paths
62
+ * and resolved using the `toAbsoluteURI` method.
66
63
  *
67
- * @param {PipelineConfig} config The configuration object.
68
- * @returns {Promise<string>} The resolved model URL.
69
- * @example
70
- * const modelUrl = await getModelUrl(config);
64
+ * @param config - The preload configuration.
65
+ * @param assetUri - The asset URI from the config.
66
+ * @returns The resolved full URL.
67
+ */
68
+ /**
69
+ * Resolves the full URL for a given asset. Non-file URIs are treated as paths and resolved
70
+ * using the `toAbsoluteURI` method. If the assetUri is already resolved, or if it's found in
71
+ * cache, it will be returned directly. If an assetUrlResolver function is provided in the
72
+ * configuration, it will be used to resolve the URL if the assetUri is not fully qualified,
73
+ * a blob URL, or in the cache.
74
+ *
75
+ * @param config - The preload configuration.
76
+ * @param assetUri - The asset URI from the config.
77
+ * @returns The resolved full URL.
71
78
  */
72
- getModelUrl({ mask: { model_url_resolver, model_uri } }: PipelineConfig | PreloadConfig): Promise<string>;
79
+ resolveUri(config: PreloadConfig, assetUri?: string): Promise<string>;
73
80
  getWorker(): Worker | undefined;
74
81
  getWorkerUrl(): string | undefined;
82
+ /**
83
+ * Prepare the worker configuration by resolving the final URLs and paths to send to the
84
+ * worker. This is necessary because we can't send functions to the worker. We also need to
85
+ * remove the assetUrlResolver function from the configuration.
86
+ *
87
+ * @param config - The preload configuration.
88
+ * @returns The worker configuration.
89
+ */
90
+ prepareWorkerConfig(config: PreloadConfig): Promise<any>;
75
91
  }
76
92
  export declare const sharedResourceManager: SharedResourceManager;
77
- /**
78
- * Preload the resources using the provided configuration. This function is used to preload the model
79
- * and the worker before creating the pipeline.
80
- *
81
- * @param config - The configuration object.
82
- */
83
- export declare const preload: (config: PreloadConfig) => Promise<void>;
84
93
  export {};
@@ -1,189 +1,151 @@
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 * as ort from 'onnxruntime-web';
11
- import { toAbsoluteURI } from './util';
12
- /**
13
- * Shared resource manager used to preload and share resources across different pipelines.
14
- * This is useful when multiple pipelines are using the same model or when the model needs
15
- * to be preloaded before the pipeline is created.
16
- */
17
- class SharedResourceManager {
18
- constructor() {
19
- this.modelSessions = {};
20
- }
21
- /**
22
- * Initialize the worker using the provided configuration.
23
- *
24
- * @param {PreloadConfig} config The configuration object.
25
- * @returns {Promise<Worker>} A promise that resolves when the worker is initialized.
26
- * @example
27
- * await initializeWorker(config);
28
- */
29
- initializeWorker(config) {
30
- return __awaiter(this, void 0, void 0, function* () {
31
- if (typeof Worker === 'undefined') {
32
- throw new Error('[ladon-ts] web workers are not supported in this environment');
33
- }
34
- const crossOriginScriptUrl = config.mask.worker_uri;
35
- const content = yield (yield fetch(crossOriginScriptUrl, { cache: 'force-cache' })).text();
36
- this.workerUrl = URL.createObjectURL(new Blob([content], { type: 'text/javascript' }));
37
- this.worker = new Worker(this.workerUrl, { type: 'module' });
38
- return this.worker;
39
- });
40
- }
41
- /**
42
- * Terminate the worker.
43
- */
44
- terminateWorker() {
45
- if (this.worker) {
46
- this.worker.terminate();
47
- this.worker = undefined;
48
- }
49
- }
50
- /**
51
- * Preload the model using the provided configuration.
52
- *
53
- * @param {PreloadConfig} config The configuration object.
54
- * @returns {Promise<void>} A promise that resolves when the model is preloaded.
55
- * @example
56
- * await preloadModel(config);
57
- */
58
- preloadModel(config) {
59
- var _a;
60
- var _b;
61
- return __awaiter(this, void 0, void 0, function* () {
62
- if (config.wasm_uri) {
63
- ort.env.wasm.wasmPaths = toAbsoluteURI(config.wasm_uri, config.base_url);
64
- }
65
- ort.env.wasm.numThreads = 0;
66
- // Resolve the model URL based on the configuration.
67
- const modelUrl = yield this.getModelUrl(config);
68
- // Use the model session cache to avoid creating multiple sessions for the same model.
69
- (_a = (_b = this.modelSessions)[modelUrl]) !== null && _a !== void 0 ? _a : (_b[modelUrl] = yield ort.InferenceSession.create(modelUrl, {
70
- executionProviders: ['wasm'],
71
- }));
72
- // Warmup the model with a dummy input to avoid latency when running the model for the first time.
73
- yield this.warmupModel(this.modelSessions[modelUrl], config.mask.input_size, config.mask.model_rank);
74
- return this.modelSessions[modelUrl];
75
- });
76
- }
77
- /**
78
- * Preload the worker using the provided configuration.
79
- *
80
- * @param {PreloadConfig} config The configuration object.
81
- * @returns {Promise<void>} A promise that resolves when the worker is preloaded.
82
- * @example
83
- * await preloadWorker(config);
84
- */
85
- preloadWorker(config) {
86
- var _a;
87
- return __awaiter(this, void 0, void 0, function* () {
88
- // If the model URL resolver is a function, We can't send the function to the worker so
89
- // we resolve the model URL here and send the resolved URL to the worker.
90
- const modelUrl = yield this.getModelUrl(config);
91
- const newConfig = Object.assign(Object.assign({}, config), { mask: Object.assign(Object.assign({}, config.mask), { model_url_resolver: modelUrl }) });
92
- // Initialize the worker.
93
- yield this.initializeWorker(newConfig);
94
- // Send the preload message to the worker.
95
- (_a = this.worker) === null || _a === void 0 ? void 0 : _a.postMessage({ type: 'preload', config: newConfig });
96
- });
97
- }
98
- /**
99
- * Warmup the model session with a dummy input to avoid latency when running the model for the first time.
100
- *
101
- * @param {ort.InferenceSession} session The model session.
102
- * @param {SizeConfig} inputSize The input size of the model.
103
- * @param {number} inputChannels The number of input channels (e.g., RGB is 3).
104
- * @param {ort.Tensor.Type} inputType The input tensor type.
105
- * @returns {Promise<void>} A promise that resolves when the model is warmed up.
106
- * @example
107
- * await warmupModel(session, inputSize, inputChannels, inputType);
108
- */
109
- warmupModel(session, inputSize = { width: 1280, height: 720 }, inputChannels = 3, inputType = 'float32') {
110
- return __awaiter(this, void 0, void 0, function* () {
111
- const numPixels = inputSize.height * inputSize.width;
112
- const dummyInputData = new Float32Array(inputChannels * numPixels).fill(0);
113
- const dummyInput = new ort.Tensor(inputType, dummyInputData, [
114
- 1,
115
- inputChannels,
116
- inputSize.height,
117
- inputSize.width,
118
- ]);
119
- const feed = { [session.inputNames[0]]: dummyInput };
120
- // Use an additional dummy tensor if the model expects a previous mask.
121
- if (inputChannels === 3) {
122
- const dummyMaskData = new Float32Array(numPixels).fill(0);
123
- const prevMaskTensor = new ort.Tensor(inputType, dummyMaskData, [
124
- 1,
125
- 1,
126
- inputSize.height,
127
- inputSize.width,
128
- ]);
129
- feed[session.inputNames[1]] = prevMaskTensor;
130
- }
131
- // Run the model with the dummy input to warm it up.
132
- yield session.run(feed);
133
- });
134
- }
135
- /**
136
- * Get the model session for the provided model URL.
137
- *
138
- * @param {string} modelUrl The model URL.
139
- * @returns {ort.InferenceSession} The model session.
140
- * @example
141
- * const session = getModelSession(modelUrl);
142
- */
143
- getModelSession(modelUrl) {
144
- return this.modelSessions[modelUrl];
145
- }
146
- /**
147
- * Resolves the model URL based on the configuration.
148
- *
149
- * @param {PipelineConfig} config The configuration object.
150
- * @returns {Promise<string>} The resolved model URL.
151
- * @example
152
- * const modelUrl = await getModelUrl(config);
153
- */
154
- getModelUrl({ mask: { model_url_resolver, model_uri } }) {
155
- return __awaiter(this, void 0, void 0, function* () {
156
- let modelUrl;
157
- if (typeof model_url_resolver === 'string') {
158
- modelUrl = model_url_resolver;
159
- }
160
- else {
161
- modelUrl = yield model_url_resolver(model_uri);
162
- }
163
- return modelUrl;
164
- });
165
- }
166
- getWorker() {
167
- return this.worker;
168
- }
169
- getWorkerUrl() {
170
- return this.workerUrl;
171
- }
172
- }
173
- // Global instance of the shared resource manager.
174
- export const sharedResourceManager = new SharedResourceManager();
175
- /**
176
- * Preload the resources using the provided configuration. This function is used to preload the model
177
- * and the worker before creating the pipeline.
178
- *
179
- * @param config - The configuration object.
180
- */
181
- export const preload = (config) => __awaiter(void 0, void 0, void 0, function* () {
182
- if (config.mask.generator === 'worker') {
183
- yield sharedResourceManager.preloadWorker(config);
184
- }
185
- else {
186
- yield sharedResourceManager.preloadModel(config);
187
- }
188
- });
189
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcmVkLXJlc291cmNlLW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3NoYXJlZC1yZXNvdXJjZS1tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLE9BQU8sS0FBSyxHQUFHLE1BQU0saUJBQWlCLENBQUM7QUFHdkMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUV2Qzs7OztHQUlHO0FBQ0gsTUFBTSxxQkFBcUI7SUFBM0I7UUFDWSxrQkFBYSxHQUF5QyxFQUFFLENBQUM7SUE0S3JFLENBQUM7SUF4S0c7Ozs7Ozs7T0FPRztJQUNHLGdCQUFnQixDQUFDLE1BQXFCOztZQUN4QyxJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVcsRUFBRTtnQkFDL0IsTUFBTSxJQUFJLEtBQUssQ0FBQyw4REFBOEQsQ0FBQyxDQUFDO2FBQ25GO1lBRUQsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztZQUNwRCxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsb0JBQW9CLEVBQUUsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1lBRTNGLElBQUksQ0FBQyxTQUFTLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3ZGLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBRTdELE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUN2QixDQUFDO0tBQUE7SUFFRDs7T0FFRztJQUNILGVBQWU7UUFDWCxJQUFJLElB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
1
+ import * as a from "onnxruntime-web";
2
+ import { isResolvedUri as d, toAbsoluteURI as m } from "./util.js";
3
+ class c {
4
+ constructor() {
5
+ this.modelSessions = {}, this.resolvedUriCache = /* @__PURE__ */ new Map();
6
+ }
7
+ /**
8
+ * Initialize the worker using the provided configuration.
9
+ *
10
+ * @param config - The configuration object.
11
+ * @returns A promise that resolves when the worker is initialized.
12
+ */
13
+ async initializeWorker(e) {
14
+ if (typeof Worker > "u")
15
+ throw new Error("[ladon-ts] web workers are not supported in this environment");
16
+ const r = await this.resolveUri(e, e.mask.workerUri), o = await (await fetch(r, { cache: "force-cache" })).text();
17
+ return this.workerUrl = URL.createObjectURL(new Blob([o], { type: "text/javascript" })), new Worker(this.workerUrl, { type: "module" });
18
+ }
19
+ /**
20
+ * Terminate the worker.
21
+ */
22
+ terminateWorker() {
23
+ this.worker && (this.worker.terminate(), this.worker = void 0);
24
+ }
25
+ /**
26
+ * Load the model using the provided configuration. This gets called by the worker when using
27
+ * the worker generator.
28
+ *
29
+ * @param config - The configuration object.
30
+ * @returns A promise that resolves when the model is preloaded.
31
+ */
32
+ async loadModel(e) {
33
+ var i;
34
+ const { mask: r, executionProviders: s } = e, o = await this.resolveUri(e, e.wasmUri);
35
+ o && (a.env.wasm.wasmPaths = o), a.env.wasm.numThreads = 1;
36
+ const t = await this.resolveUri(e, r.modelUri), n = s != null && s.length ? s : ["wasm"];
37
+ return (i = this.modelSessions)[t] || (i[t] = await a.InferenceSession.create(t, {
38
+ executionProviders: n
39
+ })), await this.warmupModel(this.modelSessions[t], r.inputSize, r.modelRank), this.modelSessions[t];
40
+ }
41
+ /**
42
+ * Preload the worker using the provided configuration.
43
+ *
44
+ * @param config - The configuration object.
45
+ * @returns A promise that resolves when the worker is preloaded.
46
+ */
47
+ async preloadWorker(e) {
48
+ const r = await this.prepareWorkerConfig(e);
49
+ this.worker = await this.initializeWorker(r), this.worker.postMessage({ type: "preload", config: r });
50
+ }
51
+ /**
52
+ * Warmup the model session with a dummy input to avoid latency when running the model for the first time.
53
+ *
54
+ * @param {ort.InferenceSession} session The model session.
55
+ * @param {ResolutionConfig} inputSize The input size of the model.
56
+ * @param {number} inputChannels The number of input channels (e.g., RGB is 3).
57
+ * @param {ort.Tensor.Type} inputType The input tensor type.
58
+ * @returns {Promise<void>} A promise that resolves when the model is warmed up.
59
+ * @example
60
+ * await warmupModel(session, inputSize, inputChannels, inputType);
61
+ */
62
+ async warmupModel(e, r = { width: 1280, height: 720 }, s = 3, o = "float32") {
63
+ const t = r.height * r.width, n = new Float32Array(s * t).fill(0), i = new a.Tensor(o, n, [
64
+ 1,
65
+ s,
66
+ r.height,
67
+ r.width
68
+ ]), l = { [e.inputNames[0]]: i };
69
+ if (s === 3) {
70
+ const w = new Float32Array(t).fill(0), h = new a.Tensor(o, w, [
71
+ 1,
72
+ 1,
73
+ r.height,
74
+ r.width
75
+ ]);
76
+ l[e.inputNames[1]] = h;
77
+ }
78
+ await e.run(l);
79
+ }
80
+ /**
81
+ * Get the model session for the provided model URL.
82
+ *
83
+ * @param {string} modelUrl The model URL.
84
+ * @returns {ort.InferenceSession} The model session.
85
+ * @example
86
+ * const session = getModelSession(modelUrl);
87
+ */
88
+ getModelSession(e) {
89
+ return this.modelSessions[e];
90
+ }
91
+ /**
92
+ * Resolves the full URL for a given asset. Non-file URIs are treated as paths
93
+ * and resolved using the `toAbsoluteURI` method.
94
+ *
95
+ * @param config - The preload configuration.
96
+ * @param assetUri - The asset URI from the config.
97
+ * @returns The resolved full URL.
98
+ */
99
+ /**
100
+ * Resolves the full URL for a given asset. Non-file URIs are treated as paths and resolved
101
+ * using the `toAbsoluteURI` method. If the assetUri is already resolved, or if it's found in
102
+ * cache, it will be returned directly. If an assetUrlResolver function is provided in the
103
+ * configuration, it will be used to resolve the URL if the assetUri is not fully qualified,
104
+ * a blob URL, or in the cache.
105
+ *
106
+ * @param config - The preload configuration.
107
+ * @param assetUri - The asset URI from the config.
108
+ * @returns The resolved full URL.
109
+ */
110
+ async resolveUri(e, r) {
111
+ if (!r)
112
+ throw new Error("Asset URI is undefined.");
113
+ if (this.resolvedUriCache.has(r))
114
+ return this.resolvedUriCache.get(r);
115
+ let s;
116
+ if (d(r) ? s = r : r.match(/\.[a-z0-9]+$/i) ? typeof e.assetUrlResolver == "function" && (s = await e.assetUrlResolver(r, e)) : s = m(r, e.baseUrl), !s)
117
+ throw new Error(`Failed to resolve asset URI: ${r}`);
118
+ return this.resolvedUriCache.set(r, s), s;
119
+ }
120
+ getWorker() {
121
+ return this.worker;
122
+ }
123
+ getWorkerUrl() {
124
+ return this.workerUrl;
125
+ }
126
+ /**
127
+ * Prepare the worker configuration by resolving the final URLs and paths to send to the
128
+ * worker. This is necessary because we can't send functions to the worker. We also need to
129
+ * remove the assetUrlResolver function from the configuration.
130
+ *
131
+ * @param config - The preload configuration.
132
+ * @returns The worker configuration.
133
+ */
134
+ async prepareWorkerConfig(e) {
135
+ const s = { ...{
136
+ ...e,
137
+ mask: {
138
+ ...e.mask,
139
+ modelUri: await this.resolveUri(e, e.mask.modelUri),
140
+ workerUri: await this.resolveUri(e, e.mask.workerUri)
141
+ },
142
+ wasmUri: await this.resolveUri(e, e.wasmUri)
143
+ }, assetUrlResolver: void 0 };
144
+ return JSON.parse(JSON.stringify(s));
145
+ }
146
+ }
147
+ const U = new c();
148
+ export {
149
+ U as sharedResourceManager
150
+ };
151
+ //# sourceMappingURL=shared-resource-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-resource-manager.js","sources":["../../../src/lib/shared-resource-manager.ts"],"sourcesContent":["import * as ort from 'onnxruntime-web';\n\nimport { PreloadConfig, ResolutionConfig, WorkerConfig } from './config-types';\nimport { isResolvedUri, toAbsoluteURI } from './util';\n\n/**\n * Shared resource manager used to preload and share resources across different pipelines.\n * This is useful when multiple pipelines are using the same model or when the model needs\n * to be preloaded before the pipeline is created.\n */\nclass SharedResourceManager {\n private modelSessions: Record<string, ort.InferenceSession> = {};\n private worker?: Worker;\n private workerUrl?: string;\n\n // In-memory cache for resolved URLs\n private resolvedUriCache: Map<string, string> = new Map();\n\n /**\n * Initialize the worker using the provided configuration.\n *\n * @param config - The configuration object.\n * @returns A promise that resolves when the worker is initialized.\n */\n public async initializeWorker(config: WorkerConfig): Promise<Worker> {\n if (typeof Worker === 'undefined') {\n throw new Error('[ladon-ts] web workers are not supported in this environment');\n }\n\n const scriptUri = await this.resolveUri(config, config.mask.workerUri);\n const response = await fetch(scriptUri, { cache: 'force-cache' });\n const workerSource = await response.text();\n\n this.workerUrl = URL.createObjectURL(new Blob([workerSource], { type: 'text/javascript' }));\n\n return new Worker(this.workerUrl, { type: 'module' });\n }\n\n /**\n * Terminate the worker.\n */\n public terminateWorker() {\n if (this.worker) {\n this.worker.terminate();\n this.worker = undefined;\n }\n }\n\n /**\n * Load the model using the provided configuration. This gets called by the worker when using\n * the worker generator.\n *\n * @param config - The configuration object.\n * @returns A promise that resolves when the model is preloaded.\n */\n public async loadModel(config: PreloadConfig) {\n const { mask, executionProviders: providers } = config;\n\n const wasmPaths = await this.resolveUri(config, config.wasmUri);\n if (wasmPaths) {\n ort.env.wasm.wasmPaths = wasmPaths;\n }\n\n // Lock to a single thread to avoid performance issues.\n ort.env.wasm.numThreads = 1;\n\n const modelUrl = await this.resolveUri(config, mask.modelUri);\n const executionProviders = providers?.length ? providers : ['wasm'];\n\n // Use the model session cache to avoid creating multiple sessions for the same model.\n this.modelSessions[modelUrl] ||= await ort.InferenceSession.create(modelUrl, {\n executionProviders,\n });\n\n // Warmup the model with a dummy input to avoid latency when running the model for the first time.\n await this.warmupModel(this.modelSessions[modelUrl], mask.inputSize, mask.modelRank);\n\n return this.modelSessions[modelUrl];\n }\n\n /**\n * Preload the worker using the provided configuration.\n *\n * @param config - The configuration object.\n * @returns A promise that resolves when the worker is preloaded.\n */\n public async preloadWorker(config: PreloadConfig) {\n const workerConfig = await this.prepareWorkerConfig(config);\n\n this.worker = await this.initializeWorker(workerConfig);\n this.worker.postMessage({ type: 'preload', config: workerConfig });\n }\n\n /**\n * Warmup the model session with a dummy input to avoid latency when running the model for the first time.\n *\n * @param {ort.InferenceSession} session The model session.\n * @param {ResolutionConfig} inputSize The input size of the model.\n * @param {number} inputChannels The number of input channels (e.g., RGB is 3).\n * @param {ort.Tensor.Type} inputType The input tensor type.\n * @returns {Promise<void>} A promise that resolves when the model is warmed up.\n * @example\n * await warmupModel(session, inputSize, inputChannels, inputType);\n */\n public async warmupModel(\n session: ort.InferenceSession,\n inputSize: ResolutionConfig = { width: 1280, height: 720 },\n inputChannels = 3,\n inputType: ort.Tensor.Type = 'float32'\n ): Promise<void> {\n const numPixels = inputSize.height * inputSize.width;\n const dummyInputData = new Float32Array(inputChannels * numPixels).fill(0);\n const dummyInput = new ort.Tensor(inputType, dummyInputData, [\n 1,\n inputChannels,\n inputSize.height,\n inputSize.width,\n ]);\n const feed = { [session.inputNames[0]]: dummyInput };\n\n // Use an additional dummy tensor if the model expects a previous mask.\n if (inputChannels === 3) {\n const dummyMaskData = new Float32Array(numPixels).fill(0);\n const prevMaskTensor = new ort.Tensor(inputType, dummyMaskData, [\n 1,\n 1,\n inputSize.height,\n inputSize.width,\n ]);\n feed[session.inputNames[1]] = prevMaskTensor;\n }\n\n // Run the model with the dummy input to warm it up.\n await session.run(feed);\n }\n\n /**\n * Get the model session for the provided model URL.\n *\n * @param {string} modelUrl The model URL.\n * @returns {ort.InferenceSession} The model session.\n * @example\n * const session = getModelSession(modelUrl);\n */\n public getModelSession(modelUrl: string) {\n return this.modelSessions[modelUrl];\n }\n\n /**\n * Resolves the full URL for a given asset. Non-file URIs are treated as paths\n * and resolved using the `toAbsoluteURI` method.\n *\n * @param config - The preload configuration.\n * @param assetUri - The asset URI from the config.\n * @returns The resolved full URL.\n */\n /**\n * Resolves the full URL for a given asset. Non-file URIs are treated as paths and resolved\n * using the `toAbsoluteURI` method. If the assetUri is already resolved, or if it's found in\n * cache, it will be returned directly. If an assetUrlResolver function is provided in the\n * configuration, it will be used to resolve the URL if the assetUri is not fully qualified,\n * a blob URL, or in the cache.\n *\n * @param config - The preload configuration.\n * @param assetUri - The asset URI from the config.\n * @returns The resolved full URL.\n */\n public async resolveUri(config: PreloadConfig, assetUri?: string): Promise<string> {\n if (!assetUri) {\n throw new Error('Asset URI is undefined.');\n }\n\n // Check if the URL is already cached\n if (this.resolvedUriCache.has(assetUri)) {\n return this.resolvedUriCache.get(assetUri) as string;\n }\n\n let resolvedUrl: string | undefined;\n\n if (isResolvedUri(assetUri)) {\n // If the assetUri is fully qualified or a blob URL, return it directly.\n // (Assets uris are resolved before being sent to the worker.)\n resolvedUrl = assetUri;\n } else if (!assetUri.match(/\\.[a-z0-9]+$/i)) {\n // Resolve as an absolute path to a non-file endpoint (e.g., wasmPaths).\n resolvedUrl = toAbsoluteURI(assetUri, config.baseUrl);\n } else if (typeof config.assetUrlResolver === 'function') {\n // Resolve via assetUrlResolver. This delegates the resolution logic to the caller.\n resolvedUrl = await config.assetUrlResolver(assetUri, config);\n }\n\n if (!resolvedUrl) {\n throw new Error(`Failed to resolve asset URI: ${assetUri}`);\n }\n\n // Cache the resolved URL\n this.resolvedUriCache.set(assetUri, resolvedUrl);\n\n return resolvedUrl;\n }\n\n public getWorker() {\n return this.worker;\n }\n\n public getWorkerUrl() {\n return this.workerUrl;\n }\n\n /**\n * Prepare the worker configuration by resolving the final URLs and paths to send to the\n * worker. This is necessary because we can't send functions to the worker. We also need to\n * remove the assetUrlResolver function from the configuration.\n *\n * @param config - The preload configuration.\n * @returns The worker configuration.\n */\n public async prepareWorkerConfig(config: PreloadConfig) {\n // Resolve and cache the URIs before sending the config to the worker. Future calls to the\n // resolveUri method will use the cache.\n const resolvedConfig: PreloadConfig = {\n ...config,\n mask: {\n ...config.mask,\n modelUri: await this.resolveUri(config, config.mask.modelUri),\n workerUri: await this.resolveUri(config, config.mask.workerUri),\n },\n wasmUri: await this.resolveUri(config, config.wasmUri),\n };\n\n // We can't send the assetUrlResolver function to the worker so we remove it from the config.\n const workerConfig = { ...resolvedConfig, assetUrlResolver: undefined };\n\n // This is a workaround to ensure the worker configuration can be sent to the worker.\n return JSON.parse(JSON.stringify(workerConfig));\n }\n}\n\n// Global instance of the shared resource manager.\nexport const sharedResourceManager = new SharedResourceManager();\n"],"names":["SharedResourceManager","config","scriptUri","workerSource","mask","providers","wasmPaths","ort","modelUrl","executionProviders","_a","workerConfig","session","inputSize","inputChannels","inputType","numPixels","dummyInputData","dummyInput","feed","dummyMaskData","prevMaskTensor","assetUri","resolvedUrl","isResolvedUri","toAbsoluteURI","sharedResourceManager"],"mappings":"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"}
@@ -51,3 +51,13 @@ export declare function lanczos3Upsample(input: Float32Array, srcWidth: number,
51
51
  export declare const toAbsoluteURI: (relativeURL: string, baseURL?: string) => string;
52
52
  export declare function compileShader(gl: WebGL2RenderingContext, shader_type: number, source: string): WebGLShader;
53
53
  export declare function linkProgram(gl: WebGL2RenderingContext, vertex_shader: WebGLShader, fragment_shader: WebGLShader): WebGLProgram;
54
+ /**
55
+ * Determines if a URI is already resolved.
56
+ * A resolved URI is either:
57
+ * - A blob URL (starts with 'blob:')
58
+ * - A fully qualified URL (e.g., http:// or https://)
59
+ *
60
+ * @param uri - The URI to check.
61
+ * @returns Whether the URI is already resolved.
62
+ */
63
+ export declare function isResolvedUri(uri: string): boolean;