@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.js ADDED
@@ -0,0 +1,105 @@
1
+ /**
2
+ * media-control is meant to extend the mediaDevices api methods such as
3
+ * `getUserMedia`, `enumerateDevices` and events on media streams and tracks.
4
+ * The final goal is to have a library that gives a stable and robust way to use
5
+ * these methods while guaranteeing that the developer has better control over
6
+ * which devices are delivered, fail, or exist.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ import { areMultipleFacingModeSupported, areTracksEnabled, createTrackDevicesChanges, deviceChanged, findAudioInputDevices, findAudioOutputDevices, findCurrentAudioOutputId, findCurrentVideoInputDeviceIdFromStream, findDeviceWithDeviceId, findDevicesByKind, findMediaInputFromMediaStreamTrack, findMediaInputFromStream, findPermissionGrantedDevices, findVideoInputDevices, getDevices, getInputDevicePermissionState, hasAnyGrantedInput, hasAnyInputs, hasAudioInputs, hasAudioOrVideoInputs, hasChangedInput, hasRequestingDevice, hasVideoInputs, interpretCurrentFacingMode, isRequestedInputDevice, isRequestedInputTrack, isRequestedResolution, isStreamingRequestedDevices, isStreamingRequestedDevicesBase, muteStreamTrack, shouldRequestDevice, stopMediaStream, toKey, toMediaDeviceInfo, toMediaDeviceInfoLike, } from './devices';
11
+ import { compareDevices, findDevice, isAudioOutput, isVideoInput, isAudioInput, isDeviceGranted, } from './utils';
12
+ import { mergeConstraints, getConstraintsHandlers, relaxInputConstraint, findDeviceFromConstraints, isExactDeviceConstraint, extractConstraintsWithKeys, applyConstraints, getValueFromConstrainNumber, getFacingModeFromConstraintString, } from './constraints';
13
+ import { eventEmitter, MediaEventType } from './eventEmitter';
14
+ import { handleMediaStream, createStreamTrackEventSubscriptions, } from './streams';
15
+ import { MediaDeviceFailure, MediaDeviceKinds, } from './types';
16
+ import { isMediaDeviceInfo, isMediaDeviceInfoArray, isMediaStreamTrack, isFacingMode, } from './typeGuards';
17
+ import { createStreamTrackMap } from './streamTrackMap';
18
+ export { setLogger } from './logger';
19
+ const state = () => {
20
+ const { dispatch, subscriber } = eventEmitter();
21
+ const streamTrackMap = createStreamTrackMap();
22
+ const { getDefaultConstraints, setDefaultConstraints } = getConstraintsHandlers();
23
+ const { getUserMedia } = handleMediaStream({
24
+ dispatch,
25
+ getDefaultConstraints,
26
+ streamTrackMap,
27
+ });
28
+ /**
29
+ * Subscription media events
30
+ *
31
+ * @beta
32
+ */
33
+ const subscribe = (listener) => {
34
+ return subscriber(listener, deviceChanged(event => {
35
+ // Can be used to keep a store in sync
36
+ dispatch({
37
+ type: MediaEventType.DevicesChanged,
38
+ devices: event.devices,
39
+ });
40
+ if (!hasAudioOrVideoInputs(event.devices)) {
41
+ return dispatch({
42
+ type: MediaEventType.NoInputDevices,
43
+ devices: event.devices,
44
+ });
45
+ }
46
+ if (event.unauthorized.length) {
47
+ dispatch({
48
+ type: MediaEventType.DevicesUnauthorized,
49
+ devices: event.unauthorized,
50
+ authorizedDevices: event.authorized,
51
+ });
52
+ }
53
+ if (event.found.length) {
54
+ // Can be used to trigger user notification of a potentially better device being available
55
+ dispatch({
56
+ type: MediaEventType.DevicesFound,
57
+ authorizedDevices: event.authorized,
58
+ unauthorizedDevices: event.unauthorized,
59
+ devices: event.found,
60
+ });
61
+ }
62
+ if (event.lost.length) {
63
+ // Can be used to trigger user notification of no longer seen devices
64
+ dispatch({
65
+ type: MediaEventType.DevicesLost,
66
+ authorizedDevices: event.authorized,
67
+ unauthorizedDevices: event.unauthorized,
68
+ devices: event.lost,
69
+ });
70
+ for (const device of event.lost) {
71
+ if (streamTrackMap.has(device)) {
72
+ // Can be used to trigger user warning that a device they were using is lost
73
+ dispatch({ type: MediaEventType.DeviceLost, device });
74
+ }
75
+ }
76
+ }
77
+ }));
78
+ };
79
+ return {
80
+ getUserMedia,
81
+ setDefaultConstraints,
82
+ subscribe,
83
+ };
84
+ };
85
+ const {
86
+ /**
87
+ * Get MediaStream with provided {@link MediaDeviceRequest | input constraints}
88
+ */
89
+ getUserMedia,
90
+ /**
91
+ * Set default media stream constraints
92
+ *
93
+ * A {@link
94
+ * https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints |
95
+ * MediaStreamConstraints} object specifying the types of media to request, along with any requirements for each type.
96
+ */
97
+ setDefaultConstraints,
98
+ /**
99
+ * Subscribe media events
100
+ */
101
+ subscribe, } = state();
102
+ export { getUserMedia, setDefaultConstraints, subscribe };
103
+ export { MediaDeviceFailure, MediaDeviceKinds, MediaEventType, applyConstraints, areMultipleFacingModeSupported, areTracksEnabled, compareDevices, createStreamTrackEventSubscriptions, createTrackDevicesChanges, deviceChanged, extractConstraintsWithKeys, findAudioInputDevices, findAudioOutputDevices, findCurrentAudioOutputId, findCurrentVideoInputDeviceIdFromStream, findDevice, findDeviceFromConstraints, findDeviceWithDeviceId, findDevicesByKind, findMediaInputFromMediaStreamTrack, findMediaInputFromStream, findPermissionGrantedDevices, findVideoInputDevices, getDevices, getFacingModeFromConstraintString, getInputDevicePermissionState, getValueFromConstrainNumber, hasAnyGrantedInput, hasAnyInputs, hasAudioInputs, hasAudioOrVideoInputs, hasChangedInput, hasRequestingDevice, hasVideoInputs, interpretCurrentFacingMode, isAudioInput, isAudioOutput, isDeviceGranted, isExactDeviceConstraint, isFacingMode, isMediaDeviceInfo, isMediaDeviceInfoArray, isMediaStreamTrack, isRequestedInputDevice, isRequestedInputTrack, isRequestedResolution, isStreamingRequestedDevices, isStreamingRequestedDevicesBase, isVideoInput, mergeConstraints, muteStreamTrack, relaxInputConstraint, shouldRequestDevice, stopMediaStream, toKey, toMediaDeviceInfo, toMediaDeviceInfoLike, };
104
+ export * from './constants';
105
+ export * from './displayMedia';
@@ -0,0 +1,3 @@
1
+ import type { Logger } from './baseLogger';
2
+ export declare let logger: Readonly<Logger>;
3
+ export declare function setLogger(newLogger: Logger): void;
package/dist/logger.js ADDED
@@ -0,0 +1,5 @@
1
+ import { createConsoleLogger } from './baseLogger';
2
+ export let logger = createConsoleLogger();
3
+ export function setLogger(newLogger) {
4
+ logger = newLogger;
5
+ }
@@ -0,0 +1,9 @@
1
+ import type { DeviceOrTrack, MediaStreamTrackLike } from './types';
2
+ export declare const createStreamTrackMap: (tracks?: MediaStreamTrackLike[]) => {
3
+ add: (track: MediaStreamTrackLike) => Map<string, MediaStreamTrackLike>;
4
+ has: (deviceOrTrack: DeviceOrTrack) => boolean | "";
5
+ clear: () => void;
6
+ remove: (track: MediaStreamTrackLike) => boolean;
7
+ size: () => number;
8
+ };
9
+ export type StreamTrackMap = ReturnType<typeof createStreamTrackMap>;
@@ -0,0 +1,79 @@
1
+ import { MediaDeviceFailure } from './types';
2
+ import { toKey } from './devices';
3
+ import { isMediaStreamTrack } from './typeGuards';
4
+ export const createStreamTrackMap = (tracks) => {
5
+ const streamTrackMap = new Map(tracks?.map(track => [toKey(track), track]));
6
+ /**
7
+ * Find track from the list of track in use.
8
+ */
9
+ const findTrack = (device) => {
10
+ return [...streamTrackMap]
11
+ .map(([_, track]) => track)
12
+ .find(track => {
13
+ const { kind } = track;
14
+ const { deviceId } = track.getSettings();
15
+ if (!deviceId) {
16
+ return false;
17
+ }
18
+ return (device.kind.includes(kind) && device.deviceId === deviceId);
19
+ });
20
+ };
21
+ /**
22
+ * Construct a `StreamTrackKey` from `DeviceOrTrack`
23
+ */
24
+ const toStreamTrackKey = (deviceOrTrack) => {
25
+ // Unify interfaces
26
+ const track = isMediaStreamTrack(deviceOrTrack)
27
+ ? deviceOrTrack
28
+ : findTrack(deviceOrTrack);
29
+ if (!track?.kind || !track.id) {
30
+ return '';
31
+ }
32
+ return toKey(track);
33
+ };
34
+ /**
35
+ * Add the `MediaStreamTrack` to `streamTrackMap`
36
+ */
37
+ const add = (track) => {
38
+ const key = toStreamTrackKey(track);
39
+ if (key) {
40
+ return streamTrackMap.set(key, track);
41
+ }
42
+ throw new Error(MediaDeviceFailure.StreamTrackNotFound);
43
+ };
44
+ /**
45
+ * Check if `streamTrackMap` has provided track or device
46
+ */
47
+ const has = (deviceOrTrack) => {
48
+ const key = toStreamTrackKey(deviceOrTrack);
49
+ return key && streamTrackMap.has(key);
50
+ };
51
+ /**
52
+ * Stop all tracks and empty `streamTrackMap`
53
+ */
54
+ const clear = () => {
55
+ streamTrackMap.forEach(track => {
56
+ track.stop();
57
+ });
58
+ streamTrackMap.clear();
59
+ };
60
+ /**
61
+ * Stop the track and remove the track from `streamTrackMap`
62
+ */
63
+ const remove = (track) => {
64
+ const key = toStreamTrackKey(track);
65
+ track.stop();
66
+ return streamTrackMap.delete(key);
67
+ };
68
+ /**
69
+ * Get the size of `streamTrackMap`
70
+ */
71
+ const size = () => streamTrackMap.size;
72
+ return {
73
+ add,
74
+ has,
75
+ clear,
76
+ remove,
77
+ size,
78
+ };
79
+ };
@@ -0,0 +1,26 @@
1
+ import type { MediaDeviceRequest, StreamTrackEventHandlers, Unsubscribe } from './types';
2
+ import type { Dispatch } from './eventEmitter';
3
+ import type { StreamTrackMap } from './streamTrackMap';
4
+ /**
5
+ * Handle media streaming related functions and events
6
+ *
7
+ * @returns getUserMedia function to stream media
8
+ *
9
+ * @internal
10
+ */
11
+ export declare const handleMediaStream: ({ dispatch, getDefaultConstraints, streamTrackMap, }: {
12
+ dispatch: Dispatch;
13
+ getDefaultConstraints: () => MediaStreamConstraints;
14
+ streamTrackMap: StreamTrackMap;
15
+ }) => {
16
+ getUserMedia: ({ audio, video, }: MediaDeviceRequest) => Promise<MediaStream>;
17
+ };
18
+ /**
19
+ * Create a MediaStreamTrack's native events subscription
20
+ *
21
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack#events
22
+ *
23
+ * @param track - The track used for the subscription
24
+ * @param handlers - An object contains the event handlers
25
+ */
26
+ export declare const createStreamTrackEventSubscriptions: (track: MediaStreamTrack, handlers: StreamTrackEventHandlers) => Unsubscribe;
@@ -0,0 +1,99 @@
1
+ import { isBoolean } from './typeGuards';
2
+ import { MediaEventType } from './eventEmitter';
3
+ import { getMediaStream } from './getMediaStream';
4
+ /**
5
+ * Handle media streaming related functions and events
6
+ *
7
+ * @returns getUserMedia function to stream media
8
+ *
9
+ * @internal
10
+ */
11
+ export const handleMediaStream = ({ dispatch, getDefaultConstraints, streamTrackMap, }) => {
12
+ const setupMediaStreamTracks = ({ stream }) => {
13
+ let userFacingMode = false;
14
+ for (const track of stream.getTracks()) {
15
+ const { facingMode } = track.getSettings();
16
+ if (track) {
17
+ streamTrackMap.add(track);
18
+ }
19
+ if (track.kind === 'video' && isBoolean(facingMode)) {
20
+ userFacingMode = facingMode;
21
+ }
22
+ const mutedListener = () => {
23
+ dispatch({ id: track.id, type: MediaEventType.Mute });
24
+ };
25
+ track.addEventListener(MediaEventType.Mute, mutedListener, false);
26
+ const unmutedListener = () => {
27
+ dispatch({ id: track.id, type: MediaEventType.Unmute });
28
+ };
29
+ track.addEventListener(MediaEventType.Unmute, unmutedListener, false);
30
+ const endedListener = () => {
31
+ dispatch({ id: track.id, type: MediaEventType.Ended });
32
+ track.removeEventListener(MediaEventType.Ended, endedListener, false);
33
+ track.removeEventListener(MediaEventType.Mute, mutedListener, false);
34
+ track.removeEventListener(MediaEventType.Unmute, unmutedListener, false);
35
+ if (streamTrackMap.has(track)) {
36
+ streamTrackMap.remove(track);
37
+ }
38
+ };
39
+ track.addEventListener('ended', endedListener, true);
40
+ }
41
+ dispatch({
42
+ facingMode: userFacingMode,
43
+ stream,
44
+ type: MediaEventType.Stream,
45
+ video: stream.getVideoTracks().length > 0,
46
+ });
47
+ };
48
+ /**
49
+ * Get MediaStream with MediaDeviceRequest
50
+ *
51
+ * @returns MediaStream
52
+ *
53
+ * @beta
54
+ */
55
+ const getUserMedia = async ({ audio, video, }) => {
56
+ try {
57
+ const stream = await getMediaStream({
58
+ audio,
59
+ video,
60
+ getDefaultConstraints,
61
+ });
62
+ setupMediaStreamTracks({ stream });
63
+ return stream;
64
+ }
65
+ catch (error) {
66
+ if (error instanceof Error) {
67
+ dispatch({ type: MediaEventType.Error, error });
68
+ }
69
+ throw error;
70
+ }
71
+ };
72
+ return { getUserMedia };
73
+ };
74
+ /**
75
+ * Create a MediaStreamTrack's native events subscription
76
+ *
77
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack#events
78
+ *
79
+ * @param track - The track used for the subscription
80
+ * @param handlers - An object contains the event handlers
81
+ */
82
+ export const createStreamTrackEventSubscriptions = (track, handlers) => {
83
+ const trackSubscriptions = Object.keys(handlers).flatMap(eventKey => {
84
+ const key = eventKey;
85
+ const trackEventHandler = handlers[key];
86
+ if (trackEventHandler) {
87
+ const handleEvent = () => trackEventHandler(track);
88
+ track.addEventListener(key, handleEvent);
89
+ const removeTrackEventHandler = () => {
90
+ track.removeEventListener(key, handleEvent);
91
+ };
92
+ return [removeTrackEventHandler];
93
+ }
94
+ return [];
95
+ });
96
+ return () => {
97
+ trackSubscriptions.forEach(unsubscribeEvent => unsubscribeEvent());
98
+ };
99
+ };
@@ -0,0 +1,89 @@
1
+ import type { ConstraintDeviceParameters, DeviceConstraint, InputConstraintSet } from './types';
2
+ export declare const isBoolean: (t: unknown) => t is boolean;
3
+ export declare const isUndefined: (t: unknown) => t is undefined;
4
+ /**
5
+ * Check if provided variable is of type number and is NOT NaN
6
+ */
7
+ export declare const isNumber: (t: unknown) => t is number;
8
+ /**
9
+ * Check if provided variable is of type integer
10
+ */
11
+ export declare const isInteger: (t: unknown) => t is number;
12
+ /**
13
+ * Check if provided variable is of type floating point
14
+ */
15
+ export declare const isFloat: (t: unknown) => t is number;
16
+ /**
17
+ * Reference https://w3c.github.io/mediacapture-main/#dom-mediatrackconstraintset
18
+ */
19
+ export declare const CONSTRAIN_STRING_KEYS: readonly ["facingMode", "resizeMode", "deviceId", "groupId"];
20
+ export declare const EXTENDED_CONSTRAIN_STRING_KEYS: readonly ["videoSegmentation", "videoSegmentationModel", "bgImageUrl", "contentHint"];
21
+ export type ExtendedConstrainStringKeys = (typeof EXTENDED_CONSTRAIN_STRING_KEYS)[number];
22
+ export type ConstrainStringKeys = (typeof CONSTRAIN_STRING_KEYS)[number];
23
+ export declare const CONSTRAIN_U_LONG_KEYS: readonly ["width", "height", "sampleRate", "sampleSize", "channelCount"];
24
+ export declare const EXTENDED_CONSTRAIN_U_LONG_KEYS: readonly ["backgroundBlurAmount", "edgeBlurAmount"];
25
+ export type ExtendedConstrainULongKeys = (typeof EXTENDED_CONSTRAIN_U_LONG_KEYS)[number];
26
+ export type ConstrainULongKeys = (typeof CONSTRAIN_U_LONG_KEYS)[number];
27
+ export declare const CONSTRAIN_DOUBLE_KEYS: readonly ["aspectRatio", "frameRate", "latency"];
28
+ export declare const EXTENDED_CONSTRAIN_DOUBLE_KEYS: readonly ["foregroundThreshold"];
29
+ export type ExtendedConstrainDoubleKeys = (typeof EXTENDED_CONSTRAIN_DOUBLE_KEYS)[number];
30
+ export type ConstrainDoubleKeys = (typeof CONSTRAIN_DOUBLE_KEYS)[number];
31
+ export declare const CONSTRAIN_BOOLEAN_KEYS: readonly ["echoCancellation", "autoGainControl", "noiseSuppression", "pan", "tilt", "zoom"];
32
+ /**
33
+ * Extends boolean constraint keys for our own implementation of the media
34
+ * feature
35
+ */
36
+ export declare const EXTENDED_CONSTRAIN_BOOLEAN_KEYS: readonly ["vad", "asd", "mixWithAdditionalMedia", "denoise", "flipHorizontal"];
37
+ export type ExtendedConstrainBooleanKeys = (typeof EXTENDED_CONSTRAIN_BOOLEAN_KEYS)[number];
38
+ export type ConstrainBooleanKeys = (typeof CONSTRAIN_BOOLEAN_KEYS)[number];
39
+ /**
40
+ * The keys from the `MediaTrackConstraintSet`
41
+ */
42
+ export declare const CONSTRAINT_SET_KEYS: readonly ["aspectRatio", "frameRate", "latency", "width", "height", "sampleRate", "sampleSize", "channelCount", "facingMode", "resizeMode", "deviceId", "groupId", "echoCancellation", "autoGainControl", "noiseSuppression", "pan", "tilt", "zoom"];
43
+ export declare const isConstrainStringKeys: (t: unknown) => t is "deviceId" | "groupId" | "resizeMode" | "facingMode";
44
+ export declare const isExtendedConstrainStringKeys: (t: unknown) => t is "videoSegmentation" | "videoSegmentationModel" | "bgImageUrl" | "contentHint";
45
+ export declare const isConstrainULongKeys: (t: unknown) => t is "width" | "height" | "sampleRate" | "sampleSize" | "channelCount";
46
+ export declare const isExtendedConstrainULongKeys: (t: unknown) => t is "backgroundBlurAmount" | "edgeBlurAmount";
47
+ export declare const isConstrainDoubleKeys: (t: unknown) => t is "aspectRatio" | "frameRate" | "latency";
48
+ export declare const isExtendedConstrainDoubleKeys: (t: unknown) => t is "foregroundThreshold";
49
+ export declare const isConstrainBooleanKeys: (t: unknown) => t is "pan" | "tilt" | "zoom" | "echoCancellation" | "autoGainControl" | "noiseSuppression";
50
+ export declare const isExtendedConstrainBooleanKeys: (t: unknown) => t is "denoise" | "vad" | "asd" | "mixWithAdditionalMedia" | "flipHorizontal";
51
+ export declare const isMediaTrackConstraintSetKey: (t: string) => t is keyof MediaTrackConstraintSet;
52
+ export declare const isMediaTrackConstraintsKey: (t: string) => t is keyof MediaTrackConstraints;
53
+ export declare const isMediaTrackConstraints: (t: unknown) => t is MediaTrackConstraints;
54
+ /**
55
+ * Check if provided is `MediaDeviceInfo`
56
+ *
57
+ * @beta
58
+ */
59
+ export declare const isMediaDeviceInfo: (t: unknown) => t is MediaDeviceInfo;
60
+ export declare const isMediaDeviceInfoArray: (t: unknown) => t is MediaDeviceInfo[];
61
+ export declare const isDeviceConstraint: (t: unknown) => t is DeviceConstraint;
62
+ export declare const isConstraintDOMString: (t: unknown) => t is string | string[];
63
+ declare const CONSTRAIN_PARAM_KEYS: readonly ["exact", "ideal"];
64
+ export type ConstrainParamKeys = (typeof CONSTRAIN_PARAM_KEYS)[number];
65
+ declare const CONSTRAIN_RANGE_KEYS: readonly ["min", "max"];
66
+ export type ConstrainRangeKeys = (typeof CONSTRAIN_RANGE_KEYS)[number];
67
+ export type ConstrainRangeParamKeys = ConstrainParamKeys | ConstrainRangeKeys;
68
+ export declare const isConstrainDOMParameters: <R>(isType: (x: unknown) => boolean, keys?: readonly ConstrainRangeParamKeys[]) => (t: unknown) => t is R;
69
+ export declare const isConstrainDOMStringParameters: (t: unknown) => t is ConstrainDOMStringParameters;
70
+ export declare const isConstrainBooleanParameters: (t: unknown) => t is ConstrainBooleanParameters;
71
+ /**
72
+ * Check if provided var is a constraint object with `min` and/or `max` key only
73
+ */
74
+ export declare const isConstrainRange: (t: unknown) => t is ConstrainDoubleRange;
75
+ export declare const isConstrainDoubleRange: (t: unknown) => t is ConstrainDoubleRange;
76
+ export declare const isConstrainULongRange: (t: unknown) => t is ConstrainULongRange;
77
+ export declare const isConstraintDeviceParameters: (t: unknown) => t is ConstraintDeviceParameters;
78
+ export declare const isConstraintSetDevice: (t: unknown) => t is DeviceConstraint | ConstraintDeviceParameters | undefined;
79
+ type ExtendedConstraintSet = Pick<InputConstraintSet, ExtendedConstrainULongKeys | ExtendedConstrainDoubleKeys | ExtendedConstrainStringKeys | ExtendedConstrainBooleanKeys | 'device'>;
80
+ export declare const isExtendedConstraint: (t: unknown) => t is ExtendedConstraintSet;
81
+ export declare const isInputConstraintSet: (t: unknown) => t is InputConstraintSet;
82
+ /**
83
+ * Check if provided is `MediaStreamTrack`
84
+ *
85
+ * @beta
86
+ */
87
+ export declare const isMediaStreamTrack: (m: unknown) => m is MediaStreamTrack;
88
+ export declare const isFacingMode: (s: unknown) => s is "user" | "environment" | "left" | "right";
89
+ export {};
@@ -0,0 +1,185 @@
1
+ import { hasOwnProperty } from '@pexip/utils';
2
+ import { FACING_MODE } from './types';
3
+ export const isBoolean = (t) => typeof t === 'boolean';
4
+ export const isUndefined = (t) => typeof t === 'undefined';
5
+ /**
6
+ * Check if provided variable is of type number and is NOT NaN
7
+ */
8
+ export const isNumber = (t) => typeof t === 'number' && !Number.isNaN(t);
9
+ /**
10
+ * Check if provided variable is of type integer
11
+ */
12
+ export const isInteger = (t) => Number.isInteger(t);
13
+ /**
14
+ * Check if provided variable is of type floating point
15
+ */
16
+ export const isFloat = (t) => isNumber(t) && !Number.isInteger(t) && Number.isFinite(t);
17
+ /**
18
+ * Reference https://w3c.github.io/mediacapture-main/#dom-mediatrackconstraintset
19
+ */
20
+ export const CONSTRAIN_STRING_KEYS = [
21
+ 'facingMode',
22
+ 'resizeMode',
23
+ 'deviceId',
24
+ 'groupId',
25
+ ];
26
+ export const EXTENDED_CONSTRAIN_STRING_KEYS = [
27
+ 'videoSegmentation',
28
+ 'videoSegmentationModel',
29
+ 'bgImageUrl',
30
+ 'contentHint',
31
+ ];
32
+ export const CONSTRAIN_U_LONG_KEYS = [
33
+ 'width',
34
+ 'height',
35
+ 'sampleRate',
36
+ 'sampleSize',
37
+ 'channelCount',
38
+ ];
39
+ export const EXTENDED_CONSTRAIN_U_LONG_KEYS = [
40
+ 'backgroundBlurAmount',
41
+ 'edgeBlurAmount',
42
+ ];
43
+ export const CONSTRAIN_DOUBLE_KEYS = [
44
+ 'aspectRatio',
45
+ 'frameRate',
46
+ 'latency',
47
+ ];
48
+ export const EXTENDED_CONSTRAIN_DOUBLE_KEYS = ['foregroundThreshold'];
49
+ export const CONSTRAIN_BOOLEAN_KEYS = [
50
+ 'echoCancellation',
51
+ 'autoGainControl',
52
+ 'noiseSuppression',
53
+ 'pan',
54
+ 'tilt',
55
+ 'zoom',
56
+ ];
57
+ /**
58
+ * Extends boolean constraint keys for our own implementation of the media
59
+ * feature
60
+ */
61
+ export const EXTENDED_CONSTRAIN_BOOLEAN_KEYS = [
62
+ // Voice Activity Detection
63
+ 'vad',
64
+ // Audio Signal Detection
65
+ 'asd',
66
+ // Mixing with another track
67
+ 'mixWithAdditionalMedia',
68
+ // Noise Suppression using our own impl
69
+ 'denoise',
70
+ // Flip the video horizontally
71
+ 'flipHorizontal',
72
+ ];
73
+ /**
74
+ * The keys from the `MediaTrackConstraintSet`
75
+ */
76
+ export const CONSTRAINT_SET_KEYS = [
77
+ ...CONSTRAIN_DOUBLE_KEYS,
78
+ ...CONSTRAIN_U_LONG_KEYS,
79
+ ...CONSTRAIN_STRING_KEYS,
80
+ ...CONSTRAIN_BOOLEAN_KEYS,
81
+ ];
82
+ export const isConstrainStringKeys = (t) => CONSTRAIN_STRING_KEYS.includes(t);
83
+ export const isExtendedConstrainStringKeys = (t) => EXTENDED_CONSTRAIN_STRING_KEYS.includes(t);
84
+ export const isConstrainULongKeys = (t) => CONSTRAIN_U_LONG_KEYS.includes(t);
85
+ export const isExtendedConstrainULongKeys = (t) => EXTENDED_CONSTRAIN_U_LONG_KEYS.includes(t);
86
+ export const isConstrainDoubleKeys = (t) => CONSTRAIN_DOUBLE_KEYS.includes(t);
87
+ export const isExtendedConstrainDoubleKeys = (t) => EXTENDED_CONSTRAIN_DOUBLE_KEYS.includes(t);
88
+ export const isConstrainBooleanKeys = (t) => CONSTRAIN_BOOLEAN_KEYS.includes(t);
89
+ export const isExtendedConstrainBooleanKeys = (t) => EXTENDED_CONSTRAIN_BOOLEAN_KEYS.includes(t);
90
+ export const isMediaTrackConstraintSetKey = (t) => CONSTRAINT_SET_KEYS.includes(t);
91
+ export const isMediaTrackConstraintsKey = (t) => isMediaTrackConstraintSetKey(t) || t === 'advanced';
92
+ export const isMediaTrackConstraints = (t) => {
93
+ if (!t || typeof t !== 'object' || Array.isArray(t) || t === null) {
94
+ return false;
95
+ }
96
+ const keys = Object.keys(t);
97
+ return (!!keys.length &&
98
+ Object.keys(t).every(key => isMediaTrackConstraintsKey(key)));
99
+ };
100
+ /**
101
+ * Check if provided is `MediaDeviceInfo`
102
+ *
103
+ * @beta
104
+ */
105
+ export const isMediaDeviceInfo = (t) => {
106
+ if (!t || typeof t !== 'object') {
107
+ return false;
108
+ }
109
+ return !!t && 'deviceId' in t && 'kind' in t;
110
+ };
111
+ export const isMediaDeviceInfoArray = (t) => {
112
+ if (Array.isArray(t) && t.length && t.some(isMediaDeviceInfo)) {
113
+ return true;
114
+ }
115
+ return false;
116
+ };
117
+ export const isDeviceConstraint = (t) => {
118
+ return isMediaDeviceInfo(t) || isMediaDeviceInfoArray(t);
119
+ };
120
+ export const isConstraintDOMString = (t) => (typeof t === 'string' && !!t) || (Array.isArray(t) && t.some(Boolean));
121
+ const CONSTRAIN_PARAM_KEYS = ['exact', 'ideal'];
122
+ const CONSTRAIN_RANGE_KEYS = ['min', 'max'];
123
+ const CONSTRAIN_KEYS = [
124
+ ...CONSTRAIN_PARAM_KEYS,
125
+ ...CONSTRAIN_RANGE_KEYS,
126
+ ];
127
+ export const isConstrainDOMParameters = (isType, keys = CONSTRAIN_PARAM_KEYS) => (t) => {
128
+ if (!t ||
129
+ typeof t !== 'object' ||
130
+ t === null ||
131
+ Object.keys(t).length <= 0) {
132
+ return false;
133
+ }
134
+ return keys.some(key => hasOwnProperty(t, key) && isType(t[key]));
135
+ };
136
+ export const isConstrainDOMStringParameters = isConstrainDOMParameters(isConstraintDOMString);
137
+ export const isConstrainBooleanParameters = isConstrainDOMParameters(isBoolean);
138
+ /**
139
+ * Check if provided var is a constraint object with `min` and/or `max` key only
140
+ */
141
+ export const isConstrainRange = isConstrainDOMParameters(t => isFloat(t) || isInteger(t), CONSTRAIN_RANGE_KEYS);
142
+ export const isConstrainDoubleRange = isConstrainDOMParameters(isFloat, CONSTRAIN_KEYS);
143
+ export const isConstrainULongRange = isConstrainDOMParameters(isInteger, CONSTRAIN_KEYS);
144
+ export const isConstraintDeviceParameters = isConstrainDOMParameters(t => isMediaDeviceInfo(t) || isMediaDeviceInfoArray(t));
145
+ export const isConstraintSetDevice = (t) => isMediaDeviceInfo(t) ||
146
+ isMediaDeviceInfoArray(t) ||
147
+ isConstraintDeviceParameters(t);
148
+ export const isExtendedConstraint = (t) => {
149
+ if (typeof t !== 'object' || t === null) {
150
+ return false;
151
+ }
152
+ if (hasOwnProperty(t, 'device')) {
153
+ const { device } = t;
154
+ return isConstraintSetDevice(device);
155
+ }
156
+ return [
157
+ ...EXTENDED_CONSTRAIN_DOUBLE_KEYS,
158
+ ...EXTENDED_CONSTRAIN_STRING_KEYS,
159
+ ...EXTENDED_CONSTRAIN_U_LONG_KEYS,
160
+ ...EXTENDED_CONSTRAIN_BOOLEAN_KEYS,
161
+ ].some(key => hasOwnProperty(t, key));
162
+ };
163
+ export const isInputConstraintSet = (t) => {
164
+ if (typeof t !== 'object' || t === null) {
165
+ return false;
166
+ }
167
+ return isExtendedConstraint(t) || isMediaTrackConstraints(t);
168
+ };
169
+ /**
170
+ * Check if provided is `MediaStreamTrack`
171
+ *
172
+ * @beta
173
+ */
174
+ export const isMediaStreamTrack = (m) => {
175
+ if (m && typeof m === 'object') {
176
+ return !!m && 'getSettings' in m;
177
+ }
178
+ return false;
179
+ };
180
+ export const isFacingMode = (s) => {
181
+ if (typeof s === 'string' && FACING_MODE.includes(s)) {
182
+ return true;
183
+ }
184
+ return false;
185
+ };