@pexip/media-control 17.2.0 → 17.4.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/dist/index.mjs DELETED
@@ -1,1699 +0,0 @@
1
- // src/types.ts
2
- var MediaDeviceKinds = /* @__PURE__ */ ((MediaDeviceKinds2) => {
3
- MediaDeviceKinds2["AUDIOINPUT"] = "audioinput";
4
- MediaDeviceKinds2["AUDIOOUTPUT"] = "audiooutput";
5
- MediaDeviceKinds2["VIDEOINPUT"] = "videoinput";
6
- return MediaDeviceKinds2;
7
- })(MediaDeviceKinds || {});
8
- var FACING_MODE = ["user", "environment", "left", "right"];
9
- var MediaDeviceFailure = /* @__PURE__ */ ((MediaDeviceFailure2) => {
10
- MediaDeviceFailure2["AbortError"] = "AbortError";
11
- MediaDeviceFailure2["AudioAndVideoDeviceNotFoundError"] = "AudioAndVideoDeviceNotFoundError";
12
- MediaDeviceFailure2["AudioInputDeviceNotFoundError"] = "AudioInputDeviceNotFoundError";
13
- MediaDeviceFailure2["MissingConstraintsError"] = "MissingConstraintsError";
14
- MediaDeviceFailure2["NotAllowedError"] = "NotAllowedError";
15
- MediaDeviceFailure2["NotFoundError"] = "NotFoundError";
16
- MediaDeviceFailure2["NotReadableError"] = "NotReadableError";
17
- MediaDeviceFailure2["OverconstrainedError"] = "OverconstrainedError";
18
- MediaDeviceFailure2["PermissionDeniedError"] = "PermissionDeniedError";
19
- MediaDeviceFailure2["SecurityError"] = "SecurityError";
20
- MediaDeviceFailure2["TrackStartError"] = "TrackStartError";
21
- MediaDeviceFailure2["TypeError"] = "TypeError";
22
- MediaDeviceFailure2["VideoInputDeviceNotFoundError"] = "VideoInputDeviceNotFoundError";
23
- MediaDeviceFailure2["NotSupportedError"] = "NotSupportedError";
24
- MediaDeviceFailure2["StreamTrackNotFound"] = "StreamTrackNotFound";
25
- return MediaDeviceFailure2;
26
- })(MediaDeviceFailure || {});
27
-
28
- // src/typeGuards.ts
29
- import { hasOwnProperty } from "@pexip/utils";
30
- var isBoolean = (t) => typeof t === "boolean";
31
- var isUndefined = (t) => typeof t === "undefined";
32
- var isNumber = (t) => typeof t === "number" && !Number.isNaN(t);
33
- var isInteger = (t) => Number.isInteger(t);
34
- var isFloat = (t) => isNumber(t) && !Number.isInteger(t) && Number.isFinite(t);
35
- var CONSTRAIN_STRING_KEYS = [
36
- "facingMode",
37
- "resizeMode",
38
- "deviceId",
39
- "groupId"
40
- ];
41
- var EXTENDED_CONSTRAIN_STRING_KEYS = [
42
- "videoSegmentation",
43
- "videoSegmentationModel",
44
- "bgImageUrl",
45
- "contentHint"
46
- ];
47
- var CONSTRAIN_U_LONG_KEYS = [
48
- "width",
49
- "height",
50
- "sampleRate",
51
- "sampleSize",
52
- "channelCount"
53
- ];
54
- var EXTENDED_CONSTRAIN_U_LONG_KEYS = [
55
- "backgroundBlurAmount",
56
- "edgeBlurAmount"
57
- ];
58
- var CONSTRAIN_DOUBLE_KEYS = [
59
- "aspectRatio",
60
- "frameRate",
61
- "latency"
62
- ];
63
- var EXTENDED_CONSTRAIN_DOUBLE_KEYS = ["foregroundThreshold"];
64
- var CONSTRAIN_BOOLEAN_KEYS = [
65
- "echoCancellation",
66
- "autoGainControl",
67
- "noiseSuppression",
68
- "pan",
69
- "tilt",
70
- "zoom"
71
- ];
72
- var EXTENDED_CONSTRAIN_BOOLEAN_KEYS = [
73
- // Voice Activity Detection
74
- "vad",
75
- // Audio Signal Detection
76
- "asd",
77
- // Mixing with another track
78
- "mixWithAdditionalMedia",
79
- // Noise Suppression using our own impl
80
- "denoise",
81
- // Flip the video horizontally
82
- "flipHorizontal"
83
- ];
84
- var CONSTRAINT_SET_KEYS = [
85
- ...CONSTRAIN_DOUBLE_KEYS,
86
- ...CONSTRAIN_U_LONG_KEYS,
87
- ...CONSTRAIN_STRING_KEYS,
88
- ...CONSTRAIN_BOOLEAN_KEYS
89
- ];
90
- var isConstrainStringKeys = (t) => CONSTRAIN_STRING_KEYS.includes(t);
91
- var isExtendedConstrainStringKeys = (t) => EXTENDED_CONSTRAIN_STRING_KEYS.includes(t);
92
- var isConstrainULongKeys = (t) => CONSTRAIN_U_LONG_KEYS.includes(t);
93
- var isExtendedConstrainULongKeys = (t) => EXTENDED_CONSTRAIN_U_LONG_KEYS.includes(t);
94
- var isConstrainDoubleKeys = (t) => CONSTRAIN_DOUBLE_KEYS.includes(t);
95
- var isExtendedConstrainDoubleKeys = (t) => EXTENDED_CONSTRAIN_DOUBLE_KEYS.includes(t);
96
- var isConstrainBooleanKeys = (t) => CONSTRAIN_BOOLEAN_KEYS.includes(t);
97
- var isExtendedConstrainBooleanKeys = (t) => EXTENDED_CONSTRAIN_BOOLEAN_KEYS.includes(t);
98
- var isMediaTrackConstraintSetKey = (t) => CONSTRAINT_SET_KEYS.includes(t);
99
- var isMediaTrackConstraintsKey = (t) => isMediaTrackConstraintSetKey(t) || t === "advanced";
100
- var isMediaTrackConstraints = (t) => {
101
- if (!t || typeof t !== "object" || Array.isArray(t) || t === null) {
102
- return false;
103
- }
104
- const keys = Object.keys(t);
105
- return !!keys.length && Object.keys(t).every((key) => isMediaTrackConstraintsKey(key));
106
- };
107
- var isMediaDeviceInfo = (t) => {
108
- if (!t || typeof t !== "object") {
109
- return false;
110
- }
111
- return !!t && "deviceId" in t && "kind" in t;
112
- };
113
- var isMediaDeviceInfoArray = (t) => {
114
- if (Array.isArray(t) && t.length && t.some(isMediaDeviceInfo)) {
115
- return true;
116
- }
117
- return false;
118
- };
119
- var isDeviceConstraint = (t) => {
120
- return isMediaDeviceInfo(t) || isMediaDeviceInfoArray(t);
121
- };
122
- var isConstraintDOMString = (t) => typeof t === "string" && !!t || Array.isArray(t) && t.some(Boolean);
123
- var CONSTRAIN_PARAM_KEYS = ["exact", "ideal"];
124
- var CONSTRAIN_RANGE_KEYS = ["min", "max"];
125
- var CONSTRAIN_KEYS = [
126
- ...CONSTRAIN_PARAM_KEYS,
127
- ...CONSTRAIN_RANGE_KEYS
128
- ];
129
- var isConstrainDOMParameters = (isType, keys = CONSTRAIN_PARAM_KEYS) => (t) => {
130
- if (!t || typeof t !== "object" || t === null || Object.keys(t).length <= 0) {
131
- return false;
132
- }
133
- return keys.some((key) => hasOwnProperty(t, key) && isType(t[key]));
134
- };
135
- var isConstrainDOMStringParameters = isConstrainDOMParameters(
136
- isConstraintDOMString
137
- );
138
- var isConstrainBooleanParameters = isConstrainDOMParameters(isBoolean);
139
- var isConstrainRange = isConstrainDOMParameters(
140
- (t) => isFloat(t) || isInteger(t),
141
- CONSTRAIN_RANGE_KEYS
142
- );
143
- var isConstrainDoubleRange = isConstrainDOMParameters(isFloat, CONSTRAIN_KEYS);
144
- var isConstrainULongRange = isConstrainDOMParameters(isInteger, CONSTRAIN_KEYS);
145
- var isConstraintDeviceParameters = isConstrainDOMParameters(
146
- (t) => isMediaDeviceInfo(t) || isMediaDeviceInfoArray(t)
147
- );
148
- var isConstraintSetDevice = (t) => isMediaDeviceInfo(t) || isMediaDeviceInfoArray(t) || isConstraintDeviceParameters(t);
149
- var isExtendedConstraint = (t) => {
150
- if (typeof t !== "object" || t === null) {
151
- return false;
152
- }
153
- if (hasOwnProperty(t, "device")) {
154
- const { device } = t;
155
- return isConstraintSetDevice(device);
156
- }
157
- return [
158
- ...EXTENDED_CONSTRAIN_DOUBLE_KEYS,
159
- ...EXTENDED_CONSTRAIN_STRING_KEYS,
160
- ...EXTENDED_CONSTRAIN_U_LONG_KEYS,
161
- ...EXTENDED_CONSTRAIN_BOOLEAN_KEYS
162
- ].some((key) => hasOwnProperty(t, key));
163
- };
164
- var isInputConstraintSet = (t) => {
165
- if (typeof t !== "object" || t === null) {
166
- return false;
167
- }
168
- return isExtendedConstraint(t) || isMediaTrackConstraints(t);
169
- };
170
- var isMediaStreamTrack = (m) => {
171
- if (m && typeof m === "object") {
172
- return !!m && "getSettings" in m;
173
- }
174
- return false;
175
- };
176
- var isFacingMode = (s) => {
177
- if (typeof s === "string" && FACING_MODE.includes(s)) {
178
- return true;
179
- }
180
- return false;
181
- };
182
-
183
- // ../../shared/baseLogger.ts
184
- var LogLevels = ((LogLevels2) => {
185
- LogLevels2[LogLevels2["trace"] = 10] = "trace";
186
- LogLevels2[LogLevels2["debug"] = 20] = "debug";
187
- LogLevels2[LogLevels2["info"] = 30] = "info";
188
- LogLevels2[LogLevels2["warn"] = 40] = "warn";
189
- LogLevels2[LogLevels2["error"] = 50] = "error";
190
- LogLevels2[LogLevels2["fatal"] = 60] = "fatal";
191
- LogLevels2[LogLevels2["silent"] = Number.MAX_SAFE_INTEGER] = "silent";
192
- return LogLevels2;
193
- })(LogLevels || {});
194
- function createConsoleLogger() {
195
- return Object.freeze({
196
- /* eslint-disable no-console -- set logger to console */
197
- fatal: (meta, message) => console.error(message, meta),
198
- error: (meta, message) => console.error(message, meta),
199
- warn: (meta, message) => console.warn(message, meta),
200
- info: (meta, message) => console.info(message, meta),
201
- debug: (meta, message) => console.debug(message, meta),
202
- trace() {
203
- },
204
- // Noop
205
- silent() {
206
- },
207
- // Noop
208
- redact() {
209
- }
210
- // Noop
211
- /* eslint-enable no-console -- set logger to console */
212
- });
213
- }
214
-
215
- // src/logger.ts
216
- var logger = createConsoleLogger();
217
- function setLogger(newLogger) {
218
- logger = newLogger;
219
- }
220
-
221
- // src/utils.ts
222
- var isSameDeviceKind = (kind) => (device) => device.kind === kind;
223
- var isAudioInput = isSameDeviceKind("audioinput" /* AUDIOINPUT */);
224
- var isVideoInput = isSameDeviceKind("videoinput" /* VIDEOINPUT */);
225
- var isAudioOutput = isSameDeviceKind("audiooutput" /* AUDIOOUTPUT */);
226
- var isDeviceGranted = (device) => Boolean(device.label);
227
- var not = (fn) => (arg) => !fn(arg);
228
- var compareDevices = (deviceInfo, key = "deviceId") => (anotherDeviceInfo) => deviceInfo.kind === anotherDeviceInfo.kind && deviceInfo[key] === anotherDeviceInfo[key];
229
- var findDevice = (deviceToFind, useFallback = true) => (devices) => {
230
- const compareIDTo = compareDevices(deviceToFind);
231
- const found = devices.find(
232
- (device) => compareIDTo(device)
233
- );
234
- if (found || !useFallback) {
235
- return found;
236
- }
237
- const compareLabelTo = compareDevices(deviceToFind, "label");
238
- return devices.find(
239
- (device) => compareLabelTo(device)
240
- );
241
- };
242
-
243
- // src/constraints.ts
244
- var isExactDeviceConstraint = (constraint) => {
245
- if (isInputConstraintSet(constraint)) {
246
- return !!constraint.device && typeof constraint.device === "object" && "exact" in constraint.device || !!constraint.deviceId && typeof constraint.deviceId === "object" && "exact" in constraint.deviceId;
247
- }
248
- return false;
249
- };
250
- var getConstraintsSetFilter = (supportedConstraints) => (trackConstraints) => {
251
- if (!isMediaTrackConstraints(trackConstraints)) {
252
- return trackConstraints;
253
- }
254
- const constraints = Object.entries(trackConstraints).reduce(
255
- (acc, [key, val]) => key === "advanced" || supportedConstraints.has(
256
- key
257
- ) ? { ...acc, [key]: val } : acc,
258
- {}
259
- );
260
- if (Object.keys(constraints).length === 0) {
261
- return true;
262
- }
263
- return constraints;
264
- };
265
- var getDefinedOnly = (obj) => {
266
- return Object.entries(obj).reduce(
267
- (acc, [key, val]) => typeof val === "undefined" ? acc : { ...acc, [key]: val },
268
- {}
269
- );
270
- };
271
- var removeUnsupportedConstraints = (constraints) => {
272
- if (!(navigator && "getSupportedConstraints" in navigator.mediaDevices)) {
273
- return constraints;
274
- }
275
- const supportedConstraints = Object.entries(
276
- navigator.mediaDevices.getSupportedConstraints()
277
- );
278
- logger.debug({ supportedConstraints }, "Supported constraints");
279
- const constraintsSetFilter = getConstraintsSetFilter(
280
- supportedConstraints.reduce(
281
- (set, [key, value]) => (
282
- // FIXME: Cast inserted to unblock typescript upgrade, will have to be verified and properly fixed.
283
- value && isMediaTrackConstraintSetKey(key) ? set.add(
284
- key
285
- ) : set
286
- ),
287
- /* @__PURE__ */ new Set()
288
- )
289
- );
290
- return getDefinedOnly({
291
- audio: constraintsSetFilter(constraints.audio),
292
- peerIdentity: constraints.peerIdentity,
293
- video: constraintsSetFilter(constraints.video)
294
- });
295
- };
296
- var mergeConstraints = (baseConstraints) => (constraints) => {
297
- if (!isInputConstraintSet(baseConstraints)) {
298
- if (isDeviceConstraint(constraints)) {
299
- return { device: constraints };
300
- }
301
- return constraints ?? false;
302
- }
303
- if (!constraints) {
304
- return false;
305
- }
306
- if (isDeviceConstraint(constraints)) {
307
- const result = {
308
- ...baseConstraints,
309
- device: constraints
310
- };
311
- delete result.facingMode;
312
- delete result.deviceId;
313
- return result;
314
- }
315
- if (isInputConstraintSet(constraints)) {
316
- const combined = { ...baseConstraints, ...constraints };
317
- const hasDeviceId = isConstraintDOMString(combined.deviceId) || isConstrainDOMStringParameters(combined.deviceId);
318
- const hasDevice = isDeviceConstraint(combined.device) || isConstraintDeviceParameters(combined.device);
319
- if (hasDeviceId && hasDevice) {
320
- const result = {
321
- ...combined
322
- };
323
- delete result.facingMode;
324
- delete result.deviceId;
325
- return result;
326
- }
327
- if (hasDevice || hasDeviceId) {
328
- delete combined.facingMode;
329
- return combined;
330
- }
331
- return combined;
332
- }
333
- return baseConstraints;
334
- };
335
- var normalizeDevice = (device) => {
336
- if (!device) {
337
- return void 0;
338
- }
339
- if (isMediaDeviceInfo(device)) {
340
- return [device];
341
- }
342
- if (Array.isArray(device)) {
343
- const devices = device.filter(isMediaDeviceInfo);
344
- if (devices.length) {
345
- return devices;
346
- }
347
- }
348
- return void 0;
349
- };
350
- var normalizeDeviceConstraint = (constraints) => {
351
- if (!constraints) {
352
- return void 0;
353
- }
354
- if (isConstraintDeviceParameters(constraints)) {
355
- return Object.keys(constraints).filter((k) => ["ideal", "exact"].includes(k)).reduce(
356
- (cs, k) => {
357
- const key = k;
358
- const value = constraints[key];
359
- const devices = normalizeDevice(value);
360
- if (devices) {
361
- return { ...cs ?? {}, [key]: devices };
362
- }
363
- return cs;
364
- },
365
- void 0
366
- );
367
- }
368
- const normalized = normalizeDevice(constraints);
369
- return normalized && { ideal: normalized };
370
- };
371
- var toDeviceIdConstraintSet = (constraint) => {
372
- const [devices, param] = extractConstrainDevice({ device: constraint });
373
- return devices && { [param]: devices.map((device) => device.deviceId) };
374
- };
375
- var toArray = (t) => {
376
- const r = Array.isArray(t) ? t : [t];
377
- return r.filter(Boolean);
378
- };
379
- var NONE = [void 0, "ideal"];
380
- var extractConstrainString = (key) => (constraints) => {
381
- const constraint = constraints[key];
382
- if (!constraint) {
383
- return NONE;
384
- }
385
- if (isConstraintDOMString(constraint)) {
386
- return [toArray(constraint), "ideal"];
387
- }
388
- if (isConstrainDOMStringParameters(constraint)) {
389
- if (constraint.exact) {
390
- const normalized = toArray(constraint.exact);
391
- if (normalized.length) {
392
- return [normalized, "exact"];
393
- }
394
- }
395
- if (constraint.ideal) {
396
- return [toArray(constraint.ideal), "ideal"];
397
- }
398
- }
399
- return NONE;
400
- };
401
- var extractConstrainBoolean = (key) => (constraints) => {
402
- const constraint = constraints[key];
403
- if (isUndefined(constraint)) {
404
- return NONE;
405
- }
406
- if (isBoolean(constraint)) {
407
- return [constraint, "ideal"];
408
- }
409
- if (isConstrainBooleanParameters(constraint)) {
410
- const { ideal, exact } = constraint;
411
- if (isBoolean(exact)) {
412
- return [exact, "exact"];
413
- }
414
- if (isBoolean(ideal)) {
415
- return [ideal, "ideal"];
416
- }
417
- }
418
- return NONE;
419
- };
420
- var extractConstrainNumber = (key) => (constraints) => {
421
- const constraint = constraints[key];
422
- if (constraint === void 0 || constraint === null) {
423
- return NONE;
424
- }
425
- if (isFloat(constraint) || isInteger(constraint)) {
426
- return [constraint, "ideal"];
427
- }
428
- if (isConstrainULongRange(constraint) || isConstrainDoubleRange(constraint)) {
429
- const { exact, ideal, min, max } = constraint;
430
- if (isFloat(min) || isFloat(max) || isInteger(min) || isInteger(max)) {
431
- return [{ min, max, ideal, exact }, "min-max"];
432
- }
433
- if (isFloat(exact) || isInteger(exact)) {
434
- return [exact, "exact"];
435
- }
436
- if (isFloat(ideal) || isInteger(ideal)) {
437
- return [ideal, "ideal"];
438
- }
439
- }
440
- return NONE;
441
- };
442
- var extractConstrainDevice = (constraints) => {
443
- if (!constraints || isBoolean(constraints) || Array.isArray(constraints) && !constraints.length) {
444
- return NONE;
445
- }
446
- const { device } = isInputConstraintSet(constraints) ? constraints : { device: constraints };
447
- if (isMediaDeviceInfo(device) || isMediaDeviceInfoArray(device)) {
448
- const normalized = normalizeDevice(device);
449
- if (normalized) {
450
- return [normalized, "ideal"];
451
- }
452
- }
453
- if (isConstraintDeviceParameters(device)) {
454
- const { exact, ideal } = normalizeDeviceConstraint(device) ?? {};
455
- if (exact) {
456
- return [exact, "exact"];
457
- }
458
- if (ideal) {
459
- return [ideal, "ideal"];
460
- }
461
- }
462
- return NONE;
463
- };
464
- var closedTo = (a, b, numDigits = 5) => {
465
- const multiplier = Math.pow(10, numDigits);
466
- return Math.round(a * multiplier) === Math.round(b * multiplier);
467
- };
468
- var between = (min, num, max) => {
469
- if (!isUndefined(min)) {
470
- if (!isUndefined(max)) {
471
- return num >= min && num <= max;
472
- }
473
- return num >= min;
474
- }
475
- if (!isUndefined(max)) {
476
- return num <= max;
477
- }
478
- return true;
479
- };
480
- var getValueFromConstrainNumber = (constraint) => {
481
- if (isNumber(constraint)) {
482
- return constraint;
483
- }
484
- const { min, max, ideal, exact } = constraint;
485
- if (exact !== void 0) {
486
- const withinRange = between(min, exact, max);
487
- if (withinRange) {
488
- return exact;
489
- }
490
- }
491
- if (ideal !== void 0) {
492
- const withinRange = between(min, ideal, max);
493
- if (withinRange) {
494
- return ideal;
495
- }
496
- }
497
- const value = max ?? min;
498
- if (value !== void 0) {
499
- return value;
500
- }
501
- throw Error("Constrain Number is undefined");
502
- };
503
- var getFacingModeFromConstraintString = (constraint) => {
504
- if (isFacingMode(constraint)) {
505
- return constraint;
506
- }
507
- return void 0;
508
- };
509
- var satisfyConstrainNumber = (constraint, num) => {
510
- if (isUndefined(constraint) || isUndefined(num)) {
511
- return true;
512
- }
513
- if (isInteger(constraint)) {
514
- return num === constraint;
515
- }
516
- if (isFloat(constraint)) {
517
- return closedTo(constraint, num);
518
- }
519
- if (isConstrainRange(constraint)) {
520
- const { min, max, ideal, exact } = constraint;
521
- const withinRange = between(min, num, max);
522
- if (isFloat(exact)) {
523
- return withinRange && closedTo(exact, num);
524
- }
525
- if (isInteger(exact)) {
526
- return withinRange && exact === num;
527
- }
528
- if (isFloat(ideal)) {
529
- return withinRange && closedTo(ideal, num);
530
- }
531
- if (isInteger(ideal)) {
532
- return withinRange && ideal === num;
533
- }
534
- return withinRange;
535
- }
536
- return false;
537
- };
538
- var resolveMediaDeviceConstraints = (constraints, base) => {
539
- const merge = mergeConstraints(base);
540
- if (isInputConstraintSet(constraints)) {
541
- if (isConstraintSetDevice(constraints.device)) {
542
- return merge(
543
- Object.keys(constraints).reduce((cs, k) => {
544
- const key = k;
545
- if (key === "device") {
546
- return {
547
- ...cs,
548
- deviceId: toDeviceIdConstraintSet(
549
- constraints.device
550
- )
551
- };
552
- }
553
- return { ...cs, [key]: constraints[key] };
554
- }, {})
555
- );
556
- }
557
- return merge(constraints);
558
- }
559
- if (isConstraintSetDevice(constraints)) {
560
- const deviceId = toDeviceIdConstraintSet(constraints);
561
- return merge({ deviceId });
562
- }
563
- if (constraints && isMediaTrackConstraints(base)) {
564
- return base;
565
- }
566
- return !!constraints;
567
- };
568
- var getMediaConstraints = ({
569
- audio,
570
- video,
571
- defaultConstraints
572
- }) => {
573
- return removeUnsupportedConstraints({
574
- audio: resolveMediaDeviceConstraints(audio, defaultConstraints.audio),
575
- video: resolveMediaDeviceConstraints(video, defaultConstraints.video)
576
- });
577
- };
578
- var applyConstraints = async (tracks, constraints) => {
579
- if (!tracks || tracks.length === 0 || Object.keys(constraints).length === 0) {
580
- return Promise.resolve();
581
- }
582
- const { audio, video } = removeUnsupportedConstraints({
583
- audio: resolveMediaDeviceConstraints(constraints.audio),
584
- video: resolveMediaDeviceConstraints(constraints.video)
585
- });
586
- await Promise.all(
587
- tracks.flatMap((track) => {
588
- if (track.kind === "audio" && isMediaTrackConstraints(audio)) {
589
- return [track.applyConstraints(audio)];
590
- }
591
- if (track.kind === "video" && isMediaTrackConstraints(video)) {
592
- return [track.applyConstraints(video)];
593
- }
594
- return [];
595
- })
596
- );
597
- };
598
- var findDeviceFrom = (devicesToFind, deviceList) => {
599
- const devicesFound = devicesToFind.flatMap((device) => {
600
- const found = findDevice(device)(deviceList);
601
- if (found) {
602
- return [found];
603
- }
604
- return [];
605
- });
606
- if (devicesFound.length) {
607
- return devicesFound;
608
- }
609
- return void 0;
610
- };
611
- var findDeviceFromDeviceConstraints = (device, devices) => {
612
- const normalized = normalizeDeviceConstraint(device);
613
- if (normalized) {
614
- const { ideal, exact } = normalized;
615
- if (exact) {
616
- return findDeviceFrom(exact, devices);
617
- }
618
- if (ideal) {
619
- return findDeviceFrom(ideal, devices);
620
- }
621
- }
622
- };
623
- var relaxDevice = (device, devices) => {
624
- const found = findDeviceFromDeviceConstraints(device, devices);
625
- if (found) {
626
- return found;
627
- }
628
- return normalizeDevice(device);
629
- };
630
- var resolveOnlyDevice = (devices) => {
631
- switch (devices.length) {
632
- case 1:
633
- return devices[0];
634
- case 0:
635
- return void 0;
636
- default:
637
- return true;
638
- }
639
- };
640
- function extractConstraints(key) {
641
- return (constraints) => {
642
- if (!constraints || typeof constraints === "boolean" || Array.isArray(constraints) && !constraints.length) {
643
- return NONE;
644
- }
645
- if (key === "device" && (isMediaDeviceInfo(constraints) || isMediaDeviceInfoArray(constraints))) {
646
- return extractConstrainDevice(constraints);
647
- }
648
- if (isInputConstraintSet(constraints)) {
649
- if (key === "device") {
650
- return extractConstrainDevice(constraints);
651
- }
652
- if (isConstrainStringKeys(key) || isExtendedConstrainStringKeys(key)) {
653
- return extractConstrainString(key)(constraints);
654
- }
655
- if (isConstrainDoubleKeys(key) || isConstrainULongKeys(key) || isExtendedConstrainULongKeys(key) || isExtendedConstrainDoubleKeys(key)) {
656
- return extractConstrainNumber(key)(constraints);
657
- }
658
- if (isConstrainBooleanKeys(key) || isExtendedConstrainBooleanKeys(key)) {
659
- return extractConstrainBoolean(key)(constraints);
660
- }
661
- }
662
- return [void 0, "ideal"];
663
- };
664
- }
665
- var extractConstraintsWithKeys = (keys) => (constraints) => keys.reduce(
666
- (result, key) => {
667
- if (key === "device") {
668
- return {
669
- ...result,
670
- [key]: extractConstraints(key)(constraints)
671
- };
672
- }
673
- if (isConstrainULongKeys(key) || isConstrainDoubleKeys(key) || isExtendedConstrainULongKeys(key) || isExtendedConstrainDoubleKeys(key)) {
674
- return {
675
- ...result,
676
- [key]: extractConstraints(key)(constraints)
677
- };
678
- }
679
- if (isConstrainStringKeys(key) || isExtendedConstrainStringKeys(key)) {
680
- return {
681
- ...result,
682
- [key]: extractConstraints(key)(constraints)
683
- };
684
- }
685
- if (isConstrainBooleanKeys(key) || isExtendedConstrainBooleanKeys(key)) {
686
- return {
687
- ...result,
688
- [key]: extractConstraints(key)(constraints)
689
- };
690
- }
691
- return result;
692
- },
693
- {}
694
- );
695
- var extractDeviceId = extractConstrainString("deviceId");
696
- var findDeviceFromConstraints = (constraints, devices) => {
697
- if (typeof constraints === "boolean") {
698
- return constraints ? resolveOnlyDevice(devices) : constraints;
699
- }
700
- if (constraints === void 0 || !devices.length || devices.some((device) => !device.label) || Array.isArray(constraints) && !constraints.length) {
701
- return void 0;
702
- }
703
- const [constrainDevices, deviceParam] = extractConstraints("device")(constraints);
704
- if (constrainDevices) {
705
- const [device] = findDeviceFrom(constrainDevices, devices) ?? [];
706
- if (device) {
707
- return device;
708
- }
709
- if (deviceParam === "exact") {
710
- return void 0;
711
- }
712
- }
713
- const [ConstrainDeviceIds, deviceIdParam] = extractConstraints("deviceId")(constraints);
714
- if (ConstrainDeviceIds) {
715
- const deviceFound = devices.find((device) => {
716
- const id = ConstrainDeviceIds.find(
717
- (id2) => id2 && device.label && device.deviceId === id2
718
- );
719
- return !!id;
720
- });
721
- if (deviceFound) {
722
- return deviceFound;
723
- }
724
- if (deviceIdParam === "exact") {
725
- return void 0;
726
- }
727
- }
728
- return resolveOnlyDevice(devices);
729
- };
730
- var relaxInputConstraint = (input, devices) => {
731
- if (devices.length === 0 || !input || typeof input === "boolean") {
732
- return input;
733
- }
734
- const [device, param] = extractConstrainDevice(input);
735
- const relaxedDevice = relaxDevice(device, devices);
736
- const otherConstraints = isInputConstraintSet(input) ? input : {};
737
- return relaxedDevice ? { ...otherConstraints, device: { [param]: relaxedDevice } } : input;
738
- };
739
- var getConstraintsHandlers = () => {
740
- let defaultConstraints = {
741
- audio: {
742
- echoCancellation: { ideal: true },
743
- noiseSuppression: { ideal: true }
744
- },
745
- video: {
746
- frameRate: { ideal: 30 }
747
- }
748
- };
749
- const setDefaultConstraints2 = (newConstraints) => {
750
- defaultConstraints = { ...defaultConstraints, ...newConstraints };
751
- };
752
- const getDefaultConstraints = () => {
753
- return defaultConstraints;
754
- };
755
- return {
756
- getDefaultConstraints,
757
- setDefaultConstraints: setDefaultConstraints2
758
- };
759
- };
760
-
761
- // src/devices.ts
762
- var SEPARATOR = ":";
763
- var toKey = ({ id, kind, label }) => [kind, id, label].join(SEPARATOR);
764
- var getDevices = async () => {
765
- if ("mediaDevices" in navigator && "enumerateDevices" in navigator.mediaDevices) {
766
- const devices = await navigator.mediaDevices.enumerateDevices();
767
- return devices;
768
- }
769
- return [];
770
- };
771
- var toDeviceKey = (device) => toKey({ id: device.deviceId, kind: device.kind, label: device.label });
772
- var toDeviceTuple = (device) => [toDeviceKey(device), device];
773
- var toDevicesMap = (devices) => {
774
- return new Map(devices.map(toDeviceTuple));
775
- };
776
- var toUniqueDevices = (devices) => {
777
- const map = toDevicesMap(devices);
778
- return Array.from(map.values());
779
- };
780
- var createTrackDevicesChanges = (prevDevices = []) => {
781
- let seen = toDevicesMap(prevDevices);
782
- return (devices) => {
783
- const found = [];
784
- const lost = [];
785
- const uniqueDevices = toUniqueDevices(devices);
786
- const { authorized, unauthorized } = uniqueDevices.reduce(
787
- (ds, d) => {
788
- if (d.label) {
789
- ds.authorized.push(d);
790
- } else {
791
- ds.unauthorized.push(d);
792
- }
793
- return ds;
794
- },
795
- { authorized: [], unauthorized: [] }
796
- );
797
- for (const device of authorized) {
798
- if (!seen.delete(toDeviceKey(device))) {
799
- found.push(device);
800
- }
801
- }
802
- for (const device of seen.values()) {
803
- lost.push(device);
804
- }
805
- seen = new Map(authorized.map(toDeviceTuple));
806
- return { unauthorized, authorized, found, lost, devices: uniqueDevices };
807
- };
808
- };
809
- var deviceChanged = (fn) => {
810
- const trackChanges = createTrackDevicesChanges();
811
- const odc = async () => {
812
- const devices = await getDevices();
813
- const changes = trackChanges(devices);
814
- fn(changes);
815
- };
816
- if (navigator.mediaDevices && "ondevicechange" in navigator.mediaDevices) {
817
- navigator.mediaDevices.ondevicechange = odc;
818
- return () => {
819
- navigator.mediaDevices.ondevicechange = null;
820
- };
821
- }
822
- const it = window.setInterval(() => void odc(), 5e3);
823
- return () => {
824
- window.clearInterval(it);
825
- };
826
- };
827
- var extractDeviceInfo = (track) => {
828
- const { deviceId, groupId, ...settings } = track.getSettings();
829
- const kind = track.kind === "audio" ? "audioinput" /* AUDIOINPUT */ : "videoinput" /* VIDEOINPUT */;
830
- return {
831
- kind,
832
- deviceId: deviceId ?? "",
833
- groupId: groupId ?? "",
834
- label: track.label,
835
- settings
836
- };
837
- };
838
- var toMediaDeviceInfoLike = (track) => {
839
- const { deviceId, label, kind, groupId } = extractDeviceInfo(track);
840
- if (!deviceId) {
841
- return;
842
- }
843
- return { deviceId, label, kind, groupId };
844
- };
845
- var compareMediaDeviceToMediaTrack = (track) => (device) => {
846
- const { deviceId } = track.getSettings();
847
- const sameLabel = device.label === track.label;
848
- const sameKind = device.kind.startsWith(track.kind);
849
- if (deviceId) {
850
- return sameKind && deviceId === device.deviceId;
851
- }
852
- return sameKind && sameLabel;
853
- };
854
- var toMediaDeviceInfoLikeJSON = (info) => ({
855
- deviceId: info.deviceId,
856
- groupId: info.groupId,
857
- kind: info.kind,
858
- label: info.label,
859
- settings: info.settings
860
- });
861
- var findMediaInputFromMediaStreamTrack = (devices) => (track) => {
862
- if (!devices.length || !track) {
863
- return void 0;
864
- }
865
- const settings = track.getSettings();
866
- const devicesWithSameKind = devices.filter(
867
- (d) => d.kind === `${track.kind}input`
868
- );
869
- const onlyDevice = devicesWithSameKind[0];
870
- if (devicesWithSameKind.length === 1 && onlyDevice) {
871
- onlyDevice.settings = settings;
872
- onlyDevice.toJSON = () => toMediaDeviceInfoLikeJSON(onlyDevice);
873
- return onlyDevice;
874
- }
875
- const device = devicesWithSameKind.find(
876
- compareMediaDeviceToMediaTrack(track)
877
- );
878
- if (device) {
879
- device.settings = settings;
880
- device.toJSON = () => toMediaDeviceInfoLikeJSON(device);
881
- return device;
882
- }
883
- return device;
884
- };
885
- var findMediaInputFromStream = (devices) => (stream) => {
886
- if (!stream || !devices.length) {
887
- return {};
888
- }
889
- const findMediaInput = findMediaInputFromMediaStreamTrack(devices);
890
- return {
891
- audioInput: findMediaInput(...stream.getAudioTracks()),
892
- videoInput: findMediaInput(...stream.getVideoTracks())
893
- };
894
- };
895
- var compareDeviceConstraintAndTrackDevice = (device) => (constraint) => {
896
- if (!device || !constraint) {
897
- return Boolean(device) === Boolean(constraint);
898
- }
899
- const normalized = normalizeDeviceConstraint(constraint);
900
- if (normalized) {
901
- const requestingDevices = Object.values(
902
- normalized
903
- ).flatMap((t) => Array.isArray(t) ? t : [t]);
904
- const compare = compareDevices(
905
- device,
906
- device.label ? "label" : "deviceId"
907
- );
908
- return requestingDevices.some(compare);
909
- }
910
- return false;
911
- };
912
- var isRequestedResolution = (request, response) => {
913
- if (!response || !request) {
914
- return Boolean(response) === Boolean(request);
915
- }
916
- if (isInputConstraintSet(request)) {
917
- const [width] = extractConstrainNumber("width")(request);
918
- const [height] = extractConstrainNumber("height")(request);
919
- const { width: responseWidth = 0, height: responseHeight = 0 } = response.settings ?? {};
920
- const portrait = responseHeight >= responseWidth;
921
- const resultWidth = portrait ? responseHeight : responseWidth;
922
- const resultHeight = portrait ? responseWidth : responseHeight;
923
- const sameWidth = satisfyConstrainNumber(width, resultWidth);
924
- const sameHeight = satisfyConstrainNumber(height, resultHeight);
925
- return sameWidth && sameHeight;
926
- }
927
- return true;
928
- };
929
- var isRequestedInputDevice = (request, response) => {
930
- if (!response || !request) {
931
- return Boolean(response) === Boolean(request);
932
- }
933
- const compareDevice = compareDeviceConstraintAndTrackDevice(response);
934
- if (isInputConstraintSet(request)) {
935
- if (isConstraintSetDevice(request.device)) {
936
- const isSameDevice = compareDevice(request.device);
937
- return isSameDevice;
938
- }
939
- if (request.deviceId) {
940
- const { deviceId } = response;
941
- if (!deviceId) {
942
- return true;
943
- }
944
- if (isConstraintDOMString(request.deviceId)) {
945
- const ids = toArray(request.deviceId);
946
- return ids.some((id) => deviceId === id);
947
- }
948
- if (isConstrainDOMStringParameters(request.deviceId)) {
949
- return Object.values(request.deviceId).flatMap(toArray).some((id) => id === deviceId);
950
- }
951
- }
952
- const facingMode = response.settings?.facingMode;
953
- if (request.facingMode && facingMode) {
954
- const [facingModes] = extractConstrainString("facingMode")(request);
955
- return facingModes?.some((fm) => fm === facingMode) ?? true;
956
- }
957
- return true;
958
- }
959
- if (isConstraintSetDevice(request)) {
960
- return compareDevice(request);
961
- }
962
- return !!response;
963
- };
964
- var isRequestedInputTrack = (request, current) => {
965
- if (!request || !current) {
966
- return Boolean(request) === Boolean(current);
967
- }
968
- if (isMediaDeviceInfo(current)) {
969
- return isRequestedInputDevice(request, current);
970
- }
971
- if (isMediaStreamTrack(current)) {
972
- const device = extractDeviceInfo(current);
973
- return isRequestedInputDevice(request, device);
974
- }
975
- return true;
976
- };
977
- var extractDevice = extractConstraintsWithKeys(["device", "deviceId"]);
978
- var hasRequestingDevice = (request, kind, currentDevices) => {
979
- if (!request) {
980
- return false;
981
- }
982
- const {
983
- device: [devices],
984
- deviceId: [deviceIds]
985
- } = extractDevice(request);
986
- if ((!devices || devices.length === 0) && (!deviceIds || deviceIds.length === 0)) {
987
- return currentDevices.some((device) => device.kind === kind);
988
- }
989
- const find = (device) => findDevice(device)(currentDevices);
990
- return devices?.some((device) => find(device)) ?? deviceIds?.some(
991
- (deviceId) => find({ kind, deviceId, label: "", groupId: "" })
992
- ) ?? false;
993
- };
994
- var shouldRequestDevice = (request, tracks, currentDevices) => {
995
- if (!request || !currentDevices.some((device) => device.label)) {
996
- return false;
997
- }
998
- const { kind } = currentDevices[0] ?? {};
999
- if (!kind || currentDevices.some((device) => device.kind !== kind)) {
1000
- throw new Error("Expect a single kind of device");
1001
- }
1002
- const [track] = tracks;
1003
- if (tracks.length === 0 || tracks.some((track2) => track2.readyState === "ended")) {
1004
- return true;
1005
- }
1006
- if (isRequestedInputTrack(request, track)) {
1007
- return false;
1008
- }
1009
- if (hasRequestingDevice(request, kind, currentDevices)) {
1010
- return true;
1011
- }
1012
- return false;
1013
- };
1014
- var resolveInputDevice = (tracksOrDevice, findInput) => {
1015
- if (isMediaDeviceInfo(tracksOrDevice)) {
1016
- return tracksOrDevice;
1017
- }
1018
- if (Array.isArray(tracksOrDevice)) {
1019
- const [track] = tracksOrDevice;
1020
- if (track?.readyState === "live") {
1021
- return findInput(track) ?? track;
1022
- }
1023
- }
1024
- return void 0;
1025
- };
1026
- var isStreamingRequestedDevicesBase = (request, tracksOrDevices, devices) => {
1027
- const audioRequest = relaxInputConstraint(request.audio, devices);
1028
- const videoRequest = relaxInputConstraint(request.video, devices);
1029
- const findInput = findMediaInputFromMediaStreamTrack(devices);
1030
- const audioInput = resolveInputDevice(tracksOrDevices.audio, findInput);
1031
- const videoInput = resolveInputDevice(tracksOrDevices.video, findInput);
1032
- const audio = isRequestedInputTrack(audioRequest, audioInput);
1033
- const video = isRequestedInputTrack(videoRequest, videoInput);
1034
- return { audio, video };
1035
- };
1036
- var isStreamingRequestedDevices = (request, stream, devices) => isStreamingRequestedDevicesBase(
1037
- request,
1038
- {
1039
- audio: stream?.getAudioTracks(),
1040
- video: stream?.getVideoTracks()
1041
- },
1042
- devices
1043
- );
1044
- var findPermissionGrantedDevices = (devices) => devices.filter(isDeviceGranted);
1045
- var toPermissionState = (devices, anyActiveStream = false) => {
1046
- const granted = devices.some((device) => device.label);
1047
- if (anyActiveStream) {
1048
- return granted ? "granted" : "denied";
1049
- }
1050
- return granted ? "granted" : "prompt";
1051
- };
1052
- var getInputDevicePermissionState = async (anyActiveStream = false) => {
1053
- try {
1054
- const video = await navigator.permissions.query({ name: "camera" });
1055
- const audio = await navigator.permissions.query({ name: "microphone" });
1056
- return { video: video.state, audio: audio.state };
1057
- } catch {
1058
- const devices = await getDevices();
1059
- return ["videoinput", "audioinput"].reduce(
1060
- (permission, kind) => {
1061
- const state2 = toPermissionState(
1062
- devices.filter((device) => device.kind === kind),
1063
- anyActiveStream
1064
- );
1065
- permission[kind === "audioinput" ? "audio" : "video"] = state2;
1066
- return permission;
1067
- },
1068
- { video: "prompt", audio: "prompt" }
1069
- );
1070
- }
1071
- };
1072
- var findCurrentAudioOutputId = (audioOutput, devices) => {
1073
- let selectedAudioOutputDeviceId = "";
1074
- if (audioOutput?.deviceId && devices) {
1075
- const latestSelectedAudioInput = findDevice(audioOutput)(devices);
1076
- if (latestSelectedAudioInput) {
1077
- selectedAudioOutputDeviceId = latestSelectedAudioInput.deviceId;
1078
- }
1079
- }
1080
- return selectedAudioOutputDeviceId;
1081
- };
1082
- var findCurrentVideoInputDeviceIdFromStream = (stream) => {
1083
- const [videoTrack] = stream.getVideoTracks();
1084
- return videoTrack && toMediaDeviceInfoLike(videoTrack)?.deviceId;
1085
- };
1086
- var findDeviceWithDeviceId = (devices, deviceId) => devices.find((d) => d.deviceId === deviceId);
1087
- var findDevicesByKind = (kind) => (devices) => devices.filter(isSameDeviceKind(kind));
1088
- var findAudioInputDevices = findDevicesByKind(
1089
- "audioinput" /* AUDIOINPUT */
1090
- );
1091
- var findVideoInputDevices = findDevicesByKind(
1092
- "videoinput" /* VIDEOINPUT */
1093
- );
1094
- var findAudioOutputDevices = findDevicesByKind(
1095
- "audiooutput" /* AUDIOOUTPUT */
1096
- );
1097
- var muteStreamTrack = (stream) => (mute, mediaType = "all") => {
1098
- switch (mediaType) {
1099
- case "audio":
1100
- stream?.getAudioTracks().forEach((track) => {
1101
- track.enabled = !mute;
1102
- });
1103
- break;
1104
- case "video":
1105
- stream?.getVideoTracks().forEach((track) => {
1106
- track.enabled = !mute;
1107
- });
1108
- break;
1109
- default:
1110
- stream?.getTracks().forEach((track) => {
1111
- track.enabled = !mute;
1112
- });
1113
- break;
1114
- }
1115
- };
1116
- var stopMediaStream = (stream, onStopped) => {
1117
- if (!stream) {
1118
- return;
1119
- }
1120
- stream.getTracks().forEach((track) => {
1121
- track.stop();
1122
- onStopped?.(track);
1123
- });
1124
- };
1125
- var areTracksEnabled = (stream, type) => {
1126
- if (!stream) {
1127
- return false;
1128
- }
1129
- const tracks = type === "audio" ? stream.getAudioTracks() : stream.getVideoTracks();
1130
- return tracks.length > 0 && tracks.every((track) => track.enabled);
1131
- };
1132
- var hasAudioOrVideoInputs = (devices) => devices.some(not(isAudioOutput));
1133
- var hasAudioInputs = (devices) => devices.some(isAudioInput);
1134
- var hasVideoInputs = (devices) => devices.some(isVideoInput);
1135
- var hasAnyGrantedInput = (devices) => devices.some(
1136
- (device) => isDeviceGranted(device) && (isVideoInput(device) || isAudioInput(device))
1137
- );
1138
- var hasAnyInputs = (devices, grantedOnly = false) => {
1139
- let anyAudioDevices = false;
1140
- let anyVideoDevices = false;
1141
- for (const device of devices) {
1142
- if (isAudioOutput(device) || grantedOnly && !isDeviceGranted(device)) {
1143
- continue;
1144
- }
1145
- if (isAudioInput(device)) {
1146
- anyAudioDevices = true;
1147
- }
1148
- if (isVideoInput(device)) {
1149
- anyVideoDevices = true;
1150
- }
1151
- if (anyVideoDevices && anyAudioDevices) {
1152
- return [true, true];
1153
- }
1154
- }
1155
- return [anyAudioDevices, anyVideoDevices];
1156
- };
1157
- var hasChangedInput = (oldInput, newInput) => {
1158
- if (isMediaDeviceInfo(newInput)) {
1159
- if (isMediaDeviceInfo(oldInput) && !compareDevices(oldInput)(newInput) || !oldInput) {
1160
- return true;
1161
- }
1162
- } else if (oldInput) {
1163
- return true;
1164
- }
1165
- return false;
1166
- };
1167
- var areMultipleFacingModeSupported = (currentDevices, getSupportedConstraints = () => navigator.mediaDevices.getSupportedConstraints()) => {
1168
- if (!getSupportedConstraints().facingMode) {
1169
- return false;
1170
- }
1171
- const set = /* @__PURE__ */ new Set();
1172
- const hasFrontAndBackCameras = currentDevices.some((device) => {
1173
- if (device.kind !== "videoinput") {
1174
- return false;
1175
- }
1176
- if (device.label.match(/front/i)) {
1177
- set.add("front");
1178
- }
1179
- if (device.label.match(/(back|rear)/i)) {
1180
- set.add("back");
1181
- }
1182
- return set.size > 1;
1183
- });
1184
- if (!hasFrontAndBackCameras) {
1185
- return false;
1186
- }
1187
- return true;
1188
- };
1189
- var interpretCurrentFacingMode = (currentTrack) => {
1190
- if (!currentTrack || currentTrack.kind !== "video") {
1191
- return void 0;
1192
- }
1193
- const settings = currentTrack.getSettings();
1194
- if ("getCapabilities" in currentTrack) {
1195
- const capabilities = currentTrack.getCapabilities();
1196
- if (capabilities.facingMode && capabilities.facingMode.length > 0) {
1197
- return settings.facingMode;
1198
- }
1199
- }
1200
- if (settings.facingMode) {
1201
- return settings.facingMode;
1202
- }
1203
- if (currentTrack.label.match(/front/i)) {
1204
- return "user";
1205
- }
1206
- if (currentTrack.label.match(/(back|rear)/i)) {
1207
- return "environment";
1208
- }
1209
- };
1210
-
1211
- // src/eventEmitter.ts
1212
- var MediaEventType = /* @__PURE__ */ ((MediaEventType2) => {
1213
- MediaEventType2["Mute"] = "mute";
1214
- MediaEventType2["Unmute"] = "unmute";
1215
- MediaEventType2["Ended"] = "ended";
1216
- MediaEventType2["DevicesChanged"] = "devices:changed";
1217
- MediaEventType2["DevicesFound"] = "devices:found";
1218
- MediaEventType2["DevicesLost"] = "devices:lost";
1219
- MediaEventType2["DeviceLost"] = "device:lost";
1220
- MediaEventType2["DevicesUnauthorized"] = "devices:unauthorized";
1221
- MediaEventType2["NoInputDevices"] = "devices:noinput";
1222
- MediaEventType2["Error"] = "error";
1223
- MediaEventType2["Stream"] = "stream";
1224
- return MediaEventType2;
1225
- })(MediaEventType || {});
1226
- var eventEmitter = () => {
1227
- const element = document.createElement("a");
1228
- const createEvent = (data) => {
1229
- return new CustomEvent("data", { detail: data });
1230
- };
1231
- return {
1232
- dispatch(event) {
1233
- element.dispatchEvent(createEvent(event));
1234
- },
1235
- subscriber(listener, onUnsubscribe) {
1236
- element.addEventListener(
1237
- "data",
1238
- listener,
1239
- false
1240
- );
1241
- return () => {
1242
- element.removeEventListener(
1243
- "data",
1244
- listener,
1245
- false
1246
- );
1247
- onUnsubscribe();
1248
- };
1249
- }
1250
- };
1251
- };
1252
-
1253
- // src/errors.ts
1254
- var isDeviceInUseError = (error) => {
1255
- return error === "NotReadableError" /* NotReadableError */ || error === "TrackStartError" /* TrackStartError */;
1256
- };
1257
- var isPermissionDeniedError = (error) => {
1258
- return error === "NotAllowedError" /* NotAllowedError */ || error === "PermissionDeniedError" /* PermissionDeniedError */;
1259
- };
1260
- var isInputNotFoundError = ({ input, kind, devices }) => (error) => {
1261
- if (error === "NotFoundError" /* NotFoundError */) {
1262
- const hasDevices = devices.some((d) => d.kind === kind);
1263
- if (typeof input === "boolean") {
1264
- if (!hasDevices && input) {
1265
- return true;
1266
- }
1267
- return input && !hasDevices;
1268
- }
1269
- if (isMediaTrackConstraints(input)) {
1270
- const [deviceIds, requirement] = extractDeviceId(input);
1271
- if (requirement === "ideal") {
1272
- return !hasDevices;
1273
- }
1274
- if (requirement === "exact") {
1275
- return !devices.some(
1276
- (device) => deviceIds?.some(
1277
- (id) => device.kind === kind && id === device.deviceId
1278
- )
1279
- );
1280
- }
1281
- }
1282
- }
1283
- return false;
1284
- };
1285
- var normalizeError = (errors, parameters = []) => {
1286
- const error = errors.find((e) => e.fn(...parameters));
1287
- if (error) {
1288
- return error.type;
1289
- }
1290
- return false;
1291
- };
1292
- var normalizeGetUserMediaError = (browserError, constraints, devices) => {
1293
- const isAudioInputNotFoundError = isInputNotFoundError({
1294
- input: constraints.audio,
1295
- kind: "audioinput",
1296
- devices
1297
- });
1298
- const isVideoInputNotFoundError = isInputNotFoundError({
1299
- input: constraints.video,
1300
- kind: "videoinput",
1301
- devices
1302
- });
1303
- const areBothInputsNotFoundError = (error2) => isAudioInputNotFoundError(error2) && isVideoInputNotFoundError(error2);
1304
- const errorsFn = [
1305
- {
1306
- fn: isDeviceInUseError,
1307
- type: "NotReadableError" /* NotReadableError */
1308
- // For now just normalize to current spec
1309
- },
1310
- {
1311
- fn: isPermissionDeniedError,
1312
- type: "NotAllowedError" /* NotAllowedError */
1313
- },
1314
- {
1315
- fn: areBothInputsNotFoundError,
1316
- type: "AudioAndVideoDeviceNotFoundError" /* AudioAndVideoDeviceNotFoundError */
1317
- },
1318
- {
1319
- fn: isAudioInputNotFoundError,
1320
- type: "AudioInputDeviceNotFoundError" /* AudioInputDeviceNotFoundError */
1321
- },
1322
- {
1323
- fn: isVideoInputNotFoundError,
1324
- type: "VideoInputDeviceNotFoundError" /* VideoInputDeviceNotFoundError */
1325
- }
1326
- ];
1327
- const errorMsg = browserError.name === "Error" ? browserError.message : browserError.name;
1328
- const error = normalizeError(errorsFn, [errorMsg]);
1329
- return error ? error : errorMsg;
1330
- };
1331
-
1332
- // src/getMediaStream.ts
1333
- var getMediaStream = async (request) => {
1334
- if (!request.audio && !request.video) {
1335
- throw new Error("MissingConstraintsError" /* MissingConstraintsError */);
1336
- }
1337
- const devices = await getDevices();
1338
- const audio = relaxInputConstraint(request.audio, devices);
1339
- const video = relaxInputConstraint(request.video, devices);
1340
- const constraints = getMediaConstraints({
1341
- audio,
1342
- video,
1343
- defaultConstraints: request.getDefaultConstraints()
1344
- });
1345
- logger.debug(
1346
- { request, constraints, devices },
1347
- "Constraints used for getting media"
1348
- );
1349
- try {
1350
- navigator.mediaDevices.dispatchEvent(new Event("devicechange"));
1351
- const stream = await navigator.mediaDevices.getUserMedia(constraints);
1352
- navigator.mediaDevices.dispatchEvent(new Event("devicechange"));
1353
- return stream;
1354
- } catch (error) {
1355
- if (error instanceof Error) {
1356
- const devices2 = await getDevices();
1357
- throw new Error(
1358
- normalizeGetUserMediaError(error, constraints, devices2)
1359
- );
1360
- }
1361
- throw error;
1362
- }
1363
- };
1364
-
1365
- // src/streams.ts
1366
- var handleMediaStream = ({
1367
- dispatch,
1368
- getDefaultConstraints,
1369
- streamTrackMap
1370
- }) => {
1371
- const setupMediaStreamTracks = ({ stream }) => {
1372
- let userFacingMode = false;
1373
- for (const track of stream.getTracks()) {
1374
- const { facingMode } = track.getSettings();
1375
- if (track) {
1376
- streamTrackMap.add(track);
1377
- }
1378
- if (track.kind === "video" && isBoolean(facingMode)) {
1379
- userFacingMode = facingMode;
1380
- }
1381
- const mutedListener = () => {
1382
- dispatch({ id: track.id, type: "mute" /* Mute */ });
1383
- };
1384
- track.addEventListener("mute" /* Mute */, mutedListener, false);
1385
- const unmutedListener = () => {
1386
- dispatch({ id: track.id, type: "unmute" /* Unmute */ });
1387
- };
1388
- track.addEventListener(
1389
- "unmute" /* Unmute */,
1390
- unmutedListener,
1391
- false
1392
- );
1393
- const endedListener = () => {
1394
- dispatch({ id: track.id, type: "ended" /* Ended */ });
1395
- track.removeEventListener(
1396
- "ended" /* Ended */,
1397
- endedListener,
1398
- false
1399
- );
1400
- track.removeEventListener(
1401
- "mute" /* Mute */,
1402
- mutedListener,
1403
- false
1404
- );
1405
- track.removeEventListener(
1406
- "unmute" /* Unmute */,
1407
- unmutedListener,
1408
- false
1409
- );
1410
- if (streamTrackMap.has(track)) {
1411
- streamTrackMap.remove(track);
1412
- }
1413
- };
1414
- track.addEventListener("ended", endedListener, true);
1415
- }
1416
- dispatch({
1417
- facingMode: userFacingMode,
1418
- stream,
1419
- type: "stream" /* Stream */,
1420
- video: stream.getVideoTracks().length > 0
1421
- });
1422
- };
1423
- const getUserMedia2 = async ({
1424
- audio,
1425
- video
1426
- }) => {
1427
- try {
1428
- const stream = await getMediaStream({
1429
- audio,
1430
- video,
1431
- getDefaultConstraints
1432
- });
1433
- setupMediaStreamTracks({ stream });
1434
- return stream;
1435
- } catch (error) {
1436
- if (error instanceof Error) {
1437
- dispatch({ type: "error" /* Error */, error });
1438
- }
1439
- throw error;
1440
- }
1441
- };
1442
- return { getUserMedia: getUserMedia2 };
1443
- };
1444
- var createStreamTrackEventSubscriptions = (track, handlers) => {
1445
- const trackSubscriptions = Object.keys(handlers).flatMap((eventKey) => {
1446
- const key = eventKey;
1447
- const trackEventHandler = handlers[key];
1448
- if (trackEventHandler) {
1449
- const handleEvent = () => trackEventHandler(track);
1450
- track.addEventListener(key, handleEvent);
1451
- const removeTrackEventHandler = () => {
1452
- track.removeEventListener(key, handleEvent);
1453
- };
1454
- return [removeTrackEventHandler];
1455
- }
1456
- return [];
1457
- });
1458
- return () => {
1459
- trackSubscriptions.forEach((unsubscribeEvent) => unsubscribeEvent());
1460
- };
1461
- };
1462
-
1463
- // src/streamTrackMap.ts
1464
- var createStreamTrackMap = (tracks) => {
1465
- const streamTrackMap = new Map(
1466
- tracks?.map((track) => [toKey(track), track])
1467
- );
1468
- const findTrack = (device) => {
1469
- return [...streamTrackMap].map(([_, track]) => track).find((track) => {
1470
- const { kind } = track;
1471
- const { deviceId } = track.getSettings();
1472
- if (!deviceId) {
1473
- return false;
1474
- }
1475
- return device.kind.includes(kind) && device.deviceId === deviceId;
1476
- });
1477
- };
1478
- const toStreamTrackKey = (deviceOrTrack) => {
1479
- const track = isMediaStreamTrack(deviceOrTrack) ? deviceOrTrack : findTrack(deviceOrTrack);
1480
- if (!track?.kind || !track.id) {
1481
- return "";
1482
- }
1483
- return toKey(track);
1484
- };
1485
- const add = (track) => {
1486
- const key = toStreamTrackKey(track);
1487
- if (key) {
1488
- return streamTrackMap.set(key, track);
1489
- }
1490
- throw new Error("StreamTrackNotFound" /* StreamTrackNotFound */);
1491
- };
1492
- const has = (deviceOrTrack) => {
1493
- const key = toStreamTrackKey(deviceOrTrack);
1494
- return key && streamTrackMap.has(key);
1495
- };
1496
- const clear = () => {
1497
- streamTrackMap.forEach((track) => {
1498
- track.stop();
1499
- });
1500
- streamTrackMap.clear();
1501
- };
1502
- const remove = (track) => {
1503
- const key = toStreamTrackKey(track);
1504
- track.stop();
1505
- return streamTrackMap.delete(key);
1506
- };
1507
- const size = () => streamTrackMap.size;
1508
- return {
1509
- add,
1510
- has,
1511
- clear,
1512
- remove,
1513
- size
1514
- };
1515
- };
1516
-
1517
- // src/constants.ts
1518
- var DISPLAY_CAPTURE_SURFACE_TYPE = {
1519
- Monitor: "monitor",
1520
- Window: "window",
1521
- Browser: "browser"
1522
- };
1523
- var CURSOR_CAPTURE_CONSTRAINT = {
1524
- Never: "never",
1525
- Always: "always",
1526
- Motion: "motion"
1527
- };
1528
- var INCLUDE_EXCLUDE_CONSTRAINT = {
1529
- Include: "include",
1530
- Exclude: "exclude"
1531
- };
1532
-
1533
- // src/displayMedia.ts
1534
- var limitSharingMonitorInterface = (constraints, stream) => {
1535
- if (!constraints.monitorTypeSurfaces || constraints.monitorTypeSurfaces !== "exclude") {
1536
- return stream;
1537
- }
1538
- for (const track of stream.getTracks()) {
1539
- const { displaySurface } = track.getSettings();
1540
- if (!displaySurface || displaySurface !== "monitor") {
1541
- continue;
1542
- }
1543
- stopMediaStream(stream);
1544
- throw new TypeError("MonitorSharingNotAllowed", {
1545
- cause: {
1546
- monitorTypeSurfaces: constraints.monitorTypeSurfaces,
1547
- track,
1548
- displaySurface
1549
- }
1550
- });
1551
- }
1552
- return stream;
1553
- };
1554
-
1555
- // src/index.ts
1556
- var state = () => {
1557
- const { dispatch, subscriber } = eventEmitter();
1558
- const streamTrackMap = createStreamTrackMap();
1559
- const { getDefaultConstraints, setDefaultConstraints: setDefaultConstraints2 } = getConstraintsHandlers();
1560
- const { getUserMedia: getUserMedia2 } = handleMediaStream({
1561
- dispatch,
1562
- getDefaultConstraints,
1563
- streamTrackMap
1564
- });
1565
- const subscribe2 = (listener) => {
1566
- return subscriber(
1567
- listener,
1568
- deviceChanged((event) => {
1569
- dispatch({
1570
- type: "devices:changed" /* DevicesChanged */,
1571
- devices: event.devices
1572
- });
1573
- if (!hasAudioOrVideoInputs(event.devices)) {
1574
- return dispatch({
1575
- type: "devices:noinput" /* NoInputDevices */,
1576
- devices: event.devices
1577
- });
1578
- }
1579
- if (event.unauthorized.length) {
1580
- dispatch({
1581
- type: "devices:unauthorized" /* DevicesUnauthorized */,
1582
- devices: event.unauthorized,
1583
- authorizedDevices: event.authorized
1584
- });
1585
- }
1586
- if (event.found.length) {
1587
- dispatch({
1588
- type: "devices:found" /* DevicesFound */,
1589
- authorizedDevices: event.authorized,
1590
- unauthorizedDevices: event.unauthorized,
1591
- devices: event.found
1592
- });
1593
- }
1594
- if (event.lost.length) {
1595
- dispatch({
1596
- type: "devices:lost" /* DevicesLost */,
1597
- authorizedDevices: event.authorized,
1598
- unauthorizedDevices: event.unauthorized,
1599
- devices: event.lost
1600
- });
1601
- for (const device of event.lost) {
1602
- if (streamTrackMap.has(device)) {
1603
- dispatch({ type: "device:lost" /* DeviceLost */, device });
1604
- }
1605
- }
1606
- }
1607
- })
1608
- );
1609
- };
1610
- return {
1611
- getUserMedia: getUserMedia2,
1612
- setDefaultConstraints: setDefaultConstraints2,
1613
- subscribe: subscribe2
1614
- };
1615
- };
1616
- var {
1617
- /**
1618
- * Get MediaStream with provided {@link MediaDeviceRequest | input constraints}
1619
- */
1620
- getUserMedia,
1621
- /**
1622
- * Set default media stream constraints
1623
- *
1624
- * A {@link
1625
- * https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints |
1626
- * MediaStreamConstraints} object specifying the types of media to request, along with any requirements for each type.
1627
- */
1628
- setDefaultConstraints,
1629
- /**
1630
- * Subscribe media events
1631
- */
1632
- subscribe
1633
- } = state();
1634
- export {
1635
- CURSOR_CAPTURE_CONSTRAINT,
1636
- DISPLAY_CAPTURE_SURFACE_TYPE,
1637
- INCLUDE_EXCLUDE_CONSTRAINT,
1638
- MediaDeviceFailure,
1639
- MediaDeviceKinds,
1640
- MediaEventType,
1641
- applyConstraints,
1642
- areMultipleFacingModeSupported,
1643
- areTracksEnabled,
1644
- compareDevices,
1645
- createStreamTrackEventSubscriptions,
1646
- createTrackDevicesChanges,
1647
- deviceChanged,
1648
- extractConstraintsWithKeys,
1649
- findAudioInputDevices,
1650
- findAudioOutputDevices,
1651
- findCurrentAudioOutputId,
1652
- findCurrentVideoInputDeviceIdFromStream,
1653
- findDevice,
1654
- findDeviceFromConstraints,
1655
- findDeviceWithDeviceId,
1656
- findDevicesByKind,
1657
- findMediaInputFromMediaStreamTrack,
1658
- findMediaInputFromStream,
1659
- findPermissionGrantedDevices,
1660
- findVideoInputDevices,
1661
- getDevices,
1662
- getFacingModeFromConstraintString,
1663
- getInputDevicePermissionState,
1664
- getUserMedia,
1665
- getValueFromConstrainNumber,
1666
- hasAnyGrantedInput,
1667
- hasAnyInputs,
1668
- hasAudioInputs,
1669
- hasAudioOrVideoInputs,
1670
- hasChangedInput,
1671
- hasRequestingDevice,
1672
- hasVideoInputs,
1673
- interpretCurrentFacingMode,
1674
- isAudioInput,
1675
- isAudioOutput,
1676
- isDeviceGranted,
1677
- isExactDeviceConstraint,
1678
- isFacingMode,
1679
- isMediaDeviceInfo,
1680
- isMediaDeviceInfoArray,
1681
- isMediaStreamTrack,
1682
- isRequestedInputDevice,
1683
- isRequestedInputTrack,
1684
- isRequestedResolution,
1685
- isStreamingRequestedDevices,
1686
- isStreamingRequestedDevicesBase,
1687
- isVideoInput,
1688
- limitSharingMonitorInterface,
1689
- mergeConstraints,
1690
- muteStreamTrack,
1691
- relaxInputConstraint,
1692
- setDefaultConstraints,
1693
- setLogger,
1694
- shouldRequestDevice,
1695
- stopMediaStream,
1696
- subscribe,
1697
- toKey,
1698
- toMediaDeviceInfoLike
1699
- };