@voltkit-rtc/client 0.7.3 → 0.9.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.
Files changed (129) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +346 -2
  3. package/dist/cjs/adaptive.d.ts +104 -0
  4. package/dist/cjs/adaptive.d.ts.map +1 -0
  5. package/dist/cjs/adaptive.js +263 -0
  6. package/dist/cjs/adaptive.js.map +1 -0
  7. package/dist/cjs/devices.d.ts +42 -0
  8. package/dist/cjs/devices.d.ts.map +1 -0
  9. package/dist/cjs/devices.js +56 -0
  10. package/dist/cjs/devices.js.map +1 -0
  11. package/dist/cjs/diagnostics.d.ts +65 -0
  12. package/dist/cjs/diagnostics.d.ts.map +1 -0
  13. package/dist/cjs/diagnostics.js +69 -0
  14. package/dist/cjs/diagnostics.js.map +1 -0
  15. package/dist/cjs/effects-core.d.ts +95 -0
  16. package/dist/cjs/effects-core.d.ts.map +1 -0
  17. package/dist/cjs/effects-core.js +154 -0
  18. package/dist/cjs/effects-core.js.map +1 -0
  19. package/dist/cjs/effects-gl.d.ts +79 -0
  20. package/dist/cjs/effects-gl.d.ts.map +1 -0
  21. package/dist/cjs/effects-gl.js +351 -0
  22. package/dist/cjs/effects-gl.js.map +1 -0
  23. package/dist/cjs/fallback.d.ts +81 -0
  24. package/dist/cjs/fallback.d.ts.map +1 -0
  25. package/dist/cjs/fallback.js +148 -0
  26. package/dist/cjs/fallback.js.map +1 -0
  27. package/dist/cjs/health.d.ts +70 -0
  28. package/dist/cjs/health.d.ts.map +1 -0
  29. package/dist/cjs/health.js +116 -0
  30. package/dist/cjs/health.js.map +1 -0
  31. package/dist/cjs/index.d.ts +396 -0
  32. package/dist/cjs/index.d.ts.map +1 -1
  33. package/dist/cjs/index.js +1367 -81
  34. package/dist/cjs/index.js.map +1 -1
  35. package/dist/cjs/link.d.ts +99 -0
  36. package/dist/cjs/link.d.ts.map +1 -0
  37. package/dist/cjs/link.js +219 -0
  38. package/dist/cjs/link.js.map +1 -0
  39. package/dist/cjs/noise-suppression.d.ts +44 -0
  40. package/dist/cjs/noise-suppression.d.ts.map +1 -0
  41. package/dist/cjs/noise-suppression.js +103 -0
  42. package/dist/cjs/noise-suppression.js.map +1 -0
  43. package/dist/cjs/preflight.d.ts +79 -0
  44. package/dist/cjs/preflight.d.ts.map +1 -0
  45. package/dist/cjs/preflight.js +159 -0
  46. package/dist/cjs/preflight.js.map +1 -0
  47. package/dist/cjs/processors.d.ts +34 -0
  48. package/dist/cjs/processors.d.ts.map +1 -0
  49. package/dist/cjs/processors.js +10 -0
  50. package/dist/cjs/processors.js.map +1 -0
  51. package/dist/cjs/speakers.d.ts +34 -0
  52. package/dist/cjs/speakers.d.ts.map +1 -0
  53. package/dist/cjs/speakers.js +71 -0
  54. package/dist/cjs/speakers.js.map +1 -0
  55. package/dist/cjs/video-effects.d.ts +93 -0
  56. package/dist/cjs/video-effects.d.ts.map +1 -0
  57. package/dist/cjs/video-effects.js +493 -0
  58. package/dist/cjs/video-effects.js.map +1 -0
  59. package/dist/esm/adaptive.d.ts +104 -0
  60. package/dist/esm/adaptive.d.ts.map +1 -0
  61. package/dist/esm/adaptive.js +256 -0
  62. package/dist/esm/adaptive.js.map +1 -0
  63. package/dist/esm/devices.d.ts +42 -0
  64. package/dist/esm/devices.d.ts.map +1 -0
  65. package/dist/esm/devices.js +50 -0
  66. package/dist/esm/devices.js.map +1 -0
  67. package/dist/esm/diagnostics.d.ts +65 -0
  68. package/dist/esm/diagnostics.d.ts.map +1 -0
  69. package/dist/esm/diagnostics.js +65 -0
  70. package/dist/esm/diagnostics.js.map +1 -0
  71. package/dist/esm/effects-core.d.ts +95 -0
  72. package/dist/esm/effects-core.d.ts.map +1 -0
  73. package/dist/esm/effects-core.js +142 -0
  74. package/dist/esm/effects-core.js.map +1 -0
  75. package/dist/esm/effects-gl.d.ts +79 -0
  76. package/dist/esm/effects-gl.d.ts.map +1 -0
  77. package/dist/esm/effects-gl.js +347 -0
  78. package/dist/esm/effects-gl.js.map +1 -0
  79. package/dist/esm/fallback.d.ts +81 -0
  80. package/dist/esm/fallback.d.ts.map +1 -0
  81. package/dist/esm/fallback.js +142 -0
  82. package/dist/esm/fallback.js.map +1 -0
  83. package/dist/esm/health.d.ts +70 -0
  84. package/dist/esm/health.d.ts.map +1 -0
  85. package/dist/esm/health.js +111 -0
  86. package/dist/esm/health.js.map +1 -0
  87. package/dist/esm/index.d.ts +396 -0
  88. package/dist/esm/index.d.ts.map +1 -1
  89. package/dist/esm/index.js +1365 -81
  90. package/dist/esm/index.js.map +1 -1
  91. package/dist/esm/link.d.ts +99 -0
  92. package/dist/esm/link.d.ts.map +1 -0
  93. package/dist/esm/link.js +214 -0
  94. package/dist/esm/link.js.map +1 -0
  95. package/dist/esm/noise-suppression.d.ts +44 -0
  96. package/dist/esm/noise-suppression.d.ts.map +1 -0
  97. package/dist/esm/noise-suppression.js +99 -0
  98. package/dist/esm/noise-suppression.js.map +1 -0
  99. package/dist/esm/preflight.d.ts +79 -0
  100. package/dist/esm/preflight.d.ts.map +1 -0
  101. package/dist/esm/preflight.js +153 -0
  102. package/dist/esm/preflight.js.map +1 -0
  103. package/dist/esm/processors.d.ts +34 -0
  104. package/dist/esm/processors.d.ts.map +1 -0
  105. package/dist/esm/processors.js +9 -0
  106. package/dist/esm/processors.js.map +1 -0
  107. package/dist/esm/speakers.d.ts +34 -0
  108. package/dist/esm/speakers.d.ts.map +1 -0
  109. package/dist/esm/speakers.js +67 -0
  110. package/dist/esm/speakers.js.map +1 -0
  111. package/dist/esm/video-effects.d.ts +93 -0
  112. package/dist/esm/video-effects.d.ts.map +1 -0
  113. package/dist/esm/video-effects.js +488 -0
  114. package/dist/esm/video-effects.js.map +1 -0
  115. package/package.json +31 -1
  116. package/src/adaptive.ts +295 -0
  117. package/src/devices.ts +70 -0
  118. package/src/diagnostics.ts +94 -0
  119. package/src/effects-core.ts +177 -0
  120. package/src/effects-gl.ts +384 -0
  121. package/src/fallback.ts +169 -0
  122. package/src/health.ts +127 -0
  123. package/src/index.ts +1364 -81
  124. package/src/link.ts +255 -0
  125. package/src/noise-suppression.ts +135 -0
  126. package/src/preflight.ts +191 -0
  127. package/src/processors.ts +35 -0
  128. package/src/speakers.ts +66 -0
  129. package/src/video-effects.ts +552 -0
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ /**
3
+ * Video effects, the parts that need no browser (docs/implementation-progress/RTC_PERF_PROGRESS.md P3-5): settings,
4
+ * fitting a background image, the size segmentation runs at, and pacing it on a slow device. Kept apart from the
5
+ * WebGL and MediaPipe code so they are tested in Node.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.MonotonicClock = exports.SegmentationPacer = exports.MAX_SEGMENT_EVERY = exports.MASK_FOLLOW = exports.DEFAULT_BLUR = exports.DEFAULT_BEAUTY = void 0;
9
+ exports.beautySettings = beautySettings;
10
+ exports.blurLevel = blurLevel;
11
+ exports.blurSigma = blurSigma;
12
+ exports.backgroundMode = backgroundMode;
13
+ exports.coverFit = coverFit;
14
+ exports.segmentationSize = segmentationSize;
15
+ exports.smoothMask = smoothMask;
16
+ exports.DEFAULT_BEAUTY = Object.freeze({ smooth: 0.5, brighten: 0.3, redness: 0.1, sharpen: 0.3 });
17
+ /** The blur behind the person, 1 (light) to 10 (strong). */
18
+ exports.DEFAULT_BLUR = 5;
19
+ const unit = (value, fallback) => typeof value === 'number' && Number.isFinite(value) ? Math.min(1, Math.max(0, value)) : fallback;
20
+ /** Beauty settings from what the app passed: `true` is the defaults, `false`/`null` is off. */
21
+ function beautySettings(options) {
22
+ if (!options)
23
+ return null;
24
+ const o = options === true ? {} : options;
25
+ return {
26
+ smooth: unit(o.smooth, exports.DEFAULT_BEAUTY.smooth),
27
+ brighten: unit(o.brighten, exports.DEFAULT_BEAUTY.brighten),
28
+ redness: unit(o.redness, exports.DEFAULT_BEAUTY.redness),
29
+ sharpen: unit(o.sharpen, exports.DEFAULT_BEAUTY.sharpen),
30
+ };
31
+ }
32
+ /** A blur level from what the app passed: 1-10, rounded; anything else is the default. */
33
+ function blurLevel(value) {
34
+ return typeof value === 'number' && Number.isFinite(value) ? Math.min(10, Math.max(1, Math.round(value))) : exports.DEFAULT_BLUR;
35
+ }
36
+ /**
37
+ * The blur's Gaussian sigma, in texels of the quarter-size picture it is computed on: a share of the picture's height,
38
+ * so a level looks the same at 480p and 1080p.
39
+ */
40
+ function blurSigma(level, blurHeight) {
41
+ return Math.max(1, (blurLevel(level) / 10) * (blurHeight / 14));
42
+ }
43
+ /** What the background setting asks of the pipeline. */
44
+ function backgroundMode(setting) {
45
+ if (setting === 'blur')
46
+ return 'blur';
47
+ if (setting && typeof setting === 'object' && 'image' in setting && setting.image)
48
+ return 'image';
49
+ return 'none';
50
+ }
51
+ /**
52
+ * Fit a background picture to the frame the way CSS `object-fit: cover` does: it fills the frame, cropped evenly on
53
+ * the long side, never stretched. Returns the texture transform `imageUv = frameUv * scale + offset`.
54
+ */
55
+ function coverFit(imageWidth, imageHeight, frameWidth, frameHeight) {
56
+ if (!(imageWidth > 0 && imageHeight > 0 && frameWidth > 0 && frameHeight > 0))
57
+ return { sx: 1, sy: 1, ox: 0, oy: 0 };
58
+ const image = imageWidth / imageHeight;
59
+ const frame = frameWidth / frameHeight;
60
+ if (image > frame) {
61
+ // Wider than the frame: its sides are cropped.
62
+ const sx = frame / image;
63
+ return { sx, sy: 1, ox: (1 - sx) / 2, oy: 0 };
64
+ }
65
+ const sy = image / frame;
66
+ return { sx: 1, sy, ox: 0, oy: (1 - sy) / 2 };
67
+ }
68
+ /** The size the person is found at: the frame scaled so its longer side is `longSide` (the model's input). */
69
+ function segmentationSize(width, height, longSide = 256) {
70
+ if (!(width > 0 && height > 0))
71
+ return { width: longSide, height: longSide };
72
+ const scale = longSide / Math.max(width, height);
73
+ return { width: Math.max(1, Math.round(width * scale)), height: Math.max(1, Math.round(height * scale)) };
74
+ }
75
+ /** How fast the mask follows a new one: lower is steadier between frames, higher follows movement sooner. */
76
+ exports.MASK_FOLLOW = 0.65;
77
+ /**
78
+ * Smooth the person mask between frames (Stream's temporal smoothing), against flicker at the edges, and write it as
79
+ * bytes for the GPU. `steady` keeps the running mask; a new size starts it over.
80
+ */
81
+ function smoothMask(confidence, steady, out, follow = exports.MASK_FOLLOW) {
82
+ const fresh = steady === null || steady.length !== confidence.length;
83
+ const running = fresh ? new Float32Array(confidence) : steady;
84
+ for (let i = 0; i < confidence.length; i += 1) {
85
+ const value = Math.min(1, Math.max(0, confidence[i]));
86
+ const next = fresh ? value : running[i] + (value - running[i]) * follow;
87
+ running[i] = next;
88
+ out[i] = Math.round(next * 255);
89
+ }
90
+ return running;
91
+ }
92
+ /** The most frames a mask is reused for before the device is called overloaded. */
93
+ exports.MAX_SEGMENT_EVERY = 6;
94
+ /**
95
+ * Amazon Chime's adaptive background filter: finding the person is the expensive part, so when it takes too much of
96
+ * each frame's time it runs only every Nth frame and the last mask is reused -- the picture still runs at the camera's
97
+ * rate. N comes back down once it is cheap again. `overloaded` is the point where even that is not enough.
98
+ */
99
+ class SegmentationPacer {
100
+ maxEvery;
101
+ average = null;
102
+ changedAt = Number.NEGATIVE_INFINITY;
103
+ every = 1;
104
+ constructor(maxEvery = exports.MAX_SEGMENT_EVERY) {
105
+ this.maxEvery = maxEvery;
106
+ }
107
+ /** Run segmentation on every this-many frames. */
108
+ get interval() {
109
+ return this.every;
110
+ }
111
+ /** Average milliseconds one segmentation takes. */
112
+ get segmentMs() {
113
+ return this.average ?? 0;
114
+ }
115
+ shouldSegment(frameIndex) {
116
+ return frameIndex % this.every === 0;
117
+ }
118
+ /** The share of the frame time segmentation takes now, given how often it runs. */
119
+ load(frameIntervalMs) {
120
+ if (this.average === null || !(frameIntervalMs > 0))
121
+ return 0;
122
+ return this.average / (this.every * frameIntervalMs);
123
+ }
124
+ /** Whether segmenting even this rarely still takes too long. */
125
+ overloaded(frameIntervalMs) {
126
+ return this.every >= this.maxEvery && this.load(frameIntervalMs) > 0.3;
127
+ }
128
+ /** One segmentation took `ms`, at a frame interval of `frameIntervalMs`. */
129
+ report(ms, frameIntervalMs, now) {
130
+ if (!Number.isFinite(ms) || ms < 0)
131
+ return;
132
+ this.average = this.average === null ? ms : this.average * 0.8 + ms * 0.2;
133
+ const load = this.load(frameIntervalMs);
134
+ if (load > 0.3 && this.every < this.maxEvery && now - this.changedAt >= 1000) {
135
+ this.every += 1;
136
+ this.changedAt = now;
137
+ }
138
+ else if (load < 0.12 && this.every > 1 && now - this.changedAt >= 3000) {
139
+ this.every -= 1;
140
+ this.changedAt = now;
141
+ }
142
+ }
143
+ }
144
+ exports.SegmentationPacer = SegmentationPacer;
145
+ /** Timestamps MediaPipe's video mode accepts: in milliseconds and always increasing. */
146
+ class MonotonicClock {
147
+ last = 0;
148
+ next(now) {
149
+ this.last = Math.max(this.last + 1, Math.round(now));
150
+ return this.last;
151
+ }
152
+ }
153
+ exports.MonotonicClock = MonotonicClock;
154
+ //# sourceMappingURL=effects-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effects-core.js","sourceRoot":"","sources":["../../src/effects-core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The WebGL2 side of video effects (docs/implementation-progress/RTC_PERF_PROGRESS.md P3-5): the camera frame and the
3
+ * person mask in, the finished picture out on one canvas. Done on the GPU as LiveKit, Stream, Twilio and TRTC do:
4
+ *
5
+ * - **Blur** at a quarter of the size (cheap at any resolution), weighted by the mask so the person's own colours never
6
+ * bleed into the blur around them -- no halo (Stream's mask-weighted blur) -- in two separable Gaussian passes.
7
+ * - **Edges** follow the person's outline rather than the mask's coarse grid: the mask is sampled jointly with the
8
+ * frame's colours (a joint bilateral filter, as Stream and Twilio refine theirs).
9
+ * - **Background picture** fitted like `object-fit: cover`.
10
+ * - **Beauty** without a face model: skin found by its colour (YCbCr), smoothed with an edge-preserving filter so eyes
11
+ * and lips stay sharp, brightened in the midtones, a touch rosier, and detail off the skin sharpened.
12
+ *
13
+ * Every texture is kept in picture order (the first row is the top); only the last pass, to the canvas, flips.
14
+ */
15
+ import type { BeautySettings } from './effects-core.js';
16
+ export interface RenderSettings {
17
+ mode: 'none' | 'blur' | 'image';
18
+ /** Gaussian sigma in quarter-size texels. */
19
+ blurSigma: number;
20
+ beauty: BeautySettings | null;
21
+ /** False until the first mask: everything is treated as background, so nothing behind the person shows meanwhile. */
22
+ maskReady: boolean;
23
+ /** Where the image texture maps (coverFit). */
24
+ cover: {
25
+ sx: number;
26
+ sy: number;
27
+ ox: number;
28
+ oy: number;
29
+ };
30
+ }
31
+ export declare class EffectsRenderer {
32
+ readonly canvas: HTMLCanvasElement | OffscreenCanvas;
33
+ private readonly gl;
34
+ private readonly downsample;
35
+ private readonly blur;
36
+ private readonly composite;
37
+ private readonly frameTexture;
38
+ private readonly maskTexture;
39
+ private readonly pictureTexture;
40
+ private readonly blurTextures;
41
+ private readonly blurBuffers;
42
+ private readonly vertices;
43
+ private readonly floatTargets;
44
+ private width;
45
+ private height;
46
+ private blurWidth;
47
+ private blurHeight;
48
+ private maskWidth;
49
+ private maskHeight;
50
+ private pictureSize;
51
+ constructor(canvas: HTMLCanvasElement | OffscreenCanvas);
52
+ get lost(): boolean;
53
+ /** The picture's size; the canvas and the blur follow it. */
54
+ setSize(width: number, height: number): void;
55
+ get size(): {
56
+ width: number;
57
+ height: number;
58
+ blurHeight: number;
59
+ };
60
+ /** The camera frame (a VideoFrame or a playing video). */
61
+ uploadFrame(source: TexImageSource): void;
62
+ /** The person mask, one byte per pixel, picture order. */
63
+ uploadMask(data: Uint8Array, width: number, height: number): void;
64
+ /** The background picture, or null to let it go. */
65
+ setPicture(image: TexImageSource | null, width?: number, height?: number): void;
66
+ get picture(): {
67
+ width: number;
68
+ height: number;
69
+ } | null;
70
+ /** Draw the finished picture onto the canvas. */
71
+ render(settings: RenderSettings): void;
72
+ /** Let the GPU resources go. */
73
+ dispose(): void;
74
+ private pass;
75
+ private bindTexture;
76
+ private texture;
77
+ private program;
78
+ }
79
+ //# sourceMappingURL=effects-gl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effects-gl.d.ts","sourceRoot":"","sources":["../../src/effects-gl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAuIxD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAChC,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,qHAAqH;IACrH,SAAS,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3D;AAOD,qBAAa,eAAe;IAC1B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,CAAC;IACrD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAyB;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAe;IAC3C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAe;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA+B;IAC5D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuC;IACnE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,WAAW,CAAkD;gBAEzD,MAAM,EAAE,iBAAiB,GAAG,eAAe;IA0BvD,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,6DAA6D;IAC7D,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAmB5C,IAAI,IAAI,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAEhE;IAED,0DAA0D;IAC1D,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAOzC,0DAA0D;IAC1D,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IASjE,oDAAoD;IACpD,UAAU,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,EAAE,KAAK,SAAI,EAAE,MAAM,SAAI,GAAG,IAAI;IAarE,IAAI,OAAO,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAEtD;IAED,iDAAiD;IACjD,MAAM,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IA6CtC,gCAAgC;IAChC,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,IAAI;IAaZ,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,OAAO;CAoBhB"}
@@ -0,0 +1,351 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EffectsRenderer = void 0;
4
+ const VERTEX = `#version 300 es
5
+ in vec2 position;
6
+ uniform float flipY;
7
+ out vec2 uv;
8
+ void main() {
9
+ uv = vec2(position.x * 0.5 + 0.5, flipY > 0.5 ? 0.5 - position.y * 0.5 : 0.5 + position.y * 0.5);
10
+ gl_Position = vec4(position, 0.0, 1.0);
11
+ }`;
12
+ /** The frame at a quarter size, premultiplied by how much of each pixel is background. */
13
+ const DOWNSAMPLE = `#version 300 es
14
+ precision mediump float;
15
+ in vec2 uv;
16
+ out vec4 color;
17
+ uniform sampler2D frame;
18
+ uniform sampler2D mask;
19
+ uniform float maskReady;
20
+ uniform vec2 edge;
21
+ void main() {
22
+ vec3 c = texture(frame, uv).rgb;
23
+ float person = maskReady > 0.5 ? smoothstep(edge.x, edge.y, texture(mask, uv).r) : 0.0;
24
+ float background = 1.0 - person;
25
+ color = vec4(c * background, background);
26
+ }`;
27
+ /** One direction of a Gaussian blur, on premultiplied colour. */
28
+ const BLUR = `#version 300 es
29
+ precision mediump float;
30
+ in vec2 uv;
31
+ out vec4 color;
32
+ uniform sampler2D source;
33
+ uniform vec2 direction;
34
+ uniform float sigma;
35
+ void main() {
36
+ vec4 sum = texture(source, uv);
37
+ float total = 1.0;
38
+ for (int i = 1; i <= 32; i++) {
39
+ float x = float(i);
40
+ if (x > sigma * 3.0) break;
41
+ float w = exp(-x * x / (2.0 * sigma * sigma));
42
+ sum += (texture(source, uv + direction * x) + texture(source, uv - direction * x)) * w;
43
+ total += 2.0 * w;
44
+ }
45
+ color = sum / total;
46
+ }`;
47
+ const COMPOSITE = `#version 300 es
48
+ precision highp float;
49
+ in vec2 uv;
50
+ out vec4 color;
51
+ uniform sampler2D frame;
52
+ uniform sampler2D mask;
53
+ uniform sampler2D blurred;
54
+ uniform sampler2D picture;
55
+ uniform int mode;
56
+ uniform float maskReady;
57
+ uniform vec2 edge;
58
+ uniform vec2 texel;
59
+ uniform vec2 maskTexel;
60
+ uniform vec4 cover;
61
+ uniform vec4 beauty;
62
+ uniform float beautyOn;
63
+ uniform float beautyRadius;
64
+
65
+ const vec2 RING[8] = vec2[8](vec2(1.0, 0.0), vec2(0.7071, 0.7071), vec2(0.0, 1.0), vec2(-0.7071, 0.7071),
66
+ vec2(-1.0, 0.0), vec2(-0.7071, -0.7071), vec2(0.0, -1.0), vec2(0.7071, -0.7071));
67
+
68
+ float skinOf(vec3 c) {
69
+ float y = dot(c, vec3(0.299, 0.587, 0.114));
70
+ float cb = 0.5 + (c.b - y) * 0.564;
71
+ float cr = 0.5 + (c.r - y) * 0.713;
72
+ float s = smoothstep(0.27, 0.31, cb) * (1.0 - smoothstep(0.49, 0.53, cb))
73
+ * smoothstep(0.51, 0.55, cr) * (1.0 - smoothstep(0.67, 0.71, cr));
74
+ return s * smoothstep(0.06, 0.15, y);
75
+ }
76
+
77
+ vec3 beautify(vec3 c0) {
78
+ vec3 sum = c0;
79
+ float total = 1.0;
80
+ for (int r = 1; r <= 2; r++) {
81
+ float radius = beautyRadius * float(r);
82
+ float near = r == 1 ? 0.8 : 0.5;
83
+ for (int i = 0; i < 8; i++) {
84
+ vec3 c = texture(frame, uv + RING[i] * radius * texel).rgb;
85
+ vec3 d = c - c0;
86
+ float w = near * exp(-dot(d, d) * 60.0);
87
+ sum += c * w;
88
+ total += w;
89
+ }
90
+ }
91
+ vec3 smoothed = sum / total;
92
+ float skin = skinOf(c0);
93
+ vec3 c = mix(c0, smoothed, beauty.x * skin);
94
+ c += (c0 - smoothed) * beauty.w * (1.0 - skin) * 1.5;
95
+ float lift = beauty.y * (0.35 + 0.65 * skin) * 0.5;
96
+ c += lift * c * (1.0 - c);
97
+ c = mix(c, c * vec3(1.06, 0.97, 0.98), beauty.z * skin);
98
+ return clamp(c, 0.0, 1.0);
99
+ }
100
+
101
+ float personAt(vec3 center) {
102
+ float sum = 0.0;
103
+ float total = 0.0;
104
+ for (int y = -1; y <= 1; y++) {
105
+ for (int x = -1; x <= 1; x++) {
106
+ vec2 o = vec2(float(x), float(y)) * maskTexel * 1.5;
107
+ vec3 d = texture(frame, uv + o).rgb - center;
108
+ float w = exp(-dot(d, d) * 40.0);
109
+ sum += texture(mask, uv + o).r * w;
110
+ total += w;
111
+ }
112
+ }
113
+ return smoothstep(edge.x, edge.y, sum / total);
114
+ }
115
+
116
+ void main() {
117
+ vec3 original = texture(frame, uv).rgb;
118
+ vec3 fg = beautyOn > 0.5 ? beautify(original) : original;
119
+ if (mode == 0) {
120
+ color = vec4(fg, 1.0);
121
+ return;
122
+ }
123
+ float person = maskReady > 0.5 ? personAt(original) : 0.0;
124
+ vec3 bg;
125
+ if (mode == 1) {
126
+ vec4 b = texture(blurred, uv);
127
+ bg = b.a > 0.02 ? b.rgb / b.a : fg;
128
+ } else {
129
+ bg = texture(picture, uv * cover.xy + cover.zw).rgb;
130
+ }
131
+ color = vec4(mix(bg, fg, person), 1.0);
132
+ }`;
133
+ /** Where the person's edge ramps, in mask confidence. */
134
+ const EDGE = [0.35, 0.7];
135
+ class EffectsRenderer {
136
+ canvas;
137
+ gl;
138
+ downsample;
139
+ blur;
140
+ composite;
141
+ frameTexture;
142
+ maskTexture;
143
+ pictureTexture;
144
+ blurTextures;
145
+ blurBuffers;
146
+ vertices;
147
+ floatTargets;
148
+ width = 0;
149
+ height = 0;
150
+ blurWidth = 0;
151
+ blurHeight = 0;
152
+ maskWidth = 1;
153
+ maskHeight = 1;
154
+ pictureSize = null;
155
+ constructor(canvas) {
156
+ this.canvas = canvas;
157
+ const gl = canvas.getContext('webgl2', { alpha: false, antialias: false, depth: false, stencil: false, premultipliedAlpha: false, desynchronized: true });
158
+ if (!gl)
159
+ throw new Error('WebGL2 is not available');
160
+ this.gl = gl;
161
+ this.floatTargets = gl.getExtension('EXT_color_buffer_float') !== null || gl.getExtension('EXT_color_buffer_half_float') !== null;
162
+ this.downsample = this.program(DOWNSAMPLE, ['frame', 'mask', 'maskReady', 'edge', 'flipY']);
163
+ this.blur = this.program(BLUR, ['source', 'direction', 'sigma', 'flipY']);
164
+ this.composite = this.program(COMPOSITE, ['frame', 'mask', 'blurred', 'picture', 'mode', 'maskReady', 'edge', 'texel', 'maskTexel', 'cover', 'beauty', 'beautyOn', 'beautyRadius', 'flipY']);
165
+ this.vertices = gl.createBuffer();
166
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.vertices);
167
+ // One triangle covering the viewport.
168
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);
169
+ this.frameTexture = this.texture();
170
+ this.maskTexture = this.texture();
171
+ this.pictureTexture = this.texture();
172
+ this.blurTextures = [this.texture(), this.texture()];
173
+ this.blurBuffers = [gl.createFramebuffer(), gl.createFramebuffer()];
174
+ // Until a mask arrives: one texel, person nowhere.
175
+ gl.bindTexture(gl.TEXTURE_2D, this.maskTexture);
176
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
177
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, 1, 1, 0, gl.RED, gl.UNSIGNED_BYTE, new Uint8Array([0]));
178
+ gl.bindTexture(gl.TEXTURE_2D, this.pictureTexture);
179
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 255]));
180
+ }
181
+ get lost() {
182
+ return this.gl.isContextLost();
183
+ }
184
+ /** The picture's size; the canvas and the blur follow it. */
185
+ setSize(width, height) {
186
+ if (width === this.width && height === this.height)
187
+ return;
188
+ this.width = width;
189
+ this.height = height;
190
+ this.canvas.width = width;
191
+ this.canvas.height = height;
192
+ this.blurWidth = Math.max(1, Math.round(width / 4));
193
+ this.blurHeight = Math.max(1, Math.round(height / 4));
194
+ const gl = this.gl;
195
+ for (let i = 0; i < 2; i += 1) {
196
+ gl.bindTexture(gl.TEXTURE_2D, this.blurTextures[i]);
197
+ if (this.floatTargets)
198
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA16F, this.blurWidth, this.blurHeight, 0, gl.RGBA, gl.HALF_FLOAT, null);
199
+ else
200
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.blurWidth, this.blurHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
201
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.blurBuffers[i]);
202
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.blurTextures[i], 0);
203
+ }
204
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
205
+ }
206
+ get size() {
207
+ return { width: this.width, height: this.height, blurHeight: this.blurHeight };
208
+ }
209
+ /** The camera frame (a VideoFrame or a playing video). */
210
+ uploadFrame(source) {
211
+ const gl = this.gl;
212
+ gl.bindTexture(gl.TEXTURE_2D, this.frameTexture);
213
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
214
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
215
+ }
216
+ /** The person mask, one byte per pixel, picture order. */
217
+ uploadMask(data, width, height) {
218
+ const gl = this.gl;
219
+ gl.bindTexture(gl.TEXTURE_2D, this.maskTexture);
220
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
221
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8, width, height, 0, gl.RED, gl.UNSIGNED_BYTE, data);
222
+ this.maskWidth = width;
223
+ this.maskHeight = height;
224
+ }
225
+ /** The background picture, or null to let it go. */
226
+ setPicture(image, width = 1, height = 1) {
227
+ const gl = this.gl;
228
+ gl.bindTexture(gl.TEXTURE_2D, this.pictureTexture);
229
+ if (image) {
230
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
231
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
232
+ this.pictureSize = { width, height };
233
+ }
234
+ else {
235
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 255]));
236
+ this.pictureSize = null;
237
+ }
238
+ }
239
+ get picture() {
240
+ return this.pictureSize;
241
+ }
242
+ /** Draw the finished picture onto the canvas. */
243
+ render(settings) {
244
+ const gl = this.gl;
245
+ if (gl.isContextLost() || this.width === 0)
246
+ return;
247
+ gl.disable(gl.BLEND);
248
+ gl.disable(gl.DEPTH_TEST);
249
+ if (settings.mode === 'blur') {
250
+ gl.viewport(0, 0, this.blurWidth, this.blurHeight);
251
+ this.pass(this.downsample, this.blurBuffers[0], 0, (u) => {
252
+ this.bindTexture(0, this.frameTexture, u.get('frame'));
253
+ this.bindTexture(1, this.maskTexture, u.get('mask'));
254
+ gl.uniform1f(u.get('maskReady'), settings.maskReady ? 1 : 0);
255
+ gl.uniform2f(u.get('edge'), EDGE[0], EDGE[1]);
256
+ });
257
+ const sigma = Math.min(settings.blurSigma, 10.5);
258
+ this.pass(this.blur, this.blurBuffers[1], 0, (u) => {
259
+ this.bindTexture(0, this.blurTextures[0], u.get('source'));
260
+ gl.uniform2f(u.get('direction'), 1 / this.blurWidth, 0);
261
+ gl.uniform1f(u.get('sigma'), sigma);
262
+ });
263
+ this.pass(this.blur, this.blurBuffers[0], 0, (u) => {
264
+ this.bindTexture(0, this.blurTextures[1], u.get('source'));
265
+ gl.uniform2f(u.get('direction'), 0, 1 / this.blurHeight);
266
+ gl.uniform1f(u.get('sigma'), sigma);
267
+ });
268
+ }
269
+ gl.viewport(0, 0, this.width, this.height);
270
+ this.pass(this.composite, null, 1, (u) => {
271
+ this.bindTexture(0, this.frameTexture, u.get('frame'));
272
+ this.bindTexture(1, this.maskTexture, u.get('mask'));
273
+ this.bindTexture(2, this.blurTextures[0], u.get('blurred'));
274
+ this.bindTexture(3, this.pictureTexture, u.get('picture'));
275
+ gl.uniform1i(u.get('mode'), settings.mode === 'blur' ? 1 : settings.mode === 'image' ? 2 : 0);
276
+ gl.uniform1f(u.get('maskReady'), settings.maskReady ? 1 : 0);
277
+ gl.uniform2f(u.get('edge'), EDGE[0], EDGE[1]);
278
+ gl.uniform2f(u.get('texel'), 1 / this.width, 1 / this.height);
279
+ gl.uniform2f(u.get('maskTexel'), 1 / this.maskWidth, 1 / this.maskHeight);
280
+ gl.uniform4f(u.get('cover'), settings.cover.sx, settings.cover.sy, settings.cover.ox, settings.cover.oy);
281
+ const b = settings.beauty;
282
+ gl.uniform4f(u.get('beauty'), b?.smooth ?? 0, b?.brighten ?? 0, b?.redness ?? 0, b?.sharpen ?? 0);
283
+ gl.uniform1f(u.get('beautyOn'), b ? 1 : 0);
284
+ // About 3 px at 720p: the skin's pores and blemishes, not its features.
285
+ gl.uniform1f(u.get('beautyRadius'), Math.max(1.5, this.height / 240));
286
+ });
287
+ }
288
+ /** Let the GPU resources go. */
289
+ dispose() {
290
+ const gl = this.gl;
291
+ for (const t of [this.frameTexture, this.maskTexture, this.pictureTexture, ...this.blurTextures])
292
+ gl.deleteTexture(t);
293
+ for (const f of this.blurBuffers)
294
+ gl.deleteFramebuffer(f);
295
+ gl.deleteBuffer(this.vertices);
296
+ for (const p of [this.downsample, this.blur, this.composite])
297
+ gl.deleteProgram(p.program);
298
+ gl.getExtension('WEBGL_lose_context')?.loseContext();
299
+ }
300
+ pass(p, target, flipY, setup) {
301
+ const gl = this.gl;
302
+ gl.bindFramebuffer(gl.FRAMEBUFFER, target);
303
+ gl.useProgram(p.program);
304
+ gl.uniform1f(p.uniforms.get('flipY'), flipY);
305
+ setup(p.uniforms);
306
+ const at = gl.getAttribLocation(p.program, 'position');
307
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.vertices);
308
+ gl.enableVertexAttribArray(at);
309
+ gl.vertexAttribPointer(at, 2, gl.FLOAT, false, 0, 0);
310
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
311
+ }
312
+ bindTexture(unit, texture, location) {
313
+ const gl = this.gl;
314
+ gl.activeTexture(gl.TEXTURE0 + unit);
315
+ gl.bindTexture(gl.TEXTURE_2D, texture);
316
+ if (location)
317
+ gl.uniform1i(location, unit);
318
+ }
319
+ texture() {
320
+ const gl = this.gl;
321
+ const t = gl.createTexture();
322
+ gl.bindTexture(gl.TEXTURE_2D, t);
323
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
324
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
325
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
326
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
327
+ return t;
328
+ }
329
+ program(fragment, names) {
330
+ const gl = this.gl;
331
+ const compile = (type, source) => {
332
+ const shader = gl.createShader(type);
333
+ gl.shaderSource(shader, source);
334
+ gl.compileShader(shader);
335
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS) && !gl.isContextLost()) {
336
+ throw new Error(`video effects: a shader did not compile: ${gl.getShaderInfoLog(shader)}`);
337
+ }
338
+ return shader;
339
+ };
340
+ const program = gl.createProgram();
341
+ gl.attachShader(program, compile(gl.VERTEX_SHADER, VERTEX));
342
+ gl.attachShader(program, compile(gl.FRAGMENT_SHADER, fragment));
343
+ gl.linkProgram(program);
344
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS) && !gl.isContextLost()) {
345
+ throw new Error(`video effects: a shader did not link: ${gl.getProgramInfoLog(program)}`);
346
+ }
347
+ return { program, uniforms: new Map(names.map((n) => [n, gl.getUniformLocation(program, n)])) };
348
+ }
349
+ }
350
+ exports.EffectsRenderer = EffectsRenderer;
351
+ //# sourceMappingURL=effects-gl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effects-gl.js","sourceRoot":"","sources":["../../src/effects-gl.ts"],"names":[],"mappings":"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"}