@webex/ladon-ts 5.5.1 → 5.6.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.
- package/CHANGELOG.md +14 -0
- package/build/module/lib/config-builder.js +1 -1
- package/build/module/lib/config-builder.js.map +1 -1
- package/build/module/lib/generator-types.d.ts +9 -1
- package/build/module/lib/pipeline.d.ts +3 -2
- package/build/module/lib/pipeline.js +5 -5
- package/build/module/lib/pipeline.js.map +1 -1
- package/build/module/lib/renderer/blur-renderer.js +21 -21
- package/build/module/lib/renderer/blur-renderer.js.map +1 -1
- package/build/module/lib/renderer/replacement-renderer.js +2 -2
- package/build/module/lib/renderer/replacement-renderer.js.map +1 -1
- package/build/module/lib/renderer/webgl-renderer.js +7 -7
- package/build/module/lib/renderer/webgl-renderer.js.map +1 -1
- package/build/module/lib/util.js +14 -14
- package/build/module/lib/util.js.map +1 -1
- package/build/module/lib/version.d.ts +1 -1
- package/build/module/lib/version.js +1 -1
- package/build/module/lib/version.js.map +1 -1
- package/build/module/lib/worker-generator.d.ts +26 -5
- package/build/module/lib/worker-generator.js +62 -58
- package/build/module/lib/worker-generator.js.map +1 -1
- package/build/module/lib/worker-manager.d.ts +60 -3
- package/build/module/lib/worker-manager.js +113 -27
- package/build/module/lib/worker-manager.js.map +1 -1
- package/build/worker/segmentation.js +253 -253
- package/build/worker/segmentation.js.map +1 -1
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### 5.6.1 (2025-05-21)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* strip query params from cached url ([#67](https://github.com/beyonddunbar/ladon-ts/issues/67)) ([32296f8](https://github.com/beyonddunbar/ladon-ts/commit/32296f84bbf4511c85b5a920136bd8c651d485e2))
|
|
11
|
+
|
|
12
|
+
## 5.6.0 (2025-05-19)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* teardown improvements ([#65](https://github.com/beyonddunbar/ladon-ts/issues/65)) ([fcc00a8](https://github.com/beyonddunbar/ladon-ts/commit/fcc00a80494724f6c75a7bf4a48434fe9644d02b))
|
|
18
|
+
|
|
5
19
|
### 5.5.1 (2025-05-06)
|
|
6
20
|
|
|
7
21
|
|
|
@@ -206,7 +206,7 @@ class a {
|
|
|
206
206
|
setMaskQuality(e) {
|
|
207
207
|
const { modelQualities: r } = s, t = this.getMaskConfig(), i = e.toLowerCase(), o = r[i];
|
|
208
208
|
if (!o)
|
|
209
|
-
throw new Error(`[ladon-ts]
|
|
209
|
+
throw new Error(`[ladon-ts] unknown quality option: ${e}`);
|
|
210
210
|
return t.qualityKey = i, Object.assign(t, o), this;
|
|
211
211
|
}
|
|
212
212
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-builder.js","sources":["../../../src/lib/config-builder.ts"],"sourcesContent":["import rawConfig from '../config.json';\n\nimport {\n AssetUrlResolver,\n BlurConfig,\n BlurStrength,\n Generator,\n InputConfig,\n MaskConfig,\n PassthroughConfig,\n PipelineConfig,\n PreloadConfig,\n Quality,\n RawConfig,\n RenderConfig,\n} from './config-types';\nimport { LIB_VERSION } from './version';\n\n/**\n * Internal mutable versions of the configurations used within the builder.\n */\ninterface MutableSizeConfig {\n height: number;\n width: number;\n}\n\ninterface MutableRenderConfig {\n type: 'blur' | 'passthrough' | 'replacement';\n horizontalMirror?: boolean;\n}\n\ninterface MutableBlurConfig extends MutableRenderConfig {\n type: 'blur';\n kernelSize: number;\n sigma: number;\n}\n\ninterface MutableReplacementConfig extends MutableRenderConfig {\n type: 'replacement';\n background: HTMLCanvasElement;\n static: boolean;\n // TODO: add reposition args for presentation mode\n}\n\ninterface MutableBaseMaskConfig {\n generator: Generator;\n generationIntervalMs: number;\n modelRank: number;\n modelUri: string;\n workerUri: string;\n inputSize?: MutableSizeConfig;\n outputSize?: MutableSizeConfig;\n upscaleSize?: MutableSizeConfig;\n}\n\ninterface MutableMaskConfig extends MutableBaseMaskConfig {\n inputSize: MutableSizeConfig;\n outputSize: MutableSizeConfig;\n upscaleSize: MutableSizeConfig;\n qualityKey?: keyof RawConfig['modelQualities'];\n}\n\ninterface MutablePipelineConfig {\n baseUrl?: string;\n wasmUri?: string;\n executionProviders?: string[];\n render?: MutableBlurConfig | MutableRenderConfig | MutableReplacementConfig;\n input?: MutableSizeConfig;\n mask?: MutableMaskConfig;\n assetUrlResolver?: AssetUrlResolver;\n}\n\n/**\n * A builder class for creating PipelineConfig instances in a flexible and intuitive way.\n */\nexport class ConfigurationBuilder {\n private config: MutablePipelineConfig = {};\n\n constructor(private env: 'int' | 'prod' = 'prod') {}\n\n /**\n * Sets the base URL for the configuration.\n * @param baseUrl The base URL to use.\n */\n public setBaseUrl(baseUrl: string): ConfigurationBuilder {\n // Remove trailing slashes from the base URL\n this.config.baseUrl = baseUrl.replace(/\\/+$/, '');\n return this;\n }\n\n /**\n * Sets the WASM URI for the configuration.\n * @param wasmUri The WASM URI to use.\n */\n public setWasmUri(wasmUri: string): ConfigurationBuilder {\n this.config.wasmUri = wasmUri;\n return this;\n }\n\n /**\n * Sets the asset URL resolver.\n * @param assetUrlResolver The asset URL resolver to use\n * @returns The current ConfigurationBuilder instance.\n */\n public setAssetUrlResolver(assetUrlResolver: AssetUrlResolver): ConfigurationBuilder {\n this.config.assetUrlResolver = assetUrlResolver;\n return this;\n }\n\n /**\n * Sets the execution providers for the ONNX runtime.\n *\n * @param executionProviders The execution providers to use.\n */\n public setExecutionProviders(executionProviders: string[]): ConfigurationBuilder {\n // Allow a single string to be passed as well. This is useful for setting a single provider.\n // This will convert the string to an array for consistency.\n if (typeof executionProviders === 'string') {\n executionProviders = [executionProviders];\n }\n this.config.executionProviders = executionProviders;\n return this;\n }\n\n /**\n * Sets the input size for the configuration.\n * @param height The height of the input.\n * @param width The width of the input.\n */\n public setInputSize(height: number, width: number): ConfigurationBuilder {\n this.config.input = { height, width };\n return this;\n }\n\n /**\n * Sets the input configuration.\n * @param inputConfig The input configuration to use.\n */\n public setInputConfig(inputConfig: InputConfig): ConfigurationBuilder {\n this.config.input = { ...inputConfig };\n return this;\n }\n\n /**\n * Sets the render configuration.\n * @param renderConfig The render configuration to use.\n */\n public setRenderConfig(renderConfig: RenderConfig): ConfigurationBuilder {\n this.config.render = { ...renderConfig } as MutableRenderConfig;\n return this;\n }\n\n /**\n * Sets the render type.\n * @param type The render type ('blur', 'passthrough', 'replacement').\n */\n public setRenderType(type: 'blur' | 'passthrough' | 'replacement'): ConfigurationBuilder {\n if (!this.config.render) {\n this.config.render = { type };\n } else {\n this.config.render.type = type;\n }\n return this;\n }\n\n /**\n * Sets the horizontal mirror property for the render configuration.\n * @param horizontalMirror Boolean indicating if horizontal mirror should be applied.\n */\n public setRenderHorizontalMirror(horizontalMirror: boolean): ConfigurationBuilder {\n if (!this.config.render) {\n throw new Error('Render config must be set before setting horizontal mirror.');\n }\n this.config.render.horizontalMirror = horizontalMirror;\n return this;\n }\n\n /**\n * Sets the blur strength for the render configuration.\n * @param blurStrength The blur strength to use.\n */\n public setBlurStrength(blurStrength: BlurStrength): ConfigurationBuilder {\n const blurConfig = ConfigurationBuilder.getBlurConfig(\n blurStrength,\n this.config.render?.horizontalMirror\n );\n this.config.render = { ...this.config.render, ...blurConfig };\n return this;\n }\n\n /**\n * Sets the blur kernel size.\n * @param kernelSize The kernel size for the blur effect.\n */\n public setBlurKernelSize(kernelSize: number): ConfigurationBuilder {\n if (!this.config.render || this.config.render.type !== 'blur') {\n throw new Error('Render config must be of type blur to set blur properties.');\n }\n (this.config.render as MutableBlurConfig).kernelSize = kernelSize;\n return this;\n }\n\n /**\n * Sets the blur sigma value.\n * @param sigma The sigma value for the blur effect.\n */\n public setBlurSigma(sigma: number): ConfigurationBuilder {\n if (!this.config.render || this.config.render.type !== 'blur') {\n throw new Error('Render config must be of type blur to set blur properties.');\n }\n (this.config.render as MutableBlurConfig).sigma = sigma;\n return this;\n }\n\n /**\n * Sets the replacement background.\n * @param background The background to use for replacement.\n */\n public setReplacementBackground(background: HTMLCanvasElement): ConfigurationBuilder {\n if (!this.config.render || this.config.render.type !== 'replacement') {\n throw new Error(\n 'Render config must be of type replacement to set replacement properties.'\n );\n }\n (this.config.render as MutableReplacementConfig).background = background;\n return this;\n }\n\n /**\n * Sets the replacement static property.\n * @param isStatic Boolean indicating if the replacement is static.\n */\n public setReplacementStatic(isStatic: boolean): ConfigurationBuilder {\n if (!this.config.render || this.config.render.type !== 'replacement') {\n throw new Error(\n 'Render config must be of type replacement to set replacement properties.'\n );\n }\n (this.config.render as MutableReplacementConfig).static = isStatic;\n return this;\n }\n\n /**\n * Sets the mask configuration.\n * @param maskConfig The mask configuration to use.\n */\n public setMaskConfig(maskConfig: MaskConfig): ConfigurationBuilder {\n this.config.mask = { ...maskConfig } as MutableMaskConfig;\n return this;\n }\n\n /**\n * Sets the mask generator.\n * @param generator The generator type (most be 'worker'; 'local' is deprecated).\n */\n public setMaskGenerator(generator: Generator): ConfigurationBuilder {\n if (generator !== 'worker') {\n console.warn('[ladon-ts] Mask generator must be \"worker\". \"local\" is deprecated.');\n }\n const mask = this.getMaskConfig();\n mask.generator = generator;\n return this;\n }\n\n /**\n * Sets the mask generation interval in milliseconds.\n * @param intervalMs The generation interval in milliseconds.\n */\n public setMaskGenerationIntervalMs(intervalMs: number): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.generationIntervalMs = intervalMs;\n return this;\n }\n\n /**\n * Sets the mask model rank.\n * @param modelRank The model rank to use.\n */\n public setMaskModelRank(modelRank: number): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.modelRank = modelRank;\n return this;\n }\n\n /**\n * Sets the mask model URI.\n * @param modelUri The model URI to use.\n */\n public setMaskModelUri(modelUri: string): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.modelUri = modelUri;\n return this;\n }\n\n /**\n * Sets the mask worker URI.\n * @param workerUri The worker URI to use.\n */\n public setMaskWorkerUri(workerUri: string): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.workerUri = workerUri;\n return this;\n }\n\n /**\n * Sets the mask input size.\n * @param height The height of the mask input.\n * @param width The width of the mask input.\n */\n public setMaskInputSize(height: number, width: number): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.inputSize = { height, width };\n return this;\n }\n\n /**\n * Sets the mask output size.\n * @param height The height of the mask output.\n * @param width The width of the mask output.\n */\n public setMaskOutputSize(height: number, width: number): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.outputSize = { height, width };\n return this;\n }\n\n /**\n * Sets the mask upscaled size.\n * @param height The height of the upscaled mask.\n * @param width The width of the upscaled mask.\n */\n public setMaskUpscaleSize(height: number, width: number): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.upscaleSize = { height, width };\n return this;\n }\n\n /**\n * Sets the quality level and updates mask configurations accordingly.\n * @param quality The desired quality level.\n */\n public setMaskQuality(quality: Quality): ConfigurationBuilder {\n const { modelQualities } = rawConfig;\n\n const mask = this.getMaskConfig();\n const qualityKey = quality.toLowerCase() as keyof RawConfig['modelQualities'];\n const qualityConfig = modelQualities[qualityKey];\n\n if (!qualityConfig) {\n throw new Error(`[ladon-ts] - unknown quality option: ${quality}`);\n }\n\n // Store the quality key for dynamic resolution later\n mask.qualityKey = qualityKey;\n\n // Copy other quality-specific properties into the mask config\n Object.assign(mask, qualityConfig);\n\n return this;\n }\n\n /**\n * Builds and returns the PreloadConfig or PipelineConfig object.\n *\n * @param requireInputConfig Whether to require the input configuration to be set before building.\n * Input size is not available at preload so this needs to be optional. The default value is true.\n *\n */\n public build(requireInputConfig = true): PipelineConfig | PreloadConfig {\n const baseUrl = this.resolveBaseUrl();\n const modelUri = this.resolveModelUri();\n const wasmUri = this.resolveWasmUri();\n const workerUri = this.resolveWorkerUri();\n\n const input = this.config.input;\n const render = this.config.render;\n const maskConfig = this.config.mask;\n const executionProviders = this.config.executionProviders;\n const assetUrlResolver = this.config.assetUrlResolver;\n\n if (!maskConfig) {\n throw new Error('Mask configuration must be set before building the configuration.');\n }\n\n const mask: MaskConfig = {\n generator: maskConfig.generator,\n generationIntervalMs: maskConfig.generationIntervalMs,\n modelRank: maskConfig.modelRank,\n inputSize: maskConfig.inputSize,\n outputSize: maskConfig.outputSize,\n upscaleSize: maskConfig.upscaleSize,\n modelUri,\n workerUri,\n };\n\n // Build the preload configuration, which is valid for both preload and pipeline.\n const preloadConfig = {\n assetUrlResolver,\n executionProviders,\n baseUrl,\n wasmUri,\n mask,\n };\n\n if (requireInputConfig) {\n if (!input) {\n throw new Error('Input must be set before building the configuration.');\n }\n\n if (!render) {\n throw new Error('Render must be set before building the configuration.');\n }\n\n // Build the full PipelineConfig\n const pipelineConfig = {\n ...preloadConfig,\n input,\n render,\n } as PipelineConfig;\n\n return pipelineConfig;\n }\n\n return preloadConfig as PreloadConfig;\n }\n\n /**\n * Returns the mask configuration, initializing it if necessary.\n */\n private getMaskConfig(): MutableMaskConfig {\n if (!this.config.mask) {\n this.config.mask = {} as MutableMaskConfig;\n }\n return this.config.mask;\n }\n\n /**\n * Returns the base URL for the configuration.\n */\n public resolveBaseUrl(): string {\n // TODO: Do we want to publish the base URL in the raw config? It seems like the models\n // auth service should be responsible for this, or the user should provide the base url.\n return this.config.baseUrl || rawConfig.baseUrls[this.env];\n }\n\n /**\n * Returns the base URL for the configuration.\n *\n * @returns The base URL for the configuration.\n */\n public resolveModelUri(): string {\n // First check if the property is explicitly set in the config, then fallback to rawConfig\n if (this.config.mask?.modelUri) {\n return this.config.mask.modelUri;\n }\n\n const mask = this.getMaskConfig();\n if (!mask.qualityKey) {\n throw new Error('[ladon-ts] No quality set, cannot infer modelFile.');\n }\n\n return this.resolveTemplate(rawConfig.modelUrlTemplate, {\n BASE_PATH_MODELS: rawConfig.basePaths.models,\n MODEL_VERSION: rawConfig.modelVersion,\n MODEL_FILE: rawConfig.modelQualities[mask.qualityKey].modelFile,\n });\n }\n\n public resolveWasmUri(): string {\n // First check if the property is explicitly set in the config, then fallback to rawConfig\n if (this.config.wasmUri) {\n return this.config.wasmUri;\n }\n\n return this.resolveTemplate(rawConfig.wasmPathTemplate, {\n BASE_PATH_WASM: rawConfig.basePaths.wasm,\n ONNX_VERSION: rawConfig.onnxVersion,\n });\n }\n\n public resolveWorkerUri(): string {\n // First check if the property is explicitly set in the config, then fallback to rawConfig\n if (this.config.mask?.workerUri) {\n return this.config.mask.workerUri;\n }\n\n return this.resolveTemplate(rawConfig.workerUrlTemplate, {\n BASE_PATH_WORKERS: rawConfig.basePaths.workers,\n LIB_VERSION: ConfigurationBuilder.getLibVersion(),\n WORKER_FILE: rawConfig.workerFile,\n });\n }\n\n /**\n * Resolves a template string with the specified values.\n *\n * @param template The template string to resolve.\n * @param values The values to use for resolution.\n * @returns The resolved template string.\n */\n private resolveTemplate(template: string, values: Record<string, string>): string {\n return template.replace(/\\$\\{([A-Z_]+)\\}/g, (_, key) => {\n if (!values[key]) {\n throw new Error(`Missing value for template variable: ${key}`);\n }\n return values[key];\n });\n }\n\n /**\n * Generates a blur configuration based on the specified blur strength.\n * @param blurStrength The desired blur strength.\n * @param horizontalMirror Whether to apply horizontal mirroring.\n */\n public static getBlurConfig(\n blurStrength: BlurStrength,\n horizontalMirror?: boolean\n ): BlurConfig {\n const strengthKey = blurStrength.toLowerCase() as keyof RawConfig['blurStrengths'];\n const blurConfig = rawConfig.blurStrengths[strengthKey];\n\n if (!blurConfig) {\n throw new Error(`[ladon-ts] Unknown blur strength: ${blurStrength}`);\n }\n\n return {\n type: 'blur',\n horizontalMirror,\n ...blurConfig,\n };\n }\n\n public static getPassthroughConfig(horizontalMirror?: boolean): PassthroughConfig {\n return {\n type: 'passthrough',\n horizontalMirror,\n };\n }\n\n /**\n * Returns the library version.\n *\n * @returns The library version.\n */\n public static getLibVersion(): string {\n return LIB_VERSION;\n }\n}\n"],"names":["ConfigurationBuilder","env","baseUrl","wasmUri","assetUrlResolver","executionProviders","height","width","inputConfig","renderConfig","type","horizontalMirror","blurStrength","blurConfig","_a","kernelSize","sigma","background","isStatic","maskConfig","generator","mask","intervalMs","modelRank","modelUri","workerUri","quality","modelQualities","rawConfig","qualityKey","qualityConfig","requireInputConfig","input","render","preloadConfig","template","values","_","key","strengthKey","LIB_VERSION"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config-builder.js","sources":["../../../src/lib/config-builder.ts"],"sourcesContent":["import rawConfig from '../config.json';\n\nimport {\n AssetUrlResolver,\n BlurConfig,\n BlurStrength,\n Generator,\n InputConfig,\n MaskConfig,\n PassthroughConfig,\n PipelineConfig,\n PreloadConfig,\n Quality,\n RawConfig,\n RenderConfig,\n} from './config-types';\nimport { LIB_VERSION } from './version';\n\n/**\n * Internal mutable versions of the configurations used within the builder.\n */\ninterface MutableSizeConfig {\n height: number;\n width: number;\n}\n\ninterface MutableRenderConfig {\n type: 'blur' | 'passthrough' | 'replacement';\n horizontalMirror?: boolean;\n}\n\ninterface MutableBlurConfig extends MutableRenderConfig {\n type: 'blur';\n kernelSize: number;\n sigma: number;\n}\n\ninterface MutableReplacementConfig extends MutableRenderConfig {\n type: 'replacement';\n background: HTMLCanvasElement;\n static: boolean;\n // TODO: add reposition args for presentation mode\n}\n\ninterface MutableBaseMaskConfig {\n generator: Generator;\n generationIntervalMs: number;\n modelRank: number;\n modelUri: string;\n workerUri: string;\n inputSize?: MutableSizeConfig;\n outputSize?: MutableSizeConfig;\n upscaleSize?: MutableSizeConfig;\n}\n\ninterface MutableMaskConfig extends MutableBaseMaskConfig {\n inputSize: MutableSizeConfig;\n outputSize: MutableSizeConfig;\n upscaleSize: MutableSizeConfig;\n qualityKey?: keyof RawConfig['modelQualities'];\n}\n\ninterface MutablePipelineConfig {\n baseUrl?: string;\n wasmUri?: string;\n executionProviders?: string[];\n render?: MutableBlurConfig | MutableRenderConfig | MutableReplacementConfig;\n input?: MutableSizeConfig;\n mask?: MutableMaskConfig;\n assetUrlResolver?: AssetUrlResolver;\n}\n\n/**\n * A builder class for creating PipelineConfig instances in a flexible and intuitive way.\n */\nexport class ConfigurationBuilder {\n private config: MutablePipelineConfig = {};\n\n constructor(private env: 'int' | 'prod' = 'prod') {}\n\n /**\n * Sets the base URL for the configuration.\n * @param baseUrl The base URL to use.\n */\n public setBaseUrl(baseUrl: string): ConfigurationBuilder {\n // Remove trailing slashes from the base URL\n this.config.baseUrl = baseUrl.replace(/\\/+$/, '');\n return this;\n }\n\n /**\n * Sets the WASM URI for the configuration.\n * @param wasmUri The WASM URI to use.\n */\n public setWasmUri(wasmUri: string): ConfigurationBuilder {\n this.config.wasmUri = wasmUri;\n return this;\n }\n\n /**\n * Sets the asset URL resolver.\n * @param assetUrlResolver The asset URL resolver to use\n * @returns The current ConfigurationBuilder instance.\n */\n public setAssetUrlResolver(assetUrlResolver: AssetUrlResolver): ConfigurationBuilder {\n this.config.assetUrlResolver = assetUrlResolver;\n return this;\n }\n\n /**\n * Sets the execution providers for the ONNX runtime.\n *\n * @param executionProviders The execution providers to use.\n */\n public setExecutionProviders(executionProviders: string[]): ConfigurationBuilder {\n // Allow a single string to be passed as well. This is useful for setting a single provider.\n // This will convert the string to an array for consistency.\n if (typeof executionProviders === 'string') {\n executionProviders = [executionProviders];\n }\n this.config.executionProviders = executionProviders;\n return this;\n }\n\n /**\n * Sets the input size for the configuration.\n * @param height The height of the input.\n * @param width The width of the input.\n */\n public setInputSize(height: number, width: number): ConfigurationBuilder {\n this.config.input = { height, width };\n return this;\n }\n\n /**\n * Sets the input configuration.\n * @param inputConfig The input configuration to use.\n */\n public setInputConfig(inputConfig: InputConfig): ConfigurationBuilder {\n this.config.input = { ...inputConfig };\n return this;\n }\n\n /**\n * Sets the render configuration.\n * @param renderConfig The render configuration to use.\n */\n public setRenderConfig(renderConfig: RenderConfig): ConfigurationBuilder {\n this.config.render = { ...renderConfig } as MutableRenderConfig;\n return this;\n }\n\n /**\n * Sets the render type.\n * @param type The render type ('blur', 'passthrough', 'replacement').\n */\n public setRenderType(type: 'blur' | 'passthrough' | 'replacement'): ConfigurationBuilder {\n if (!this.config.render) {\n this.config.render = { type };\n } else {\n this.config.render.type = type;\n }\n return this;\n }\n\n /**\n * Sets the horizontal mirror property for the render configuration.\n * @param horizontalMirror Boolean indicating if horizontal mirror should be applied.\n */\n public setRenderHorizontalMirror(horizontalMirror: boolean): ConfigurationBuilder {\n if (!this.config.render) {\n throw new Error('Render config must be set before setting horizontal mirror.');\n }\n this.config.render.horizontalMirror = horizontalMirror;\n return this;\n }\n\n /**\n * Sets the blur strength for the render configuration.\n * @param blurStrength The blur strength to use.\n */\n public setBlurStrength(blurStrength: BlurStrength): ConfigurationBuilder {\n const blurConfig = ConfigurationBuilder.getBlurConfig(\n blurStrength,\n this.config.render?.horizontalMirror\n );\n this.config.render = { ...this.config.render, ...blurConfig };\n return this;\n }\n\n /**\n * Sets the blur kernel size.\n * @param kernelSize The kernel size for the blur effect.\n */\n public setBlurKernelSize(kernelSize: number): ConfigurationBuilder {\n if (!this.config.render || this.config.render.type !== 'blur') {\n throw new Error('Render config must be of type blur to set blur properties.');\n }\n (this.config.render as MutableBlurConfig).kernelSize = kernelSize;\n return this;\n }\n\n /**\n * Sets the blur sigma value.\n * @param sigma The sigma value for the blur effect.\n */\n public setBlurSigma(sigma: number): ConfigurationBuilder {\n if (!this.config.render || this.config.render.type !== 'blur') {\n throw new Error('Render config must be of type blur to set blur properties.');\n }\n (this.config.render as MutableBlurConfig).sigma = sigma;\n return this;\n }\n\n /**\n * Sets the replacement background.\n * @param background The background to use for replacement.\n */\n public setReplacementBackground(background: HTMLCanvasElement): ConfigurationBuilder {\n if (!this.config.render || this.config.render.type !== 'replacement') {\n throw new Error(\n 'Render config must be of type replacement to set replacement properties.'\n );\n }\n (this.config.render as MutableReplacementConfig).background = background;\n return this;\n }\n\n /**\n * Sets the replacement static property.\n * @param isStatic Boolean indicating if the replacement is static.\n */\n public setReplacementStatic(isStatic: boolean): ConfigurationBuilder {\n if (!this.config.render || this.config.render.type !== 'replacement') {\n throw new Error(\n 'Render config must be of type replacement to set replacement properties.'\n );\n }\n (this.config.render as MutableReplacementConfig).static = isStatic;\n return this;\n }\n\n /**\n * Sets the mask configuration.\n * @param maskConfig The mask configuration to use.\n */\n public setMaskConfig(maskConfig: MaskConfig): ConfigurationBuilder {\n this.config.mask = { ...maskConfig } as MutableMaskConfig;\n return this;\n }\n\n /**\n * Sets the mask generator.\n * @param generator The generator type (most be 'worker'; 'local' is deprecated).\n */\n public setMaskGenerator(generator: Generator): ConfigurationBuilder {\n if (generator !== 'worker') {\n console.warn('[ladon-ts] Mask generator must be \"worker\". \"local\" is deprecated.');\n }\n const mask = this.getMaskConfig();\n mask.generator = generator;\n return this;\n }\n\n /**\n * Sets the mask generation interval in milliseconds.\n * @param intervalMs The generation interval in milliseconds.\n */\n public setMaskGenerationIntervalMs(intervalMs: number): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.generationIntervalMs = intervalMs;\n return this;\n }\n\n /**\n * Sets the mask model rank.\n * @param modelRank The model rank to use.\n */\n public setMaskModelRank(modelRank: number): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.modelRank = modelRank;\n return this;\n }\n\n /**\n * Sets the mask model URI.\n * @param modelUri The model URI to use.\n */\n public setMaskModelUri(modelUri: string): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.modelUri = modelUri;\n return this;\n }\n\n /**\n * Sets the mask worker URI.\n * @param workerUri The worker URI to use.\n */\n public setMaskWorkerUri(workerUri: string): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.workerUri = workerUri;\n return this;\n }\n\n /**\n * Sets the mask input size.\n * @param height The height of the mask input.\n * @param width The width of the mask input.\n */\n public setMaskInputSize(height: number, width: number): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.inputSize = { height, width };\n return this;\n }\n\n /**\n * Sets the mask output size.\n * @param height The height of the mask output.\n * @param width The width of the mask output.\n */\n public setMaskOutputSize(height: number, width: number): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.outputSize = { height, width };\n return this;\n }\n\n /**\n * Sets the mask upscaled size.\n * @param height The height of the upscaled mask.\n * @param width The width of the upscaled mask.\n */\n public setMaskUpscaleSize(height: number, width: number): ConfigurationBuilder {\n const mask = this.getMaskConfig();\n mask.upscaleSize = { height, width };\n return this;\n }\n\n /**\n * Sets the quality level and updates mask configurations accordingly.\n * @param quality The desired quality level.\n */\n public setMaskQuality(quality: Quality): ConfigurationBuilder {\n const { modelQualities } = rawConfig;\n\n const mask = this.getMaskConfig();\n const qualityKey = quality.toLowerCase() as keyof RawConfig['modelQualities'];\n const qualityConfig = modelQualities[qualityKey];\n\n if (!qualityConfig) {\n throw new Error(`[ladon-ts] unknown quality option: ${quality}`);\n }\n\n // Store the quality key for dynamic resolution later\n mask.qualityKey = qualityKey;\n\n // Copy other quality-specific properties into the mask config\n Object.assign(mask, qualityConfig);\n\n return this;\n }\n\n /**\n * Builds and returns the PreloadConfig or PipelineConfig object.\n *\n * @param requireInputConfig Whether to require the input configuration to be set before building.\n * Input size is not available at preload so this needs to be optional. The default value is true.\n *\n */\n public build(requireInputConfig = true): PipelineConfig | PreloadConfig {\n const baseUrl = this.resolveBaseUrl();\n const modelUri = this.resolveModelUri();\n const wasmUri = this.resolveWasmUri();\n const workerUri = this.resolveWorkerUri();\n\n const input = this.config.input;\n const render = this.config.render;\n const maskConfig = this.config.mask;\n const executionProviders = this.config.executionProviders;\n const assetUrlResolver = this.config.assetUrlResolver;\n\n if (!maskConfig) {\n throw new Error('Mask configuration must be set before building the configuration.');\n }\n\n const mask: MaskConfig = {\n generator: maskConfig.generator,\n generationIntervalMs: maskConfig.generationIntervalMs,\n modelRank: maskConfig.modelRank,\n inputSize: maskConfig.inputSize,\n outputSize: maskConfig.outputSize,\n upscaleSize: maskConfig.upscaleSize,\n modelUri,\n workerUri,\n };\n\n // Build the preload configuration, which is valid for both preload and pipeline.\n const preloadConfig = {\n assetUrlResolver,\n executionProviders,\n baseUrl,\n wasmUri,\n mask,\n };\n\n if (requireInputConfig) {\n if (!input) {\n throw new Error('Input must be set before building the configuration.');\n }\n\n if (!render) {\n throw new Error('Render must be set before building the configuration.');\n }\n\n // Build the full PipelineConfig\n const pipelineConfig = {\n ...preloadConfig,\n input,\n render,\n } as PipelineConfig;\n\n return pipelineConfig;\n }\n\n return preloadConfig as PreloadConfig;\n }\n\n /**\n * Returns the mask configuration, initializing it if necessary.\n */\n private getMaskConfig(): MutableMaskConfig {\n if (!this.config.mask) {\n this.config.mask = {} as MutableMaskConfig;\n }\n return this.config.mask;\n }\n\n /**\n * Returns the base URL for the configuration.\n */\n public resolveBaseUrl(): string {\n // TODO: Do we want to publish the base URL in the raw config? It seems like the models\n // auth service should be responsible for this, or the user should provide the base url.\n return this.config.baseUrl || rawConfig.baseUrls[this.env];\n }\n\n /**\n * Returns the base URL for the configuration.\n *\n * @returns The base URL for the configuration.\n */\n public resolveModelUri(): string {\n // First check if the property is explicitly set in the config, then fallback to rawConfig\n if (this.config.mask?.modelUri) {\n return this.config.mask.modelUri;\n }\n\n const mask = this.getMaskConfig();\n if (!mask.qualityKey) {\n throw new Error('[ladon-ts] No quality set, cannot infer modelFile.');\n }\n\n return this.resolveTemplate(rawConfig.modelUrlTemplate, {\n BASE_PATH_MODELS: rawConfig.basePaths.models,\n MODEL_VERSION: rawConfig.modelVersion,\n MODEL_FILE: rawConfig.modelQualities[mask.qualityKey].modelFile,\n });\n }\n\n public resolveWasmUri(): string {\n // First check if the property is explicitly set in the config, then fallback to rawConfig\n if (this.config.wasmUri) {\n return this.config.wasmUri;\n }\n\n return this.resolveTemplate(rawConfig.wasmPathTemplate, {\n BASE_PATH_WASM: rawConfig.basePaths.wasm,\n ONNX_VERSION: rawConfig.onnxVersion,\n });\n }\n\n public resolveWorkerUri(): string {\n // First check if the property is explicitly set in the config, then fallback to rawConfig\n if (this.config.mask?.workerUri) {\n return this.config.mask.workerUri;\n }\n\n return this.resolveTemplate(rawConfig.workerUrlTemplate, {\n BASE_PATH_WORKERS: rawConfig.basePaths.workers,\n LIB_VERSION: ConfigurationBuilder.getLibVersion(),\n WORKER_FILE: rawConfig.workerFile,\n });\n }\n\n /**\n * Resolves a template string with the specified values.\n *\n * @param template The template string to resolve.\n * @param values The values to use for resolution.\n * @returns The resolved template string.\n */\n private resolveTemplate(template: string, values: Record<string, string>): string {\n return template.replace(/\\$\\{([A-Z_]+)\\}/g, (_, key) => {\n if (!values[key]) {\n throw new Error(`Missing value for template variable: ${key}`);\n }\n return values[key];\n });\n }\n\n /**\n * Generates a blur configuration based on the specified blur strength.\n * @param blurStrength The desired blur strength.\n * @param horizontalMirror Whether to apply horizontal mirroring.\n */\n public static getBlurConfig(\n blurStrength: BlurStrength,\n horizontalMirror?: boolean\n ): BlurConfig {\n const strengthKey = blurStrength.toLowerCase() as keyof RawConfig['blurStrengths'];\n const blurConfig = rawConfig.blurStrengths[strengthKey];\n\n if (!blurConfig) {\n throw new Error(`[ladon-ts] Unknown blur strength: ${blurStrength}`);\n }\n\n return {\n type: 'blur',\n horizontalMirror,\n ...blurConfig,\n };\n }\n\n public static getPassthroughConfig(horizontalMirror?: boolean): PassthroughConfig {\n return {\n type: 'passthrough',\n horizontalMirror,\n };\n }\n\n /**\n * Returns the library version.\n *\n * @returns The library version.\n */\n public static getLibVersion(): string {\n return LIB_VERSION;\n }\n}\n"],"names":["ConfigurationBuilder","env","baseUrl","wasmUri","assetUrlResolver","executionProviders","height","width","inputConfig","renderConfig","type","horizontalMirror","blurStrength","blurConfig","_a","kernelSize","sigma","background","isStatic","maskConfig","generator","mask","intervalMs","modelRank","modelUri","workerUri","quality","modelQualities","rawConfig","qualityKey","qualityConfig","requireInputConfig","input","render","preloadConfig","template","values","_","key","strengthKey","LIB_VERSION"],"mappings":"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"}
|
|
@@ -16,10 +16,18 @@ export interface LadonOutput {
|
|
|
16
16
|
timestamp: number;
|
|
17
17
|
warm: boolean;
|
|
18
18
|
}
|
|
19
|
+
export interface WorkerGeneratedResult {
|
|
20
|
+
facesAndLandmarks: FacesAndLandmarks;
|
|
21
|
+
gesture: Float32Array;
|
|
22
|
+
mask: Float32Array;
|
|
23
|
+
motion: number;
|
|
24
|
+
timestamp: number;
|
|
25
|
+
status: string;
|
|
26
|
+
}
|
|
19
27
|
export interface MaskGenerator {
|
|
20
28
|
getLadonOutput(input: Uint8ClampedArray, timestamp: number): Promise<LadonOutput>;
|
|
21
29
|
load(): Promise<void>;
|
|
22
30
|
isLoaded(): boolean;
|
|
23
31
|
postRender(input: Uint8ClampedArray, timestamp: number): Promise<void>;
|
|
24
|
-
destroy(): void
|
|
32
|
+
destroy(): Promise<void>;
|
|
25
33
|
}
|
|
@@ -11,7 +11,8 @@ export interface IPipeline {
|
|
|
11
11
|
onFrame(timestamp: number, maskNeeded?: boolean): Promise<IFrameInferenceResult>;
|
|
12
12
|
isLoaded(): boolean;
|
|
13
13
|
load(): Promise<void>;
|
|
14
|
-
destroy(): void
|
|
14
|
+
destroy(): Promise<void>;
|
|
15
|
+
reset(): void;
|
|
15
16
|
}
|
|
16
17
|
export declare class Pipeline implements IPipeline {
|
|
17
18
|
private inputCanvas;
|
|
@@ -81,5 +82,5 @@ export declare class Pipeline implements IPipeline {
|
|
|
81
82
|
/**
|
|
82
83
|
* Destroys the pipeline and cleans up resources.
|
|
83
84
|
*/
|
|
84
|
-
destroy(): void
|
|
85
|
+
destroy(): Promise<void>;
|
|
85
86
|
}
|
|
@@ -11,7 +11,7 @@ class k {
|
|
|
11
11
|
willReadFrequently: !0
|
|
12
12
|
});
|
|
13
13
|
if (!a)
|
|
14
|
-
throw new Error("[ladon-ts]
|
|
14
|
+
throw new Error("[ladon-ts] Error getting input context 2d");
|
|
15
15
|
this.inputCanvasCtx = a;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
@@ -24,7 +24,7 @@ class k {
|
|
|
24
24
|
*/
|
|
25
25
|
async onFrame(e, t = !0) {
|
|
26
26
|
if (!this.generator || !this.renderer)
|
|
27
|
-
throw new Error("[ladon-ts]
|
|
27
|
+
throw new Error("[ladon-ts] Pipeline is not loaded.");
|
|
28
28
|
const s = this.getInputFrameData(t);
|
|
29
29
|
if (s instanceof Uint8ClampedArray ? ((!this.frameDataBuffer || this.frameDataBuffer.length !== s.length) && (this.frameDataBuffer = new Uint8ClampedArray(s.length)), this.frameDataBuffer.set(s), this.frameQueue.push({ timestamp: e, frameData: this.frameDataBuffer })) : this.frameQueue.push({ timestamp: e, frameData: s }), t || !this.lastMaskResult) {
|
|
30
30
|
const r = s, a = this.getMaskImageData(r), i = await this.generator.getLadonOutput(a, e);
|
|
@@ -119,7 +119,7 @@ class k {
|
|
|
119
119
|
this.renderer = new o(this.outputCanvas, this.config);
|
|
120
120
|
break;
|
|
121
121
|
default:
|
|
122
|
-
throw new Error("[ladon-ts]
|
|
122
|
+
throw new Error("[ladon-ts] Renderer not implemented.");
|
|
123
123
|
}
|
|
124
124
|
await this.renderer.load(), this.generator = new n(this.config), await this.generator.load(), this.loaded = !0;
|
|
125
125
|
}
|
|
@@ -135,9 +135,9 @@ class k {
|
|
|
135
135
|
/**
|
|
136
136
|
* Destroys the pipeline and cleans up resources.
|
|
137
137
|
*/
|
|
138
|
-
destroy() {
|
|
138
|
+
async destroy() {
|
|
139
139
|
var e, t;
|
|
140
|
-
this.reset(), (e = this.
|
|
140
|
+
this.reset(), (e = this.renderer) == null || e.destroy(), await ((t = this.generator) == null ? void 0 : t.destroy()), this.frameDataBuffer = void 0, this.loaded = !1;
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
export {
|
|
@@ -1 +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 MaskGenerator,\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(timestamp: number, maskNeeded?: boolean): 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 private frameDataBuffer?: Uint8ClampedArray;\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 - 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 // Reuse or create buffer for frame data copies, which is needed to ensure the data is not modified\n // or garbage collected before the inference is done.\n if (frameData instanceof Uint8ClampedArray) {\n if (!this.frameDataBuffer || this.frameDataBuffer.length !== frameData.length) {\n this.frameDataBuffer = new Uint8ClampedArray(frameData.length);\n }\n this.frameDataBuffer.set(frameData);\n this.frameQueue.push({ timestamp, frameData: this.frameDataBuffer });\n } else {\n // For video elements, just pass the reference\n this.frameQueue.push({ timestamp, frameData });\n }\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 const modelInput = this.config.mask.inputSize;\n const inputImage = this.config.input;\n\n // Check if resizing is needed based on configuration.\n if (modelInput.width === inputImage.width && modelInput.height === inputImage.height) {\n return rawImageData;\n }\n\n // Resize the image data.\n return resizeImage(\n rawImageData,\n inputImage.width,\n inputImage.height,\n modelInput.width,\n modelInput.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 this.generator = new WorkerGenerator(this.config);\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 this.frameDataBuffer = undefined;\n }\n}\n"],"names":["Pipeline","inputCanvas","outputCanvas","config","videoElement","inputCanvasCtx","timestamp","performInference","frameData","rawImageData","maskImageData","maskResult","frame","maskEntry","_a","needFreshImageData","modelInput","inputImage","resizeImage","performedInference","BlurRenderer","PassthroughRenderer","ReplacementRenderer","WorkerGenerator","_b"],"mappings":"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"}
|
|
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 MaskGenerator,\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(timestamp: number, maskNeeded?: boolean): Promise<IFrameInferenceResult>;\n isLoaded(): boolean;\n load(): Promise<void>;\n destroy(): Promise<void>;\n reset(): 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 private frameDataBuffer?: Uint8ClampedArray;\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 - 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 // Reuse or create buffer for frame data copies, which is needed to ensure the data is not modified\n // or garbage collected before the inference is done.\n if (frameData instanceof Uint8ClampedArray) {\n if (!this.frameDataBuffer || this.frameDataBuffer.length !== frameData.length) {\n this.frameDataBuffer = new Uint8ClampedArray(frameData.length);\n }\n this.frameDataBuffer.set(frameData);\n this.frameQueue.push({ timestamp, frameData: this.frameDataBuffer });\n } else {\n // For video elements, just pass the reference\n this.frameQueue.push({ timestamp, frameData });\n }\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 const modelInput = this.config.mask.inputSize;\n const inputImage = this.config.input;\n\n // Check if resizing is needed based on configuration.\n if (modelInput.width === inputImage.width && modelInput.height === inputImage.height) {\n return rawImageData;\n }\n\n // Resize the image data.\n return resizeImage(\n rawImageData,\n inputImage.width,\n inputImage.height,\n modelInput.width,\n modelInput.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 this.generator = new WorkerGenerator(this.config);\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 async destroy(): Promise<void> {\n this.reset();\n this.renderer?.destroy();\n await this.generator?.destroy();\n this.frameDataBuffer = undefined;\n this.loaded = false;\n }\n}\n"],"names":["Pipeline","inputCanvas","outputCanvas","config","videoElement","inputCanvasCtx","timestamp","performInference","frameData","rawImageData","maskImageData","maskResult","frame","maskEntry","_a","needFreshImageData","modelInput","inputImage","resizeImage","performedInference","BlurRenderer","PassthroughRenderer","ReplacementRenderer","WorkerGenerator","_b"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { compileShader as o, linkProgram as h } from "../util.js";
|
|
2
2
|
import { WebGLRenderer as a } from "./webgl-renderer.js";
|
|
3
3
|
class _ extends a {
|
|
4
|
-
constructor(
|
|
5
|
-
if (super(
|
|
4
|
+
constructor(e, i) {
|
|
5
|
+
if (super(e, i), this.output_canvas = e, this.config = i, this.fragment_shader_common = `#version 300 es
|
|
6
6
|
precision highp float;
|
|
7
7
|
|
|
8
8
|
#define KERNEL_SIZE ${this.config.render.kernelSize}
|
|
@@ -64,9 +64,9 @@ void main() {
|
|
|
64
64
|
outColor = vec4(color, 1.0);
|
|
65
65
|
}
|
|
66
66
|
`, this.config.render.kernelSize % 2 === 0)
|
|
67
|
-
throw new Error("[ladon-ts]
|
|
67
|
+
throw new Error("[ladon-ts] Kernel_size must be odd");
|
|
68
68
|
{
|
|
69
|
-
const
|
|
69
|
+
const r = o(
|
|
70
70
|
this.gl,
|
|
71
71
|
this.gl.VERTEX_SHADER,
|
|
72
72
|
this.vertex_shader_src
|
|
@@ -75,14 +75,14 @@ void main() {
|
|
|
75
75
|
this.gl.FRAGMENT_SHADER,
|
|
76
76
|
this.fragment_shader_pass_1_src
|
|
77
77
|
);
|
|
78
|
-
this.program_1 = h(this.gl,
|
|
78
|
+
this.program_1 = h(this.gl, r, t), this.gl.useProgram(this.program_1);
|
|
79
79
|
const s = this.gl.createFramebuffer();
|
|
80
80
|
if (!s)
|
|
81
|
-
throw new Error("[ladon-ts]
|
|
81
|
+
throw new Error("[ladon-ts] Error creating framebuffer");
|
|
82
82
|
this.framebuffer = s;
|
|
83
83
|
const n = this.gl.createTexture();
|
|
84
84
|
if (!n)
|
|
85
|
-
throw new Error("[ladon-ts]
|
|
85
|
+
throw new Error("[ladon-ts] Error creating output texture");
|
|
86
86
|
this.transfer_texture = n, this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.framebuffer), this.gl.bindTexture(this.gl.TEXTURE_2D, this.transfer_texture), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR), this.gl.texParameteri(
|
|
87
87
|
this.gl.TEXTURE_2D,
|
|
88
88
|
this.gl.TEXTURE_WRAP_S,
|
|
@@ -110,11 +110,11 @@ void main() {
|
|
|
110
110
|
), this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null), this.setSharedUniforms(this.program_1);
|
|
111
111
|
const l = this.gl.getUniformLocation(this.program_1, "u_kernel");
|
|
112
112
|
if (!l)
|
|
113
|
-
throw new Error('[ladon-ts]
|
|
113
|
+
throw new Error('[ladon-ts] Error finding "u_kernel" uniform');
|
|
114
114
|
this.gl.uniform1fv(l, this.getBlurKernel());
|
|
115
115
|
}
|
|
116
116
|
{
|
|
117
|
-
const
|
|
117
|
+
const r = o(
|
|
118
118
|
this.gl,
|
|
119
119
|
this.gl.VERTEX_SHADER,
|
|
120
120
|
this.vertex_shader_src
|
|
@@ -123,34 +123,34 @@ void main() {
|
|
|
123
123
|
this.gl.FRAGMENT_SHADER,
|
|
124
124
|
this.fragment_shader_pass_2_src
|
|
125
125
|
);
|
|
126
|
-
this.program_2 = h(this.gl,
|
|
126
|
+
this.program_2 = h(this.gl, r, t), this.gl.useProgram(this.program_2);
|
|
127
127
|
const s = this.gl.getUniformLocation(this.program_2, "u_blur");
|
|
128
128
|
if (!s)
|
|
129
|
-
throw new Error('[ladon-ts]
|
|
129
|
+
throw new Error('[ladon-ts] Error finding "u_blur" uniform');
|
|
130
130
|
this.u_blur = s, this.gl.activeTexture(this.gl.TEXTURE2), this.gl.bindTexture(this.gl.TEXTURE_2D, this.transfer_texture), this.gl.uniform1i(this.u_blur, 2), this.setSharedUniforms(this.program_2);
|
|
131
131
|
const n = this.gl.getUniformLocation(this.program_2, "u_kernel");
|
|
132
132
|
if (!n)
|
|
133
|
-
throw new Error('[ladon-ts]
|
|
133
|
+
throw new Error('[ladon-ts] Error finding "u_kernel" uniform');
|
|
134
134
|
this.gl.uniform1fv(n, this.getBlurKernel());
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
|
-
async render(
|
|
138
|
-
this.uploadVideoStream(
|
|
137
|
+
async render(e, i) {
|
|
138
|
+
this.uploadVideoStream(e), this.uploadMask(i), this.gl.useProgram(this.program_1), this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.framebuffer), this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length / 3), this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null), this.gl.useProgram(this.program_2), this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length / 3), this.postDraw();
|
|
139
139
|
}
|
|
140
140
|
async load() {
|
|
141
141
|
}
|
|
142
142
|
destroy() {
|
|
143
143
|
}
|
|
144
144
|
getBlurKernel() {
|
|
145
|
-
const
|
|
145
|
+
const e = [];
|
|
146
146
|
let i = 0;
|
|
147
|
-
for (let
|
|
148
|
-
let t =
|
|
149
|
-
t = Math.exp(-(t ** 2) / this.config.render.sigma ** 2),
|
|
147
|
+
for (let r = 0; r < this.config.render.kernelSize; r++) {
|
|
148
|
+
let t = r - (this.config.render.kernelSize - 1) / 2;
|
|
149
|
+
t = Math.exp(-(t ** 2) / this.config.render.sigma ** 2), e.push(t), i += t;
|
|
150
150
|
}
|
|
151
|
-
for (let
|
|
152
|
-
r
|
|
153
|
-
return new Float32Array(
|
|
151
|
+
for (let r = 0; r < this.config.render.kernelSize; r++)
|
|
152
|
+
e[r] = e[r] / i;
|
|
153
|
+
return new Float32Array(e);
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blur-renderer.js","sources":["../../../../src/lib/renderer/blur-renderer.ts"],"sourcesContent":["import { BlurConfig, PipelineConfig } from '../config-types';\nimport { FrameData, LadonOutput } from '../generator';\nimport { compileShader, linkProgram } from '../util';\n\nimport { LadonRenderer } from './ladon-renderer';\nimport { WebGLRenderer } from './webgl-renderer';\n\nexport class BlurRenderer extends WebGLRenderer implements LadonRenderer {\n private program_1: WebGLProgram;\n private program_2: WebGLProgram;\n\n private framebuffer: WebGLFramebuffer;\n private transfer_texture: WebGLTexture;\n\n private u_blur: WebGLUniformLocation;\n\n private fragment_shader_common = `#version 300 es\nprecision highp float;\n\n#define KERNEL_SIZE ${(this.config.render as BlurConfig).kernelSize}\n#define HORIZONTAL vec2(1.0, 0.0)\n#define VERTICAL vec2(0.0, 1.0)\n\nout vec4 outColor;\n\nuniform sampler2D u_image;\nuniform sampler2D u_mask;\nuniform vec2 u_resolution;\nuniform float u_kernel[KERNEL_SIZE];\n\n// Function to retrieve the mask value\nfloat get_mask(vec2 st) {\n return texture(u_mask, st).r;\n}\n\n// Get the inverse of the masked area\nfloat get_inv_mask(vec2 st) {\n return 1.0 - get_mask(st);\n}\n\n// Blurring function\nvec3 blur(sampler2D src, vec2 uv, vec2 direction) {\n vec4 accum = vec4(0.0);\n vec2 step = direction / u_resolution;\n int offset = (KERNEL_SIZE - 1) / 2;\n\n float weightSum = 0.0;\n for (int i = 0; i < KERNEL_SIZE; i++) {\n vec2 sampleUV = uv + step * float(i - offset);\n vec4 sampleTex = texture(src, sampleUV);\n float weight = u_kernel[i];\n accum += sampleTex * weight;\n weightSum += weight;\n }\n\n weightSum = max(weightSum, 0.001); // Avoid division by zero\n return accum.rgb / weightSum;\n}\n`;\n\n private fragment_shader_pass_1_src =\n this.fragment_shader_common +\n `\nvoid main() {\n vec2 st = gl_FragCoord.xy / u_resolution;\n outColor = vec4(blur(u_image, st, HORIZONTAL), 1.0);\n}\n`;\n\n public fragment_shader_pass_2_src =\n this.fragment_shader_common +\n `\nuniform sampler2D u_blur;\n\nvoid main() {\n ${this.getUVCalculation()};\n\n vec3 blurred = blur(u_blur, st, VERTICAL);\n vec3 original = texture(u_image, st).rgb;\n float mask = get_inv_mask(st); // Use inverse mask to blur background, not user\n\n // Correct blending based on the mask\n vec3 color = mix(original, blurred, mask); // Ensure mask properly determines blur influence on background\n outColor = vec4(color, 1.0);\n}\n`;\n\n constructor(public output_canvas: HTMLCanvasElement, public readonly config: PipelineConfig) {\n super(output_canvas, config);\n\n if ((this.config.render as BlurConfig).kernelSize % 2 === 0) {\n throw new Error('[ladon-ts] - kernel_size must be odd');\n }\n\n // program pass 1 setup\n {\n const vertex_shader = compileShader(\n this.gl,\n this.gl.VERTEX_SHADER,\n this.vertex_shader_src\n );\n const fragment_shader = compileShader(\n this.gl,\n this.gl.FRAGMENT_SHADER,\n this.fragment_shader_pass_1_src\n );\n\n this.program_1 = linkProgram(this.gl, vertex_shader, fragment_shader);\n this.gl.useProgram(this.program_1);\n\n const framebuffer = this.gl.createFramebuffer();\n if (!framebuffer) {\n throw new Error('[ladon-ts] - error creating framebuffer');\n }\n this.framebuffer = framebuffer;\n\n const transfer_texture = this.gl.createTexture();\n if (!transfer_texture) {\n throw new Error('[ladon-ts] - error creating output texture');\n }\n this.transfer_texture = transfer_texture;\n\n this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.framebuffer);\n this.gl.bindTexture(this.gl.TEXTURE_2D, this.transfer_texture);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n this.gl.texParameteri(\n this.gl.TEXTURE_2D,\n this.gl.TEXTURE_WRAP_S,\n this.gl.CLAMP_TO_EDGE\n );\n this.gl.texParameteri(\n this.gl.TEXTURE_2D,\n this.gl.TEXTURE_WRAP_T,\n this.gl.CLAMP_TO_EDGE\n );\n this.gl.texImage2D(\n this.gl.TEXTURE_2D,\n 0,\n this.gl.RGBA,\n this.config.input.width,\n this.config.input.height,\n 0,\n this.gl.RGBA,\n this.gl.UNSIGNED_BYTE,\n null\n );\n this.gl.framebufferTexture2D(\n this.gl.FRAMEBUFFER,\n this.gl.COLOR_ATTACHMENT0,\n this.gl.TEXTURE_2D,\n this.transfer_texture,\n 0\n );\n this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);\n\n this.setSharedUniforms(this.program_1);\n\n const u_kernel = this.gl.getUniformLocation(this.program_1, 'u_kernel');\n if (!u_kernel) {\n throw new Error('[ladon-ts] - error finding \"u_kernel\" uniform');\n }\n this.gl.uniform1fv(u_kernel, this.getBlurKernel());\n }\n\n // program pass 2 setup\n {\n const vertex_shader = compileShader(\n this.gl,\n this.gl.VERTEX_SHADER,\n this.vertex_shader_src\n );\n const fragment_shader = compileShader(\n this.gl,\n this.gl.FRAGMENT_SHADER,\n this.fragment_shader_pass_2_src\n );\n\n this.program_2 = linkProgram(this.gl, vertex_shader, fragment_shader);\n this.gl.useProgram(this.program_2);\n\n const u_blur = this.gl.getUniformLocation(this.program_2, 'u_blur');\n if (!u_blur) {\n throw new Error('[ladon-ts] - error finding \"u_blur\" uniform');\n }\n this.u_blur = u_blur;\n this.gl.activeTexture(this.gl.TEXTURE2);\n this.gl.bindTexture(this.gl.TEXTURE_2D, this.transfer_texture);\n this.gl.uniform1i(this.u_blur, 2);\n\n this.setSharedUniforms(this.program_2);\n\n const u_kernel = this.gl.getUniformLocation(this.program_2, 'u_kernel');\n if (!u_kernel) {\n throw new Error('[ladon-ts] - error finding \"u_kernel\" uniform');\n }\n this.gl.uniform1fv(u_kernel, this.getBlurKernel());\n }\n }\n\n public async render(input: FrameData, mask?: LadonOutput): Promise<void> {\n this.uploadVideoStream(input);\n this.uploadMask(mask);\n\n // program pass 1 - blur in one direction & output to framebuffer\n this.gl.useProgram(this.program_1);\n\n this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.framebuffer);\n this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length / 3);\n this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);\n\n // program pass 2 - blur in other direction & draw to screen\n this.gl.useProgram(this.program_2);\n this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length / 3);\n\n this.postDraw();\n }\n\n public async load(): Promise<void> {\n // empty\n }\n\n public destroy(): void {\n // empty\n }\n\n private getBlurKernel(): Float32Array {\n const kernel = [];\n let sum = 0;\n for (let i = 0; i < (this.config.render as BlurConfig).kernelSize; i++) {\n let w = i - ((this.config.render as BlurConfig).kernelSize - 1) / 2;\n w = Math.exp(-(w ** 2) / (this.config.render as BlurConfig).sigma ** 2);\n kernel.push(w);\n sum += w;\n }\n\n for (let i = 0; i < (this.config.render as BlurConfig).kernelSize; i++) {\n kernel[i] = kernel[i] / sum;\n }\n\n return new Float32Array(kernel);\n }\n}\n"],"names":["BlurRenderer","WebGLRenderer","output_canvas","config","vertex_shader","compileShader","fragment_shader","linkProgram","framebuffer","transfer_texture","u_kernel","u_blur","input","mask","kernel","sum","i","w"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"blur-renderer.js","sources":["../../../../src/lib/renderer/blur-renderer.ts"],"sourcesContent":["import { BlurConfig, PipelineConfig } from '../config-types';\nimport { FrameData, LadonOutput } from '../generator';\nimport { compileShader, linkProgram } from '../util';\n\nimport { LadonRenderer } from './ladon-renderer';\nimport { WebGLRenderer } from './webgl-renderer';\n\nexport class BlurRenderer extends WebGLRenderer implements LadonRenderer {\n private program_1: WebGLProgram;\n private program_2: WebGLProgram;\n\n private framebuffer: WebGLFramebuffer;\n private transfer_texture: WebGLTexture;\n\n private u_blur: WebGLUniformLocation;\n\n private fragment_shader_common = `#version 300 es\nprecision highp float;\n\n#define KERNEL_SIZE ${(this.config.render as BlurConfig).kernelSize}\n#define HORIZONTAL vec2(1.0, 0.0)\n#define VERTICAL vec2(0.0, 1.0)\n\nout vec4 outColor;\n\nuniform sampler2D u_image;\nuniform sampler2D u_mask;\nuniform vec2 u_resolution;\nuniform float u_kernel[KERNEL_SIZE];\n\n// Function to retrieve the mask value\nfloat get_mask(vec2 st) {\n return texture(u_mask, st).r;\n}\n\n// Get the inverse of the masked area\nfloat get_inv_mask(vec2 st) {\n return 1.0 - get_mask(st);\n}\n\n// Blurring function\nvec3 blur(sampler2D src, vec2 uv, vec2 direction) {\n vec4 accum = vec4(0.0);\n vec2 step = direction / u_resolution;\n int offset = (KERNEL_SIZE - 1) / 2;\n\n float weightSum = 0.0;\n for (int i = 0; i < KERNEL_SIZE; i++) {\n vec2 sampleUV = uv + step * float(i - offset);\n vec4 sampleTex = texture(src, sampleUV);\n float weight = u_kernel[i];\n accum += sampleTex * weight;\n weightSum += weight;\n }\n\n weightSum = max(weightSum, 0.001); // Avoid division by zero\n return accum.rgb / weightSum;\n}\n`;\n\n private fragment_shader_pass_1_src =\n this.fragment_shader_common +\n `\nvoid main() {\n vec2 st = gl_FragCoord.xy / u_resolution;\n outColor = vec4(blur(u_image, st, HORIZONTAL), 1.0);\n}\n`;\n\n public fragment_shader_pass_2_src =\n this.fragment_shader_common +\n `\nuniform sampler2D u_blur;\n\nvoid main() {\n ${this.getUVCalculation()};\n\n vec3 blurred = blur(u_blur, st, VERTICAL);\n vec3 original = texture(u_image, st).rgb;\n float mask = get_inv_mask(st); // Use inverse mask to blur background, not user\n\n // Correct blending based on the mask\n vec3 color = mix(original, blurred, mask); // Ensure mask properly determines blur influence on background\n outColor = vec4(color, 1.0);\n}\n`;\n\n constructor(public output_canvas: HTMLCanvasElement, public readonly config: PipelineConfig) {\n super(output_canvas, config);\n\n if ((this.config.render as BlurConfig).kernelSize % 2 === 0) {\n throw new Error('[ladon-ts] Kernel_size must be odd');\n }\n\n // program pass 1 setup\n {\n const vertex_shader = compileShader(\n this.gl,\n this.gl.VERTEX_SHADER,\n this.vertex_shader_src\n );\n const fragment_shader = compileShader(\n this.gl,\n this.gl.FRAGMENT_SHADER,\n this.fragment_shader_pass_1_src\n );\n\n this.program_1 = linkProgram(this.gl, vertex_shader, fragment_shader);\n this.gl.useProgram(this.program_1);\n\n const framebuffer = this.gl.createFramebuffer();\n if (!framebuffer) {\n throw new Error('[ladon-ts] Error creating framebuffer');\n }\n this.framebuffer = framebuffer;\n\n const transfer_texture = this.gl.createTexture();\n if (!transfer_texture) {\n throw new Error('[ladon-ts] Error creating output texture');\n }\n this.transfer_texture = transfer_texture;\n\n this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.framebuffer);\n this.gl.bindTexture(this.gl.TEXTURE_2D, this.transfer_texture);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n this.gl.texParameteri(\n this.gl.TEXTURE_2D,\n this.gl.TEXTURE_WRAP_S,\n this.gl.CLAMP_TO_EDGE\n );\n this.gl.texParameteri(\n this.gl.TEXTURE_2D,\n this.gl.TEXTURE_WRAP_T,\n this.gl.CLAMP_TO_EDGE\n );\n this.gl.texImage2D(\n this.gl.TEXTURE_2D,\n 0,\n this.gl.RGBA,\n this.config.input.width,\n this.config.input.height,\n 0,\n this.gl.RGBA,\n this.gl.UNSIGNED_BYTE,\n null\n );\n this.gl.framebufferTexture2D(\n this.gl.FRAMEBUFFER,\n this.gl.COLOR_ATTACHMENT0,\n this.gl.TEXTURE_2D,\n this.transfer_texture,\n 0\n );\n this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);\n\n this.setSharedUniforms(this.program_1);\n\n const u_kernel = this.gl.getUniformLocation(this.program_1, 'u_kernel');\n if (!u_kernel) {\n throw new Error('[ladon-ts] Error finding \"u_kernel\" uniform');\n }\n this.gl.uniform1fv(u_kernel, this.getBlurKernel());\n }\n\n // program pass 2 setup\n {\n const vertex_shader = compileShader(\n this.gl,\n this.gl.VERTEX_SHADER,\n this.vertex_shader_src\n );\n const fragment_shader = compileShader(\n this.gl,\n this.gl.FRAGMENT_SHADER,\n this.fragment_shader_pass_2_src\n );\n\n this.program_2 = linkProgram(this.gl, vertex_shader, fragment_shader);\n this.gl.useProgram(this.program_2);\n\n const u_blur = this.gl.getUniformLocation(this.program_2, 'u_blur');\n if (!u_blur) {\n throw new Error('[ladon-ts] Error finding \"u_blur\" uniform');\n }\n this.u_blur = u_blur;\n this.gl.activeTexture(this.gl.TEXTURE2);\n this.gl.bindTexture(this.gl.TEXTURE_2D, this.transfer_texture);\n this.gl.uniform1i(this.u_blur, 2);\n\n this.setSharedUniforms(this.program_2);\n\n const u_kernel = this.gl.getUniformLocation(this.program_2, 'u_kernel');\n if (!u_kernel) {\n throw new Error('[ladon-ts] Error finding \"u_kernel\" uniform');\n }\n this.gl.uniform1fv(u_kernel, this.getBlurKernel());\n }\n }\n\n public async render(input: FrameData, mask?: LadonOutput): Promise<void> {\n this.uploadVideoStream(input);\n this.uploadMask(mask);\n\n // program pass 1 - blur in one direction & output to framebuffer\n this.gl.useProgram(this.program_1);\n\n this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.framebuffer);\n this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length / 3);\n this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);\n\n // program pass 2 - blur in other direction & draw to screen\n this.gl.useProgram(this.program_2);\n this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length / 3);\n\n this.postDraw();\n }\n\n public async load(): Promise<void> {\n // empty\n }\n\n public destroy(): void {\n // empty\n }\n\n private getBlurKernel(): Float32Array {\n const kernel = [];\n let sum = 0;\n for (let i = 0; i < (this.config.render as BlurConfig).kernelSize; i++) {\n let w = i - ((this.config.render as BlurConfig).kernelSize - 1) / 2;\n w = Math.exp(-(w ** 2) / (this.config.render as BlurConfig).sigma ** 2);\n kernel.push(w);\n sum += w;\n }\n\n for (let i = 0; i < (this.config.render as BlurConfig).kernelSize; i++) {\n kernel[i] = kernel[i] / sum;\n }\n\n return new Float32Array(kernel);\n }\n}\n"],"names":["BlurRenderer","WebGLRenderer","output_canvas","config","vertex_shader","compileShader","fragment_shader","linkProgram","framebuffer","transfer_texture","u_kernel","u_blur","input","mask","kernel","sum","i","w"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ class c extends h {
|
|
|
5
5
|
super(t, r), this.output_canvas = t, this.config = r;
|
|
6
6
|
const e = this.config.render.background.getContext("2d", { willReadFrequently: !0 });
|
|
7
7
|
if (!e)
|
|
8
|
-
throw new Error("[ladon-ts]
|
|
8
|
+
throw new Error("[ladon-ts] Could not get background canvas context 2d");
|
|
9
9
|
this.background_canvas_ctx = e, this.fragment_shader = this.buildFragmentShader();
|
|
10
10
|
const s = i(this.gl, this.gl.VERTEX_SHADER, this.vertex_shader_src), a = i(
|
|
11
11
|
this.gl,
|
|
@@ -59,7 +59,7 @@ void main() {
|
|
|
59
59
|
);
|
|
60
60
|
const r = this.gl.getUniformLocation(this.program, "u_background");
|
|
61
61
|
if (!r)
|
|
62
|
-
throw new Error('[ladon-ts]
|
|
62
|
+
throw new Error('[ladon-ts] Error finding "u_background" uniform');
|
|
63
63
|
this.gl.activeTexture(this.gl.TEXTURE2), this.gl.bindTexture(this.gl.TEXTURE_2D, this.background_texture), this.gl.uniform1i(r, 2);
|
|
64
64
|
}
|
|
65
65
|
async render(t, r) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replacement-renderer.js","sources":["../../../../src/lib/renderer/replacement-renderer.ts"],"sourcesContent":["// replacement-renderer.ts\n\nimport { PipelineConfig, ReplacementConfig } from '../config-types';\nimport { FrameData, LadonOutput } from '../generator';\nimport { compileShader, linkProgram } from '../util';\n\nimport { LadonRenderer } from './ladon-renderer';\nimport { WebGLRenderer } from './webgl-renderer';\n\nexport class ReplacementRenderer extends WebGLRenderer implements LadonRenderer {\n private program: WebGLProgram;\n private background_canvas_ctx: CanvasRenderingContext2D;\n\n protected background_texture!: WebGLTexture;\n protected fragment_shader!: string;\n\n constructor(public output_canvas: HTMLCanvasElement, public readonly config: PipelineConfig) {\n super(output_canvas, config);\n\n const background_canvas_ctx = (\n this.config.render as ReplacementConfig\n ).background.getContext('2d', { willReadFrequently: true });\n if (!background_canvas_ctx) {\n throw new Error('[ladon-ts]
|
|
1
|
+
{"version":3,"file":"replacement-renderer.js","sources":["../../../../src/lib/renderer/replacement-renderer.ts"],"sourcesContent":["// replacement-renderer.ts\n\nimport { PipelineConfig, ReplacementConfig } from '../config-types';\nimport { FrameData, LadonOutput } from '../generator';\nimport { compileShader, linkProgram } from '../util';\n\nimport { LadonRenderer } from './ladon-renderer';\nimport { WebGLRenderer } from './webgl-renderer';\n\nexport class ReplacementRenderer extends WebGLRenderer implements LadonRenderer {\n private program: WebGLProgram;\n private background_canvas_ctx: CanvasRenderingContext2D;\n\n protected background_texture!: WebGLTexture;\n protected fragment_shader!: string;\n\n constructor(public output_canvas: HTMLCanvasElement, public readonly config: PipelineConfig) {\n super(output_canvas, config);\n\n const background_canvas_ctx = (\n this.config.render as ReplacementConfig\n ).background.getContext('2d', { willReadFrequently: true });\n if (!background_canvas_ctx) {\n throw new Error('[ladon-ts] Could not get background canvas context 2d');\n }\n this.background_canvas_ctx = background_canvas_ctx;\n\n // Build the fragment shader\n this.fragment_shader = this.buildFragmentShader();\n\n // Compile and link shaders\n const vertex_shader = compileShader(this.gl, this.gl.VERTEX_SHADER, this.vertex_shader_src);\n const fragment_shader = compileShader(\n this.gl,\n this.gl.FRAGMENT_SHADER,\n this.fragment_shader\n );\n\n this.program = linkProgram(this.gl, vertex_shader, fragment_shader);\n this.gl.useProgram(this.program);\n\n this.setSharedUniforms(this.program);\n\n // Set up background texture\n this.setupBackgroundTexture();\n }\n\n protected buildFragmentShader(): string {\n return `${this.fragment_shader_header}\n \nuniform sampler2D u_background;\n\n${this.shared_shader_functions}\n\nvoid main() {\n ${this.getUVCalculation()}\n\n vec3 background = texture(u_background, st).rgb;\n vec3 image = texture(u_image, st).rgb;\n float mask = get_mask(st);\n\n vec3 color = mix(background, image, mask);\n outColor = vec4(color, 1.0);\n}`;\n }\n\n protected setupBackgroundTexture() {\n const backgroundData = this.background_canvas_ctx.getImageData(\n 0,\n 0,\n (this.config.render as ReplacementConfig).background.width,\n (this.config.render as ReplacementConfig).background.height\n );\n\n this.background_texture = this.createTexture(\n this.gl.RGBA,\n (this.config.render as ReplacementConfig).background.width,\n (this.config.render as ReplacementConfig).background.height,\n () => {\n this.gl.texImage2D(\n this.gl.TEXTURE_2D,\n 0,\n this.gl.RGBA,\n backgroundData.width,\n backgroundData.height,\n 0,\n this.gl.RGBA,\n this.gl.UNSIGNED_BYTE,\n backgroundData.data\n );\n }\n );\n\n const u_background = this.gl.getUniformLocation(this.program, 'u_background');\n if (!u_background) {\n throw new Error('[ladon-ts] Error finding \"u_background\" uniform');\n }\n this.gl.activeTexture(this.gl.TEXTURE2);\n this.gl.bindTexture(this.gl.TEXTURE_2D, this.background_texture);\n this.gl.uniform1i(u_background, 2);\n }\n\n public async render(input: FrameData, mask?: LadonOutput): Promise<void> {\n this.uploadVideoStream(input);\n this.uploadMask(mask);\n\n if (!(this.config.render as ReplacementConfig).static) {\n const backgroundData = this.background_canvas_ctx.getImageData(\n 0,\n 0,\n (this.config.render as ReplacementConfig).background.width,\n (this.config.render as ReplacementConfig).background.height\n ).data;\n\n this.gl.activeTexture(this.gl.TEXTURE2);\n this.gl.bindTexture(this.gl.TEXTURE_2D, this.background_texture);\n this.gl.texImage2D(\n this.gl.TEXTURE_2D,\n 0,\n this.gl.RGBA,\n (this.config.render as ReplacementConfig).background.width,\n (this.config.render as ReplacementConfig).background.height,\n 0,\n this.gl.RGBA,\n this.gl.UNSIGNED_BYTE,\n backgroundData\n );\n }\n\n this.gl.useProgram(this.program);\n\n this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length / 3);\n\n this.postDraw();\n }\n\n public async load(): Promise<void> {\n // empty\n }\n\n public destroy(): void {\n // empty\n }\n}\n"],"names":["ReplacementRenderer","WebGLRenderer","output_canvas","config","background_canvas_ctx","vertex_shader","compileShader","fragment_shader","linkProgram","backgroundData","u_background","input","mask"],"mappings":"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"}
|
|
@@ -53,13 +53,13 @@ float get_mask(vec2 uv) {
|
|
|
53
53
|
else {
|
|
54
54
|
const s = this.output_canvas.getContext("2d");
|
|
55
55
|
if (!s)
|
|
56
|
-
throw new Error("[ladon-ts]
|
|
56
|
+
throw new Error("[ladon-ts] Output canvas context must be webgl2 or 2d");
|
|
57
57
|
this.output_canvas_2d = s, this.intermediate_canvas = document.createElement("canvas"), this.intermediate_canvas.height = this.config.input.height, this.intermediate_canvas.width = this.config.input.width;
|
|
58
58
|
const r = this.intermediate_canvas.getContext("webgl2", {
|
|
59
59
|
antialias: !0
|
|
60
60
|
});
|
|
61
61
|
if (!r)
|
|
62
|
-
throw new Error("[ladon-ts]
|
|
62
|
+
throw new Error("[ladon-ts] Error getting output context webgl");
|
|
63
63
|
this.gl = r;
|
|
64
64
|
}
|
|
65
65
|
this.initTexturesAndBuffers();
|
|
@@ -76,11 +76,11 @@ float get_mask(vec2 uv) {
|
|
|
76
76
|
);
|
|
77
77
|
const t = this.gl.createVertexArray();
|
|
78
78
|
if (!t)
|
|
79
|
-
throw new Error("[ladon-ts]
|
|
79
|
+
throw new Error("[ladon-ts] Error creating vertex array");
|
|
80
80
|
this.gl.bindVertexArray(t);
|
|
81
81
|
const i = this.gl.createBuffer();
|
|
82
82
|
if (!i)
|
|
83
|
-
throw new Error("[ladon-ts]
|
|
83
|
+
throw new Error("[ladon-ts] Error creating buffer");
|
|
84
84
|
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, i), this.gl.bufferData(this.gl.ARRAY_BUFFER, this.verts, this.gl.STATIC_DRAW), this.gl.vertexAttribPointer(0, 3, this.gl.FLOAT, !1, 0, 0), this.gl.enableVertexAttribArray(0), this.gl.viewport(0, 0, this.config.input.width, this.config.input.height);
|
|
85
85
|
}
|
|
86
86
|
createTexture(t, i, e, s = () => {
|
|
@@ -98,7 +98,7 @@ float get_mask(vec2 uv) {
|
|
|
98
98
|
}) {
|
|
99
99
|
const r = this.gl.createTexture();
|
|
100
100
|
if (!r)
|
|
101
|
-
throw new Error("[ladon-ts]
|
|
101
|
+
throw new Error("[ladon-ts] Error creating texture");
|
|
102
102
|
return this.gl.bindTexture(this.gl.TEXTURE_2D, r), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE), s(), this.gl.bindTexture(this.gl.TEXTURE_2D, null), r;
|
|
103
103
|
}
|
|
104
104
|
getUVCalculation() {
|
|
@@ -107,11 +107,11 @@ float get_mask(vec2 uv) {
|
|
|
107
107
|
setSharedUniforms(t) {
|
|
108
108
|
const i = this.gl.getUniformLocation(t, "u_resolution");
|
|
109
109
|
if (!i)
|
|
110
|
-
throw new Error('[ladon-ts]
|
|
110
|
+
throw new Error('[ladon-ts] Error finding "u_resolution" uniform');
|
|
111
111
|
this.gl.uniform2f(i, this.config.input.width, this.config.input.height);
|
|
112
112
|
const e = this.gl.getUniformLocation(t, "u_image");
|
|
113
113
|
if (!e)
|
|
114
|
-
throw new Error('[ladon-ts]
|
|
114
|
+
throw new Error('[ladon-ts] Error finding "u_image" uniform');
|
|
115
115
|
this.gl.activeTexture(this.gl.TEXTURE0), this.gl.bindTexture(this.gl.TEXTURE_2D, this.image_texture), this.gl.uniform1i(e, 0);
|
|
116
116
|
const s = this.gl.getUniformLocation(t, "u_mask");
|
|
117
117
|
s && (this.gl.activeTexture(this.gl.TEXTURE1), this.gl.bindTexture(this.gl.TEXTURE_2D, this.mask_texture), this.gl.uniform1i(s, 1));
|