@stream-io/video-filters-web 0.8.6 → 0.8.7

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 (51) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/esm/index.js +10 -0
  3. package/dist/esm/index.js.map +1 -0
  4. package/dist/esm/src/BaseVideoProcessor.js +107 -0
  5. package/dist/esm/src/BaseVideoProcessor.js.map +1 -0
  6. package/dist/esm/src/FallbackGenerator.js +58 -0
  7. package/dist/esm/src/FallbackGenerator.js.map +1 -0
  8. package/dist/esm/src/FallbackProcessor.js +89 -0
  9. package/dist/esm/src/FallbackProcessor.js.map +1 -0
  10. package/dist/esm/src/FullScreenBlur.js +41 -0
  11. package/dist/esm/src/FullScreenBlur.js.map +1 -0
  12. package/dist/esm/src/FullScreenBlurRenderer.js +276 -0
  13. package/dist/esm/src/FullScreenBlurRenderer.js.map +1 -0
  14. package/dist/esm/src/VirtualBackground.js +143 -0
  15. package/dist/esm/src/VirtualBackground.js.map +1 -0
  16. package/dist/esm/src/WebGLRenderer.js +723 -0
  17. package/dist/esm/src/WebGLRenderer.js.map +1 -0
  18. package/dist/esm/src/compatibility.js +48 -0
  19. package/dist/esm/src/compatibility.js.map +1 -0
  20. package/dist/esm/src/legacy/createRenderer.js +33 -0
  21. package/dist/esm/src/legacy/createRenderer.js.map +1 -0
  22. package/dist/esm/src/legacy/helpers/webglHelper.js +94 -0
  23. package/dist/esm/src/legacy/helpers/webglHelper.js.map +1 -0
  24. package/dist/esm/src/legacy/segmentation.js +14 -0
  25. package/dist/esm/src/legacy/segmentation.js.map +1 -0
  26. package/dist/esm/src/legacy/tflite-simd.js +728 -0
  27. package/dist/esm/src/legacy/tflite-simd.js.map +1 -0
  28. package/dist/esm/src/legacy/tflite.js +31 -0
  29. package/dist/esm/src/legacy/tflite.js.map +1 -0
  30. package/dist/esm/src/legacy/webgl2/backgroundBlurStage.js +202 -0
  31. package/dist/esm/src/legacy/webgl2/backgroundBlurStage.js.map +1 -0
  32. package/dist/esm/src/legacy/webgl2/backgroundImageStage.js +157 -0
  33. package/dist/esm/src/legacy/webgl2/backgroundImageStage.js.map +1 -0
  34. package/dist/esm/src/legacy/webgl2/jointBilateralFilterStage.js +113 -0
  35. package/dist/esm/src/legacy/webgl2/jointBilateralFilterStage.js.map +1 -0
  36. package/dist/esm/src/legacy/webgl2/resizingStage.js +57 -0
  37. package/dist/esm/src/legacy/webgl2/resizingStage.js.map +1 -0
  38. package/dist/esm/src/legacy/webgl2/softmaxStage.js +51 -0
  39. package/dist/esm/src/legacy/webgl2/softmaxStage.js.map +1 -0
  40. package/dist/esm/src/legacy/webgl2/webgl2Pipeline.js +105 -0
  41. package/dist/esm/src/legacy/webgl2/webgl2Pipeline.js.map +1 -0
  42. package/dist/esm/src/mediapipe.js +16 -0
  43. package/dist/esm/src/mediapipe.js.map +1 -0
  44. package/dist/esm/src/types.js +11 -0
  45. package/dist/esm/src/types.js.map +1 -0
  46. package/dist/esm/src/version.js +5 -0
  47. package/dist/esm/src/version.js.map +1 -0
  48. package/dist/index.cjs.js +1 -1
  49. package/package.json +3 -3
  50. package/dist/index.es.js +0 -3022
  51. package/dist/index.es.js.map +0 -1
@@ -0,0 +1,113 @@
1
+ import { compileShader, createPipelineStageProgram, glsl } from '../helpers/webglHelper.js';
2
+
3
+ function buildJointBilateralFilterStage(gl, vertexShader, positionBuffer, texCoordBuffer, inputTexture, outputTexture, canvas, segmentationConfig) {
4
+ const fragmentShaderSource = glsl `#version 300 es
5
+
6
+ precision highp float;
7
+
8
+ uniform sampler2D u_inputFrame;
9
+ uniform sampler2D u_segmentationMask;
10
+ uniform vec2 u_texelSize;
11
+ uniform float u_step;
12
+ uniform float u_radius;
13
+ uniform float u_offset;
14
+ uniform float u_sigmaTexel;
15
+ uniform float u_sigmaColor;
16
+
17
+ in vec2 v_texCoord;
18
+ out vec4 outColor;
19
+
20
+ float gaussian(float x, float sigma) {
21
+ float coeff = -0.5 / (sigma * sigma * 4.0 + 1.0e-6);
22
+ return exp((x * x) * coeff);
23
+ }
24
+
25
+ void main() {
26
+ vec2 centerCoord = v_texCoord;
27
+ vec3 centerColor = texture(u_inputFrame, centerCoord).rgb;
28
+ float newVal = 0.0;
29
+
30
+ float spaceWeight = 0.0;
31
+ float colorWeight = 0.0;
32
+ float totalWeight = 0.0;
33
+
34
+ // Subsample kernel space.
35
+ for (float i = -u_radius + u_offset; i <= u_radius; i += u_step) {
36
+ for (float j = -u_radius + u_offset; j <= u_radius; j += u_step) {
37
+ vec2 shift = vec2(j, i) * u_texelSize;
38
+ vec2 coord = vec2(centerCoord + shift);
39
+ vec3 frameColor = texture(u_inputFrame, coord).rgb;
40
+ float outVal = texture(u_segmentationMask, coord).a;
41
+
42
+ spaceWeight = gaussian(distance(centerCoord, coord), u_sigmaTexel);
43
+ colorWeight = gaussian(distance(centerColor, frameColor), u_sigmaColor);
44
+ totalWeight += spaceWeight * colorWeight;
45
+
46
+ newVal += spaceWeight * colorWeight * outVal;
47
+ }
48
+ }
49
+ newVal /= totalWeight;
50
+
51
+ outColor = vec4(vec3(0.0), newVal);
52
+ }
53
+ `;
54
+ const { width: segmentationWidth, height: segmentationHeight } = segmentationConfig;
55
+ const { width: outputWidth, height: outputHeight } = canvas;
56
+ const texelWidth = 1 / outputWidth;
57
+ const texelHeight = 1 / outputHeight;
58
+ const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
59
+ const program = createPipelineStageProgram(gl, vertexShader, fragmentShader, positionBuffer, texCoordBuffer);
60
+ const inputFrameLocation = gl.getUniformLocation(program, 'u_inputFrame');
61
+ const segmentationMaskLocation = gl.getUniformLocation(program, 'u_segmentationMask');
62
+ const texelSizeLocation = gl.getUniformLocation(program, 'u_texelSize');
63
+ const stepLocation = gl.getUniformLocation(program, 'u_step');
64
+ const radiusLocation = gl.getUniformLocation(program, 'u_radius');
65
+ const offsetLocation = gl.getUniformLocation(program, 'u_offset');
66
+ const sigmaTexelLocation = gl.getUniformLocation(program, 'u_sigmaTexel');
67
+ const sigmaColorLocation = gl.getUniformLocation(program, 'u_sigmaColor');
68
+ const frameBuffer = gl.createFramebuffer();
69
+ gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
70
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0);
71
+ gl.useProgram(program);
72
+ gl.uniform1i(inputFrameLocation, 0);
73
+ gl.uniform1i(segmentationMaskLocation, 1);
74
+ gl.uniform2f(texelSizeLocation, texelWidth, texelHeight);
75
+ // Ensures default values are configured to prevent infinite
76
+ // loop in fragment shader
77
+ updateSigmaSpace(0);
78
+ updateSigmaColor(0);
79
+ function render() {
80
+ gl.viewport(0, 0, outputWidth, outputHeight);
81
+ gl.useProgram(program);
82
+ gl.activeTexture(gl.TEXTURE1);
83
+ gl.bindTexture(gl.TEXTURE_2D, inputTexture);
84
+ gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
85
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
86
+ }
87
+ function updateSigmaSpace(sigmaSpace) {
88
+ sigmaSpace *= Math.max(outputWidth / segmentationWidth, outputHeight / segmentationHeight);
89
+ const kSparsityFactor = 0.66; // Higher is sparser.
90
+ const step = Math.max(1, Math.sqrt(sigmaSpace) * kSparsityFactor);
91
+ const radius = sigmaSpace;
92
+ const offset = step > 1 ? step * 0.5 : 0;
93
+ const sigmaTexel = Math.max(texelWidth, texelHeight) * sigmaSpace;
94
+ gl.useProgram(program);
95
+ gl.uniform1f(stepLocation, step);
96
+ gl.uniform1f(radiusLocation, radius);
97
+ gl.uniform1f(offsetLocation, offset);
98
+ gl.uniform1f(sigmaTexelLocation, sigmaTexel);
99
+ }
100
+ function updateSigmaColor(sigmaColor) {
101
+ gl.useProgram(program);
102
+ gl.uniform1f(sigmaColorLocation, sigmaColor);
103
+ }
104
+ function cleanUp() {
105
+ gl.deleteFramebuffer(frameBuffer);
106
+ gl.deleteProgram(program);
107
+ gl.deleteShader(fragmentShader);
108
+ }
109
+ return { render, updateSigmaSpace, updateSigmaColor, cleanUp };
110
+ }
111
+
112
+ export { buildJointBilateralFilterStage };
113
+ //# sourceMappingURL=jointBilateralFilterStage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jointBilateralFilterStage.js","sources":["../../../../../../../src/legacy/webgl2/jointBilateralFilterStage.ts"],"sourcesContent":["import {\n compileShader,\n createPipelineStageProgram,\n glsl,\n} from '../helpers/webglHelper';\nimport { SegmentationParams } from '../segmentation';\n\nexport function buildJointBilateralFilterStage(\n gl: WebGL2RenderingContext,\n vertexShader: WebGLShader,\n positionBuffer: WebGLBuffer,\n texCoordBuffer: WebGLBuffer,\n inputTexture: WebGLTexture,\n outputTexture: WebGLTexture,\n canvas: HTMLCanvasElement,\n segmentationConfig: SegmentationParams,\n) {\n const fragmentShaderSource = glsl`#version 300 es\n\n precision highp float;\n\n uniform sampler2D u_inputFrame;\n uniform sampler2D u_segmentationMask;\n uniform vec2 u_texelSize;\n uniform float u_step;\n uniform float u_radius;\n uniform float u_offset;\n uniform float u_sigmaTexel;\n uniform float u_sigmaColor;\n\n in vec2 v_texCoord;\n out vec4 outColor;\n\n float gaussian(float x, float sigma) {\n float coeff = -0.5 / (sigma * sigma * 4.0 + 1.0e-6);\n return exp((x * x) * coeff);\n }\n\n void main() {\n vec2 centerCoord = v_texCoord;\n vec3 centerColor = texture(u_inputFrame, centerCoord).rgb;\n float newVal = 0.0;\n\n float spaceWeight = 0.0;\n float colorWeight = 0.0;\n float totalWeight = 0.0;\n\n // Subsample kernel space.\n for (float i = -u_radius + u_offset; i <= u_radius; i += u_step) {\n for (float j = -u_radius + u_offset; j <= u_radius; j += u_step) {\n vec2 shift = vec2(j, i) * u_texelSize;\n vec2 coord = vec2(centerCoord + shift);\n vec3 frameColor = texture(u_inputFrame, coord).rgb;\n float outVal = texture(u_segmentationMask, coord).a;\n\n spaceWeight = gaussian(distance(centerCoord, coord), u_sigmaTexel);\n colorWeight = gaussian(distance(centerColor, frameColor), u_sigmaColor);\n totalWeight += spaceWeight * colorWeight;\n\n newVal += spaceWeight * colorWeight * outVal;\n }\n }\n newVal /= totalWeight;\n\n outColor = vec4(vec3(0.0), newVal);\n }\n `;\n\n const { width: segmentationWidth, height: segmentationHeight } =\n segmentationConfig;\n const { width: outputWidth, height: outputHeight } = canvas;\n const texelWidth = 1 / outputWidth;\n const texelHeight = 1 / outputHeight;\n\n const fragmentShader = compileShader(\n gl,\n gl.FRAGMENT_SHADER,\n fragmentShaderSource,\n );\n const program = createPipelineStageProgram(\n gl,\n vertexShader,\n fragmentShader,\n positionBuffer,\n texCoordBuffer,\n );\n const inputFrameLocation = gl.getUniformLocation(program, 'u_inputFrame');\n const segmentationMaskLocation = gl.getUniformLocation(\n program,\n 'u_segmentationMask',\n );\n const texelSizeLocation = gl.getUniformLocation(program, 'u_texelSize');\n const stepLocation = gl.getUniformLocation(program, 'u_step');\n const radiusLocation = gl.getUniformLocation(program, 'u_radius');\n const offsetLocation = gl.getUniformLocation(program, 'u_offset');\n const sigmaTexelLocation = gl.getUniformLocation(program, 'u_sigmaTexel');\n const sigmaColorLocation = gl.getUniformLocation(program, 'u_sigmaColor');\n\n const frameBuffer = gl.createFramebuffer();\n gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n outputTexture,\n 0,\n );\n\n gl.useProgram(program);\n gl.uniform1i(inputFrameLocation, 0);\n gl.uniform1i(segmentationMaskLocation, 1);\n gl.uniform2f(texelSizeLocation, texelWidth, texelHeight);\n\n // Ensures default values are configured to prevent infinite\n // loop in fragment shader\n updateSigmaSpace(0);\n updateSigmaColor(0);\n\n function render() {\n gl.viewport(0, 0, outputWidth, outputHeight);\n gl.useProgram(program);\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, inputTexture);\n gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n\n function updateSigmaSpace(sigmaSpace: number) {\n sigmaSpace *= Math.max(\n outputWidth / segmentationWidth,\n outputHeight / segmentationHeight,\n );\n\n const kSparsityFactor = 0.66; // Higher is sparser.\n const step = Math.max(1, Math.sqrt(sigmaSpace) * kSparsityFactor);\n const radius = sigmaSpace;\n const offset = step > 1 ? step * 0.5 : 0;\n const sigmaTexel = Math.max(texelWidth, texelHeight) * sigmaSpace;\n\n gl.useProgram(program);\n gl.uniform1f(stepLocation, step);\n gl.uniform1f(radiusLocation, radius);\n gl.uniform1f(offsetLocation, offset);\n gl.uniform1f(sigmaTexelLocation, sigmaTexel);\n }\n\n function updateSigmaColor(sigmaColor: number) {\n gl.useProgram(program);\n gl.uniform1f(sigmaColorLocation, sigmaColor);\n }\n\n function cleanUp() {\n gl.deleteFramebuffer(frameBuffer);\n gl.deleteProgram(program);\n gl.deleteShader(fragmentShader);\n }\n\n return { render, updateSigmaSpace, updateSigmaColor, cleanUp };\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { compileShader, createPipelineStageProgram, createTexture, glsl, readPixelsAsync } from '../helpers/webglHelper.js';
2
+
3
+ function buildResizingStage(gl, vertexShader, positionBuffer, texCoordBuffer, tflite, segmentationConfig, onError) {
4
+ const fragmentShaderSource = glsl `#version 300 es
5
+
6
+ precision highp float;
7
+ uniform sampler2D u_inputFrame;
8
+ in vec2 v_texCoord;
9
+ out vec4 outColor;
10
+
11
+ void main() {
12
+ outColor = texture(u_inputFrame, v_texCoord);
13
+ }
14
+ `;
15
+ // TFLite memory will be accessed as float32
16
+ const tfliteInputMemoryOffset = tflite._getInputMemoryOffset() / 4;
17
+ const { width: outputWidth, height: outputHeight } = segmentationConfig;
18
+ const outputPixelCount = outputWidth * outputHeight;
19
+ const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
20
+ const program = createPipelineStageProgram(gl, vertexShader, fragmentShader, positionBuffer, texCoordBuffer);
21
+ const inputFrameLocation = gl.getUniformLocation(program, 'u_inputFrame');
22
+ const outputTexture = createTexture(gl, gl.RGBA8, outputWidth, outputHeight);
23
+ const frameBuffer = gl.createFramebuffer();
24
+ gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
25
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0);
26
+ const outputPixels = new Uint8Array(outputPixelCount * 4);
27
+ gl.useProgram(program);
28
+ gl.uniform1i(inputFrameLocation, 0);
29
+ function render() {
30
+ gl.viewport(0, 0, outputWidth, outputHeight);
31
+ gl.useProgram(program);
32
+ gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
33
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
34
+ // Downloads pixels asynchronously from GPU while rendering the current frame.
35
+ // The pixels will be available in the next frame render which results
36
+ // in offsets in the segmentation output but increases the frame rate.
37
+ readPixelsAsync(gl, 0, 0, outputWidth, outputHeight, gl.RGBA, gl.UNSIGNED_BYTE, outputPixels).catch((error) => {
38
+ });
39
+ for (let i = 0; i < outputPixelCount; i++) {
40
+ const tfliteIndex = tfliteInputMemoryOffset + i * 3;
41
+ const outputIndex = i * 4;
42
+ tflite.HEAPF32[tfliteIndex] = outputPixels[outputIndex] / 255;
43
+ tflite.HEAPF32[tfliteIndex + 1] = outputPixels[outputIndex + 1] / 255;
44
+ tflite.HEAPF32[tfliteIndex + 2] = outputPixels[outputIndex + 2] / 255;
45
+ }
46
+ }
47
+ function cleanUp() {
48
+ gl.deleteFramebuffer(frameBuffer);
49
+ gl.deleteTexture(outputTexture);
50
+ gl.deleteProgram(program);
51
+ gl.deleteShader(fragmentShader);
52
+ }
53
+ return { render, cleanUp };
54
+ }
55
+
56
+ export { buildResizingStage };
57
+ //# sourceMappingURL=resizingStage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resizingStage.js","sources":["../../../../../../../src/legacy/webgl2/resizingStage.ts"],"sourcesContent":["import { TFLite } from '../tflite';\nimport {\n compileShader,\n createPipelineStageProgram,\n createTexture,\n glsl,\n readPixelsAsync,\n} from '../helpers/webglHelper';\nimport { SegmentationParams } from '../segmentation';\n\nexport function buildResizingStage(\n gl: WebGL2RenderingContext,\n vertexShader: WebGLShader,\n positionBuffer: WebGLBuffer,\n texCoordBuffer: WebGLBuffer,\n tflite: TFLite,\n segmentationConfig: SegmentationParams,\n onError?: (error: any) => void,\n) {\n const fragmentShaderSource = glsl`#version 300 es\n\n precision highp float;\n uniform sampler2D u_inputFrame;\n in vec2 v_texCoord;\n out vec4 outColor;\n\n void main() {\n outColor = texture(u_inputFrame, v_texCoord);\n }\n `;\n\n // TFLite memory will be accessed as float32\n const tfliteInputMemoryOffset = tflite._getInputMemoryOffset() / 4;\n\n const { width: outputWidth, height: outputHeight } = segmentationConfig;\n const outputPixelCount = outputWidth * outputHeight;\n\n const fragmentShader = compileShader(\n gl,\n gl.FRAGMENT_SHADER,\n fragmentShaderSource,\n );\n const program = createPipelineStageProgram(\n gl,\n vertexShader,\n fragmentShader,\n positionBuffer,\n texCoordBuffer,\n );\n const inputFrameLocation = gl.getUniformLocation(program, 'u_inputFrame');\n const outputTexture = createTexture(gl, gl.RGBA8, outputWidth, outputHeight);\n\n const frameBuffer = gl.createFramebuffer();\n gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n outputTexture,\n 0,\n );\n const outputPixels = new Uint8Array(outputPixelCount * 4);\n\n gl.useProgram(program);\n gl.uniform1i(inputFrameLocation, 0);\n\n function render() {\n gl.viewport(0, 0, outputWidth, outputHeight);\n gl.useProgram(program);\n gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n\n // Downloads pixels asynchronously from GPU while rendering the current frame.\n // The pixels will be available in the next frame render which results\n // in offsets in the segmentation output but increases the frame rate.\n readPixelsAsync(\n gl,\n 0,\n 0,\n outputWidth,\n outputHeight,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n outputPixels,\n ).catch((error: any) => {\n onError?.(error);\n });\n\n for (let i = 0; i < outputPixelCount; i++) {\n const tfliteIndex = tfliteInputMemoryOffset + i * 3;\n const outputIndex = i * 4;\n tflite.HEAPF32[tfliteIndex] = outputPixels[outputIndex] / 255;\n tflite.HEAPF32[tfliteIndex + 1] = outputPixels[outputIndex + 1] / 255;\n tflite.HEAPF32[tfliteIndex + 2] = outputPixels[outputIndex + 2] / 255;\n }\n }\n\n function cleanUp() {\n gl.deleteFramebuffer(frameBuffer);\n gl.deleteTexture(outputTexture);\n gl.deleteProgram(program);\n gl.deleteShader(fragmentShader);\n }\n\n return { render, cleanUp };\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { compileShader, createPipelineStageProgram, createTexture, glsl } from '../helpers/webglHelper.js';
2
+
3
+ function buildSoftmaxStage(gl, vertexShader, positionBuffer, texCoordBuffer, tflite, outputTexture, segmentationConfig) {
4
+ const fragmentShaderSource = glsl `#version 300 es
5
+
6
+ precision highp float;
7
+
8
+ uniform sampler2D u_inputSegmentation;
9
+ in vec2 v_texCoord;
10
+ out vec4 outColor;
11
+
12
+ void main() {
13
+ vec2 segmentation = texture(u_inputSegmentation, v_texCoord).rg;
14
+ float shift = max(segmentation.r, segmentation.g);
15
+ float backgroundExp = exp(segmentation.r - shift);
16
+ float personExp = exp(segmentation.g - shift);
17
+ outColor = vec4(vec3(0.0), personExp / (backgroundExp + personExp));
18
+ }
19
+ `;
20
+ // TFLite memory will be accessed as float32
21
+ const tfliteOutputMemoryOffset = tflite._getOutputMemoryOffset() / 4;
22
+ const { width: segmentationWidth, height: segmentationHeight } = segmentationConfig;
23
+ const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
24
+ const program = createPipelineStageProgram(gl, vertexShader, fragmentShader, positionBuffer, texCoordBuffer);
25
+ const inputLocation = gl.getUniformLocation(program, 'u_inputSegmentation');
26
+ const inputTexture = createTexture(gl, gl.RG32F, segmentationWidth, segmentationHeight);
27
+ const frameBuffer = gl.createFramebuffer();
28
+ gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
29
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0);
30
+ gl.useProgram(program);
31
+ gl.uniform1i(inputLocation, 1);
32
+ function render() {
33
+ gl.viewport(0, 0, segmentationWidth, segmentationHeight);
34
+ gl.useProgram(program);
35
+ gl.activeTexture(gl.TEXTURE1);
36
+ gl.bindTexture(gl.TEXTURE_2D, inputTexture);
37
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, segmentationWidth, segmentationHeight, gl.RG, gl.FLOAT, tflite.HEAPF32, tfliteOutputMemoryOffset);
38
+ gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
39
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
40
+ }
41
+ function cleanUp() {
42
+ gl.deleteFramebuffer(frameBuffer);
43
+ gl.deleteTexture(inputTexture);
44
+ gl.deleteProgram(program);
45
+ gl.deleteShader(fragmentShader);
46
+ }
47
+ return { render, cleanUp };
48
+ }
49
+
50
+ export { buildSoftmaxStage };
51
+ //# sourceMappingURL=softmaxStage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"softmaxStage.js","sources":["../../../../../../../src/legacy/webgl2/softmaxStage.ts"],"sourcesContent":["import { TFLite } from '../tflite';\nimport {\n compileShader,\n createPipelineStageProgram,\n createTexture,\n glsl,\n} from '../helpers/webglHelper';\nimport { SegmentationParams } from '../segmentation';\n\nexport function buildSoftmaxStage(\n gl: WebGL2RenderingContext,\n vertexShader: WebGLShader,\n positionBuffer: WebGLBuffer,\n texCoordBuffer: WebGLBuffer,\n tflite: TFLite,\n outputTexture: WebGLTexture,\n segmentationConfig: SegmentationParams,\n) {\n const fragmentShaderSource = glsl`#version 300 es\n\n precision highp float;\n\n uniform sampler2D u_inputSegmentation;\n in vec2 v_texCoord;\n out vec4 outColor;\n\n void main() {\n vec2 segmentation = texture(u_inputSegmentation, v_texCoord).rg;\n float shift = max(segmentation.r, segmentation.g);\n float backgroundExp = exp(segmentation.r - shift);\n float personExp = exp(segmentation.g - shift);\n outColor = vec4(vec3(0.0), personExp / (backgroundExp + personExp));\n }\n `;\n\n // TFLite memory will be accessed as float32\n const tfliteOutputMemoryOffset = tflite._getOutputMemoryOffset() / 4;\n const { width: segmentationWidth, height: segmentationHeight } =\n segmentationConfig;\n\n const fragmentShader = compileShader(\n gl,\n gl.FRAGMENT_SHADER,\n fragmentShaderSource,\n );\n const program = createPipelineStageProgram(\n gl,\n vertexShader,\n fragmentShader,\n positionBuffer,\n texCoordBuffer,\n );\n const inputLocation = gl.getUniformLocation(program, 'u_inputSegmentation');\n const inputTexture = createTexture(\n gl,\n gl.RG32F,\n segmentationWidth,\n segmentationHeight,\n );\n\n const frameBuffer = gl.createFramebuffer();\n gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n outputTexture,\n 0,\n );\n\n gl.useProgram(program);\n gl.uniform1i(inputLocation, 1);\n\n function render() {\n gl.viewport(0, 0, segmentationWidth, segmentationHeight);\n gl.useProgram(program);\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, inputTexture);\n gl.texSubImage2D(\n gl.TEXTURE_2D,\n 0,\n 0,\n 0,\n segmentationWidth,\n segmentationHeight,\n gl.RG,\n gl.FLOAT,\n tflite.HEAPF32,\n tfliteOutputMemoryOffset,\n );\n gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n\n function cleanUp() {\n gl.deleteFramebuffer(frameBuffer);\n gl.deleteTexture(inputTexture);\n gl.deleteProgram(program);\n gl.deleteShader(fragmentShader);\n }\n\n return { render, cleanUp };\n}\n"],"names":[],"mappings":";;AASM,SAAU,iBAAiB,CAC/B,EAA0B,EAC1B,YAAyB,EACzB,cAA2B,EAC3B,cAA2B,EAC3B,MAAc,EACd,aAA2B,EAC3B,kBAAsC,EAAA;IAEtC,MAAM,oBAAoB,GAAG,IAAI,CAAA,CAAA;;;;;;;;;;;;;;;GAehC;;IAGD,MAAM,wBAAwB,GAAG,MAAM,CAAC,sBAAsB,EAAE,GAAG,CAAC;IACpE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAC5D,kBAAkB;AAEpB,IAAA,MAAM,cAAc,GAAG,aAAa,CAClC,EAAE,EACF,EAAE,CAAC,eAAe,EAClB,oBAAoB,CACrB;AACD,IAAA,MAAM,OAAO,GAAG,0BAA0B,CACxC,EAAE,EACF,YAAY,EACZ,cAAc,EACd,cAAc,EACd,cAAc,CACf;IACD,MAAM,aAAa,GAAG,EAAE,CAAC,kBAAkB,CAAC,OAAO,EAAE,qBAAqB,CAAC;AAC3E,IAAA,MAAM,YAAY,GAAG,aAAa,CAChC,EAAE,EACF,EAAE,CAAC,KAAK,EACR,iBAAiB,EACjB,kBAAkB,CACnB;AAED,IAAA,MAAM,WAAW,GAAG,EAAE,CAAC,iBAAiB,EAAE;IAC1C,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC;AAC/C,IAAA,EAAE,CAAC,oBAAoB,CACrB,EAAE,CAAC,WAAW,EACd,EAAE,CAAC,iBAAiB,EACpB,EAAE,CAAC,UAAU,EACb,aAAa,EACb,CAAC,CACF;AAED,IAAA,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;AACtB,IAAA,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAC;AAE9B,IAAA,SAAS,MAAM,GAAA;QACb,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,iBAAiB,EAAE,kBAAkB,CAAC;AACxD,QAAA,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;AACtB,QAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,QAAQ,CAAC;QAC7B,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,YAAY,CAAC;AAC3C,QAAA,EAAE,CAAC,aAAa,CACd,EAAE,CAAC,UAAU,EACb,CAAC,EACD,CAAC,EACD,CAAC,EACD,iBAAiB,EACjB,kBAAkB,EAClB,EAAE,CAAC,EAAE,EACL,EAAE,CAAC,KAAK,EACR,MAAM,CAAC,OAAO,EACd,wBAAwB,CACzB;QACD,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC;QAC/C,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC;IACxC;AAEA,IAAA,SAAS,OAAO,GAAA;AACd,QAAA,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC;AACjC,QAAA,EAAE,CAAC,aAAa,CAAC,YAAY,CAAC;AAC9B,QAAA,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC;AACzB,QAAA,EAAE,CAAC,YAAY,CAAC,cAAc,CAAC;IACjC;AAEA,IAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;AAC5B;;;;"}
@@ -0,0 +1,105 @@
1
+ import { compileShader, createTexture, glsl } from '../helpers/webglHelper.js';
2
+ import { buildBackgroundBlurStage } from './backgroundBlurStage.js';
3
+ import { buildBackgroundImageStage } from './backgroundImageStage.js';
4
+ import { buildJointBilateralFilterStage } from './jointBilateralFilterStage.js';
5
+ import { buildResizingStage } from './resizingStage.js';
6
+ import { buildSoftmaxStage } from './softmaxStage.js';
7
+
8
+ function buildWebGL2Pipeline(videoSource, backgroundImage, blurLevel, backgroundFilter, canvas, tflite, segmentationConfig, onError) {
9
+ const gl = canvas.getContext('webgl2');
10
+ if (!gl)
11
+ throw new Error('WebGL2 is not supported');
12
+ if (gl.isContextLost())
13
+ throw new Error('WebGL2 context was lost');
14
+ const { width: frameWidth, height: frameHeight } = videoSource;
15
+ const { width: segmentationWidth, height: segmentationHeight } = segmentationConfig;
16
+ const vertexShaderSource = glsl `#version 300 es
17
+
18
+ in vec2 a_position;
19
+ in vec2 a_texCoord;
20
+ out vec2 v_texCoord;
21
+
22
+ void main() {
23
+ gl_Position = vec4(a_position, 0.0, 1.0);
24
+ v_texCoord = a_texCoord;
25
+ }
26
+ `;
27
+ const vertexShader = compileShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
28
+ const vertexArray = gl.createVertexArray();
29
+ gl.bindVertexArray(vertexArray);
30
+ const positionBuffer = gl.createBuffer();
31
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
32
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1.0, -1, -1, 1.0, 1.0, 1.0]), gl.STATIC_DRAW);
33
+ const texCoordBuffer = gl.createBuffer();
34
+ gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
35
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0]), gl.STATIC_DRAW);
36
+ // We don't use texStorage2D here because texImage2D seems faster
37
+ // to upload video texture than texSubImage2D even though the latter
38
+ // is supposed to be the recommended way:
39
+ // https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_best_practices#use_texstorage_to_create_textures
40
+ const inputFrameTexture = gl.createTexture();
41
+ gl.bindTexture(gl.TEXTURE_2D, inputFrameTexture);
42
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
43
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
44
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
45
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
46
+ // TODO Rename segmentation and person mask to be more specific
47
+ const segmentationTexture = createTexture(gl, gl.RGBA8, segmentationWidth, segmentationHeight);
48
+ const personMaskTexture = createTexture(gl, gl.RGBA8, frameWidth, frameHeight);
49
+ const resizingStage = buildResizingStage(gl, vertexShader, positionBuffer, texCoordBuffer, tflite, segmentationConfig);
50
+ const loadSegmentationStage = buildSoftmaxStage(gl, vertexShader, positionBuffer, texCoordBuffer, tflite, segmentationTexture, segmentationConfig);
51
+ const jointBilateralFilterStage = buildJointBilateralFilterStage(gl, vertexShader, positionBuffer, texCoordBuffer, segmentationTexture, personMaskTexture, canvas, segmentationConfig);
52
+ const backgroundStage = backgroundFilter === 'blur'
53
+ ? buildBackgroundBlurStage(gl, vertexShader, positionBuffer, texCoordBuffer, personMaskTexture, canvas, blurLevel || 'high')
54
+ : buildBackgroundImageStage(gl, positionBuffer, texCoordBuffer, personMaskTexture, backgroundImage, canvas);
55
+ function render() {
56
+ gl.activeTexture(gl.TEXTURE0);
57
+ gl.bindTexture(gl.TEXTURE_2D, inputFrameTexture);
58
+ // texImage2D seems faster than texSubImage2D to upload
59
+ // video texture
60
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, videoSource);
61
+ gl.bindVertexArray(vertexArray);
62
+ resizingStage.render();
63
+ tflite._runInference();
64
+ loadSegmentationStage.render();
65
+ jointBilateralFilterStage.render();
66
+ backgroundStage.render();
67
+ }
68
+ function updatePostProcessingConfig() {
69
+ jointBilateralFilterStage.updateSigmaSpace(1);
70
+ jointBilateralFilterStage.updateSigmaColor(0.1);
71
+ if (backgroundFilter === 'image') {
72
+ const backgroundImageStage = backgroundStage;
73
+ backgroundImageStage.updateCoverage([0.5, 0.75]);
74
+ backgroundImageStage.updateLightWrapping(0.3);
75
+ backgroundImageStage.updateBlendMode('screen');
76
+ }
77
+ else if (backgroundFilter === 'blur') {
78
+ const backgroundBlurStage = backgroundStage;
79
+ backgroundBlurStage.updateCoverage([0.5, 0.75]);
80
+ }
81
+ else {
82
+ // TODO Handle no background in a separate pipeline path
83
+ const backgroundImageStage = backgroundStage;
84
+ backgroundImageStage.updateCoverage([0, 0.9999]);
85
+ backgroundImageStage.updateLightWrapping(0);
86
+ }
87
+ }
88
+ function cleanUp() {
89
+ backgroundStage.cleanUp();
90
+ jointBilateralFilterStage.cleanUp();
91
+ loadSegmentationStage.cleanUp();
92
+ resizingStage.cleanUp();
93
+ gl.deleteTexture(personMaskTexture);
94
+ gl.deleteTexture(segmentationTexture);
95
+ gl.deleteTexture(inputFrameTexture);
96
+ gl.deleteBuffer(texCoordBuffer);
97
+ gl.deleteBuffer(positionBuffer);
98
+ gl.deleteVertexArray(vertexArray);
99
+ gl.deleteShader(vertexShader);
100
+ }
101
+ return { render, updatePostProcessingConfig, cleanUp };
102
+ }
103
+
104
+ export { buildWebGL2Pipeline };
105
+ //# sourceMappingURL=webgl2Pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webgl2Pipeline.js","sources":["../../../../../../../src/legacy/webgl2/webgl2Pipeline.ts"],"sourcesContent":["import { TFLite } from '../tflite';\nimport { compileShader, createTexture, glsl } from '../helpers/webglHelper';\nimport {\n BackgroundBlurStage,\n buildBackgroundBlurStage,\n} from './backgroundBlurStage';\nimport {\n BackgroundImageStage,\n buildBackgroundImageStage,\n} from './backgroundImageStage';\nimport { buildJointBilateralFilterStage } from './jointBilateralFilterStage';\nimport { buildResizingStage } from './resizingStage';\nimport { buildSoftmaxStage } from './softmaxStage';\nimport { SegmentationParams } from '../segmentation';\nimport type { BackgroundBlurLevel, BackgroundFilter } from '../../types';\n\nexport function buildWebGL2Pipeline(\n videoSource: HTMLVideoElement,\n backgroundImage: HTMLImageElement | undefined,\n blurLevel: BackgroundBlurLevel | undefined,\n backgroundFilter: BackgroundFilter,\n canvas: HTMLCanvasElement,\n tflite: TFLite,\n segmentationConfig: SegmentationParams,\n onError?: (error: any) => void,\n) {\n const gl = canvas.getContext('webgl2')!;\n if (!gl) throw new Error('WebGL2 is not supported');\n if (gl.isContextLost()) throw new Error('WebGL2 context was lost');\n\n const { width: frameWidth, height: frameHeight } = videoSource;\n const { width: segmentationWidth, height: segmentationHeight } =\n segmentationConfig;\n\n const vertexShaderSource = glsl`#version 300 es\n\n in vec2 a_position;\n in vec2 a_texCoord;\n out vec2 v_texCoord;\n\n void main() {\n gl_Position = vec4(a_position, 0.0, 1.0);\n v_texCoord = a_texCoord;\n }\n `;\n const vertexShader = compileShader(gl, gl.VERTEX_SHADER, vertexShaderSource);\n\n const vertexArray = gl.createVertexArray();\n gl.bindVertexArray(vertexArray);\n\n const positionBuffer = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0]),\n gl.STATIC_DRAW,\n );\n\n const texCoordBuffer = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0]),\n gl.STATIC_DRAW,\n );\n\n // We don't use texStorage2D here because texImage2D seems faster\n // to upload video texture than texSubImage2D even though the latter\n // is supposed to be the recommended way:\n // https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_best_practices#use_texstorage_to_create_textures\n const inputFrameTexture = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, inputFrameTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n\n // TODO Rename segmentation and person mask to be more specific\n const segmentationTexture = createTexture(\n gl,\n gl.RGBA8,\n segmentationWidth,\n segmentationHeight,\n )!;\n const personMaskTexture = createTexture(\n gl,\n gl.RGBA8,\n frameWidth,\n frameHeight,\n )!;\n\n const resizingStage = buildResizingStage(\n gl,\n vertexShader,\n positionBuffer,\n texCoordBuffer,\n tflite,\n segmentationConfig,\n onError,\n );\n const loadSegmentationStage = buildSoftmaxStage(\n gl,\n vertexShader,\n positionBuffer,\n texCoordBuffer,\n tflite,\n segmentationTexture,\n segmentationConfig,\n );\n\n const jointBilateralFilterStage = buildJointBilateralFilterStage(\n gl,\n vertexShader,\n positionBuffer,\n texCoordBuffer,\n segmentationTexture,\n personMaskTexture,\n canvas,\n segmentationConfig,\n );\n const backgroundStage =\n backgroundFilter === 'blur'\n ? buildBackgroundBlurStage(\n gl,\n vertexShader,\n positionBuffer,\n texCoordBuffer,\n personMaskTexture,\n canvas,\n blurLevel || 'high',\n )\n : buildBackgroundImageStage(\n gl,\n positionBuffer,\n texCoordBuffer,\n personMaskTexture,\n backgroundImage,\n canvas,\n );\n\n function render() {\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, inputFrameTexture);\n\n // texImage2D seems faster than texSubImage2D to upload\n // video texture\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n videoSource,\n );\n\n gl.bindVertexArray(vertexArray);\n\n resizingStage.render();\n\n tflite._runInference();\n\n loadSegmentationStage.render();\n jointBilateralFilterStage.render();\n backgroundStage.render();\n }\n\n function updatePostProcessingConfig() {\n jointBilateralFilterStage.updateSigmaSpace(1);\n jointBilateralFilterStage.updateSigmaColor(0.1);\n\n if (backgroundFilter === 'image') {\n const backgroundImageStage = backgroundStage as BackgroundImageStage;\n backgroundImageStage.updateCoverage([0.5, 0.75]);\n backgroundImageStage.updateLightWrapping(0.3);\n backgroundImageStage.updateBlendMode('screen');\n } else if (backgroundFilter === 'blur') {\n const backgroundBlurStage = backgroundStage as BackgroundBlurStage;\n backgroundBlurStage.updateCoverage([0.5, 0.75]);\n } else {\n // TODO Handle no background in a separate pipeline path\n const backgroundImageStage = backgroundStage as BackgroundImageStage;\n backgroundImageStage.updateCoverage([0, 0.9999]);\n backgroundImageStage.updateLightWrapping(0);\n }\n }\n\n function cleanUp() {\n backgroundStage.cleanUp();\n jointBilateralFilterStage.cleanUp();\n loadSegmentationStage.cleanUp();\n resizingStage.cleanUp();\n\n gl.deleteTexture(personMaskTexture);\n gl.deleteTexture(segmentationTexture);\n gl.deleteTexture(inputFrameTexture);\n gl.deleteBuffer(texCoordBuffer);\n gl.deleteBuffer(positionBuffer);\n gl.deleteVertexArray(vertexArray);\n gl.deleteShader(vertexShader);\n }\n\n return { render, updatePostProcessingConfig, cleanUp };\n}\n"],"names":[],"mappings":";;;;;;;SAgBgB,mBAAmB,CACjC,WAA6B,EAC7B,eAA6C,EAC7C,SAA0C,EAC1C,gBAAkC,EAClC,MAAyB,EACzB,MAAc,EACd,kBAAsC,EACtC,OAA8B,EAAA;IAE9B,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAE;AACvC,IAAA,IAAI,CAAC,EAAE;AAAE,QAAA,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;IACnD,IAAI,EAAE,CAAC,aAAa,EAAE;AAAE,QAAA,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;IAElE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW;IAC9D,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAC5D,kBAAkB;IAEpB,MAAM,kBAAkB,GAAG,IAAI,CAAA,CAAA;;;;;;;;;;GAU9B;AACD,IAAA,MAAM,YAAY,GAAG,aAAa,CAAC,EAAE,EAAE,EAAE,CAAC,aAAa,EAAE,kBAAkB,CAAC;AAE5E,IAAA,MAAM,WAAW,GAAG,EAAE,CAAC,iBAAiB,EAAE;AAC1C,IAAA,EAAE,CAAC,eAAe,CAAC,WAAW,CAAC;AAE/B,IAAA,MAAM,cAAc,GAAG,EAAE,CAAC,YAAY,EAAG;IACzC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,YAAY,EAAE,cAAc,CAAC;AAC9C,IAAA,EAAE,CAAC,UAAU,CACX,EAAE,CAAC,YAAY,EACf,IAAI,YAAY,CAAC,CAAC,EAAI,EAAE,EAAI,EAAE,GAAG,EAAE,EAAI,EAAE,EAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,EAC9D,EAAE,CAAC,WAAW,CACf;AAED,IAAA,MAAM,cAAc,GAAG,EAAE,CAAC,YAAY,EAAG;IACzC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,YAAY,EAAE,cAAc,CAAC;AAC9C,IAAA,EAAE,CAAC,UAAU,CACX,EAAE,CAAC,YAAY,EACf,IAAI,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,EAC1D,EAAE,CAAC,WAAW,CACf;;;;;AAMD,IAAA,MAAM,iBAAiB,GAAG,EAAE,CAAC,aAAa,EAAE;IAC5C,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,iBAAiB,CAAC;AAChD,IAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC;AACpE,IAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC;AACpE,IAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,OAAO,CAAC;AAClE,IAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,OAAO,CAAC;;AAGlE,IAAA,MAAM,mBAAmB,GAAG,aAAa,CACvC,EAAE,EACF,EAAE,CAAC,KAAK,EACR,iBAAiB,EACjB,kBAAkB,CAClB;AACF,IAAA,MAAM,iBAAiB,GAAG,aAAa,CACrC,EAAE,EACF,EAAE,CAAC,KAAK,EACR,UAAU,EACV,WAAW,CACX;AAEF,IAAA,MAAM,aAAa,GAAG,kBAAkB,CACtC,EAAE,EACF,YAAY,EACZ,cAAc,EACd,cAAc,EACd,MAAM,EACN,kBACO,CACR;AACD,IAAA,MAAM,qBAAqB,GAAG,iBAAiB,CAC7C,EAAE,EACF,YAAY,EACZ,cAAc,EACd,cAAc,EACd,MAAM,EACN,mBAAmB,EACnB,kBAAkB,CACnB;IAED,MAAM,yBAAyB,GAAG,8BAA8B,CAC9D,EAAE,EACF,YAAY,EACZ,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,MAAM,EACN,kBAAkB,CACnB;AACD,IAAA,MAAM,eAAe,GACnB,gBAAgB,KAAK;AACnB,UAAE,wBAAwB,CACtB,EAAE,EACF,YAAY,EACZ,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,MAAM,EACN,SAAS,IAAI,MAAM;AAEvB,UAAE,yBAAyB,CACvB,EAAE,EACF,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,MAAM,CACP;AAEP,IAAA,SAAS,MAAM,GAAA;AACb,QAAA,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,QAAQ,CAAC;QAC7B,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,iBAAiB,CAAC;;;QAIhD,EAAE,CAAC,UAAU,CACX,EAAE,CAAC,UAAU,EACb,CAAC,EACD,EAAE,CAAC,IAAI,EACP,EAAE,CAAC,IAAI,EACP,EAAE,CAAC,aAAa,EAChB,WAAW,CACZ;AAED,QAAA,EAAE,CAAC,eAAe,CAAC,WAAW,CAAC;QAE/B,aAAa,CAAC,MAAM,EAAE;QAEtB,MAAM,CAAC,aAAa,EAAE;QAEtB,qBAAqB,CAAC,MAAM,EAAE;QAC9B,yBAAyB,CAAC,MAAM,EAAE;QAClC,eAAe,CAAC,MAAM,EAAE;IAC1B;AAEA,IAAA,SAAS,0BAA0B,GAAA;AACjC,QAAA,yBAAyB,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAC7C,QAAA,yBAAyB,CAAC,gBAAgB,CAAC,GAAG,CAAC;AAE/C,QAAA,IAAI,gBAAgB,KAAK,OAAO,EAAE;YAChC,MAAM,oBAAoB,GAAG,eAAuC;YACpE,oBAAoB,CAAC,cAAc,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAChD,YAAA,oBAAoB,CAAC,mBAAmB,CAAC,GAAG,CAAC;AAC7C,YAAA,oBAAoB,CAAC,eAAe,CAAC,QAAQ,CAAC;QAChD;AAAO,aAAA,IAAI,gBAAgB,KAAK,MAAM,EAAE;YACtC,MAAM,mBAAmB,GAAG,eAAsC;YAClE,mBAAmB,CAAC,cAAc,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACjD;aAAO;;YAEL,MAAM,oBAAoB,GAAG,eAAuC;YACpE,oBAAoB,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAChD,YAAA,oBAAoB,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAC7C;IACF;AAEA,IAAA,SAAS,OAAO,GAAA;QACd,eAAe,CAAC,OAAO,EAAE;QACzB,yBAAyB,CAAC,OAAO,EAAE;QACnC,qBAAqB,CAAC,OAAO,EAAE;QAC/B,aAAa,CAAC,OAAO,EAAE;AAEvB,QAAA,EAAE,CAAC,aAAa,CAAC,iBAAiB,CAAC;AACnC,QAAA,EAAE,CAAC,aAAa,CAAC,mBAAmB,CAAC;AACrC,QAAA,EAAE,CAAC,aAAa,CAAC,iBAAiB,CAAC;AACnC,QAAA,EAAE,CAAC,YAAY,CAAC,cAAc,CAAC;AAC/B,QAAA,EAAE,CAAC,YAAY,CAAC,cAAc,CAAC;AAC/B,QAAA,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC;AACjC,QAAA,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC;IAC/B;AAEA,IAAA,OAAO,EAAE,MAAM,EAAE,0BAA0B,EAAE,OAAO,EAAE;AACxD;;;;"}
@@ -0,0 +1,16 @@
1
+ import { packageName, version } from './version.js';
2
+
3
+ let lastModelFilePath = '';
4
+ let modelFileCache;
5
+ const loadMediaPipe = async (options = {}) => {
6
+ const { basePath = `https://unpkg.com/${packageName}@${version}/mediapipe`, modelPath = `${basePath}/models/selfie_segmenter_landscape.tflite`, } = options;
7
+ const model = modelPath === lastModelFilePath && modelFileCache
8
+ ? modelFileCache
9
+ : await fetch(modelPath).then((r) => r.arrayBuffer());
10
+ modelFileCache = model;
11
+ lastModelFilePath = modelPath;
12
+ return model;
13
+ };
14
+
15
+ export { loadMediaPipe };
16
+ //# sourceMappingURL=mediapipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediapipe.js","sources":["../../../../../src/mediapipe.ts"],"sourcesContent":["import { packageName, version } from './version';\n\nlet lastModelFilePath = '';\nlet modelFileCache: ArrayBuffer | undefined;\nexport const loadMediaPipe = async (\n options: {\n basePath?: string;\n modelPath?: string;\n } = {},\n): Promise<ArrayBuffer> => {\n const {\n basePath = `https://unpkg.com/${packageName}@${version}/mediapipe`,\n modelPath = `${basePath}/models/selfie_segmenter_landscape.tflite`,\n } = options;\n\n const model =\n modelPath === lastModelFilePath && modelFileCache\n ? modelFileCache\n : await fetch(modelPath).then((r) => r.arrayBuffer());\n\n modelFileCache = model;\n lastModelFilePath = modelPath;\n\n return model;\n};\n"],"names":[],"mappings":";;AAEA,IAAI,iBAAiB,GAAG,EAAE;AAC1B,IAAI,cAAuC;MAC9B,aAAa,GAAG,OAC3B,OAAA,GAGI,EAAE,KACkB;AACxB,IAAA,MAAM,EACJ,QAAQ,GAAG,CAAA,kBAAA,EAAqB,WAAW,IAAI,OAAO,CAAA,UAAA,CAAY,EAClE,SAAS,GAAG,CAAA,EAAG,QAAQ,2CAA2C,GACnE,GAAG,OAAO;AAEX,IAAA,MAAM,KAAK,GACT,SAAS,KAAK,iBAAiB,IAAI;AACjC,UAAE;AACF,UAAE,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IAEzD,cAAc,GAAG,KAAK;IACtB,iBAAiB,GAAG,SAAS;AAE7B,IAAA,OAAO,KAAK;AACd;;;;"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Maps blur level to blur strength values.
3
+ */
4
+ const BACKGROUND_BLUR_MAP = {
5
+ low: 3,
6
+ medium: 5,
7
+ high: 7,
8
+ };
9
+
10
+ export { BACKGROUND_BLUR_MAP };
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sources":["../../../../../src/types.ts"],"sourcesContent":["export type BackgroundSource = {\n type: string;\n media?: ImageBitmap | ReadableStream;\n url: string;\n video?: HTMLVideoElement;\n track?: MediaStreamTrack;\n};\nexport type BackgroundFilter = 'blur' | 'image';\nexport type BackgroundBlurLevel = 'low' | 'medium' | 'high' | number;\n\n/**\n * Options for controlling the segmentation mask smoothing.\n * These values are passed to the WebGL shader that blends\n * consecutive segmentation masks over time.\n */\nexport interface SegmentationOptions {\n /**\n * Controls how fast the mask adapts to new segmentation results.\n * Higher values make the mask react faster but may cause flickering.\n * Lower values produce smoother transitions but increase latency.\n * Value should be between 0 and 1.\n * @default 0.8\n */\n smoothingFactor?: number;\n\n /**\n * Lower edge of the smoothstep function applied to the confidence mask.\n * Confidence values below this are mapped to 0 (background).\n * Value should be between 0 and 1, and less than smoothstepMax.\n * @default 0.6\n */\n smoothstepMin?: number;\n\n /**\n * Upper edge of the smoothstep function applied to the confidence mask.\n * Confidence values above this are mapped to 1 (foreground).\n * Value should be between 0 and 1, and greater than smoothstepMin.\n * @default 0.9\n */\n smoothstepMax?: number;\n}\n\nexport interface SegmenterOptions {\n backgroundSource?: BackgroundSource | null;\n bgBlur: number;\n bgBlurRadius: number;\n isSelfieMode: boolean;\n segmentationOptions?: SegmentationOptions;\n}\n/**\n * Static configuration for the processor, defining which background\n * effect should be applied and how it should behave.\n */\nexport interface BackgroundOptions {\n basePath?: string;\n modelPath?: string;\n backgroundFilter?: BackgroundFilter;\n backgroundBlurLevel?: BackgroundBlurLevel;\n backgroundImage?: string | undefined;\n segmentationOptions?: SegmentationOptions;\n}\n\n/**\n * Performance statistics for video processing.\n */\nexport interface PerformanceStats {\n delay: number;\n fps: number;\n timestamp: number;\n}\n\n/**\n * Runtime hooks for handling lifecycle or error events.\n */\nexport interface VideoTrackProcessorHooks {\n onError?: (error: unknown) => void;\n onStats?: (stats: PerformanceStats) => void;\n}\n\n/**\n * Maps blur level to blur strength values.\n */\nexport const BACKGROUND_BLUR_MAP: Record<'low' | 'medium' | 'high', number> = {\n low: 3,\n medium: 5,\n high: 7,\n};\n"],"names":[],"mappings":"AA+EA;;AAEG;AACI,MAAM,mBAAmB,GAA8C;AAC5E,IAAA,GAAG,EAAE,CAAC;AACN,IAAA,MAAM,EAAE,CAAC;AACT,IAAA,IAAI,EAAE,CAAC;;;;;"}
@@ -0,0 +1,5 @@
1
+ const version = "0.8.7";
2
+ const packageName = "@stream-io/video-filters-web";
3
+
4
+ export { packageName, version };
5
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sources":["../../../../../src/version.ts"],"sourcesContent":["export const version = process.env.PKG_VERSION || '0.0.0-development';\nexport const packageName =\n process.env.PKG_NAME || '@stream-io/video-filters-web';\n"],"names":[],"mappings":"AAAO,MAAM,OAAO,GAAG;AAChB,MAAM,WAAW,GACtB;;;;"}
package/dist/index.cjs.js CHANGED
@@ -1561,7 +1561,7 @@ const createTFLiteSIMDModule = (__Module) => {
1561
1561
  return __Module.ready;
1562
1562
  };
1563
1563
 
1564
- const version = "0.8.6";
1564
+ const version = "0.8.7";
1565
1565
  const packageName = "@stream-io/video-filters-web";
1566
1566
 
1567
1567
  // @ts-expect-error - module is not declared
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@stream-io/video-filters-web",
3
- "version": "0.8.6",
3
+ "version": "0.8.7",
4
4
  "main": "./dist/index.cjs.js",
5
- "module": "./dist/index.es.js",
5
+ "module": "./dist/esm/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "license": "See license in LICENSE",
8
8
  "scripts": {
9
9
  "clean": "rimraf dist",
10
10
  "start": "rollup -c -w",
11
- "build": "NODE_ENV=production rollup -c"
11
+ "build": "yarn clean && NODE_ENV=production rollup -c"
12
12
  },
13
13
  "repository": {
14
14
  "type": "git",