@pexip/media-processor 18.5.0 → 19.1.0
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 +49 -0
- package/dist/common/backends/webgl/blender.js +3 -1
- package/dist/common/backends/webgl/blur.js +20 -5
- package/dist/common/backends/webgl/canvas.js +3 -0
- package/dist/common/backends/webgl/renderer.d.ts +2 -8
- package/dist/common/backends/webgl/renderer.js +46 -54
- package/dist/common/backends/webgl/smoothingMask.js +3 -1
- package/dist/common/backends/webgl/texture.js +3 -1
- package/dist/common/backends/webgl/textureToTexture.js +3 -1
- package/dist/common/backends/webgl/webglUtils.js +1 -0
- package/dist/common/canvasRenderUtils.d.ts +14 -9
- package/dist/common/canvasRenderUtils.js +26 -5
- package/dist/common/constants.d.ts +38 -6
- package/dist/common/constants.js +37 -6
- package/dist/common/tsconfig.tsbuildinfo +1 -1
- package/dist/common/types/messageEvents.d.ts +40 -5
- package/dist/common/types/processor.d.ts +13 -3
- package/dist/common/types/render.d.ts +11 -5
- package/dist/common/utils.d.ts +4 -3
- package/dist/common/utils.js +15 -6
- package/dist/main/tsconfig.tsbuildinfo +1 -1
- package/dist/main/video/canvasTransform.js +9 -0
- package/dist/main/video/constants.d.ts +1 -0
- package/dist/main/video/constants.js +1 -0
- package/dist/main/video/segmenters/mediapipe.d.ts +2 -1
- package/dist/main/video/segmenters/mediapipe.js +128 -34
- package/dist/main/video/transformer.js +14 -2
- package/dist/main/video/types.d.ts +4 -1
- package/dist/main/video/utils.d.ts +4 -1
- package/dist/main/video/utils.js +42 -15
- package/dist/main/video/videoStreamTrackProcessor.js +6 -11
- package/dist/workers/mediaWorker.js +14 -14
- package/dist/workers/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,54 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 19.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e3a9d84: Update mediapipe and related asset to v0.10.20
|
|
8
|
+
|
|
9
|
+
## 19.0.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 5b9daa4: Update @mediapipe/tasks-vision to 0.10.17
|
|
14
|
+
- 164a3e2: extract assert function
|
|
15
|
+
- 4fd97b2: Handle WebGL ContextLost & ContextRestored events
|
|
16
|
+
|
|
17
|
+
There is no way we could avoid context lost and we should have a robust
|
|
18
|
+
context lost handling in-place.
|
|
19
|
+
|
|
20
|
+
The following changes have been made:
|
|
21
|
+
|
|
22
|
+
- Handle WebGL context lost and restore events
|
|
23
|
+
- Dispatch custom event messages from WebWorker to Main thread
|
|
24
|
+
- Add debug capabilities to segmenter
|
|
25
|
+
- Allow Process Worker to restart processing
|
|
26
|
+
- Add reset() function to canvasRenderUtils
|
|
27
|
+
- Handle failed to create VideoFrame during the context lost
|
|
28
|
+
- Make Renderer stateless and Process Worker stateful
|
|
29
|
+
- Add restart function to Process Worker
|
|
30
|
+
- Ensure there is no processing when error occurs
|
|
31
|
+
- Workaround 2D Canvas context lost event bug
|
|
32
|
+
https://issues.chromium.org/issues/372756071
|
|
33
|
+
|
|
34
|
+
Related issues:
|
|
35
|
+
|
|
36
|
+
- Closes https://github.com/pexip/mcu/issues/39045
|
|
37
|
+
- Closes https://gitlab.com/pexip/zoo/-/issues/4896
|
|
38
|
+
|
|
39
|
+
Reference https://toji.dev/webgpu-best-practices/device-loss.html
|
|
40
|
+
|
|
41
|
+
- db258ca: Bump @mediapipe/task-visions to v0.10.18
|
|
42
|
+
- dfd1900: Timeout play video
|
|
43
|
+
|
|
44
|
+
### Patch Changes
|
|
45
|
+
|
|
46
|
+
- 22a807b: Fix multi-trnasformer assertion
|
|
47
|
+
- Updated dependencies [164a3e2]
|
|
48
|
+
- Updated dependencies [b13010c]
|
|
49
|
+
- Updated dependencies [66a8f72]
|
|
50
|
+
- @pexip/utils@16.13.0
|
|
51
|
+
|
|
3
52
|
## 18.5.0
|
|
4
53
|
|
|
5
54
|
### Minor Changes
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { assert } from '
|
|
1
|
+
import { assert } from '@pexip/utils';
|
|
2
|
+
import { RENDERING_EVENTS } from '../../constants';
|
|
2
3
|
import { m3 } from '../../m3';
|
|
3
4
|
import { createGLProgram, createAndSetupTexture } from './webglUtils';
|
|
4
5
|
import { vertexShaderSource } from './shaders/vertexShader';
|
|
@@ -61,6 +62,7 @@ export const createBlendRenderer = (processor) => {
|
|
|
61
62
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0);
|
|
62
63
|
return {
|
|
63
64
|
render: ({ mask, foreground, background, }) => {
|
|
65
|
+
assert(!gl.isContextLost(), RENDERING_EVENTS.ContextLost);
|
|
64
66
|
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
|
|
65
67
|
gl.viewport(0, 0, processor.width, processor.height);
|
|
66
68
|
gl.useProgram(program);
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { assert
|
|
1
|
+
import { assert } from '@pexip/utils';
|
|
2
|
+
import { clamping } from '../../utils';
|
|
3
|
+
import { RENDERING_EVENTS } from '../../constants';
|
|
2
4
|
import { m3 } from '../../m3';
|
|
3
5
|
import { createAndSetupTexture, createGLProgram } from './webglUtils';
|
|
4
6
|
import { vertexShaderSource } from './shaders/vertexShader';
|
|
@@ -84,6 +86,7 @@ export const createBlurRenderer = (processor, pass) => {
|
|
|
84
86
|
const blurBuffers = generateBlurBuffers(pass + 1);
|
|
85
87
|
return {
|
|
86
88
|
render: (frame, pass) => {
|
|
89
|
+
assert(!gl.isContextLost(), RENDERING_EVENTS.ContextLost);
|
|
87
90
|
gl.useProgram(program);
|
|
88
91
|
gl.bindVertexArray(vao);
|
|
89
92
|
// Frame texture
|
|
@@ -112,8 +115,14 @@ export const createBlurRenderer = (processor, pass) => {
|
|
|
112
115
|
gl.uniformMatrix3fv(uniformLocations.matrix, false, matrix);
|
|
113
116
|
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
114
117
|
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
const error = gl.getError();
|
|
119
|
+
assert(error !== gl.CONTEXT_LOST_WEBGL, RENDERING_EVENTS.ContextLost);
|
|
120
|
+
assert(!gl.isContextLost(), RENDERING_EVENTS.ContextLost);
|
|
121
|
+
if (status !== gl.FRAMEBUFFER_COMPLETE ||
|
|
122
|
+
error !== gl.NO_ERROR) {
|
|
123
|
+
throw new Error(RENDERING_EVENTS.SamplingError, {
|
|
124
|
+
cause: `downsampling FrameBuffer Status: ${status}`,
|
|
125
|
+
});
|
|
117
126
|
}
|
|
118
127
|
// for the next draw, use the texture we just rendered to.
|
|
119
128
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
@@ -130,8 +139,14 @@ export const createBlurRenderer = (processor, pass) => {
|
|
|
130
139
|
gl.uniformMatrix3fv(uniformLocations.matrix, false, matrix);
|
|
131
140
|
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
132
141
|
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
133
|
-
|
|
134
|
-
|
|
142
|
+
const error = gl.getError();
|
|
143
|
+
assert(error !== gl.CONTEXT_LOST_WEBGL, RENDERING_EVENTS.ContextLost);
|
|
144
|
+
assert(!gl.isContextLost(), RENDERING_EVENTS.ContextLost);
|
|
145
|
+
if (status !== gl.FRAMEBUFFER_COMPLETE ||
|
|
146
|
+
error !== gl.NO_ERROR) {
|
|
147
|
+
throw new Error(RENDERING_EVENTS.SamplingError, {
|
|
148
|
+
cause: `Upsampling FrameBuffer Status: ${status}`,
|
|
149
|
+
});
|
|
135
150
|
}
|
|
136
151
|
// for the next draw, use the texture we just rendered to.
|
|
137
152
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { assert } from '@pexip/utils';
|
|
1
2
|
import { m3 } from '../../m3';
|
|
3
|
+
import { RENDERING_EVENTS } from '../../constants';
|
|
2
4
|
import { createGLProgram } from './webglUtils';
|
|
3
5
|
import { vertexShaderSource } from './shaders/vertexShader';
|
|
4
6
|
import { textureFragmentShaderSource } from './shaders/textureFragmentShader';
|
|
@@ -53,6 +55,7 @@ export const createCanvasRenderer = (processor) => {
|
|
|
53
55
|
gl.vertexAttribPointer(attribLocations.texCoord, 2, gl.FLOAT, false, 0, 0);
|
|
54
56
|
return {
|
|
55
57
|
render: (texture) => {
|
|
58
|
+
assert(!gl.isContextLost(), RENDERING_EVENTS.ContextLost);
|
|
56
59
|
// Draw on the Canvas
|
|
57
60
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
58
61
|
gl.viewport(0, 0, processor.width, processor.height);
|
|
@@ -1,8 +1,2 @@
|
|
|
1
|
-
import type { Renderer,
|
|
2
|
-
|
|
3
|
-
interface Options extends Partial<RendererOptions> {
|
|
4
|
-
backgroundImageInits?: ImageMapIterable;
|
|
5
|
-
onError?: (error: Error) => void;
|
|
6
|
-
}
|
|
7
|
-
export declare const createRenderer: (canvas?: OffscreenCanvas, { backgroundBlurAmount, backgroundImageUrl, edgeBlurAmount, effects, foregroundThreshold, maskCombineRatio, onError, backgroundImageInits, }?: Options) => Renderer;
|
|
8
|
-
export {};
|
|
1
|
+
import type { Renderer, RenderEventHandlers } from '../../types/render';
|
|
2
|
+
export declare const createRenderer: (canvas: OffscreenCanvas | undefined, renderEventHandlers: RenderEventHandlers) => Renderer;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { assert } from '@pexip/utils';
|
|
2
|
+
import { PROCESSING_WIDTH, PROCESSING_HEIGHT, EDGE_BLUR_AMOUNT, BACKGROUND_BLUR_AMOUNT, RENDERING_EVENTS, } from '../../constants';
|
|
3
3
|
import { toTextureInfo } from './webglUtils';
|
|
4
4
|
import { createTextureRenderer } from './texture';
|
|
5
5
|
import { createBlurRenderer } from './blur';
|
|
@@ -19,14 +19,14 @@ const createLazyProps = (stateBuilder) => {
|
|
|
19
19
|
},
|
|
20
20
|
});
|
|
21
21
|
};
|
|
22
|
-
export const createRenderer = (canvas = new OffscreenCanvas(PROCESSING_WIDTH, PROCESSING_HEIGHT),
|
|
22
|
+
export const createRenderer = (canvas = new OffscreenCanvas(PROCESSING_WIDTH, PROCESSING_HEIGHT), renderEventHandlers) => {
|
|
23
23
|
const rendererCreator = {
|
|
24
24
|
videoFrameRenderer: () => createTextureRenderer(canvas),
|
|
25
25
|
canvasRenderer: () => createCanvasRenderer(canvas),
|
|
26
26
|
backgroundImageRenderer: () => createTextureRenderer(canvas),
|
|
27
27
|
blendRenderer: () => createBlendRenderer(canvas),
|
|
28
|
-
blurRenderer: () => createBlurRenderer(canvas,
|
|
29
|
-
maskBlurRenderer: () => createBlurRenderer(canvas,
|
|
28
|
+
blurRenderer: () => createBlurRenderer(canvas, BACKGROUND_BLUR_AMOUNT),
|
|
29
|
+
maskBlurRenderer: () => createBlurRenderer(canvas, EDGE_BLUR_AMOUNT),
|
|
30
30
|
textureRenderer: () => createTextureToTextureRenderer(canvas),
|
|
31
31
|
smoothingMaskRenderer: () => createSmoothingMaskRenderer(canvas),
|
|
32
32
|
release: (states) => () => Object.keys(states).forEach(key => key !== 'release' &&
|
|
@@ -34,14 +34,8 @@ export const createRenderer = (canvas = new OffscreenCanvas(PROCESSING_WIDTH, PR
|
|
|
34
34
|
};
|
|
35
35
|
let lazyProps = createLazyProps(rendererCreator);
|
|
36
36
|
const props = {
|
|
37
|
-
backgroundBlurAmount,
|
|
38
|
-
backgroundImageUrl,
|
|
39
|
-
edgeBlurAmount,
|
|
40
|
-
effects,
|
|
41
|
-
foregroundThreshold,
|
|
42
|
-
maskCombineRatio,
|
|
43
37
|
canvas,
|
|
44
|
-
|
|
38
|
+
gl: null,
|
|
45
39
|
// TODO: refactor to avoid repeated codes
|
|
46
40
|
get videoFrameRenderer() {
|
|
47
41
|
return lazyProps.videoFrameRenderer;
|
|
@@ -69,55 +63,45 @@ export const createRenderer = (canvas = new OffscreenCanvas(PROCESSING_WIDTH, PR
|
|
|
69
63
|
return lazyProps.smoothingMaskRenderer;
|
|
70
64
|
},
|
|
71
65
|
};
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
updateProps(options);
|
|
66
|
+
const handleContextLost = (event) => {
|
|
67
|
+
event.preventDefault();
|
|
68
|
+
cleanup();
|
|
69
|
+
renderEventHandlers.contextLost(event.statusMessage);
|
|
78
70
|
};
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
return onError?.(error);
|
|
82
|
-
}
|
|
83
|
-
throw error;
|
|
71
|
+
const handleContextRestored = (event) => {
|
|
72
|
+
renderEventHandlers.contextRestored(event.statusMessage);
|
|
84
73
|
};
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
74
|
+
const handleContextCreationError = (event) => {
|
|
75
|
+
renderEventHandlers.contextCreationError(event.statusMessage);
|
|
76
|
+
};
|
|
77
|
+
const init = () => {
|
|
78
|
+
canvas.addEventListener('webglcontextlost', handleContextLost);
|
|
79
|
+
canvas.addEventListener('webglcontextrestored', handleContextRestored);
|
|
80
|
+
canvas.addEventListener('webglcontextcreationerror', handleContextCreationError);
|
|
81
|
+
props.gl = canvas.getContext('webgl2', {
|
|
82
|
+
premultipliedAlpha: false,
|
|
83
|
+
powerPreference: 'high-performance',
|
|
84
|
+
});
|
|
85
|
+
assert(props.gl, RENDERING_EVENTS.ContextCreationError);
|
|
89
86
|
};
|
|
90
87
|
const render = (mask, frame, options) => {
|
|
91
|
-
|
|
92
|
-
updateProps(options);
|
|
93
|
-
}
|
|
88
|
+
assert(!props.gl?.isContextLost(), RENDERING_EVENTS.ContextLost);
|
|
94
89
|
const smoothedMask = props.smoothingMaskRenderer.render({
|
|
95
90
|
mask: toTextureInfo(mask),
|
|
96
91
|
prevMask: props.prevMask,
|
|
97
|
-
},
|
|
92
|
+
}, options);
|
|
98
93
|
const frameTexture = props.videoFrameRenderer.render(frame);
|
|
99
94
|
let background = frameTexture;
|
|
100
|
-
if (
|
|
101
|
-
background = props.blurRenderer.render(frameTexture,
|
|
95
|
+
if (options.effects === 'blur' && options.backgroundBlurAmount) {
|
|
96
|
+
background = props.blurRenderer.render(frameTexture, options.backgroundBlurAmount);
|
|
102
97
|
}
|
|
103
|
-
else if (
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
width: backgroundImage.width,
|
|
111
|
-
height: backgroundImage.height,
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
props.backgroundImages
|
|
116
|
-
.tryFetchingImage(props.backgroundImageUrl)
|
|
117
|
-
.catch(error => {
|
|
118
|
-
handleError(new Error(`FailedToLoadBackgroundImage: ${props.backgroundImageUrl}`, { cause: error }));
|
|
119
|
-
});
|
|
120
|
-
}
|
|
98
|
+
else if (options?.effects === 'overlay' && options.backgroundImage) {
|
|
99
|
+
background = props.backgroundImageRenderer.render({
|
|
100
|
+
frame: options.backgroundImage,
|
|
101
|
+
timestamp: performance.now(),
|
|
102
|
+
width: options.backgroundImage.width,
|
|
103
|
+
height: options.backgroundImage.height,
|
|
104
|
+
});
|
|
121
105
|
}
|
|
122
106
|
const blendedFrameTexture = props.blendRenderer.render({
|
|
123
107
|
mask: smoothedMask,
|
|
@@ -128,11 +112,19 @@ export const createRenderer = (canvas = new OffscreenCanvas(PROCESSING_WIDTH, PR
|
|
|
128
112
|
// Cloned the current smoothedMask so it can be fed back to the next round
|
|
129
113
|
props.prevMask = props.textureRenderer.render(smoothedMask);
|
|
130
114
|
};
|
|
131
|
-
const
|
|
115
|
+
const cleanup = () => {
|
|
132
116
|
lazyProps.release();
|
|
133
117
|
lazyProps = createLazyProps(rendererCreator);
|
|
134
|
-
props.backgroundImages.clear();
|
|
135
118
|
props.prevMask = undefined;
|
|
136
119
|
};
|
|
137
|
-
|
|
120
|
+
const release = () => {
|
|
121
|
+
canvas.removeEventListener('webglcontextlost', handleContextLost);
|
|
122
|
+
canvas.removeEventListener('webglcontextrestored', handleContextRestored);
|
|
123
|
+
canvas.removeEventListener('webglcontextcreationerror', handleContextCreationError);
|
|
124
|
+
cleanup();
|
|
125
|
+
};
|
|
126
|
+
const isContextLost = () => {
|
|
127
|
+
return !!props.gl?.isContextLost();
|
|
128
|
+
};
|
|
129
|
+
return { init, render, release, isContextLost };
|
|
138
130
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { assert } from '
|
|
1
|
+
import { assert } from '@pexip/utils';
|
|
2
2
|
import { m3 } from '../../m3';
|
|
3
|
+
import { RENDERING_EVENTS } from '../../constants';
|
|
3
4
|
import { createGLProgram, createAndSetupTexture } from './webglUtils';
|
|
4
5
|
import { vertexShaderSource } from './shaders/vertexShader';
|
|
5
6
|
import { smoothingMaskFragmentShaderSource } from './shaders/smoothingMaskFragmentShader';
|
|
@@ -61,6 +62,7 @@ export const createSmoothingMaskRenderer = (processor) => {
|
|
|
61
62
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0);
|
|
62
63
|
return {
|
|
63
64
|
render: ({ mask, prevMask, }, options) => {
|
|
65
|
+
assert(!gl.isContextLost(), RENDERING_EVENTS.ContextLost);
|
|
64
66
|
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
|
|
65
67
|
gl.viewport(0, 0, processor.width, processor.height);
|
|
66
68
|
gl.clearColor(0, 0, 0, 0);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { assert } from '
|
|
1
|
+
import { assert } from '@pexip/utils';
|
|
2
|
+
import { RENDERING_EVENTS } from '../../constants';
|
|
2
3
|
import { m3 } from '../../m3';
|
|
3
4
|
import { createAndSetupTexture, createGLProgram } from './webglUtils';
|
|
4
5
|
import { vertexShaderSource } from './shaders/vertexShader';
|
|
@@ -60,6 +61,7 @@ export const createTextureRenderer = (processor) => {
|
|
|
60
61
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0);
|
|
61
62
|
return {
|
|
62
63
|
render: (video) => {
|
|
64
|
+
assert(!gl.isContextLost(), RENDERING_EVENTS.ContextLost);
|
|
63
65
|
// Draw on the frame buffer
|
|
64
66
|
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
|
|
65
67
|
gl.viewport(0, 0, processor.width, processor.height);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { assert } from '
|
|
1
|
+
import { assert } from '@pexip/utils';
|
|
2
|
+
import { RENDERING_EVENTS } from '../../constants';
|
|
2
3
|
import { m3 } from '../../m3';
|
|
3
4
|
import { createAndSetupTexture, createGLProgram } from './webglUtils';
|
|
4
5
|
import { vertexShaderSource } from './shaders/vertexShader';
|
|
@@ -59,6 +60,7 @@ export const createTextureToTextureRenderer = (processor) => {
|
|
|
59
60
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0);
|
|
60
61
|
return {
|
|
61
62
|
render: (inputTexture) => {
|
|
63
|
+
assert(!gl.isContextLost(), RENDERING_EVENTS.ContextLost);
|
|
62
64
|
// Draw on the frame buffer
|
|
63
65
|
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
|
|
64
66
|
gl.viewport(0, 0, processor.width, processor.height);
|
|
@@ -166,6 +166,7 @@ export const getLocations = (gl, program, locations) => Object.keys(locations).r
|
|
|
166
166
|
export const createGLProgram = (processCanvas, { attribs, uniforms, vertexSrc, fragmentSrc, }) => {
|
|
167
167
|
const gl = processCanvas.getContext('webgl2', {
|
|
168
168
|
premultipliedAlpha: false,
|
|
169
|
+
powerPreference: 'high-performance',
|
|
169
170
|
});
|
|
170
171
|
if (!gl) {
|
|
171
172
|
throw new Error('WebGL2 is not supported');
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import type { Segmentation } from './types/media';
|
|
2
|
-
|
|
3
|
-
drawImageDataCanvas
|
|
4
|
-
maskCanvas
|
|
5
|
-
blurredMaskCanvas
|
|
6
|
-
blurredCanvas
|
|
7
|
-
downScaledCanvas
|
|
8
|
-
backgroundImageCanvas
|
|
9
|
-
inputCanvas
|
|
10
|
-
}
|
|
2
|
+
declare const INTERNAL_CANVAS_KEYS: {
|
|
3
|
+
readonly drawImageDataCanvas: "drawImageDataCanvas";
|
|
4
|
+
readonly maskCanvas: "maskCanvas";
|
|
5
|
+
readonly blurredMaskCanvas: "blurredMaskCanvas";
|
|
6
|
+
readonly blurredCanvas: "blurredCanvas";
|
|
7
|
+
readonly downScaledCanvas: "downScaledCanvas";
|
|
8
|
+
readonly backgroundImageCanvas: "backgroundImageCanvas";
|
|
9
|
+
readonly inputCanvas: "inputCanvas";
|
|
10
|
+
};
|
|
11
|
+
type InternalCanvasKeys = keyof typeof INTERNAL_CANVAS_KEYS;
|
|
12
|
+
type InternalCanvases = {
|
|
13
|
+
[key in InternalCanvasKeys]?: OffscreenCanvas;
|
|
14
|
+
};
|
|
11
15
|
export interface Point {
|
|
12
16
|
x: number;
|
|
13
17
|
y: number;
|
|
@@ -58,5 +62,6 @@ export declare const createCanvasRenderUtils: (processingWidth: number, processi
|
|
|
58
62
|
offscreenCanvasName: keyof InternalCanvases;
|
|
59
63
|
preserveOldDrawing?: boolean | undefined;
|
|
60
64
|
}) => OffscreenCanvas;
|
|
65
|
+
reset: () => void;
|
|
61
66
|
};
|
|
62
67
|
export {};
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import { resize } from './utils';
|
|
2
|
+
const INTERNAL_CANVAS_KEYS = {
|
|
3
|
+
drawImageDataCanvas: 'drawImageDataCanvas',
|
|
4
|
+
maskCanvas: 'maskCanvas',
|
|
5
|
+
blurredMaskCanvas: 'blurredMaskCanvas',
|
|
6
|
+
blurredCanvas: 'blurredCanvas',
|
|
7
|
+
downScaledCanvas: 'downScaledCanvas',
|
|
8
|
+
backgroundImageCanvas: 'backgroundImageCanvas',
|
|
9
|
+
inputCanvas: 'inputCanvas',
|
|
10
|
+
};
|
|
2
11
|
export const getCanvasRenderingContext2D = (canvas, options) => {
|
|
3
12
|
const context = canvas.getContext('2d', options);
|
|
4
13
|
if (!context) {
|
|
@@ -67,14 +76,15 @@ export const createCanvasRenderUtils = (processingWidth, processingHeight) => {
|
|
|
67
76
|
const props = {
|
|
68
77
|
downScaleFactor: 3,
|
|
69
78
|
};
|
|
79
|
+
const createInternalCanvas = (canvasName) => createOffscreenCanvas(canvasName === 'downScaledCanvas'
|
|
80
|
+
? Math.trunc(processingWidth / props.downScaleFactor)
|
|
81
|
+
: processingWidth, canvasName === 'downScaledCanvas'
|
|
82
|
+
? Math.trunc(processingHeight / props.downScaleFactor)
|
|
83
|
+
: processingHeight);
|
|
70
84
|
const getCanvas = (canvasName) => {
|
|
71
85
|
const canvas = props[canvasName];
|
|
72
86
|
if (!canvas) {
|
|
73
|
-
const canvas =
|
|
74
|
-
? Math.trunc(processingWidth / props.downScaleFactor)
|
|
75
|
-
: processingWidth, canvasName === 'downScaledCanvas'
|
|
76
|
-
? Math.trunc(processingHeight / props.downScaleFactor)
|
|
77
|
-
: processingHeight);
|
|
87
|
+
const canvas = createInternalCanvas(canvasName);
|
|
78
88
|
props[canvasName] = canvas;
|
|
79
89
|
return canvas;
|
|
80
90
|
}
|
|
@@ -256,5 +266,16 @@ export const createCanvasRenderUtils = (processingWidth, processingHeight) => {
|
|
|
256
266
|
renderImageToOffScreenCanvas,
|
|
257
267
|
renderImageDataToOffScreenCanvas,
|
|
258
268
|
drawAndBlurImageOnOffScreenCanvas,
|
|
269
|
+
reset: () => {
|
|
270
|
+
Object.keys(INTERNAL_CANVAS_KEYS).forEach(key => {
|
|
271
|
+
const canvasKey = key;
|
|
272
|
+
const canvas = props[canvasKey];
|
|
273
|
+
if (canvas && canvas instanceof OffscreenCanvas) {
|
|
274
|
+
// Reset Canvas by creating a new one as it is more reliable
|
|
275
|
+
// than setting the width and height to 0 in the situation of context lost
|
|
276
|
+
props[canvasKey] = createInternalCanvas(canvasKey);
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
},
|
|
259
280
|
};
|
|
260
281
|
};
|
|
@@ -5,17 +5,22 @@ export declare const FOREGROUND_THRESHOLD = 0.5;
|
|
|
5
5
|
export declare const BACKGROUND_BLUR_AMOUNT = 3;
|
|
6
6
|
export declare const EDGE_BLUR_AMOUNT = 3;
|
|
7
7
|
export declare const MASK_COMBINE_RATIO = 0.5;
|
|
8
|
+
/**
|
|
9
|
+
* Process status
|
|
10
|
+
*/
|
|
8
11
|
export declare const PROCESS_STATUS: {
|
|
9
|
-
readonly
|
|
12
|
+
readonly Closed: "closed";
|
|
13
|
+
readonly Closing: "closing";
|
|
14
|
+
readonly Destroyed: "destroyed";
|
|
15
|
+
readonly Destroying: "destroying";
|
|
10
16
|
readonly Error: "Error";
|
|
17
|
+
readonly Idle: "idle";
|
|
18
|
+
readonly New: "new";
|
|
11
19
|
readonly Opened: "opened";
|
|
12
20
|
readonly Opening: "opening";
|
|
13
21
|
readonly Processing: "processing";
|
|
14
|
-
readonly
|
|
15
|
-
readonly
|
|
16
|
-
readonly Closed: "closed";
|
|
17
|
-
readonly Destroying: "destroying";
|
|
18
|
-
readonly Destroyed: "destroyed";
|
|
22
|
+
readonly Updated: "updated";
|
|
23
|
+
readonly Updating: "updating";
|
|
19
24
|
};
|
|
20
25
|
export type ProcessStatus = ExtractValueTypes<typeof PROCESS_STATUS>;
|
|
21
26
|
export declare const RENDER_EFFECT: {
|
|
@@ -24,4 +29,31 @@ export declare const RENDER_EFFECT: {
|
|
|
24
29
|
readonly Overlay: "overlay";
|
|
25
30
|
};
|
|
26
31
|
export type RenderEffects = ExtractValueTypes<typeof RENDER_EFFECT>;
|
|
32
|
+
export declare const RENDERING_EVENTS: {
|
|
33
|
+
/**
|
|
34
|
+
* Triggered when failed to create a context
|
|
35
|
+
*/
|
|
36
|
+
readonly ContextCreationError: "ContextCreationError";
|
|
37
|
+
/**
|
|
38
|
+
* Triggered when context is lost
|
|
39
|
+
*/
|
|
40
|
+
readonly ContextLost: "ContextLost";
|
|
41
|
+
/**
|
|
42
|
+
* Triggered when context is restored
|
|
43
|
+
*/
|
|
44
|
+
readonly ContextRestored: "ContextRestored";
|
|
45
|
+
/**
|
|
46
|
+
* Triggered when there is unknown error
|
|
47
|
+
*/
|
|
48
|
+
readonly Error: "Error";
|
|
49
|
+
/**
|
|
50
|
+
* Triggered when the processor is restarted
|
|
51
|
+
*/
|
|
52
|
+
readonly ProcessorRestarted: "ProcessorRestarted";
|
|
53
|
+
/**
|
|
54
|
+
* Triggered when sampling error occurs
|
|
55
|
+
*/
|
|
56
|
+
readonly SamplingError: "SamplingError";
|
|
57
|
+
};
|
|
58
|
+
export type RenderingEvents = ExtractValueTypes<typeof RENDERING_EVENTS>;
|
|
27
59
|
export {};
|
package/dist/common/constants.js
CHANGED
|
@@ -4,20 +4,51 @@ export const FOREGROUND_THRESHOLD = 0.5;
|
|
|
4
4
|
export const BACKGROUND_BLUR_AMOUNT = 3; // Between 1 and 20
|
|
5
5
|
export const EDGE_BLUR_AMOUNT = 3; // Between 0 and 20
|
|
6
6
|
export const MASK_COMBINE_RATIO = 0.5;
|
|
7
|
+
/**
|
|
8
|
+
* Process status
|
|
9
|
+
*/
|
|
7
10
|
export const PROCESS_STATUS = {
|
|
8
|
-
|
|
11
|
+
Closed: 'closed',
|
|
12
|
+
Closing: 'closing',
|
|
13
|
+
Destroyed: 'destroyed',
|
|
14
|
+
Destroying: 'destroying',
|
|
9
15
|
Error: 'Error',
|
|
16
|
+
Idle: 'idle',
|
|
17
|
+
New: 'new',
|
|
10
18
|
Opened: 'opened',
|
|
11
19
|
Opening: 'opening',
|
|
12
20
|
Processing: 'processing',
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Closed: 'closed',
|
|
16
|
-
Destroying: 'destroying',
|
|
17
|
-
Destroyed: 'destroyed',
|
|
21
|
+
Updated: 'updated',
|
|
22
|
+
Updating: 'updating',
|
|
18
23
|
};
|
|
19
24
|
export const RENDER_EFFECT = {
|
|
20
25
|
None: 'none',
|
|
21
26
|
Blur: 'blur',
|
|
22
27
|
Overlay: 'overlay',
|
|
23
28
|
};
|
|
29
|
+
export const RENDERING_EVENTS = {
|
|
30
|
+
/**
|
|
31
|
+
* Triggered when failed to create a context
|
|
32
|
+
*/
|
|
33
|
+
ContextCreationError: 'ContextCreationError',
|
|
34
|
+
/**
|
|
35
|
+
* Triggered when context is lost
|
|
36
|
+
*/
|
|
37
|
+
ContextLost: 'ContextLost',
|
|
38
|
+
/**
|
|
39
|
+
* Triggered when context is restored
|
|
40
|
+
*/
|
|
41
|
+
ContextRestored: 'ContextRestored',
|
|
42
|
+
/**
|
|
43
|
+
* Triggered when there is unknown error
|
|
44
|
+
*/
|
|
45
|
+
Error: 'Error',
|
|
46
|
+
/**
|
|
47
|
+
* Triggered when the processor is restarted
|
|
48
|
+
*/
|
|
49
|
+
ProcessorRestarted: 'ProcessorRestarted',
|
|
50
|
+
/**
|
|
51
|
+
* Triggered when sampling error occurs
|
|
52
|
+
*/
|
|
53
|
+
SamplingError: 'SamplingError',
|
|
54
|
+
};
|