mediasfu-shared 1.0.1 → 1.0.2

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 (125) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +103 -222
  3. package/dist/index.cjs +7500 -2163
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +4203 -273
  6. package/dist/index.js +7521 -2184
  7. package/dist/index.js.map +1 -1
  8. package/package.json +85 -78
  9. package/src/ProducerClient/producerClientEmits/joinRoomClient.ts +57 -0
  10. package/src/ProducerClient/producerClientEmits/updateRoomParametersClient.ts +401 -0
  11. package/src/consumers/addVideosGrid.ts +3 -2
  12. package/src/consumers/changeVids.ts +111 -41
  13. package/src/consumers/checkPermission.ts +35 -1
  14. package/src/consumers/connectRecvTransport.ts +42 -1
  15. package/src/consumers/consumerResume.ts +2 -2
  16. package/src/consumers/dispStreams.ts +83 -37
  17. package/src/consumers/frameworkConsumerContract.ts +6 -0
  18. package/src/consumers/generatePageContent.ts +24 -10
  19. package/src/consumers/getPipedProducersAlt.ts +112 -16
  20. package/src/consumers/gridLayout/addVideosGrid.engine.ts +42 -0
  21. package/src/consumers/gridLayout/prepopulateUserMedia.engine.ts +444 -0
  22. package/src/consumers/mixStreams.ts +45 -14
  23. package/src/consumers/onScreenChanges.ts +25 -10
  24. package/src/consumers/prepopulateUserMedia.ts +3 -2
  25. package/src/consumers/processConsumerTransports.ts +68 -23
  26. package/src/consumers/processConsumerTransportsAudio.ts +53 -16
  27. package/src/consumers/reUpdateInter.ts +61 -21
  28. package/src/consumers/readjust.ts +30 -14
  29. package/src/consumers/reorderStreams.ts +76 -42
  30. package/src/consumers/resumePauseAudioStreams.ts +66 -17
  31. package/src/consumers/resumePauseStreams.ts +53 -10
  32. package/src/consumers/socketReceiveMethods/joinConsumeRoom.ts +8 -0
  33. package/src/consumers/socketReceiveMethods/newPipeProducer.ts +114 -0
  34. package/src/consumers/socketReceiveMethods/producerClosed.ts +13 -0
  35. package/src/consumers/streamSuccessScreen.ts +2 -2
  36. package/src/consumers/streamSuccessVideo.ts +5 -0
  37. package/src/consumers/translationConsumerSwitch.ts +299 -0
  38. package/src/index.ts +85 -1
  39. package/src/methods/coHostMethods/modifyCoHostSettings.ts +9 -9
  40. package/src/methods/displaySettings/modifyDisplaySettings.ts +5 -0
  41. package/src/methods/index.ts +66 -0
  42. package/src/methods/message/sendMessage.ts +12 -29
  43. package/src/methods/panelists/focusPanelists.ts +83 -0
  44. package/src/methods/panelists/index.ts +3 -0
  45. package/src/methods/panelists/launchPanelists.ts +13 -0
  46. package/src/methods/panelists/updatePanelists.ts +135 -0
  47. package/src/methods/permissions/index.ts +3 -0
  48. package/src/methods/permissions/launchPermissions.ts +13 -0
  49. package/src/methods/permissions/updateParticipantPermission.ts +127 -0
  50. package/src/methods/permissions/updatePermissionConfig.ts +52 -0
  51. package/src/methods/polls/pollUpdated.ts +88 -0
  52. package/src/methods/recording/confirmRecording.ts +15 -12
  53. package/src/methods/recording/recordResumeTimer.ts +2 -2
  54. package/src/methods/recording/recordStartTimer.ts +2 -2
  55. package/src/methods/recording/timeLeftRecording.ts +25 -0
  56. package/src/methods/requests/hostRequestResponse.ts +153 -0
  57. package/src/methods/settings/modifySettings.ts +17 -17
  58. package/src/methods/socketReceive/allMembers.ts +450 -0
  59. package/src/methods/socketReceive/allMembersRest.ts +480 -0
  60. package/src/methods/socketReceive/allWaitingRoomMembers.ts +35 -0
  61. package/src/methods/socketReceive/banParticipant.ts +73 -0
  62. package/src/methods/socketReceive/controlMediaHost.ts +280 -0
  63. package/src/methods/socketReceive/disconnect.ts +40 -0
  64. package/src/methods/socketReceive/disconnectUserSelf.ts +56 -0
  65. package/src/methods/socketReceive/getDomains.ts +112 -0
  66. package/src/methods/socketReceive/meetingEnded.ts +49 -0
  67. package/src/methods/socketReceive/meetingStillThere.ts +26 -0
  68. package/src/methods/socketReceive/panelistReceiveMethods.ts +195 -0
  69. package/src/methods/socketReceive/participantRequested.ts +48 -0
  70. package/src/methods/socketReceive/permissionReceiveMethods.ts +59 -0
  71. package/src/methods/socketReceive/personJoined.ts +35 -0
  72. package/src/methods/socketReceive/producerMediaClosed.ts +223 -0
  73. package/src/methods/socketReceive/producerMediaPaused.ts +267 -0
  74. package/src/methods/socketReceive/producerMediaResumed.ts +157 -0
  75. package/src/methods/socketReceive/reInitiateRecording.ts +53 -0
  76. package/src/methods/socketReceive/receiveMessage.ts +117 -0
  77. package/src/methods/socketReceive/recordingNotice.ts +286 -0
  78. package/src/methods/socketReceive/roomRecordParams.ts +122 -0
  79. package/src/methods/socketReceive/screenProducerId.ts +61 -0
  80. package/src/methods/socketReceive/startRecords.ts +46 -0
  81. package/src/methods/socketReceive/stoppedRecording.ts +44 -0
  82. package/src/methods/socketReceive/translationReceiveMethods.ts +581 -0
  83. package/src/methods/socketReceive/updateConsumingDomains.ts +128 -0
  84. package/src/methods/socketReceive/updateMediaSettings.ts +45 -0
  85. package/src/methods/socketReceive/updatedCoHost.ts +75 -0
  86. package/src/methods/socketReceive/userWaiting.ts +45 -0
  87. package/src/methods/stream/clickAudio.ts +380 -0
  88. package/src/methods/stream/clickChat.ts +36 -0
  89. package/src/methods/stream/clickScreenShare.ts +173 -0
  90. package/src/methods/stream/clickVideo.ts +22 -5
  91. package/src/methods/stream/index.ts +1 -0
  92. package/src/methods/utils/SoundPlayer.ts +31 -0
  93. package/src/methods/utils/checkLimitsAndMakeRequest.ts +156 -2
  94. package/src/methods/utils/createResponseJoinRoom.ts +47 -0
  95. package/src/methods/utils/createRoomOnMediaSFU.ts +160 -0
  96. package/src/methods/utils/formatNumber.ts +42 -0
  97. package/src/methods/utils/generateRandomMessages.ts +70 -0
  98. package/src/methods/utils/generateRandomParticipants.ts +100 -0
  99. package/src/methods/utils/generateRandomPolls.ts +43 -0
  100. package/src/methods/utils/generateRandomRequestList.ts +51 -0
  101. package/src/methods/utils/generateRandomWaitingRoomList.ts +17 -0
  102. package/src/methods/utils/getModalPosition.ts +23 -0
  103. package/src/methods/utils/getOverlayPosition.ts +37 -0
  104. package/src/methods/utils/initialValuesState.ts +405 -0
  105. package/src/methods/utils/joinRoomOnMediaSFU.ts +124 -0
  106. package/src/methods/utils/liveSubtitle.ts +107 -0
  107. package/src/methods/utils/meetingTimeRemaining.ts +33 -0
  108. package/src/methods/utils/meetingTimer/startMeetingProgressTimer.ts +72 -0
  109. package/src/methods/utils/producer/aParams.ts +10 -0
  110. package/src/methods/utils/producer/hParams.ts +26 -0
  111. package/src/methods/utils/producer/screenParams.ts +13 -0
  112. package/src/methods/utils/producer/vParams.ts +26 -0
  113. package/src/methods/utils/producer/videoCaptureConstraints.ts +65 -0
  114. package/src/methods/utils/resolveMediaSFURoomApi.ts +16 -0
  115. package/src/methods/utils/sleep.ts +24 -0
  116. package/src/methods/utils/translationLanguages.ts +308 -0
  117. package/src/methods/utils/webrtc.ts +44 -0
  118. package/src/methods/welcome/handleWelcomeRequest.ts +11 -2
  119. package/src/methods/welcome/index.ts +5 -1
  120. package/src/methods/whiteboard/captureCanvasStream.ts +128 -0
  121. package/src/producers/producerEmits/joinConRoom.ts +2 -2
  122. package/src/producers/producerEmits/joinLocalRoom.ts +240 -0
  123. package/src/producers/producerEmits/joinRoom.ts +129 -0
  124. package/src/types/shared-base-types.ts +14 -3
  125. package/src/types/types.ts +255 -0
@@ -0,0 +1,405 @@
1
+ export const initialValuesState = {
2
+ // The following are the initial values
3
+
4
+ roomName: '',
5
+ member: '',
6
+ adminPasscode: '',
7
+ islevel: '1',
8
+ coHost: 'No coHost',
9
+ coHostResponsibility: [
10
+ { name: 'participants', value: false, dedicated: false },
11
+ { name: 'media', value: false, dedicated: false },
12
+ { name: 'waiting', value: false, dedicated: false },
13
+ { name: 'chat', value: false, dedicated: false },
14
+ ],
15
+ youAreCoHost: false,
16
+ youAreHost: false,
17
+ confirmedToRecord: false,
18
+ meetingDisplayType: 'media',
19
+ meetingVideoOptimized: false,
20
+ eventType: 'webinar',
21
+ participants: [],
22
+ filteredParticipants: [],
23
+ participantsCounter: 0,
24
+ participantsFilter: '',
25
+
26
+ validated: false,
27
+ localUIMode: false,
28
+ socket: {},
29
+ localSocket: undefined,
30
+ roomData: null,
31
+ device: null,
32
+ apiKey: '',
33
+ apiUserName: '',
34
+ apiToken: '',
35
+ link: '',
36
+
37
+ consume_sockets: [],
38
+ rtpCapabilities: null,
39
+ roomRecvIPs: [],
40
+ meetingRoomParams: null,
41
+ itemPageLimit: 4,
42
+ audioOnlyRoom: false,
43
+ addForBasic: false,
44
+ screenPageLimit: 4,
45
+ shareScreenStarted: false,
46
+ shared: false,
47
+ targetOrientation: 'landscape',
48
+ targetResolution: 'sd',
49
+ targetResolutionHost: 'sd',
50
+ vidCons: { width: 640, height: 360 },
51
+ frameRate: 10,
52
+ hParams: {},
53
+ vParams: {},
54
+ screenParams: {},
55
+ aParams: {},
56
+
57
+ // Initial Values for New Recording Fields
58
+ recordingAudioPausesLimit: 0,
59
+ recordingAudioPausesCount: 0,
60
+ recordingAudioSupport: false,
61
+ recordingAudioPeopleLimit: 0,
62
+ recordingAudioParticipantsTimeLimit: 0,
63
+ recordingVideoPausesCount: 0,
64
+ recordingVideoPausesLimit: 0,
65
+ recordingVideoSupport: false,
66
+ recordingVideoPeopleLimit: 0,
67
+ recordingVideoParticipantsTimeLimit: 0,
68
+ recordingAllParticipantsSupport: false,
69
+ recordingVideoParticipantsSupport: false,
70
+ recordingAllParticipantsFullRoomSupport: false,
71
+ recordingVideoParticipantsFullRoomSupport: false,
72
+ recordingPreferredOrientation: 'landscape',
73
+ recordingSupportForOtherOrientation: false,
74
+ recordingMultiFormatsSupport: false,
75
+
76
+ userRecordingParams: {
77
+ mainSpecs: {
78
+ mediaOptions: 'video',
79
+ audioOptions: 'all',
80
+ videoOptions: 'all',
81
+ videoType: 'fullDisplay',
82
+ videoOptimized: false,
83
+ recordingDisplayType: 'media',
84
+ addHLS: false,
85
+ },
86
+ dispSpecs: {
87
+ nameTags: true,
88
+ backgroundColor: '#000000',
89
+ nameTagsColor: '#ffffff',
90
+ orientationVideo: 'portrait',
91
+ },
92
+ },
93
+
94
+ canRecord: false,
95
+ startReport: false,
96
+ endReport: false,
97
+ recordTimerInterval: null,
98
+ recordStartTime: 0,
99
+ recordElapsedTime: 0,
100
+ isTimerRunning: false,
101
+ canPauseResume: false,
102
+ recordChangeSeconds: 15000,
103
+ pauseLimit: 0,
104
+ pauseRecordCount: 0,
105
+ canLaunchRecord: true,
106
+ stopLaunchRecord: false,
107
+
108
+ // Room properties
109
+ participantsAll: [],
110
+ firstAll: false,
111
+ updateMainWindow: false,
112
+ first_round: false,
113
+ landScaped: false,
114
+ lock_screen: false,
115
+ screenId: '',
116
+ allVideoStreams: [],
117
+ newLimitedStreams: [],
118
+ newLimitedStreamsIDs: [],
119
+ activeSounds: [],
120
+ screenShareIDStream: '',
121
+ screenShareNameStream: '',
122
+ adminIDStream: '',
123
+ adminNameStream: '',
124
+ youYouStream: [],
125
+ youYouStreamIDs: [],
126
+ localStream: null,
127
+ recordStarted: false,
128
+ recordResumed: false,
129
+ recordPaused: false,
130
+ recordStopped: false,
131
+ adminRestrictSetting: false,
132
+ videoRequestState: null,
133
+ videoRequestTime: 0,
134
+ videoAction: false,
135
+ localStreamVideo: null,
136
+ userDefaultVideoInputDevice: '',
137
+ currentFacingMode: 'user',
138
+ prevFacingMode: 'user',
139
+ defVideoID: '',
140
+ allowed: false,
141
+ dispActiveNames: [],
142
+ activeNames: [],
143
+ prevActiveNames: [],
144
+ p_activeNames: [],
145
+ p_dispActiveNames: [],
146
+ membersReceived: false,
147
+ deferScreenReceived: false,
148
+ hostFirstSwitch: false,
149
+ micAction: false,
150
+ screenAction: false,
151
+ chatAction: false,
152
+ audioRequestState: null,
153
+ screenRequestState: null,
154
+ chatRequestState: null,
155
+ audioRequestTime: 0,
156
+ screenRequestTime: 0,
157
+ chatRequestTime: 0,
158
+ updateRequestIntervalSeconds: 240,
159
+ oldSoundIds: [],
160
+ hostLabel: 'Host',
161
+ mainScreenFilled: false,
162
+ localStreamScreen: null,
163
+ screenAlreadyOn: false,
164
+ chatAlreadyOn: false,
165
+ redirectURL: '',
166
+ oldAllStreams: [],
167
+ adminVidID: '',
168
+ streamNames: [],
169
+ non_alVideoStreams: [],
170
+ sortAudioLoudness: false,
171
+ audioDecibels: [],
172
+ mixed_alVideoStreams: [],
173
+ non_alVideoStreams_muted: [],
174
+ paginatedStreams: [],
175
+ localStreamAudio: null,
176
+ defAudioID: '',
177
+ userDefaultAudioInputDevice: '',
178
+ userDefaultAudioOutputDevice: '',
179
+ prevAudioInputDevice: '',
180
+ prevVideoInputDevice: '',
181
+ audioPaused: false,
182
+ mainScreenPerson: '',
183
+ adminOnMainScreen: false,
184
+ screenStates: [{
185
+ mainScreenPerson: '',
186
+ mainScreenProducerId: '',
187
+ mainScreenFilled: false,
188
+ adminOnMainScreen: false,
189
+ }],
190
+ prevScreenStates: [{
191
+ mainScreenPerson: '',
192
+ mainScreenProducerId: '',
193
+ mainScreenFilled: false,
194
+ adminOnMainScreen: false,
195
+ }],
196
+ updateDateState: null,
197
+ lastUpdate: null,
198
+ nForReadjustRecord: 0,
199
+ fixedPageLimit: 4,
200
+ removeAltGrid: false,
201
+ nForReadjust: 0,
202
+ reorderInterval: 30000,
203
+ fastReorderInterval: 10000,
204
+ lastReorderTime: 0,
205
+ audStreamNames: [],
206
+ currentUserPage: 0,
207
+ mainHeightWidth: 0,
208
+ prevMainHeightWidth: 0,
209
+ prevDoPaginate: false,
210
+ doPaginate: false,
211
+ shareEnded: false,
212
+ lStreams: [],
213
+ chatRefStreams: [],
214
+ controlHeight: 0,
215
+ isWideScreen: false,
216
+ isMediumScreen: false,
217
+ isSmallScreen: false,
218
+ addGrid: false,
219
+ addAltGrid: false,
220
+ gridRows: 0,
221
+ gridCols: 0,
222
+ altGridRows: 0,
223
+ altGridCols: 0,
224
+ numberPages: 0,
225
+ currentStreams: [],
226
+ showMiniView: false,
227
+ nStream: null,
228
+ defer_receive: false,
229
+ allAudioStreams: [],
230
+ remoteScreenStream: [],
231
+ screenProducer: null,
232
+ localScreenProducer: null,
233
+ gotAllVids: false,
234
+ paginationHeightWidth: 40,
235
+ paginationDirection: 'horizontal',
236
+ gridSizes: {
237
+ gridWidth: 0, gridHeight: 0, altGridWidth: 0, altGridHeight: 0,
238
+ },
239
+ screenForceFullDisplay: false,
240
+ mainGridStream: [],
241
+ otherGridStreams: [[], []],
242
+ audioOnlyStreams: [],
243
+ videoInputs: [],
244
+ audioInputs: [],
245
+ meetingProgressTime: '00:00:00',
246
+ meetingElapsedTime: 0,
247
+ ref_participants: [],
248
+
249
+ // Messaging, event, modals, and other UI states
250
+ messages: [],
251
+ startDirectMessage: false,
252
+ directMessageDetails: null,
253
+ showMessagesBadge: false,
254
+ audioSetting: 'allow',
255
+ videoSetting: 'allow',
256
+ screenshareSetting: 'allow',
257
+ chatSetting: 'allow',
258
+ displayOption: 'media',
259
+ autoWave: true,
260
+ forceFullDisplay: true,
261
+ prevForceFullDisplay: false,
262
+ prevMeetingDisplayType: 'video',
263
+ waitingRoomFilter: '',
264
+ waitingRoomList: [],
265
+ waitingRoomCounter: 0,
266
+ filteredWaitingRoomList: [],
267
+ requestFilter: '',
268
+ requestList: [],
269
+ requestCounter: 0,
270
+ filteredRequestList: [],
271
+ totalReqWait: 0,
272
+ alertVisible: false,
273
+ alertMessage: '',
274
+ alertType: 'success',
275
+ alertDuration: 3000,
276
+ progressTimerVisible: true,
277
+ progressTimerValue: 0,
278
+ isMenuModalVisible: false,
279
+ isRecordingModalVisible: false,
280
+ isSettingsModalVisible: false,
281
+ isRequestsModalVisible: false,
282
+ isWaitingModalVisible: false,
283
+ isCoHostModalVisible: false,
284
+ isMediaSettingsModalVisible: false,
285
+ isDisplaySettingsModalVisible: false,
286
+ isParticipantsModalVisible: false,
287
+ isMessagesModalVisible: false,
288
+ isConfirmExitModalVisible: false,
289
+ isConfirmHereModalVisible: false,
290
+ isShareEventModalVisible: false,
291
+ isLoadingModalVisible: false,
292
+
293
+ recordingMediaOptions: 'video',
294
+ recordingAudioOptions: 'all',
295
+ recordingVideoOptions: 'all',
296
+ recordingVideoType: 'fullDisplay',
297
+ recordingVideoOptimized: false,
298
+ recordingDisplayType: 'video',
299
+ recordingAddHLS: true,
300
+ recordingNameTags: true,
301
+ recordingBackgroundColor: '#83c0e9',
302
+ recordingNameTagsColor: '#ffffff',
303
+ recordingAddText: false,
304
+ recordingCustomText: 'Add Text',
305
+ recordingCustomTextPosition: 'top',
306
+ recordingCustomTextColor: '#ffffff',
307
+ recordingOrientationVideo: 'landscape',
308
+ clearedToResume: true,
309
+ clearedToRecord: true,
310
+ recordState: 'green',
311
+ showRecordButtons: false,
312
+ recordingProgressTime: '00:00:00',
313
+ audioSwitching: false,
314
+ videoSwitching: false,
315
+ videoAlreadyOn: false,
316
+ audioAlreadyOn: false,
317
+ componentSizes: {
318
+ mainHeight: 0, otherHeight: 0, mainWidth: 0, otherWidth: 0,
319
+ },
320
+ hasCameraPermission: false,
321
+ hasAudioPermission: false,
322
+ transportCreated: false,
323
+ localTransportCreated: false,
324
+ transportCreatedVideo: false,
325
+ transportCreatedAudio: false,
326
+ transportCreatedScreen: false,
327
+ producerTransport: null,
328
+ localProducerTransport: null,
329
+ videoProducer: null,
330
+ localVideoProducer: null,
331
+ params: {},
332
+ videoParams: {},
333
+ audioParams: {},
334
+ audioProducer: null,
335
+ localAudioProducer: null,
336
+ consumerTransports: [],
337
+ consumingTransports: [],
338
+
339
+ // Polls
340
+ polls: [],
341
+ poll: null,
342
+ isPollModalVisible: false,
343
+
344
+ // Background
345
+ customImage: '',
346
+ selectedImage: '',
347
+ segmentVideo: null,
348
+ selfieSegmentation: null,
349
+ pauseSegmentation: false,
350
+ processedStream: null,
351
+ keepBackground: false,
352
+ backgroundHasChanged: false,
353
+ virtualStream: null,
354
+ mainCanvas: null,
355
+ prevKeepBackground: false,
356
+ appliedBackground: false,
357
+ isBackgroundModalVisible: false,
358
+ autoClickBackground: false,
359
+
360
+ // Breakout Rooms
361
+ breakoutRooms: [],
362
+ currentRoomIndex: 0,
363
+ canStartBreakout: false,
364
+ breakOutRoomStarted: false,
365
+ breakOutRoomEnded: false,
366
+ hostNewRoom: -1,
367
+ limitedBreakRoom: [],
368
+ mainRoomsLength: 0,
369
+ memberRoom: -1,
370
+ isBreakoutRoomsModalVisible: false,
371
+
372
+ // Whiteboard
373
+ whiteboardUsers: [],
374
+ currentWhiteboardIndex: 0,
375
+ canStartWhiteboard: false,
376
+ whiteboardStarted: false,
377
+ whiteboardEnded: false,
378
+ whiteboardLimit: 4,
379
+ isWhiteboardModalVisible: false,
380
+ isConfigureWhiteboardModalVisible: false,
381
+ shapes: [],
382
+ useImageBackground: true,
383
+ redoStack: [],
384
+ undoStack: [],
385
+ canvasStream: null,
386
+ canvasWhiteboard: null,
387
+
388
+ // Screenboard
389
+ canvasScreenboard: null,
390
+ processedScreenStream: null,
391
+ annotateScreenStream: false,
392
+ mainScreenCanvas: null,
393
+ isScreenboardModalVisible: false,
394
+
395
+ // Control Buttons
396
+ micActive: false,
397
+ videoActive: false,
398
+ screenShareActive: false,
399
+ endCallActive: false,
400
+ participantsActive: false,
401
+ menuActive: false,
402
+ commentsActive: false,
403
+ };
404
+
405
+ export type InitialValuesStateType = typeof initialValuesState;
@@ -0,0 +1,124 @@
1
+ import type { CreateMediaSFURoomOptions, JoinMediaSFURoomOptions } from '../../types/types';
2
+ import { resolveMediaSFURoomApi } from './resolveMediaSFURoomApi';
3
+
4
+ export type CreateJoinRoomType = (options: {
5
+ payload: CreateMediaSFURoomOptions | JoinMediaSFURoomOptions;
6
+ apiUserName: string;
7
+ apiKey: string;
8
+ localLink?: string;
9
+ }) => Promise<{
10
+ data: CreateJoinRoomResponse | CreateJoinRoomError | null;
11
+ success: boolean;
12
+ }>;
13
+
14
+ export interface CreateJoinRoomResponse {
15
+ message: string;
16
+ roomName: string;
17
+ secureCode?: string;
18
+ publicURL: string;
19
+ link: string;
20
+ secret: string;
21
+ success: boolean;
22
+ }
23
+
24
+ export interface CreateJoinRoomError {
25
+ error: string;
26
+ success?: boolean;
27
+ }
28
+
29
+ export type JoinRoomOnMediaSFUType = (options: {
30
+ payload: JoinMediaSFURoomOptions;
31
+ apiUserName: string;
32
+ apiKey: string;
33
+ localLink?: string;
34
+ }) => Promise<{
35
+ data: CreateJoinRoomResponse | CreateJoinRoomError | null;
36
+ success: boolean;
37
+ }>;
38
+
39
+ const readResponseError = async (response: Response): Promise<string> => {
40
+ const fallbackMessage = `HTTP error! Status: ${response.status}`;
41
+
42
+ try {
43
+ const responseText = await response.text();
44
+
45
+ if (!responseText) {
46
+ return fallbackMessage;
47
+ }
48
+
49
+ const parsedResponse = JSON.parse(responseText) as { error?: string; message?: string };
50
+ return parsedResponse.error || parsedResponse.message || responseText;
51
+ } catch {
52
+ return fallbackMessage;
53
+ }
54
+ };
55
+
56
+ /**
57
+ * Calls the MediaSFU join-room API and returns a normalized success/error result.
58
+ *
59
+ * This helper supports both cloud and self-hosted deployments through the
60
+ * optional `localLink` override.
61
+ *
62
+ * @param options API request options including credentials and join payload.
63
+ * @returns A result object containing either parsed response data or an error payload.
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * const result = await joinRoomOnMediaSFU({
68
+ * payload: { action: 'join', meetingID: 'room123', userName: 'Ada' },
69
+ * apiUserName: 'sampleuser',
70
+ * apiKey: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
71
+ * });
72
+ *
73
+ * if (result.success) {
74
+ * console.log(result.data?.roomName);
75
+ * }
76
+ * ```
77
+ */
78
+ export const joinRoomOnMediaSFU: CreateJoinRoomType = async ({
79
+ payload,
80
+ apiUserName,
81
+ apiKey,
82
+ localLink = '',
83
+ }) => {
84
+ try {
85
+ if (
86
+ !apiUserName ||
87
+ !apiKey ||
88
+ apiUserName === 'yourAPIUSERNAME' ||
89
+ apiKey === 'yourAPIKEY' ||
90
+ apiKey.length !== 64 ||
91
+ apiUserName.length < 6
92
+ ) {
93
+ return { data: { error: 'Invalid credentials' }, success: false };
94
+ }
95
+
96
+ const finalLink = resolveMediaSFURoomApi(localLink, 'joinRoom');
97
+
98
+ const response = await fetch(finalLink, {
99
+ method: 'POST',
100
+ headers: {
101
+ 'Content-Type': 'application/json',
102
+ Authorization: `Bearer ${apiUserName}:${apiKey}`,
103
+ },
104
+ body: JSON.stringify(payload),
105
+ });
106
+
107
+ if (!response.ok) {
108
+ throw new Error(await readResponseError(response));
109
+ }
110
+
111
+ const data = await response.json();
112
+ return { data, success: true };
113
+ } catch (error) {
114
+ const errorMessage = (
115
+ error as { reason?: string; message?: string }
116
+ ).reason || (
117
+ error as { reason?: string; message?: string }
118
+ ).message || 'unknown error';
119
+ return {
120
+ data: { error: `Unable to join room, ${errorMessage}` },
121
+ success: false,
122
+ };
123
+ }
124
+ };
@@ -0,0 +1,107 @@
1
+ export interface TranslationTranscriptData {
2
+ speakerId: string;
3
+ speakerName?: string;
4
+ language: string;
5
+ originalText: string;
6
+ translatedText?: string;
7
+ timestamp?: number;
8
+ targetLanguage?: string;
9
+ isFinal?: boolean;
10
+ [key: string]: any;
11
+ }
12
+
13
+ export interface LiveSubtitle {
14
+ text: string;
15
+ language: string;
16
+ timestamp: number;
17
+ expiresAt: number;
18
+ speakerId: string;
19
+ speakerName?: string;
20
+ }
21
+
22
+ export interface UpdateLiveSubtitlesOptions {
23
+ currentSubtitles: Map<string, LiveSubtitle>;
24
+ transcript: TranslationTranscriptData;
25
+ now?: number;
26
+ }
27
+
28
+ export const createLiveSubtitle = (params: {
29
+ text: string;
30
+ language: string;
31
+ speakerId: string;
32
+ speakerName?: string;
33
+ timestamp?: number;
34
+ }): LiveSubtitle => {
35
+ const timestamp = params.timestamp ?? Date.now();
36
+ const duration = Math.min(8000, Math.max(3000, 3000 + params.text.length * 50));
37
+
38
+ return {
39
+ text: params.text,
40
+ language: params.language,
41
+ timestamp,
42
+ expiresAt: timestamp + duration,
43
+ speakerId: params.speakerId,
44
+ speakerName: params.speakerName,
45
+ };
46
+ };
47
+
48
+ export const isSubtitleExpired = (subtitle: LiveSubtitle, now = Date.now()): boolean => {
49
+ return now >= subtitle.expiresAt;
50
+ };
51
+
52
+ export const pruneExpiredSubtitles = (
53
+ subtitles: Map<string, LiveSubtitle>,
54
+ now = Date.now(),
55
+ ): Map<string, LiveSubtitle> => {
56
+ const next = new Map(subtitles);
57
+
58
+ for (const [key, subtitle] of next.entries()) {
59
+ if (isSubtitleExpired(subtitle, now)) {
60
+ next.delete(key);
61
+ }
62
+ }
63
+
64
+ return next;
65
+ };
66
+
67
+ export const updateLiveSubtitlesFromTranscript = ({
68
+ currentSubtitles,
69
+ transcript,
70
+ now,
71
+ }: UpdateLiveSubtitlesOptions): Map<string, LiveSubtitle> => {
72
+ const subtitle = createLiveSubtitle({
73
+ text: transcript.translatedText || transcript.originalText,
74
+ language: transcript.language,
75
+ speakerId: transcript.speakerId,
76
+ speakerName: transcript.speakerName,
77
+ timestamp: now ?? transcript.timestamp,
78
+ });
79
+
80
+ const next = pruneExpiredSubtitles(currentSubtitles, subtitle.timestamp);
81
+ next.set(transcript.speakerId, subtitle);
82
+
83
+ if (transcript.speakerName) {
84
+ next.set(transcript.speakerName, subtitle);
85
+ }
86
+
87
+ return next;
88
+ };
89
+
90
+ export const getSubtitleForSpeaker = (
91
+ subtitles: Map<string, LiveSubtitle>,
92
+ speakerId: string,
93
+ speakerName?: string,
94
+ now = Date.now(),
95
+ ): LiveSubtitle | null => {
96
+ const activeSubtitles = pruneExpiredSubtitles(subtitles, now);
97
+
98
+ if (speakerId && activeSubtitles.has(speakerId)) {
99
+ return activeSubtitles.get(speakerId) || null;
100
+ }
101
+
102
+ if (speakerName && activeSubtitles.has(speakerName)) {
103
+ return activeSubtitles.get(speakerName) || null;
104
+ }
105
+
106
+ return null;
107
+ };
@@ -0,0 +1,33 @@
1
+ import type { EventType, ShowAlert } from '../../types/types';
2
+
3
+ export interface MeetingTimeRemainingOptions {
4
+ timeRemaining: number;
5
+ showAlert?: ShowAlert;
6
+ eventType: EventType;
7
+ }
8
+
9
+ export type MeetingTimeRemainingType = (options: MeetingTimeRemainingOptions) => Promise<void>;
10
+
11
+ /**
12
+ * Shows a meeting countdown alert for non-chat event types.
13
+ *
14
+ * @param options Function options including the remaining time in milliseconds.
15
+ * @returns A promise that resolves after the alert has been evaluated and dispatched.
16
+ */
17
+ export const meetingTimeRemaining = async ({
18
+ timeRemaining,
19
+ showAlert,
20
+ eventType,
21
+ }: MeetingTimeRemainingOptions): Promise<void> => {
22
+ const minutes = Math.floor(timeRemaining / 60000);
23
+ const seconds = Math.floor((timeRemaining % 60000) / 1000);
24
+ const timeRemainingString = `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
25
+
26
+ if (eventType !== 'chat') {
27
+ showAlert?.({
28
+ message: `The event will end in ${timeRemainingString} minutes.`,
29
+ type: 'success',
30
+ duration: 3000,
31
+ });
32
+ }
33
+ };