@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,263 @@
1
+ "use strict";
2
+ /**
3
+ * Adaptive stream: receive each remote video at the size it is shown, and not
4
+ * at all while nobody can see it.
5
+ *
6
+ * The app attaches the element that shows a video (`attachVideo`). From that
7
+ * element's size on screen (CSS pixels × devicePixelRatio, at most 2) the
8
+ * smallest simulcast layer that fills it sharply is chosen; while no attached
9
+ * element is visible (scrolled away, `display: none`, the tab in the
10
+ * background) the video is paused at the media server, so it costs no
11
+ * bandwidth and no decoding. This is what LiveKit calls adaptiveStream and
12
+ * Tencent TRTC "small stream + receiveWhenViewVisible": the single biggest
13
+ * saving on a viewer with several tiles, where every tile otherwise decodes
14
+ * the publisher's full-size layer.
15
+ *
16
+ * Pure decisions are exported for tests; the browser parts (observers,
17
+ * timers) are injected.
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.AdaptiveVideos = exports.LOWER_AFTER_MS = exports.PAUSE_AFTER_MS = exports.MAX_UPSCALE = exports.MAX_PIXEL_RATIO = void 0;
21
+ exports.layerForBox = layerForBox;
22
+ exports.wantFor = wantFor;
23
+ exports.pageIsVisible = pageIsVisible;
24
+ /** Never ask for more than twice the CSS size: a 3× phone screen gains nothing visible from it. */
25
+ exports.MAX_PIXEL_RATIO = 2;
26
+ /** A layer shown at most this much bigger than it is still looks sharp: avoids a whole layer for a few pixels. */
27
+ exports.MAX_UPSCALE = 1.15;
28
+ /**
29
+ * The smallest layer that fills `box` sharply, or null when the layers are
30
+ * not known (an older publisher): then the server chooses, as before.
31
+ *
32
+ * With `cover` the picture is scaled until it fills the box (a part is
33
+ * cropped), with `contain` until it fits. Either way the scale is measured
34
+ * against each layer's own size, so a portrait layer list works too.
35
+ */
36
+ function layerForBox(layers, box, pixelRatio = 1) {
37
+ const usable = layers.filter((l) => l.width > 0 && l.height > 0).sort((a, b) => a.width * a.height - b.width * b.height);
38
+ if (!usable.length || box.width <= 0 || box.height <= 0)
39
+ return null;
40
+ const ratio = Math.min(exports.MAX_PIXEL_RATIO, Math.max(1, pixelRatio || 1));
41
+ const w = box.width * ratio;
42
+ const h = box.height * ratio;
43
+ for (const layer of usable) {
44
+ const scale = box.fit === 'cover' ? Math.max(w / layer.width, h / layer.height) : Math.min(w / layer.width, h / layer.height);
45
+ // The layer is at most slightly upscaled on screen.
46
+ if (scale <= exports.MAX_UPSCALE)
47
+ return layer.spatialLayer;
48
+ }
49
+ return usable[usable.length - 1].spatialLayer;
50
+ }
51
+ /**
52
+ * The largest view among the visible ones decides; any visible view keeps the video flowing. A view not measured
53
+ * yet (just attached, before layout) counts as shown at the server's choice, so attaching never pauses a video
54
+ * for the moment before the browser has sized the element.
55
+ */
56
+ function wantFor(views, layers, pixelRatio, pageVisible) {
57
+ if (pageVisible && views.some((v) => v.measured === false))
58
+ return { visible: true, spatialLayer: null };
59
+ const shown = pageVisible ? views.filter((v) => v.visible && v.box.width > 0 && v.box.height > 0) : [];
60
+ if (!shown.length)
61
+ return { visible: false, spatialLayer: null };
62
+ let best = null;
63
+ for (const view of shown) {
64
+ const layer = layerForBox(layers, view.box, pixelRatio);
65
+ if (layer === null)
66
+ return { visible: true, spatialLayer: null };
67
+ best = best === null ? layer : Math.max(best, layer);
68
+ }
69
+ return { visible: true, spatialLayer: best };
70
+ }
71
+ /** Pause a hidden video only after this long, so scrolling past or a quick tab switch does not stop it. */
72
+ exports.PAUSE_AFTER_MS = 1500;
73
+ /** Go down a layer only after this long (going up is immediate): a tile shrinking for a moment keeps its picture. */
74
+ exports.LOWER_AFTER_MS = 1200;
75
+ const FLOWING = { visible: true, spatialLayer: null };
76
+ const sameWant = (a, b) => a !== null && a.visible === b.visible && a.spatialLayer === b.spatialLayer;
77
+ /**
78
+ * The videos being shown, by producer id. Decisions are applied through the
79
+ * host; going up (or becoming visible) is applied at once, going down (or
80
+ * hiding) after a short delay.
81
+ */
82
+ class AdaptiveVideos {
83
+ host;
84
+ entries = new Map();
85
+ stopPage = null;
86
+ constructor(host) {
87
+ this.host = host;
88
+ }
89
+ /** Show `producerId` in `element`; returns the function that stops. */
90
+ attach(producerId, element) {
91
+ let entry = this.entries.get(producerId);
92
+ if (!entry) {
93
+ entry = { views: new Map(), applied: null, timer: null };
94
+ this.entries.set(producerId, entry);
95
+ }
96
+ if (entry.views.has(element))
97
+ return () => this.detach(producerId, element);
98
+ const view = { box: { width: 0, height: 0, fit: 'contain' }, visible: true, measured: false, stop: () => undefined };
99
+ entry.views.set(element, view);
100
+ view.stop = this.observe(element, (box, visible) => {
101
+ if (box) {
102
+ view.box = box;
103
+ view.measured = true;
104
+ }
105
+ if (visible !== null)
106
+ view.visible = visible;
107
+ this.update(producerId);
108
+ });
109
+ if (!this.stopPage)
110
+ this.stopPage = this.watchPage(() => { for (const id of this.entries.keys())
111
+ this.update(id); });
112
+ this.update(producerId);
113
+ return () => this.detach(producerId, element);
114
+ }
115
+ detach(producerId, element) {
116
+ const entry = this.entries.get(producerId);
117
+ const view = entry?.views.get(element);
118
+ if (!entry || !view)
119
+ return;
120
+ view.stop();
121
+ entry.views.delete(element);
122
+ if (entry.views.size) {
123
+ this.update(producerId);
124
+ return;
125
+ }
126
+ // Nothing shows it any more: back to how it was before (flowing, the server's choice).
127
+ this.clear(entry);
128
+ this.entries.delete(producerId);
129
+ if (entry.applied && !sameWant(entry.applied, { visible: true, spatialLayer: null }))
130
+ this.host.apply(producerId, { visible: true, spatialLayer: null });
131
+ if (!this.entries.size) {
132
+ this.stopPage?.();
133
+ this.stopPage = null;
134
+ }
135
+ }
136
+ /** Whether the app shows this video through attachVideo (its decisions then apply to new consumers too). */
137
+ has(producerId) {
138
+ return this.entries.has(producerId);
139
+ }
140
+ /** The decision in force, for a consumer made (or made again) after it: null when the app does not attach it. */
141
+ current(producerId) {
142
+ const entry = this.entries.get(producerId);
143
+ return entry ? this.decide(producerId, entry) : null;
144
+ }
145
+ /**
146
+ * A new consumer was made with `current()` applied (its layers, and paused when hidden): record that as applied,
147
+ * so nothing is sent twice, and drop a pending change made for the old one.
148
+ */
149
+ consumed(producerId) {
150
+ const entry = this.entries.get(producerId);
151
+ if (!entry)
152
+ return;
153
+ this.clear(entry);
154
+ entry.applied = this.decide(producerId, entry);
155
+ }
156
+ /** Stop everything (the session closed). */
157
+ dispose() {
158
+ for (const entry of this.entries.values()) {
159
+ this.clear(entry);
160
+ for (const view of entry.views.values())
161
+ view.stop();
162
+ }
163
+ this.entries.clear();
164
+ this.stopPage?.();
165
+ this.stopPage = null;
166
+ }
167
+ decide(producerId, entry) {
168
+ return wantFor([...entry.views.values()], this.host.layers(producerId), this.host.pixelRatio?.() ?? 1, this.host.pageVisible?.() ?? true);
169
+ }
170
+ update(producerId) {
171
+ const entry = this.entries.get(producerId);
172
+ if (!entry)
173
+ return;
174
+ const want = this.decide(producerId, entry);
175
+ // Nothing applied yet is the server's choice, flowing: asking for exactly that sends nothing.
176
+ if (sameWant(entry.applied ?? FLOWING, want)) {
177
+ this.clear(entry);
178
+ entry.applied ??= want;
179
+ return;
180
+ }
181
+ // Nothing applied yet means the video flows at the server's choice.
182
+ const prev = entry.applied ?? { visible: true, spatialLayer: null };
183
+ // Hiding, or a smaller layer than one applied, waits; anything else (showing, a bigger layer, a first layer) is at once.
184
+ const lower = (prev.visible && !want.visible) ||
185
+ (want.visible && prev.visible && want.spatialLayer !== null && prev.spatialLayer !== null && want.spatialLayer < prev.spatialLayer);
186
+ // Already waiting to lower: a repeated report must not restart the wait; it applies what is wanted when it runs out.
187
+ if (lower && entry.timer !== null)
188
+ return;
189
+ this.clear(entry);
190
+ if (!lower) {
191
+ entry.applied = want;
192
+ this.host.apply(producerId, want);
193
+ return;
194
+ }
195
+ const delay = want.visible ? exports.LOWER_AFTER_MS : exports.PAUSE_AFTER_MS;
196
+ entry.timer = (this.host.setTimer ?? ((fn, ms) => setTimeout(fn, ms)))(() => {
197
+ entry.timer = null;
198
+ const now = this.decide(producerId, entry);
199
+ if (sameWant(entry.applied, now))
200
+ return;
201
+ entry.applied = now;
202
+ this.host.apply(producerId, now);
203
+ }, delay);
204
+ }
205
+ clear(entry) {
206
+ if (entry.timer !== null)
207
+ (this.host.clearTimer ?? ((h) => clearTimeout(h)))(entry.timer);
208
+ entry.timer = null;
209
+ }
210
+ observe(element, onChange) {
211
+ if (this.host.observe)
212
+ return this.host.observe(element, onChange);
213
+ return observeElement(element, onChange);
214
+ }
215
+ watchPage(listener) {
216
+ if (this.host.onPageVisibility)
217
+ return this.host.onPageVisibility(listener);
218
+ if (typeof document === 'undefined')
219
+ return () => undefined;
220
+ document.addEventListener('visibilitychange', listener);
221
+ return () => document.removeEventListener('visibilitychange', listener);
222
+ }
223
+ }
224
+ exports.AdaptiveVideos = AdaptiveVideos;
225
+ /** How an element fits its picture: a video's object-fit, else contain. */
226
+ function fitOf(element) {
227
+ try {
228
+ const fit = typeof getComputedStyle === 'function' ? getComputedStyle(element).objectFit : '';
229
+ return fit === 'cover' || fit === 'fill' ? 'cover' : 'contain';
230
+ }
231
+ catch {
232
+ return 'contain';
233
+ }
234
+ }
235
+ /** The browser's observers: size (ResizeObserver) and visibility on screen (IntersectionObserver). */
236
+ function observeElement(element, onChange) {
237
+ const stops = [];
238
+ const measure = () => {
239
+ const rect = element.getBoundingClientRect();
240
+ onChange({ width: rect.width, height: rect.height, fit: fitOf(element) }, null);
241
+ };
242
+ if (typeof ResizeObserver !== 'undefined') {
243
+ const resize = new ResizeObserver(() => measure());
244
+ resize.observe(element);
245
+ stops.push(() => resize.disconnect());
246
+ }
247
+ if (typeof IntersectionObserver !== 'undefined') {
248
+ const seen = new IntersectionObserver((entries) => {
249
+ const last = entries[entries.length - 1];
250
+ if (last)
251
+ onChange(null, last.isIntersecting);
252
+ });
253
+ seen.observe(element);
254
+ stops.push(() => seen.disconnect());
255
+ }
256
+ measure();
257
+ return () => stops.forEach((stop) => stop());
258
+ }
259
+ /** The page is visible (not a background tab). */
260
+ function pageIsVisible() {
261
+ return typeof document === 'undefined' || document.visibilityState !== 'hidden';
262
+ }
263
+ //# sourceMappingURL=adaptive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptive.js","sourceRoot":"","sources":["../../src/adaptive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Cameras, microphones and speakers (docs/implementation-progress/RTC_PERF_PROGRESS.md I1).
3
+ *
4
+ * What the big SDKs do, read from their code:
5
+ * - Amazon Chime (`DefaultDeviceController`): lists devices by kind, watches `devicechange` and tells observers
6
+ * which lists changed; a microphone that ends is replaced so audio keeps flowing, a camera that ends is stopped and
7
+ * reported (`audioInputStreamEnded` / `videoInputStreamEnded`) -- never swapped for another camera on its own.
8
+ * - LiveKit (`Room.handleDeviceChange`, `switchActiveDevice`): switches the published track to a chosen device; when
9
+ * the active audio device disappears it moves to the first available one.
10
+ * - Tencent TRTC: `DEVICE_CHANGED {type, action: add | remove | active}`.
11
+ *
12
+ * This module holds the pure parts: comparing device lists and building the constraints for a chosen device.
13
+ */
14
+ export type DeviceKind = 'audioinput' | 'videoinput' | 'audiooutput';
15
+ /** A camera, microphone or speaker, as the browser lists it. Labels are empty until a permission was granted. */
16
+ export interface MediaDevice {
17
+ deviceId: string;
18
+ groupId: string;
19
+ kind: DeviceKind;
20
+ label: string;
21
+ }
22
+ export interface DevicesChangedEvent {
23
+ /** Every device now. */
24
+ devices: MediaDevice[];
25
+ added: MediaDevice[];
26
+ removed: MediaDevice[];
27
+ }
28
+ /** The browser's device list, optionally of one kind. Empty outside a browser. */
29
+ export declare function enumerate(kind?: DeviceKind): Promise<MediaDevice[]>;
30
+ /** What appeared and what went between two lists. */
31
+ export declare function diffDevices(before: readonly MediaDevice[], after: readonly MediaDevice[]): {
32
+ added: MediaDevice[];
33
+ removed: MediaDevice[];
34
+ };
35
+ /**
36
+ * The constraints for capturing `deviceId` (or the system default when null), keeping everything else the app asked
37
+ * for: size, frame rate, echo cancellation. `base` is what publish was given for that kind.
38
+ */
39
+ export declare function constraintsFor(base: boolean | MediaTrackConstraints | undefined, deviceId: string | null): MediaTrackConstraints;
40
+ /** The device a live track captures, when it is a device capture at all (a canvas or a processed track has none). */
41
+ export declare function deviceIdOf(track: MediaStreamTrack | null | undefined): string | null;
42
+ //# sourceMappingURL=devices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devices.d.ts","sourceRoot":"","sources":["../../src/devices.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,aAAa,CAAC;AAErE,iHAAiH;AACjH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,wBAAwB;IACxB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,kFAAkF;AAClF,wBAAsB,SAAS,CAAC,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAQzE;AAID,qDAAqD;AACrD,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,EAAE,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG;IAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IAAC,OAAO,EAAE,WAAW,EAAE,CAAA;CAAE,CAO3I;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,qBAAqB,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,qBAAqB,CAKhI;AAED,qHAAqH;AACrH,wBAAgB,UAAU,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAGpF"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ /**
3
+ * Cameras, microphones and speakers (docs/implementation-progress/RTC_PERF_PROGRESS.md I1).
4
+ *
5
+ * What the big SDKs do, read from their code:
6
+ * - Amazon Chime (`DefaultDeviceController`): lists devices by kind, watches `devicechange` and tells observers
7
+ * which lists changed; a microphone that ends is replaced so audio keeps flowing, a camera that ends is stopped and
8
+ * reported (`audioInputStreamEnded` / `videoInputStreamEnded`) -- never swapped for another camera on its own.
9
+ * - LiveKit (`Room.handleDeviceChange`, `switchActiveDevice`): switches the published track to a chosen device; when
10
+ * the active audio device disappears it moves to the first available one.
11
+ * - Tencent TRTC: `DEVICE_CHANGED {type, action: add | remove | active}`.
12
+ *
13
+ * This module holds the pure parts: comparing device lists and building the constraints for a chosen device.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.enumerate = enumerate;
17
+ exports.diffDevices = diffDevices;
18
+ exports.constraintsFor = constraintsFor;
19
+ exports.deviceIdOf = deviceIdOf;
20
+ /** The browser's device list, optionally of one kind. Empty outside a browser. */
21
+ async function enumerate(kind) {
22
+ const md = typeof navigator !== 'undefined' ? navigator.mediaDevices : undefined;
23
+ if (!md?.enumerateDevices)
24
+ return [];
25
+ const all = await md.enumerateDevices();
26
+ return all
27
+ .filter((d) => d.kind === 'audioinput' || d.kind === 'videoinput' || d.kind === 'audiooutput')
28
+ .filter((d) => !kind || d.kind === kind)
29
+ .map((d) => ({ deviceId: d.deviceId, groupId: d.groupId, kind: d.kind, label: d.label }));
30
+ }
31
+ const key = (d) => `${d.kind}:${d.deviceId}`;
32
+ /** What appeared and what went between two lists. */
33
+ function diffDevices(before, after) {
34
+ const was = new Set(before.map(key));
35
+ const now = new Set(after.map(key));
36
+ return {
37
+ added: after.filter((d) => !was.has(key(d))),
38
+ removed: before.filter((d) => !now.has(key(d))),
39
+ };
40
+ }
41
+ /**
42
+ * The constraints for capturing `deviceId` (or the system default when null), keeping everything else the app asked
43
+ * for: size, frame rate, echo cancellation. `base` is what publish was given for that kind.
44
+ */
45
+ function constraintsFor(base, deviceId) {
46
+ const rest = typeof base === 'object' && base !== null ? { ...base } : {};
47
+ delete rest.deviceId;
48
+ delete rest.groupId;
49
+ return deviceId === null ? rest : { ...rest, deviceId: { exact: deviceId } };
50
+ }
51
+ /** The device a live track captures, when it is a device capture at all (a canvas or a processed track has none). */
52
+ function deviceIdOf(track) {
53
+ const id = track?.getSettings?.().deviceId;
54
+ return typeof id === 'string' && id.length > 0 ? id : null;
55
+ }
56
+ //# sourceMappingURL=devices.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devices.js","sourceRoot":"","sources":["../../src/devices.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;AAoBH,8BAQC;AAKD,kCAOC;AAMD,wCAKC;AAGD,gCAGC;AAtCD,kFAAkF;AAC3E,KAAK,UAAU,SAAS,CAAC,IAAiB;IAC/C,MAAM,EAAE,GAAG,OAAO,SAAS,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IACjF,IAAI,CAAC,EAAE,EAAE,gBAAgB;QAAE,OAAO,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,gBAAgB,EAAE,CAAC;IACxC,OAAO,GAAG;SACP,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC;SAC7F,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC;SACvC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAkB,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAC5G,CAAC;AAED,MAAM,GAAG,GAAG,CAAC,CAAc,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;AAE1D,qDAAqD;AACrD,SAAgB,WAAW,CAAC,MAA8B,EAAE,KAA6B;IACvF,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;KAChD,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,cAAc,CAAC,IAAiD,EAAE,QAAuB;IACvG,MAAM,IAAI,GAA0B,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACjG,OAAO,IAAI,CAAC,QAAQ,CAAC;IACrB,OAAO,IAAI,CAAC,OAAO,CAAC;IACpB,OAAO,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC;AAC/E,CAAC;AAED,qHAAqH;AACrH,SAAgB,UAAU,CAAC,KAA0C;IACnE,MAAM,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,QAAQ,CAAC;IAC3C,OAAO,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Diagnostics for support (docs/implementation-progress/RTC_PERF_PROGRESS.md S4).
3
+ *
4
+ * Agora uploads its SDK log on request (`enableLogUpload`), Twilio sends call telemetry to Insights, Stream Video
5
+ * traces session events to its servers. Shipping telemetry needs a backend; what helps today is a snapshot an app can
6
+ * attach to a support ticket: the SDK's recent events (a ring buffer) and its state now.
7
+ */
8
+ /** This package's version; kept equal to package.json by a test. */
9
+ export declare const SDK_VERSION = "0.9.0";
10
+ /** How many recent events the log keeps. */
11
+ export declare const DIAGNOSTICS_LOG_SIZE = 200;
12
+ export interface DiagnosticsEntry {
13
+ /** Unix ms. */
14
+ at: number;
15
+ event: string;
16
+ /** A short summary of what the event carried (no media objects). */
17
+ detail?: string;
18
+ }
19
+ /** A ring buffer of the SDK's recent events. */
20
+ export declare class DiagnosticsLog {
21
+ private readonly now;
22
+ private readonly entries;
23
+ constructor(now?: () => number);
24
+ /** Keep an emitted event, when it is one worth keeping. */
25
+ record(event: string, args: unknown[]): void;
26
+ list(): DiagnosticsEntry[];
27
+ }
28
+ export interface DiagnosticsTransport {
29
+ state: string;
30
+ path: {
31
+ protocol: 'udp' | 'tcp' | null;
32
+ relayed: boolean;
33
+ } | null;
34
+ }
35
+ export interface Diagnostics {
36
+ sdk: string;
37
+ at: number;
38
+ userAgent: string;
39
+ connectionState: string;
40
+ room: string | null;
41
+ identity: string | null;
42
+ role: string | null;
43
+ transports: {
44
+ send: DiagnosticsTransport | null;
45
+ recv: DiagnosticsTransport | null;
46
+ };
47
+ network: {
48
+ rttMs: number | null;
49
+ availableKbps: number | null;
50
+ } | null;
51
+ published: {
52
+ source: string;
53
+ kind: string;
54
+ paused: boolean;
55
+ }[];
56
+ received: {
57
+ identity: string;
58
+ source: string;
59
+ kind: string;
60
+ paused: boolean;
61
+ }[];
62
+ /** Recent events, oldest first. */
63
+ log: DiagnosticsEntry[];
64
+ }
65
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,oEAAoE;AACpE,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC,4CAA4C;AAC5C,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,MAAM,WAAW,gBAAgB;IAC/B,eAAe;IACf,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA6BD,gDAAgD;AAChD,qBAAa,cAAc;IAGb,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFhC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;gBAErB,GAAG,GAAE,MAAM,MAAiB;IAEzD,2DAA2D;IAC3D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAa5C,IAAI,IAAI,gBAAgB,EAAE;CAG3B;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE;QAAE,QAAQ,EAAE,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;CACnE;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE;QAAE,IAAI,EAAE,oBAAoB,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI,CAAA;KAAE,CAAC;IACrF,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IACvE,SAAS,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC/D,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAChF,mCAAmC;IACnC,GAAG,EAAE,gBAAgB,EAAE,CAAC;CACzB"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ /**
3
+ * Diagnostics for support (docs/implementation-progress/RTC_PERF_PROGRESS.md S4).
4
+ *
5
+ * Agora uploads its SDK log on request (`enableLogUpload`), Twilio sends call telemetry to Insights, Stream Video
6
+ * traces session events to its servers. Shipping telemetry needs a backend; what helps today is a snapshot an app can
7
+ * attach to a support ticket: the SDK's recent events (a ring buffer) and its state now.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.DiagnosticsLog = exports.DIAGNOSTICS_LOG_SIZE = exports.SDK_VERSION = void 0;
11
+ /** This package's version; kept equal to package.json by a test. */
12
+ exports.SDK_VERSION = '0.9.0';
13
+ /** How many recent events the log keeps. */
14
+ exports.DIAGNOSTICS_LOG_SIZE = 200;
15
+ /** The events worth keeping for support, and how to summarise each. */
16
+ const SUMMARY = {
17
+ connectionStateChanged: ([e]) => { const s = e; return `${s.previous} → ${s.state}`; },
18
+ disconnected: ([reason]) => String(reason),
19
+ closed: ([reason]) => String(reason),
20
+ mustReconnect: ([e]) => e.reason,
21
+ mediaReconnecting: ([e]) => { const m = e; return `${m.transportId} ${m.reconnecting ? 'recovering' : 'recovered'}`; },
22
+ error: ([e]) => {
23
+ const err = e;
24
+ const message = err.message ?? '';
25
+ // RpcError's message already starts with its code.
26
+ return (err.code && !message.startsWith(`${err.code}:`) ? `${err.code}: ${message}` : message).slice(0, 300);
27
+ },
28
+ streamFallback: ([e]) => { const f = e; return `${f.producerId} ${f.fallback ? 'held' : 'back'} (${f.reason})`; },
29
+ mediaWarning: ([e]) => { const w = e; return `${w.code} ${w.active ? 'started' : 'cleared'}`; },
30
+ cpuConstrained: ([e]) => String(e.constrained),
31
+ videoLimited: ([e]) => e.reason,
32
+ localTrackEnded: ([e]) => { const t = e; return `${t.kind} ${t.recovered ? 'recovered' : 'off'}`; },
33
+ devicesChanged: ([e]) => { const d = e; return `+${d.added?.length ?? 0} -${d.removed?.length ?? 0}`; },
34
+ kicked: ([e]) => e.reason,
35
+ roomClosed: ([e]) => e.reason,
36
+ usageLimit: ([e]) => e.reason,
37
+ autoplayFailed: () => undefined,
38
+ trackEnded: ([e]) => e.producerId,
39
+ track: ([e]) => { const t = e; return `${t.identity} ${t.source}`; },
40
+ };
41
+ /** A ring buffer of the SDK's recent events. */
42
+ class DiagnosticsLog {
43
+ now;
44
+ entries = [];
45
+ constructor(now = Date.now) {
46
+ this.now = now;
47
+ }
48
+ /** Keep an emitted event, when it is one worth keeping. */
49
+ record(event, args) {
50
+ const summarize = SUMMARY[event];
51
+ if (!summarize)
52
+ return;
53
+ let detail;
54
+ try {
55
+ detail = summarize(args);
56
+ }
57
+ catch {
58
+ detail = undefined;
59
+ }
60
+ this.entries.push(detail === undefined ? { at: this.now(), event } : { at: this.now(), event, detail });
61
+ if (this.entries.length > exports.DIAGNOSTICS_LOG_SIZE)
62
+ this.entries.shift();
63
+ }
64
+ list() {
65
+ return this.entries.map((e) => ({ ...e }));
66
+ }
67
+ }
68
+ exports.DiagnosticsLog = DiagnosticsLog;
69
+ //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/diagnostics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Video effects, the parts that need no browser (docs/implementation-progress/RTC_PERF_PROGRESS.md P3-5): settings,
3
+ * fitting a background image, the size segmentation runs at, and pacing it on a slow device. Kept apart from the
4
+ * WebGL and MediaPipe code so they are tested in Node.
5
+ */
6
+ /** A background picture: a URL, or anything the browser can draw. */
7
+ export type BackgroundImageSource = string | Blob | ImageBitmap | HTMLImageElement | HTMLCanvasElement | OffscreenCanvas;
8
+ /** What happens behind the person: nothing, a blur, or a picture. */
9
+ export type BackgroundSetting = 'none' | 'blur' | {
10
+ image: BackgroundImageSource;
11
+ };
12
+ /** Beauty, each 0-1 (Agora's beauty effect has the same four). */
13
+ export interface BeautyOptions {
14
+ /** Skin smoothing. Default 0.5. */
15
+ smooth?: number;
16
+ /** Brightening. Default 0.3. */
17
+ brighten?: number;
18
+ /** A rosier skin. Default 0.1. */
19
+ redness?: number;
20
+ /** Sharper eyes, hair and edges (not skin). Default 0.3. */
21
+ sharpen?: number;
22
+ }
23
+ export interface BeautySettings {
24
+ smooth: number;
25
+ brighten: number;
26
+ redness: number;
27
+ sharpen: number;
28
+ }
29
+ export declare const DEFAULT_BEAUTY: Readonly<BeautySettings>;
30
+ /** The blur behind the person, 1 (light) to 10 (strong). */
31
+ export declare const DEFAULT_BLUR = 5;
32
+ /** Beauty settings from what the app passed: `true` is the defaults, `false`/`null` is off. */
33
+ export declare function beautySettings(options: BeautyOptions | boolean | null | undefined): BeautySettings | null;
34
+ /** A blur level from what the app passed: 1-10, rounded; anything else is the default. */
35
+ export declare function blurLevel(value: unknown): number;
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
+ export declare function blurSigma(level: number, blurHeight: number): number;
41
+ /** What the background setting asks of the pipeline. */
42
+ export declare function backgroundMode(setting: BackgroundSetting | undefined | null): 'none' | 'blur' | 'image';
43
+ /**
44
+ * Fit a background picture to the frame the way CSS `object-fit: cover` does: it fills the frame, cropped evenly on
45
+ * the long side, never stretched. Returns the texture transform `imageUv = frameUv * scale + offset`.
46
+ */
47
+ export declare function coverFit(imageWidth: number, imageHeight: number, frameWidth: number, frameHeight: number): {
48
+ sx: number;
49
+ sy: number;
50
+ ox: number;
51
+ oy: number;
52
+ };
53
+ /** The size the person is found at: the frame scaled so its longer side is `longSide` (the model's input). */
54
+ export declare function segmentationSize(width: number, height: number, longSide?: number): {
55
+ width: number;
56
+ height: number;
57
+ };
58
+ /** How fast the mask follows a new one: lower is steadier between frames, higher follows movement sooner. */
59
+ export declare const MASK_FOLLOW = 0.65;
60
+ /**
61
+ * Smooth the person mask between frames (Stream's temporal smoothing), against flicker at the edges, and write it as
62
+ * bytes for the GPU. `steady` keeps the running mask; a new size starts it over.
63
+ */
64
+ export declare function smoothMask(confidence: Float32Array, steady: Float32Array | null, out: Uint8Array, follow?: number): Float32Array;
65
+ /** The most frames a mask is reused for before the device is called overloaded. */
66
+ export declare const MAX_SEGMENT_EVERY = 6;
67
+ /**
68
+ * Amazon Chime's adaptive background filter: finding the person is the expensive part, so when it takes too much of
69
+ * each frame's time it runs only every Nth frame and the last mask is reused -- the picture still runs at the camera's
70
+ * rate. N comes back down once it is cheap again. `overloaded` is the point where even that is not enough.
71
+ */
72
+ export declare class SegmentationPacer {
73
+ private readonly maxEvery;
74
+ private average;
75
+ private changedAt;
76
+ private every;
77
+ constructor(maxEvery?: number);
78
+ /** Run segmentation on every this-many frames. */
79
+ get interval(): number;
80
+ /** Average milliseconds one segmentation takes. */
81
+ get segmentMs(): number;
82
+ shouldSegment(frameIndex: number): boolean;
83
+ /** The share of the frame time segmentation takes now, given how often it runs. */
84
+ load(frameIntervalMs: number): number;
85
+ /** Whether segmenting even this rarely still takes too long. */
86
+ overloaded(frameIntervalMs: number): boolean;
87
+ /** One segmentation took `ms`, at a frame interval of `frameIntervalMs`. */
88
+ report(ms: number, frameIntervalMs: number, now: number): void;
89
+ }
90
+ /** Timestamps MediaPipe's video mode accepts: in milliseconds and always increasing. */
91
+ export declare class MonotonicClock {
92
+ private last;
93
+ next(now: number): number;
94
+ }
95
+ //# sourceMappingURL=effects-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effects-core.d.ts","sourceRoot":"","sources":["../../src/effects-core.ts"],"names":[],"mappings":"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"}