mediasfu-shared 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +228 -0
  3. package/dist/index.cjs +7707 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.ts +7285 -0
  6. package/dist/index.js +7690 -0
  7. package/dist/index.js.map +1 -0
  8. package/package.json +78 -0
  9. package/src/ProducerClient/producerClientEmits/createDeviceClient.ts +68 -0
  10. package/src/consumers/addVideosGrid.ts +18 -0
  11. package/src/consumers/autoAdjust.ts +100 -0
  12. package/src/consumers/calculateRowsAndColumns.ts +51 -0
  13. package/src/consumers/changeVids.ts +753 -0
  14. package/src/consumers/checkGrid.ts +100 -0
  15. package/src/consumers/checkPermission.ts +89 -0
  16. package/src/consumers/checkScreenShare.ts +114 -0
  17. package/src/consumers/closeAndResize.ts +401 -0
  18. package/src/consumers/compareActiveNames.ts +122 -0
  19. package/src/consumers/compareScreenStates.ts +117 -0
  20. package/src/consumers/connectIps.ts +175 -0
  21. package/src/consumers/connectLocalIps.ts +103 -0
  22. package/src/consumers/connectRecvTransport.ts +158 -0
  23. package/src/consumers/connectSendTransport.ts +150 -0
  24. package/src/consumers/connectSendTransportAudio.ts +161 -0
  25. package/src/consumers/connectSendTransportScreen.ts +169 -0
  26. package/src/consumers/connectSendTransportVideo.ts +149 -0
  27. package/src/consumers/consumerResume.ts +25 -0
  28. package/src/consumers/controlMedia.ts +118 -0
  29. package/src/consumers/createSendTransport.ts +312 -0
  30. package/src/consumers/disconnectSendTransportAudio.ts +170 -0
  31. package/src/consumers/disconnectSendTransportScreen.ts +130 -0
  32. package/src/consumers/disconnectSendTransportVideo.ts +161 -0
  33. package/src/consumers/dispStreams.ts +694 -0
  34. package/src/consumers/generatePageContent.ts +118 -0
  35. package/src/consumers/getEstimate.ts +124 -0
  36. package/src/consumers/getPipedProducersAlt.ts +96 -0
  37. package/src/consumers/getProducersPiped.ts +89 -0
  38. package/src/consumers/getVideos.ts +107 -0
  39. package/src/consumers/mixStreams.ts +97 -0
  40. package/src/consumers/onScreenChanges.ts +106 -0
  41. package/src/consumers/prepopulateUserMedia.ts +18 -0
  42. package/src/consumers/processConsumerTransports.ts +157 -0
  43. package/src/consumers/processConsumerTransportsAudio.ts +121 -0
  44. package/src/consumers/rePort.ts +123 -0
  45. package/src/consumers/reUpdateInter.ts +289 -0
  46. package/src/consumers/readjust.ts +170 -0
  47. package/src/consumers/receiveAllPipedTransports.ts +77 -0
  48. package/src/consumers/receiveRoomMessages.ts +55 -0
  49. package/src/consumers/reorderStreams.ts +246 -0
  50. package/src/consumers/requestScreenShare.ts +103 -0
  51. package/src/consumers/resumePauseAudioStreams.ts +174 -0
  52. package/src/consumers/resumePauseStreams.ts +110 -0
  53. package/src/consumers/resumeSendTransportAudio.ts +143 -0
  54. package/src/consumers/signalNewConsumerTransport.ts +179 -0
  55. package/src/consumers/socketReceiveMethods/joinConsumeRoom.ts +130 -0
  56. package/src/consumers/socketReceiveMethods/newPipeProducer.ts +138 -0
  57. package/src/consumers/socketReceiveMethods/producerClosed.ts +102 -0
  58. package/src/consumers/startShareScreen.ts +124 -0
  59. package/src/consumers/stopShareScreen.ts +241 -0
  60. package/src/consumers/streamSuccessAudio.ts +297 -0
  61. package/src/consumers/streamSuccessAudioSwitch.ts +315 -0
  62. package/src/consumers/streamSuccessScreen.ts +255 -0
  63. package/src/consumers/streamSuccessVideo.ts +373 -0
  64. package/src/consumers/switchUserAudio.ts +140 -0
  65. package/src/consumers/switchUserVideo.ts +201 -0
  66. package/src/consumers/switchUserVideoAlt.ts +331 -0
  67. package/src/consumers/trigger.ts +250 -0
  68. package/src/consumers/updateMiniCardsGrid.ts +150 -0
  69. package/src/consumers/updateParticipantAudioDecibels.ts +56 -0
  70. package/src/index.ts +119 -0
  71. package/src/methods/background/launchBackground.ts +16 -0
  72. package/src/methods/breakoutRooms/breakoutRoomUpdated.ts +161 -0
  73. package/src/methods/breakoutRooms/handleStartBreakout.ts +96 -0
  74. package/src/methods/breakoutRooms/handleStopBreakout.ts +72 -0
  75. package/src/methods/breakoutRooms/index.ts +4 -0
  76. package/src/methods/breakoutRooms/launchBreakoutRooms.ts +31 -0
  77. package/src/methods/coHost/launchCoHost.ts +28 -0
  78. package/src/methods/coHostMethods/index.ts +2 -0
  79. package/src/methods/coHostMethods/modifyCoHostSettings.ts +94 -0
  80. package/src/methods/displaySettings/index.ts +1 -0
  81. package/src/methods/displaySettings/launchDisplaySettings.ts +31 -0
  82. package/src/methods/displaySettings/modifyDisplaySettings.ts +242 -0
  83. package/src/methods/exit/confirmExit.ts +60 -0
  84. package/src/methods/exit/index.ts +2 -0
  85. package/src/methods/exit/launchConfirmExit.ts +29 -0
  86. package/src/methods/index.ts +5 -0
  87. package/src/methods/mediaSettings/launchMediaSettings.ts +61 -0
  88. package/src/methods/menu/launchMenuModal.ts +28 -0
  89. package/src/methods/message/index.ts +1 -0
  90. package/src/methods/message/launchMessages.ts +27 -0
  91. package/src/methods/message/sendMessage.ts +175 -0
  92. package/src/methods/participants/index.ts +3 -0
  93. package/src/methods/participants/launchParticipants.ts +25 -0
  94. package/src/methods/participants/messageParticipants.ts +78 -0
  95. package/src/methods/participants/muteParticipants.ts +79 -0
  96. package/src/methods/participants/removeParticipants.ts +97 -0
  97. package/src/methods/polls/handleCreatePoll.ts +66 -0
  98. package/src/methods/polls/handleEndPoll.ts +64 -0
  99. package/src/methods/polls/handleVotePoll.ts +76 -0
  100. package/src/methods/polls/index.ts +3 -0
  101. package/src/methods/polls/launchPoll.ts +25 -0
  102. package/src/methods/prejoin/handleCreateRoom.ts +441 -0
  103. package/src/methods/prejoin/handleJoinRoom.ts +153 -0
  104. package/src/methods/prejoin/index.ts +14 -0
  105. package/src/methods/recording/checkPauseState.ts +57 -0
  106. package/src/methods/recording/checkResumeState.ts +42 -0
  107. package/src/methods/recording/confirmRecording.ts +241 -0
  108. package/src/methods/recording/launchRecording.ts +114 -0
  109. package/src/methods/recording/recordPauseTimer.ts +52 -0
  110. package/src/methods/recording/recordResumeTimer.ts +92 -0
  111. package/src/methods/recording/recordStartTimer.ts +106 -0
  112. package/src/methods/recording/recordUpdateTimer.ts +49 -0
  113. package/src/methods/recording/startRecording.ts +268 -0
  114. package/src/methods/recording/stopRecording.ts +124 -0
  115. package/src/methods/recording/updateRecording.ts +245 -0
  116. package/src/methods/requests/index.ts +1 -0
  117. package/src/methods/requests/launchRequests.ts +25 -0
  118. package/src/methods/requests/respondToRequests.ts +108 -0
  119. package/src/methods/settings/index.ts +2 -0
  120. package/src/methods/settings/launchSettings.ts +25 -0
  121. package/src/methods/settings/modifySettings.ts +99 -0
  122. package/src/methods/stream/clickVideo.ts +337 -0
  123. package/src/methods/stream/index.ts +3 -0
  124. package/src/methods/stream/switchAudio.ts +73 -0
  125. package/src/methods/stream/switchVideo.ts +148 -0
  126. package/src/methods/stream/switchVideoAlt.ts +152 -0
  127. package/src/methods/utils/checkLimitsAndMakeRequest.ts +103 -0
  128. package/src/methods/utils/validateAlphanumeric.ts +41 -0
  129. package/src/methods/waiting/index.ts +1 -0
  130. package/src/methods/waiting/launchWaiting.ts +26 -0
  131. package/src/methods/waiting/respondToWaiting.ts +82 -0
  132. package/src/methods/welcome/handleWelcomeRequest.ts +189 -0
  133. package/src/methods/welcome/index.ts +5 -0
  134. package/src/methods/whiteboard/handleStartWhiteboard.ts +65 -0
  135. package/src/methods/whiteboard/handleStopWhiteboard.ts +48 -0
  136. package/src/methods/whiteboard/index.ts +4 -0
  137. package/src/methods/whiteboard/launchConfigureWhiteboard.ts +29 -0
  138. package/src/producers/producerEmits/joinConRoom.ts +153 -0
  139. package/src/sockets/SocketManager.ts +232 -0
  140. package/src/types/shared-base-types.ts +752 -0
  141. package/src/types/types.ts +84 -0
@@ -0,0 +1,201 @@
1
+ import { clickVideo, ClickVideoParameters } from "../methods/stream/clickVideo";
2
+ import { ShowAlert, VidCons, RequestPermissionCameraType, StreamSuccessVideoType, SleepType, StreamSuccessVideoParameters } from "../types/types";
3
+
4
+ export interface SwitchUserVideoParameters extends StreamSuccessVideoParameters, ClickVideoParameters {
5
+ audioOnlyRoom: boolean;
6
+ frameRate: number;
7
+ vidCons: VidCons;
8
+ prevVideoInputDevice: string;
9
+ userDefaultVideoInputDevice: string;
10
+ showAlert?: ShowAlert;
11
+ mediaDevices: MediaDevices;
12
+ hasCameraPermission: boolean;
13
+ updateVideoSwitching: (state: boolean) => void;
14
+ updateUserDefaultVideoInputDevice: (deviceId: string) => void;
15
+
16
+ // media functions
17
+ requestPermissionCamera: RequestPermissionCameraType;
18
+ streamSuccessVideo: StreamSuccessVideoType;
19
+ sleep: SleepType;
20
+ checkMediaPermission: boolean;
21
+
22
+ getUpdatedAllParams: () => SwitchUserVideoParameters;
23
+ [key: string]: any;
24
+ }
25
+
26
+ export interface SwitchUserVideoOptions {
27
+ videoPreference: string;
28
+ checkoff: boolean;
29
+ parameters: SwitchUserVideoParameters;
30
+ }
31
+
32
+ // Export the type definition for the function
33
+ export type SwitchUserVideoType = (options: SwitchUserVideoOptions) => Promise<void>;
34
+
35
+ /**
36
+ * Switches the user's video input device based on the provided options.
37
+ *
38
+ * @param {SwitchUserVideoOptions} options - The options for switching the user's video.
39
+ * @param {string} options.videoPreference - The preferred video input device ID.
40
+ * @param {boolean} options.checkoff - Flag indicating whether to turn off the video.
41
+ * @param {Object} options.parameters - Additional parameters required for switching the video.
42
+ * @param {boolean} options.parameters.audioOnlyRoom - Indicates if the room is audio-only.
43
+ * @param {number} options.parameters.frameRate - The desired frame rate for the video.
44
+ * @param {Object} options.parameters.vidCons - Video constraints such as width and height.
45
+ * @param {string} options.parameters.prevVideoInputDevice - The previous video input device ID.
46
+ * @param {Function} options.parameters.showAlert - Function to show alerts to the user.
47
+ * @param {Object} options.parameters.mediaDevices - Media devices object to access user media.
48
+ * @param {boolean} options.parameters.hasCameraPermission - Indicates if the user has camera permission.
49
+ * @param {Function} options.parameters.updateVideoSwitching - Function to update video switching state.
50
+ * @param {Function} options.parameters.updateUserDefaultVideoInputDevice - Function to update the default video input device.
51
+ * @param {Function} options.parameters.requestPermissionCamera - Function to request camera permission.
52
+ * @param {Function} options.parameters.streamSuccessVideo - Function to handle successful video stream.
53
+ * @param {Function} options.parameters.sleep - Function to pause execution for a specified duration.
54
+ * @param {Function} options.parameters.checkMediaPermission - Function to check media permissions.
55
+ *
56
+ * @returns {Promise<void>} A promise that resolves when the video input device has been successfully switched.
57
+ *
58
+ * @throws Will throw an error if the audio input device cannot be accessed or if there is an unexpected error.
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * await switchUserVideo({
63
+ * videoPreference: 'video-device-id',
64
+ * checkoff: false,
65
+ * parameters: {
66
+ * audioOnlyRoom: false,
67
+ * frameRate: 30,
68
+ * vidCons: { width: 640, height: 480 },
69
+ * prevVideoInputDevice: 'prev-video-device-id',
70
+ * showAlert: showAlertFunction,
71
+ * mediaDevices: navigator.mediaDevices,
72
+ * hasCameraPermission: true,
73
+ * updateVideoSwitching: updateVideoSwitchingFunction,
74
+ * updateUserDefaultVideoInputDevice: updateUserDefaultVideoInputDeviceFunction,
75
+ * requestPermissionCamera: requestPermissionCameraFunction,
76
+ * streamSuccessVideo: streamSuccessVideoFunction,
77
+ * sleep: sleepFunction,
78
+ * checkMediaPermission: true,
79
+ * getUpdatedAllParams: getUpdatedAllParamsFunction,
80
+ * },
81
+ * });
82
+ * ```
83
+ */
84
+
85
+ export async function switchUserVideo({
86
+ videoPreference,
87
+ checkoff,
88
+ parameters,
89
+ }: SwitchUserVideoOptions): Promise<void> {
90
+ const {
91
+ audioOnlyRoom,
92
+ frameRate,
93
+ vidCons,
94
+ prevVideoInputDevice,
95
+ showAlert,
96
+ mediaDevices,
97
+ hasCameraPermission,
98
+ updateVideoSwitching,
99
+ updateUserDefaultVideoInputDevice,
100
+
101
+ //mediasfu functions
102
+ requestPermissionCamera,
103
+ streamSuccessVideo,
104
+ sleep,
105
+ checkMediaPermission,
106
+ } = parameters;
107
+
108
+ try {
109
+ // Check if it's an audio-only room
110
+ if (audioOnlyRoom) {
111
+
112
+ showAlert?.({
113
+ message: "You cannot turn on your camera in an audio-only event.",
114
+ type: "danger",
115
+ duration: 3000,
116
+ });
117
+
118
+ return;
119
+ }
120
+
121
+ // If checkoff is not true, trigger a click on the video button to turn off the video
122
+ if (!checkoff) {
123
+ await clickVideo({ parameters });
124
+ updateVideoSwitching(true);
125
+ await sleep({ ms: 500 });
126
+ updateVideoSwitching(false);
127
+ }
128
+
129
+ // Check camera permission
130
+ if (!hasCameraPermission) {
131
+ if (checkMediaPermission) {
132
+ const statusCamera = await requestPermissionCamera();
133
+ if (statusCamera !== "granted") {
134
+
135
+ showAlert?.({
136
+ message:
137
+ "Allow access to your camera or check if your camera is not being used by another application.",
138
+ type: "danger",
139
+ duration: 3000,
140
+ });
141
+
142
+ return;
143
+ }
144
+ }
145
+ }
146
+
147
+ let mediaConstraints: MediaStreamConstraints;
148
+
149
+ if (vidCons && vidCons.width && vidCons.height) {
150
+ mediaConstraints = {
151
+ video: {
152
+ deviceId: { exact: videoPreference },
153
+ ...vidCons,
154
+ frameRate: { ideal: frameRate },
155
+ },
156
+ audio: false,
157
+ };
158
+ } else {
159
+ mediaConstraints = {
160
+ video: {
161
+ deviceId: { exact: videoPreference },
162
+ frameRate: { ideal: frameRate },
163
+ },
164
+ audio: false,
165
+ };
166
+ }
167
+
168
+ // Get user media with the defined constraints
169
+ await mediaDevices
170
+ .getUserMedia(mediaConstraints)
171
+ .then(async (stream) => {
172
+ await streamSuccessVideo({ stream, parameters });
173
+ })
174
+ .catch(async () => {
175
+ // Handle errors and revert to the previous video input device
176
+ updateUserDefaultVideoInputDevice(prevVideoInputDevice);
177
+
178
+
179
+ showAlert?.({
180
+ message:
181
+ "Error switching; not accessible, might need to turn off your video and turn it back on after switching.",
182
+ type: "danger",
183
+ duration: 3000,
184
+ });
185
+
186
+ });
187
+ } catch {
188
+ // Handle unexpected errors and revert to the previous video input device
189
+ updateUserDefaultVideoInputDevice(prevVideoInputDevice);
190
+
191
+
192
+ showAlert?.({
193
+ message:
194
+ "Error switching; not accessible, might need to turn off your video and turn it back on after switching.",
195
+ type: "danger",
196
+ duration: 3000,
197
+ });
198
+
199
+ }
200
+ }
201
+
@@ -0,0 +1,331 @@
1
+ import { clickVideo, ClickVideoParameters } from "../methods/stream/clickVideo";
2
+ import { ShowAlert, VidCons, RequestPermissionCameraType, StreamSuccessVideoType, SleepType, StreamSuccessVideoParameters } from "../types/types";
3
+
4
+
5
+ export interface SwitchUserVideoAltParameters extends StreamSuccessVideoParameters, ClickVideoParameters {
6
+ audioOnlyRoom: boolean;
7
+ frameRate: number;
8
+ vidCons: VidCons;
9
+ showAlert?: ShowAlert;
10
+ mediaDevices: MediaDevices;
11
+ hasCameraPermission: boolean;
12
+ updateVideoSwitching: (state: boolean) => void;
13
+ updateCurrentFacingMode: (mode: string) => void;
14
+
15
+ // mediasfu functions
16
+ requestPermissionCamera: RequestPermissionCameraType;
17
+ streamSuccessVideo: StreamSuccessVideoType;
18
+ sleep: SleepType;
19
+ checkMediaPermission: boolean;
20
+ getUpdatedAllParams: () => SwitchUserVideoAltParameters;
21
+
22
+ [key: string]: any;
23
+ }
24
+
25
+ export interface SwitchUserVideoAltOptions {
26
+ videoPreference: string;
27
+ checkoff: boolean;
28
+ parameters: SwitchUserVideoAltParameters;
29
+ }
30
+
31
+ // Export the type definition for the function
32
+ export type SwitchUserVideoAltType = (options: SwitchUserVideoAltOptions) => Promise<void>;
33
+
34
+ /**
35
+ * Switches the user's video stream based on the provided video preference and other parameters.
36
+ *
37
+ * @param {SwitchUserVideoAltOptions} options - The options for switching the user's video.
38
+ * @param {string} options.videoPreference - The preferred video facing mode (e.g., "user" or "environment").
39
+ * @param {boolean} options.checkoff - A flag indicating whether to turn off the video before switching.
40
+ * @param {SwitchUserVideoAltParameters} options.parameters - The parameters required for switching the video.
41
+ *
42
+ * @returns {Promise<void>} A promise that resolves when the video switching is complete.
43
+ *
44
+ * @throws Will throw an error if there is an issue with switching the video.
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * const options = {
49
+ * videoPreference: "user",
50
+ * checkoff: false,
51
+ * parameters: {
52
+ * audioOnlyRoom: false,
53
+ * frameRate: 30,
54
+ * vidCons: { width: 640, height: 480 },
55
+ * showAlert: showNotification,
56
+ * mediaDevices: navigator.mediaDevices,
57
+ * hasCameraPermission: true,
58
+ * updateVideoSwitching: updateVideoSwitchingState,
59
+ * updateCurrentFacingMode: updateCurrentFacingMode,
60
+ * requestPermissionCamera: requestCameraPermission,
61
+ * streamSuccessVideo: streamSuccessVideoFunction,
62
+ * sleep: sleepFunction,
63
+ * checkMediaPermission: true,
64
+ * getUpdatedAllParams: getUpdatedAllParamsFunction,
65
+ * },
66
+ * };
67
+ *
68
+ * switchUserVideoAlt(options)
69
+ * .then(() => {
70
+ * console.log("Video switched successfully");
71
+ * })
72
+ * .catch((error) => {
73
+ * console.error("Error switching video:", error);
74
+ * });
75
+ * ```
76
+ */
77
+
78
+ export async function switchUserVideoAlt({
79
+ videoPreference,
80
+ checkoff,
81
+ parameters,
82
+ }: SwitchUserVideoAltOptions): Promise<void> {
83
+ const updatedParameters = parameters.getUpdatedAllParams();
84
+
85
+ const {
86
+ audioOnlyRoom,
87
+ frameRate,
88
+ vidCons,
89
+ showAlert,
90
+ mediaDevices,
91
+ hasCameraPermission,
92
+ updateVideoSwitching,
93
+ updateCurrentFacingMode,
94
+
95
+ //mediasfu functions
96
+ requestPermissionCamera,
97
+ streamSuccessVideo,
98
+ sleep,
99
+ checkMediaPermission,
100
+ } = parameters;
101
+
102
+ let { currentFacingMode, prevFacingMode } = updatedParameters;
103
+
104
+ try {
105
+ if (audioOnlyRoom) {
106
+ showAlert?.({
107
+ message: "You cannot turn on your camera in an audio-only event.",
108
+ type: "danger",
109
+ duration: 3000,
110
+ });
111
+ return;
112
+ }
113
+
114
+ // If checkoff is not true, trigger a click on the video button to turn off the video
115
+ if (!checkoff) {
116
+ await clickVideo({ parameters });
117
+ updateVideoSwitching(true);
118
+ await sleep({ ms: 500 });
119
+ updateVideoSwitching(false);
120
+ }
121
+
122
+ // Check camera permission
123
+ if (!hasCameraPermission && checkMediaPermission) {
124
+ const statusCamera = await requestPermissionCamera();
125
+ if (statusCamera !== "granted") {
126
+ showAlert?.({
127
+ message:
128
+ "Allow access to your camera or check if your camera is not being used by another application.",
129
+ type: "danger",
130
+ duration: 3000,
131
+ });
132
+ return;
133
+ }
134
+ }
135
+
136
+ // Enumerate video devices
137
+ const videoDevices = await mediaDevices.enumerateDevices();
138
+
139
+ // Define media constraints based on preferences and options
140
+ let mediaConstraints = {};
141
+
142
+ if (vidCons && vidCons.width && vidCons.height) {
143
+ mediaConstraints = {
144
+ video: {
145
+ facingMode: { exact: videoPreference },
146
+ ...vidCons,
147
+ frameRate: { ideal: frameRate },
148
+ },
149
+ audio: false,
150
+ };
151
+ } else {
152
+ mediaConstraints = {
153
+ video: {
154
+ facingMode: { exact: videoPreference },
155
+ frameRate: { ideal: frameRate },
156
+ },
157
+ audio: false,
158
+ };
159
+ }
160
+
161
+ // Get user media with the defined constraints
162
+ await mediaDevices
163
+ .getUserMedia(mediaConstraints)
164
+ .then(async (stream) => {
165
+ await streamSuccessVideo({ stream, parameters });
166
+ })
167
+ .catch(async () => {
168
+ let videoDevicesFront: MediaDeviceInfo[] = [];
169
+
170
+ // Filter video devices based on the preferred facing mode
171
+ if (videoPreference === "user") {
172
+ videoDevicesFront = videoDevices.filter(
173
+ (device) =>
174
+ device.label.includes("front") && device.kind === "videoinput"
175
+ );
176
+ } else {
177
+ videoDevicesFront = videoDevices.filter(
178
+ (device) =>
179
+ device.label.includes("back") && device.kind === "videoinput"
180
+ );
181
+ }
182
+
183
+ if (videoDevicesFront.length > 0) {
184
+ videoDevicesFront.forEach((device) => {
185
+ if (device.kind === "videoinput") {
186
+ let videoDeviceId = device.deviceId;
187
+
188
+ // Update media constraints with the specific video device
189
+ if (vidCons && vidCons.width && vidCons.height) {
190
+ mediaConstraints = {
191
+ video: {
192
+ deviceId: { exact: videoDeviceId },
193
+ ...vidCons,
194
+ frameRate: { ideal: frameRate },
195
+ },
196
+ audio: false,
197
+ };
198
+ } else {
199
+ mediaConstraints = {
200
+ video: {
201
+ deviceId: { exact: videoDeviceId },
202
+ frameRate: { ideal: frameRate },
203
+ },
204
+ audio: false,
205
+ };
206
+ }
207
+
208
+ // Try to get user media with the new constraints
209
+ mediaDevices
210
+ .getUserMedia(mediaConstraints)
211
+ .then(async (stream) => {
212
+ await streamSuccessVideo({ stream, parameters });
213
+ })
214
+ .catch(() => {
215
+ // If the current video device is the last one in the list, show the error; otherwise, try the next device
216
+ if (
217
+ videoDeviceId ===
218
+ videoDevicesFront[videoDevicesFront.length - 1].deviceId
219
+ ) {
220
+ currentFacingMode = prevFacingMode;
221
+ updateCurrentFacingMode(currentFacingMode);
222
+
223
+ showAlert?.({
224
+ message:
225
+ "Error switching; not accessible, might need to turn off your video and turn it back on after switching.",
226
+ type: "danger",
227
+ duration: 3000,
228
+ });
229
+
230
+ }
231
+ });
232
+ }
233
+ });
234
+ } else {
235
+ // Show error if no compatible video devices are found
236
+ currentFacingMode = prevFacingMode;
237
+ updateCurrentFacingMode(currentFacingMode);
238
+
239
+
240
+ showAlert?.({
241
+ message:
242
+ "Error switching; not accessible, might need to turn off your video and turn it back on after switching.",
243
+ type: "danger",
244
+ duration: 3000,
245
+ });
246
+
247
+ }
248
+ });
249
+ } catch {
250
+ // Handle any unexpected errors
251
+
252
+ const videoDevices = await mediaDevices.enumerateDevices();
253
+ // Handle any unexpected errors
254
+ let videoDevicesFront: MediaDeviceInfo[] = [];
255
+ if (videoPreference === "user") {
256
+ videoDevicesFront = videoDevices.filter(
257
+ (device) =>
258
+ device.label.includes("front") && device.kind === "videoinput"
259
+ );
260
+ } else {
261
+ videoDevicesFront = videoDevices.filter(
262
+ (device) =>
263
+ device.label.includes("back") && device.kind === "videoinput"
264
+ );
265
+ }
266
+
267
+ let mediaConstraints = {};
268
+
269
+ if (videoDevicesFront.length > 0) {
270
+ videoDevicesFront.forEach((device) => {
271
+ if (device.kind === "videoinput") {
272
+ let videoDeviceId = device.deviceId;
273
+
274
+ if (vidCons && vidCons.width && vidCons.height) {
275
+ mediaConstraints = {
276
+ video: {
277
+ deviceId: { exact: videoDeviceId },
278
+ ...vidCons,
279
+ frameRate: { ideal: frameRate },
280
+ },
281
+ audio: false,
282
+ };
283
+ } else {
284
+ mediaConstraints = {
285
+ video: {
286
+ deviceId: { exact: videoDeviceId },
287
+ frameRate: { ideal: frameRate },
288
+ },
289
+ audio: false,
290
+ };
291
+ }
292
+
293
+ mediaDevices
294
+ .getUserMedia(mediaConstraints)
295
+ .then(async (stream) => {
296
+ await streamSuccessVideo({ stream, parameters });
297
+ })
298
+ .catch(() => {
299
+ if (
300
+ videoDeviceId ===
301
+ videoDevicesFront[videoDevicesFront.length - 1].deviceId
302
+ ) {
303
+ currentFacingMode = prevFacingMode;
304
+ updateCurrentFacingMode(currentFacingMode);
305
+
306
+ showAlert?.({
307
+ message:
308
+ "Error switching; not accessible, might need to turn off your video and turn it back on after switching.",
309
+ type: "danger",
310
+ duration: 3000,
311
+ });
312
+
313
+ }
314
+ });
315
+ }
316
+ });
317
+ } else {
318
+ currentFacingMode = prevFacingMode;
319
+ updateCurrentFacingMode(currentFacingMode);
320
+
321
+
322
+ showAlert?.({
323
+ message:
324
+ "Error switching; not accessible, might need to turn off your video and turn it back on after switching.",
325
+ type: "danger",
326
+ duration: 3000,
327
+ });
328
+
329
+ }
330
+ }
331
+ }