@pexip/media-processor 17.4.0 → 18.0.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 +30 -0
- package/dist/common/backends/webgl/blender.d.ts +11 -0
- package/dist/common/backends/webgl/blender.js +104 -0
- package/dist/common/backends/webgl/blur.d.ts +5 -0
- package/dist/common/backends/webgl/blur.js +153 -0
- package/dist/common/backends/webgl/canvas.d.ts +5 -0
- package/dist/common/backends/webgl/canvas.js +77 -0
- package/dist/common/backends/webgl/renderer.d.ts +8 -0
- package/dist/common/backends/webgl/renderer.js +126 -0
- package/dist/common/backends/webgl/shaders/blendFragmentShader.d.ts +1 -0
- package/dist/common/backends/webgl/shaders/blendFragmentShader.js +63 -0
- package/dist/common/backends/webgl/shaders/dualFilterBlurFragmentShader.d.ts +1 -0
- package/dist/common/backends/webgl/shaders/dualFilterBlurFragmentShader.js +45 -0
- package/dist/common/backends/webgl/shaders/textureFragmentShader.d.ts +1 -0
- package/dist/common/backends/webgl/shaders/textureFragmentShader.js +16 -0
- package/dist/common/backends/webgl/shaders/vertexShader.d.ts +1 -0
- package/dist/common/backends/webgl/shaders/vertexShader.js +19 -0
- package/dist/common/backends/webgl/texture.d.ts +6 -0
- package/dist/common/backends/webgl/texture.js +94 -0
- package/dist/common/backends/webgl/types.d.ts +5 -0
- package/dist/common/backends/webgl/types.js +1 -0
- package/dist/common/backends/webgl/webgl.mock.js +8 -0
- package/dist/common/backends/webgl/webglUtils.d.ts +80 -0
- package/dist/common/backends/webgl/webglUtils.js +194 -0
- package/dist/common/canvasRenderUtils.d.ts +62 -0
- package/dist/{main/video → common}/canvasRenderUtils.js +100 -61
- package/dist/common/constants.d.ts +27 -0
- package/dist/common/constants.js +23 -0
- package/dist/common/index.d.ts +9 -0
- package/dist/common/index.js +9 -0
- package/dist/common/m3.d.ts +17 -0
- package/dist/common/m3.js +69 -0
- package/dist/common/tsconfig.tsbuildinfo +1 -0
- package/dist/common/types/media.d.ts +22 -0
- package/dist/common/types/media.js +1 -0
- package/dist/common/types/messageEvents.d.ts +31 -0
- package/dist/common/types/messageEvents.js +1 -0
- package/dist/common/types/processor.d.ts +15 -0
- package/dist/common/types/processor.js +1 -0
- package/dist/common/types/render.d.ts +38 -0
- package/dist/common/types/render.js +1 -0
- package/dist/common/types/segmentation.d.ts +99 -0
- package/dist/common/types/segmentation.js +4 -0
- package/dist/common/types/utils.d.ts +19 -0
- package/dist/common/types/utils.js +1 -0
- package/dist/common/utils.d.ts +35 -0
- package/dist/common/utils.js +129 -0
- package/dist/main/benchUtils.d.ts +3 -2
- package/dist/main/benchUtils.js +7 -6
- package/dist/main/index.d.ts +2 -0
- package/dist/main/index.js +2 -0
- package/dist/main/process.d.ts +1 -11
- package/dist/main/process.js +0 -20
- package/dist/main/tsconfig.tsbuildinfo +1 -1
- package/dist/main/types.d.ts +2 -2
- package/dist/main/video/canvasTransform.d.ts +14 -5
- package/dist/main/video/canvasTransform.js +101 -86
- package/dist/main/video/constants.d.ts +0 -6
- package/dist/main/video/constants.js +0 -6
- package/dist/main/video/index.d.ts +2 -2
- package/dist/main/video/index.js +2 -2
- package/dist/main/video/load.d.ts +0 -14
- package/dist/main/video/load.js +0 -8
- package/dist/main/video/segmenters/mediapipe.d.ts +9 -11
- package/dist/main/video/segmenters/mediapipe.js +127 -77
- package/dist/main/video/typeGuards.d.ts +0 -1
- package/dist/main/video/typeGuards.js +2 -8
- package/dist/main/video/types.d.ts +19 -61
- package/dist/main/video/types.js +1 -20
- package/dist/main/video/utils.d.ts +5 -12
- package/dist/main/video/utils.js +5 -152
- package/dist/main/video/video.js +1 -0
- package/dist/main/video/videoStreamTrackProcessor.js +7 -4
- package/dist/workers/global.d.js +0 -0
- package/dist/workers/mediaWorker.d.ts +1 -0
- package/dist/workers/mediaWorker.js +188 -0
- package/dist/workers/tsconfig.tsbuildinfo +1 -1
- package/package.json +21 -13
- package/dist/main/video/canvasRenderUtils.d.ts +0 -27
- package/dist/main/video/segmenters/index.d.ts +0 -1
- package/dist/main/video/segmenters/index.js +0 -1
- package/dist/workers/index.js +0 -1
- /package/dist/{workers/index.d.ts → common/backends/webgl/webgl.mock.d.ts} +0 -0
|
@@ -1,35 +1,16 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*/
|
|
8
|
-
export type MaskUnderlyingType = 'canvasimagesource' | 'imagedata' | 'tensor';
|
|
9
|
-
export interface Mask {
|
|
10
|
-
toCanvasImageSource(): Promise<CanvasImageSource>;
|
|
11
|
-
toImageData(): Promise<ImageData>;
|
|
12
|
-
toTensor(): Promise<Tensor3D>;
|
|
13
|
-
getUnderlyingType(): MaskUnderlyingType;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Interfaces from "tensorflow-models/body-segmentation" interfaces
|
|
17
|
-
*/
|
|
18
|
-
export interface Segmentation {
|
|
19
|
-
maskValueToLabel: (maskValue: number) => string;
|
|
20
|
-
mask: Mask;
|
|
21
|
-
}
|
|
1
|
+
import type { ProcessStatus } from '../../common/constants';
|
|
2
|
+
import type { ProcessInputType, VideoFrameLike } from '../../common/types/media';
|
|
3
|
+
import type { RendererOptions } from '../../common/types/render';
|
|
4
|
+
import type { SegmentationModelAsset } from '../../common/types/segmentation';
|
|
5
|
+
import type { ProcessorOptions } from '../../common/types/processor';
|
|
6
|
+
import type { Transform } from '../types';
|
|
22
7
|
export type Color = {
|
|
23
8
|
r: number;
|
|
24
9
|
g: number;
|
|
25
10
|
b: number;
|
|
26
11
|
a: number;
|
|
27
12
|
};
|
|
28
|
-
export type
|
|
29
|
-
export type RenderEffects = (typeof RENDER_EFFECTS)[number];
|
|
30
|
-
export type ProcessInputType = ImageData | HTMLVideoElement | HTMLImageElement | OffscreenCanvas | HTMLCanvasElement | ImageBitmap;
|
|
31
|
-
export type InputFrame = CanvasImageSource | VideoFrame;
|
|
32
|
-
export type ImageType = CanvasImageSource | ProcessInputType | VideoFrame;
|
|
13
|
+
export type InputFrame = HTMLCanvasElement | OffscreenCanvas | VideoFrame | ImageBitmap;
|
|
33
14
|
interface ProcessingSize {
|
|
34
15
|
/**
|
|
35
16
|
* Processing Width size
|
|
@@ -40,58 +21,35 @@ interface ProcessingSize {
|
|
|
40
21
|
*/
|
|
41
22
|
height: number;
|
|
42
23
|
}
|
|
43
|
-
export interface RenderParams extends ProcessingSize {
|
|
44
|
-
/**
|
|
45
|
-
* Range in between 0 and 1
|
|
46
|
-
* @defaultValue `0.5`
|
|
47
|
-
*/
|
|
48
|
-
foregroundThreshold: number;
|
|
49
|
-
/**
|
|
50
|
-
* Range in between 0 and 20
|
|
51
|
-
* @defaultValue `3`
|
|
52
|
-
*/
|
|
53
|
-
backgroundBlurAmount: number;
|
|
54
|
-
/**
|
|
55
|
-
* Range in between 0 and 20
|
|
56
|
-
* @defaultValue `3`
|
|
57
|
-
*/
|
|
58
|
-
edgeBlurAmount: number;
|
|
59
|
-
/**
|
|
60
|
-
* @defaultValue `false`
|
|
61
|
-
*/
|
|
62
|
-
flipHorizontal: boolean;
|
|
63
|
-
/**
|
|
64
|
-
* @defaultValue `none`
|
|
65
|
-
*/
|
|
66
|
-
effects: RenderEffects;
|
|
67
|
-
/**
|
|
68
|
-
* Background image used for background replacement
|
|
69
|
-
*/
|
|
70
|
-
backgroundImage: Canvas | undefined;
|
|
71
|
-
}
|
|
72
24
|
export interface AsyncAssets {
|
|
73
25
|
tfjsCoreLoaded: boolean;
|
|
74
26
|
tfjsBackendLoaded: boolean;
|
|
75
27
|
glueLoaded: boolean;
|
|
76
28
|
}
|
|
77
|
-
export type ProcessStatus = 'created' | 'opened' | 'opening' | 'processing' | 'idle' | 'closed' | 'destroying' | 'destroyed';
|
|
78
29
|
export interface Process {
|
|
79
30
|
status: ProcessStatus;
|
|
80
31
|
open(): Promise<void>;
|
|
81
32
|
close(): void;
|
|
82
33
|
destroy(): Promise<void>;
|
|
83
34
|
}
|
|
35
|
+
export interface BackgroundImage {
|
|
36
|
+
key: string;
|
|
37
|
+
image: Blob;
|
|
38
|
+
}
|
|
84
39
|
export interface Segmenter extends Process, ProcessingSize {
|
|
85
|
-
|
|
86
|
-
|
|
40
|
+
modelAsset: SegmentationModelAsset;
|
|
41
|
+
backgroundImage?: BackgroundImage;
|
|
42
|
+
open(options?: ProcessorOptions): Promise<void>;
|
|
43
|
+
update(options: ProcessorOptions): Promise<void>;
|
|
44
|
+
process(input: VideoFrameLike, options?: RendererOptions): Promise<VideoFrameLike | undefined>;
|
|
87
45
|
}
|
|
88
46
|
export interface Detector<T> extends Process {
|
|
89
47
|
detect(input: ProcessInputType): Promise<T>;
|
|
90
48
|
}
|
|
91
|
-
export interface SegmentationParams extends
|
|
49
|
+
export interface SegmentationParams extends RendererOptions {
|
|
92
50
|
segmenter: Segmenter;
|
|
93
|
-
|
|
94
|
-
|
|
51
|
+
width: number;
|
|
52
|
+
height: number;
|
|
95
53
|
}
|
|
96
54
|
export type SegmentationTransform = Transform<InputFrame, InputFrame> & SegmentationParams & Omit<Process, 'open'>;
|
|
97
55
|
export {};
|
package/dist/main/video/types.js
CHANGED
|
@@ -1,20 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
/**
|
|
3
|
-
* Pass through, and thus there is no effects applied
|
|
4
|
-
*/
|
|
5
|
-
'none',
|
|
6
|
-
/**
|
|
7
|
-
* Background blur effects
|
|
8
|
-
*/
|
|
9
|
-
'blur',
|
|
10
|
-
/**
|
|
11
|
-
* Background overlay effects
|
|
12
|
-
*/
|
|
13
|
-
'overlay',
|
|
14
|
-
];
|
|
15
|
-
export const SEG_MODELS = [
|
|
16
|
-
/**
|
|
17
|
-
* Mediapipe's Selfie Segmentation model
|
|
18
|
-
*/
|
|
19
|
-
'mediapipeSelfie',
|
|
20
|
-
];
|
|
1
|
+
export {};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { Tensor3D } from '@tensorflow/tfjs-core';
|
|
2
1
|
/**
|
|
3
2
|
* We support several ways to get image inputs.
|
|
4
3
|
*/
|
|
5
4
|
export type InputImage = HTMLVideoElement | HTMLImageElement | HTMLCanvasElement;
|
|
6
|
-
import type {
|
|
5
|
+
import type { Frame, Canvas, CanvasContext, Callback } from '../types';
|
|
7
6
|
import { subscribeVisibilityChangeEvent } from '../utils';
|
|
8
|
-
import type {
|
|
7
|
+
import type { ImageType, ProcessInputType, Rect } from '../../common/types/media';
|
|
8
|
+
import type { Color } from './types';
|
|
9
9
|
/**
|
|
10
10
|
* Draw the source onto the provided canvas according to the destination rect
|
|
11
11
|
*
|
|
@@ -62,18 +62,11 @@ export declare const playVideo: (video: HTMLVideoElement) => Promise<void>;
|
|
|
62
62
|
export declare const loadImage: (image: HTMLImageElement, src: string) => Promise<void>;
|
|
63
63
|
export declare const toNumber: (value: number | SVGAnimatedLength) => number;
|
|
64
64
|
export declare const getCanvasRenderingContext2D: (canvas: Canvas, options?: CanvasRenderingContext2DSettings) => CanvasRenderingContext2D;
|
|
65
|
-
export declare const
|
|
66
|
-
export declare const
|
|
67
|
-
export declare const toImageDataLossy: (image: CanvasImageSource | Tensor3D) => Promise<ImageData>;
|
|
68
|
-
export declare const toTensorLossy: (image: CanvasImageSource | ImageData) => Promise<Tensor3D>;
|
|
69
|
-
/**
|
|
70
|
-
* Construct a Segmentation object with tensorflow-models/shared utils
|
|
71
|
-
*/
|
|
72
|
-
export declare const toSegmentation: (data: CanvasImageSource | ImageData | Tensor3D, type: MaskUnderlyingType, maskValueToLabel: (value: number) => string) => Segmentation;
|
|
65
|
+
export declare const hasVideoFrameSupport: () => boolean;
|
|
66
|
+
export declare const isVideoFrame: (t: unknown) => t is VideoFrame;
|
|
73
67
|
export declare const flipCanvasHorizontal: (canvas: Canvas) => void;
|
|
74
68
|
export declare const drawStroke: (bytes: Uint8ClampedArray, row: number, column: number, width: number, radius: number, color?: Color) => void;
|
|
75
69
|
export declare const isSegmentationBoundary: (data: Uint8ClampedArray, row: number, column: number, width: number, isForegroundId: boolean[], alphaCutoff: number, radius?: number) => boolean;
|
|
76
|
-
export declare const toBinaryMask: (segmentation: Segmentation | Segmentation[], foreground?: Color, background?: Color, drawContour?: boolean, foregroundThreshold?: number, foregroundMaskValues?: number[]) => Promise<ImageData | null>;
|
|
77
70
|
type Draw = (input: ImageType) => Promise<Canvas>;
|
|
78
71
|
export declare const createInputImageConvertor: (draw: Draw) => (input: ProcessInputType) => Promise<InputImage>;
|
|
79
72
|
export declare const ensure: <T>(prop: T, message?: string) => NonNullable<T>;
|
package/dist/main/video/utils.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Tensor, browser } from '@tensorflow/tfjs-core/dist/base.js';
|
|
2
1
|
import { createAsyncCallbackLoop, subscribeVisibilityChangeEvent, } from '../utils';
|
|
3
2
|
/**
|
|
4
3
|
* Draw the source onto the provided canvas according to the destination rect
|
|
@@ -165,99 +164,12 @@ export const getCanvasRenderingContext2D = (canvas, options) => {
|
|
|
165
164
|
}
|
|
166
165
|
return context;
|
|
167
166
|
};
|
|
168
|
-
export const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return
|
|
167
|
+
export const hasVideoFrameSupport = () => 'VideoFrame' in window;
|
|
168
|
+
export const isVideoFrame = (t) => {
|
|
169
|
+
if (hasVideoFrameSupport() && t instanceof VideoFrame) {
|
|
170
|
+
return true;
|
|
172
171
|
}
|
|
173
|
-
|
|
174
|
-
return { height: image.displayHeight, width: image.displayWidth };
|
|
175
|
-
}
|
|
176
|
-
if ('offsetHeight' in image &&
|
|
177
|
-
image.offsetHeight !== 0 &&
|
|
178
|
-
'offsetWidth' in image &&
|
|
179
|
-
image.offsetWidth !== 0) {
|
|
180
|
-
return { height: image.offsetHeight, width: image.offsetWidth };
|
|
181
|
-
}
|
|
182
|
-
if ('height' in image &&
|
|
183
|
-
image.height !== 0 &&
|
|
184
|
-
'width' in image &&
|
|
185
|
-
image.width !== 0) {
|
|
186
|
-
return { height: toNumber(image.height), width: toNumber(image.width) };
|
|
187
|
-
}
|
|
188
|
-
throw new Error('Unknown input image');
|
|
189
|
-
};
|
|
190
|
-
export const toHTMLCanvasElementLossy = async (image) => {
|
|
191
|
-
const { width, height } = getImageSize(image);
|
|
192
|
-
const canvas = createCanvas(width, height);
|
|
193
|
-
if (image instanceof Tensor) {
|
|
194
|
-
await browser.toPixels(image, canvas);
|
|
195
|
-
return canvas;
|
|
196
|
-
}
|
|
197
|
-
const context = getCanvasRenderingContext2D(canvas);
|
|
198
|
-
if (image instanceof ImageData) {
|
|
199
|
-
context.putImageData(image, 0, 0);
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
context.drawImage(image, 0, 0);
|
|
203
|
-
}
|
|
204
|
-
return canvas;
|
|
205
|
-
};
|
|
206
|
-
export const toImageDataLossy = async (image) => {
|
|
207
|
-
const { width, height } = getImageSize(image);
|
|
208
|
-
if (image instanceof Tensor) {
|
|
209
|
-
return new ImageData(await browser.toPixels(image), width, height);
|
|
210
|
-
}
|
|
211
|
-
const canvas = createOffscreenCanvas(width, height);
|
|
212
|
-
const context = getCanvasRenderingContext2D(canvas);
|
|
213
|
-
context.drawImage(image, 0, 0);
|
|
214
|
-
return context.getImageData(0, 0, canvas.width, canvas.height);
|
|
215
|
-
};
|
|
216
|
-
export const toTensorLossy = async (image) => {
|
|
217
|
-
const pixelsInput = image instanceof SVGImageElement ||
|
|
218
|
-
image instanceof OffscreenCanvas ||
|
|
219
|
-
image instanceof VideoFrame
|
|
220
|
-
? await toHTMLCanvasElementLossy(image)
|
|
221
|
-
: image;
|
|
222
|
-
return browser.fromPixels(pixelsInput, 4);
|
|
223
|
-
};
|
|
224
|
-
/**
|
|
225
|
-
* Construct a Segmentation object with tensorflow-models/shared utils
|
|
226
|
-
*/
|
|
227
|
-
export const toSegmentation = (data, type, maskValueToLabel) => {
|
|
228
|
-
const mask = {
|
|
229
|
-
toCanvasImageSource: async () => {
|
|
230
|
-
if (data instanceof HTMLCanvasElement) {
|
|
231
|
-
return data;
|
|
232
|
-
}
|
|
233
|
-
if (data instanceof HTMLVideoElement ||
|
|
234
|
-
data instanceof ImageBitmap ||
|
|
235
|
-
data instanceof HTMLImageElement) {
|
|
236
|
-
const canvas = createCanvas(data.width, data.height);
|
|
237
|
-
const context = canvas.getContext('2d');
|
|
238
|
-
context?.drawImage(data, 0, 0, data.width, data.height);
|
|
239
|
-
return canvas;
|
|
240
|
-
}
|
|
241
|
-
return await toHTMLCanvasElementLossy(data);
|
|
242
|
-
},
|
|
243
|
-
toImageData: async () => {
|
|
244
|
-
if (data instanceof ImageData) {
|
|
245
|
-
return data;
|
|
246
|
-
}
|
|
247
|
-
return await toImageDataLossy(data);
|
|
248
|
-
},
|
|
249
|
-
toTensor: async () => {
|
|
250
|
-
if (data instanceof Tensor) {
|
|
251
|
-
return data;
|
|
252
|
-
}
|
|
253
|
-
return await toTensorLossy(data);
|
|
254
|
-
},
|
|
255
|
-
getUnderlyingType: () => type,
|
|
256
|
-
};
|
|
257
|
-
return {
|
|
258
|
-
maskValueToLabel,
|
|
259
|
-
mask,
|
|
260
|
-
};
|
|
172
|
+
return false;
|
|
261
173
|
};
|
|
262
174
|
export const flipCanvasHorizontal = (canvas) => {
|
|
263
175
|
const ctx = getCanvasRenderingContext2D(canvas);
|
|
@@ -300,65 +212,6 @@ export const isSegmentationBoundary = (data, row, column, width, isForegroundId,
|
|
|
300
212
|
}
|
|
301
213
|
return numberBackgroundPixels > 0;
|
|
302
214
|
};
|
|
303
|
-
export const toBinaryMask = async (segmentation, foreground = {
|
|
304
|
-
r: 0,
|
|
305
|
-
g: 0,
|
|
306
|
-
b: 0,
|
|
307
|
-
a: 0,
|
|
308
|
-
}, background = {
|
|
309
|
-
r: 0,
|
|
310
|
-
g: 0,
|
|
311
|
-
b: 0,
|
|
312
|
-
a: 255,
|
|
313
|
-
}, drawContour = false, foregroundThreshold = 0.5, foregroundMaskValues = Array.from({ length: 256 }, (_, i) => i)) => {
|
|
314
|
-
const segmentations = !Array.isArray(segmentation)
|
|
315
|
-
? [segmentation]
|
|
316
|
-
: segmentation;
|
|
317
|
-
if (segmentations.length === 0) {
|
|
318
|
-
return null;
|
|
319
|
-
}
|
|
320
|
-
const masks = await Promise.all(segmentations.map(segmentation => segmentation.mask.toImageData()));
|
|
321
|
-
const [imageData] = masks;
|
|
322
|
-
if (!imageData) {
|
|
323
|
-
return null;
|
|
324
|
-
}
|
|
325
|
-
const { width, height } = imageData;
|
|
326
|
-
const bytes = new Uint8ClampedArray(width * height * 4);
|
|
327
|
-
const alphaCutoff = Math.round(255 * foregroundThreshold);
|
|
328
|
-
const isForegroundId = new Array(256).fill(false);
|
|
329
|
-
foregroundMaskValues.forEach(id => (isForegroundId[id] = true));
|
|
330
|
-
for (let i = 0; i < height; i++) {
|
|
331
|
-
for (let j = 0; j < width; j++) {
|
|
332
|
-
const n = i * width + j;
|
|
333
|
-
bytes[4 * n + 0] = background.r;
|
|
334
|
-
bytes[4 * n + 1] = background.g;
|
|
335
|
-
bytes[4 * n + 2] = background.b;
|
|
336
|
-
bytes[4 * n + 3] = background.a;
|
|
337
|
-
for (const mask of masks) {
|
|
338
|
-
const maskForegroundColor = mask.data[4 * n];
|
|
339
|
-
const maskAlphaColor = mask.data[4 * n + 3];
|
|
340
|
-
if (maskForegroundColor !== undefined &&
|
|
341
|
-
isForegroundId[maskForegroundColor] &&
|
|
342
|
-
maskAlphaColor !== undefined &&
|
|
343
|
-
maskAlphaColor >= alphaCutoff) {
|
|
344
|
-
bytes[4 * n] = foreground.r;
|
|
345
|
-
bytes[4 * n + 1] = foreground.g;
|
|
346
|
-
bytes[4 * n + 2] = foreground.b;
|
|
347
|
-
bytes[4 * n + 3] = foreground.a;
|
|
348
|
-
if (drawContour &&
|
|
349
|
-
i - 1 >= 0 &&
|
|
350
|
-
i + 1 < height &&
|
|
351
|
-
j - 1 >= 0 &&
|
|
352
|
-
j + 1 < width &&
|
|
353
|
-
isSegmentationBoundary(mask.data, i, j, width, isForegroundId, alphaCutoff)) {
|
|
354
|
-
drawStroke(bytes, i, j, width, 1);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
return new ImageData(bytes, width, height);
|
|
361
|
-
};
|
|
362
215
|
export const createInputImageConvertor = (draw) => async (input) => {
|
|
363
216
|
return (input instanceof ImageData || input instanceof ImageBitmap
|
|
364
217
|
? await draw(input)
|
package/dist/main/video/video.js
CHANGED
|
@@ -34,6 +34,7 @@ export const createVideoProcessor = (transformers, processTrack) => {
|
|
|
34
34
|
stopStreamTracks(props.outputStream);
|
|
35
35
|
props.outputStream = undefined;
|
|
36
36
|
props.processing = false;
|
|
37
|
+
transformers.forEach(transformer => transformer.close());
|
|
37
38
|
};
|
|
38
39
|
const destroy = async () => {
|
|
39
40
|
close();
|
|
@@ -2,9 +2,11 @@ import { createMediaStreamTrackProcessor } from '../processor';
|
|
|
2
2
|
import { createMediaStreamTrackGenerator } from '../generator';
|
|
3
3
|
import { createStreamTransformer } from '../transformer';
|
|
4
4
|
import { stopStreamTracks } from '../utils';
|
|
5
|
+
import { PROCESSING_HEIGHT, PROCESSING_WIDTH } from '../../common/constants';
|
|
6
|
+
import { getImageSize } from '../../common/canvasRenderUtils';
|
|
5
7
|
import { adaptInputFrameTransformer, nullTransformController, } from './transformer';
|
|
6
|
-
import { toVideoElement, playVideo, createFrameCallbackRequest, createCanvas,
|
|
7
|
-
import { AbortReason,
|
|
8
|
+
import { toVideoElement, playVideo, createFrameCallbackRequest, createCanvas, getCanvasRenderingContext2D, } from './utils';
|
|
9
|
+
import { AbortReason, FRAME_RATE } from './constants';
|
|
8
10
|
export const createVideoTrackProcessor = () => (track, transformers, { signal } = {}) => {
|
|
9
11
|
if (!transformers.length) {
|
|
10
12
|
return Promise.resolve(track);
|
|
@@ -53,11 +55,12 @@ export const createVideoTrackProcessorWithFallback = ({ width = PROCESSING_WIDTH
|
|
|
53
55
|
return;
|
|
54
56
|
}
|
|
55
57
|
const frameSize = getImageSize(frame);
|
|
56
|
-
if (frameSize.height !== outputCanvas.height
|
|
58
|
+
if (frameSize.height !== outputCanvas.height ||
|
|
59
|
+
frameSize.width !== outputCanvas.width) {
|
|
57
60
|
outputCanvas.height = frameSize.height;
|
|
58
61
|
outputCanvas.width = frameSize.width;
|
|
59
62
|
}
|
|
60
|
-
ctx.drawImage(frame, 0, 0,
|
|
63
|
+
ctx.drawImage(frame, 0, 0, outputCanvas.width, outputCanvas.height);
|
|
61
64
|
},
|
|
62
65
|
terminate: () => {
|
|
63
66
|
stop();
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|