mediasfu-shared 1.0.1 → 1.0.3

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 (127) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +103 -222
  3. package/dist/index.cjs +7634 -2180
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +4203 -273
  6. package/dist/index.js +7663 -2209
  7. package/dist/index.js.map +1 -1
  8. package/package.json +96 -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/connectIps.ts +3 -1
  15. package/src/consumers/connectLocalIps.ts +3 -1
  16. package/src/consumers/connectRecvTransport.ts +96 -1
  17. package/src/consumers/consumerResume.ts +2 -2
  18. package/src/consumers/dispStreams.ts +83 -37
  19. package/src/consumers/frameworkConsumerContract.ts +6 -0
  20. package/src/consumers/generatePageContent.ts +24 -10
  21. package/src/consumers/getPipedProducersAlt.ts +112 -16
  22. package/src/consumers/gridLayout/addVideosGrid.engine.ts +42 -0
  23. package/src/consumers/gridLayout/prepopulateUserMedia.engine.ts +444 -0
  24. package/src/consumers/mixStreams.ts +45 -14
  25. package/src/consumers/onScreenChanges.ts +25 -10
  26. package/src/consumers/prepopulateUserMedia.ts +3 -2
  27. package/src/consumers/processConsumerTransports.ts +68 -23
  28. package/src/consumers/processConsumerTransportsAudio.ts +146 -17
  29. package/src/consumers/reUpdateInter.ts +61 -21
  30. package/src/consumers/readjust.ts +30 -14
  31. package/src/consumers/reorderStreams.ts +76 -42
  32. package/src/consumers/resumePauseAudioStreams.ts +66 -17
  33. package/src/consumers/resumePauseStreams.ts +53 -10
  34. package/src/consumers/socketReceiveMethods/joinConsumeRoom.ts +8 -0
  35. package/src/consumers/socketReceiveMethods/newPipeProducer.ts +114 -0
  36. package/src/consumers/socketReceiveMethods/producerClosed.ts +13 -0
  37. package/src/consumers/streamSuccessScreen.ts +2 -2
  38. package/src/consumers/streamSuccessVideo.ts +5 -0
  39. package/src/consumers/translationConsumerSwitch.ts +321 -0
  40. package/src/index.ts +85 -1
  41. package/src/methods/coHostMethods/modifyCoHostSettings.ts +9 -9
  42. package/src/methods/displaySettings/modifyDisplaySettings.ts +5 -0
  43. package/src/methods/index.ts +66 -0
  44. package/src/methods/message/sendMessage.ts +12 -29
  45. package/src/methods/panelists/focusPanelists.ts +83 -0
  46. package/src/methods/panelists/index.ts +3 -0
  47. package/src/methods/panelists/launchPanelists.ts +13 -0
  48. package/src/methods/panelists/updatePanelists.ts +135 -0
  49. package/src/methods/permissions/index.ts +3 -0
  50. package/src/methods/permissions/launchPermissions.ts +13 -0
  51. package/src/methods/permissions/updateParticipantPermission.ts +127 -0
  52. package/src/methods/permissions/updatePermissionConfig.ts +52 -0
  53. package/src/methods/polls/pollUpdated.ts +88 -0
  54. package/src/methods/recording/confirmRecording.ts +15 -12
  55. package/src/methods/recording/recordResumeTimer.ts +2 -2
  56. package/src/methods/recording/recordStartTimer.ts +2 -2
  57. package/src/methods/recording/timeLeftRecording.ts +25 -0
  58. package/src/methods/requests/hostRequestResponse.ts +158 -0
  59. package/src/methods/settings/modifySettings.ts +17 -17
  60. package/src/methods/socketReceive/allMembers.ts +450 -0
  61. package/src/methods/socketReceive/allMembersRest.ts +480 -0
  62. package/src/methods/socketReceive/allWaitingRoomMembers.ts +35 -0
  63. package/src/methods/socketReceive/banParticipant.ts +73 -0
  64. package/src/methods/socketReceive/controlMediaHost.ts +280 -0
  65. package/src/methods/socketReceive/disconnect.ts +40 -0
  66. package/src/methods/socketReceive/disconnectUserSelf.ts +56 -0
  67. package/src/methods/socketReceive/getDomains.ts +112 -0
  68. package/src/methods/socketReceive/meetingEnded.ts +49 -0
  69. package/src/methods/socketReceive/meetingStillThere.ts +26 -0
  70. package/src/methods/socketReceive/panelistReceiveMethods.ts +195 -0
  71. package/src/methods/socketReceive/participantRequested.ts +48 -0
  72. package/src/methods/socketReceive/permissionReceiveMethods.ts +59 -0
  73. package/src/methods/socketReceive/personJoined.ts +35 -0
  74. package/src/methods/socketReceive/producerMediaClosed.ts +223 -0
  75. package/src/methods/socketReceive/producerMediaPaused.ts +267 -0
  76. package/src/methods/socketReceive/producerMediaResumed.ts +157 -0
  77. package/src/methods/socketReceive/reInitiateRecording.ts +53 -0
  78. package/src/methods/socketReceive/receiveMessage.ts +117 -0
  79. package/src/methods/socketReceive/recordingNotice.ts +286 -0
  80. package/src/methods/socketReceive/roomRecordParams.ts +122 -0
  81. package/src/methods/socketReceive/screenProducerId.ts +61 -0
  82. package/src/methods/socketReceive/startRecords.ts +46 -0
  83. package/src/methods/socketReceive/stoppedRecording.ts +44 -0
  84. package/src/methods/socketReceive/translationReceiveMethods.ts +581 -0
  85. package/src/methods/socketReceive/updateConsumingDomains.ts +128 -0
  86. package/src/methods/socketReceive/updateMediaSettings.ts +45 -0
  87. package/src/methods/socketReceive/updatedCoHost.ts +75 -0
  88. package/src/methods/socketReceive/userWaiting.ts +45 -0
  89. package/src/methods/stream/clickAudio.ts +380 -0
  90. package/src/methods/stream/clickChat.ts +36 -0
  91. package/src/methods/stream/clickScreenShare.ts +173 -0
  92. package/src/methods/stream/clickVideo.ts +28 -6
  93. package/src/methods/stream/index.ts +1 -0
  94. package/src/methods/utils/SoundPlayer.ts +31 -0
  95. package/src/methods/utils/checkLimitsAndMakeRequest.ts +156 -2
  96. package/src/methods/utils/createResponseJoinRoom.ts +47 -0
  97. package/src/methods/utils/createRoomOnMediaSFU.ts +160 -0
  98. package/src/methods/utils/formatNumber.ts +42 -0
  99. package/src/methods/utils/generateRandomMessages.ts +70 -0
  100. package/src/methods/utils/generateRandomParticipants.ts +100 -0
  101. package/src/methods/utils/generateRandomPolls.ts +43 -0
  102. package/src/methods/utils/generateRandomRequestList.ts +51 -0
  103. package/src/methods/utils/generateRandomWaitingRoomList.ts +17 -0
  104. package/src/methods/utils/getModalPosition.ts +23 -0
  105. package/src/methods/utils/getOverlayPosition.ts +37 -0
  106. package/src/methods/utils/initialValuesState.ts +405 -0
  107. package/src/methods/utils/joinRoomOnMediaSFU.ts +124 -0
  108. package/src/methods/utils/liveSubtitle.ts +107 -0
  109. package/src/methods/utils/meetingTimeRemaining.ts +33 -0
  110. package/src/methods/utils/meetingTimer/startMeetingProgressTimer.ts +72 -0
  111. package/src/methods/utils/producer/aParams.ts +10 -0
  112. package/src/methods/utils/producer/hParams.ts +26 -0
  113. package/src/methods/utils/producer/screenParams.ts +13 -0
  114. package/src/methods/utils/producer/vParams.ts +26 -0
  115. package/src/methods/utils/producer/videoCaptureConstraints.ts +65 -0
  116. package/src/methods/utils/resolveMediaSFURoomApi.ts +28 -0
  117. package/src/methods/utils/sleep.ts +24 -0
  118. package/src/methods/utils/translationLanguages.ts +308 -0
  119. package/src/methods/utils/webrtc.ts +44 -0
  120. package/src/methods/welcome/handleWelcomeRequest.ts +11 -2
  121. package/src/methods/welcome/index.ts +5 -1
  122. package/src/methods/whiteboard/captureCanvasStream.ts +128 -0
  123. package/src/producers/producerEmits/joinConRoom.ts +2 -2
  124. package/src/producers/producerEmits/joinLocalRoom.ts +240 -0
  125. package/src/producers/producerEmits/joinRoom.ts +129 -0
  126. package/src/types/shared-base-types.ts +14 -3
  127. package/src/types/types.ts +255 -0
@@ -1,13 +1,41 @@
1
1
  import { Stream, Participant } from "../types/types";
2
2
 
3
- export interface MixStreamsOptions {
4
- alVideoStreams: (Stream | Participant)[];
5
- non_alVideoStreams: Participant[];
6
- ref_participants: (Stream | Participant)[];
3
+ interface MixStreamLike {
4
+ producerId?: string | null;
5
+ muted?: boolean | null;
6
+ }
7
+
8
+ interface MixParticipantLike {
9
+ videoID?: string | null;
10
+ muted?: boolean | null;
11
+ }
12
+
13
+ const getProducerId = (value: unknown): string | null | undefined => {
14
+ return (value as MixStreamLike | null | undefined)?.producerId;
15
+ };
16
+
17
+ const getVideoId = (value: unknown): string | null | undefined => {
18
+ return (value as MixParticipantLike | null | undefined)?.videoID;
19
+ };
20
+
21
+ const getMuted = (value: unknown): boolean | null | undefined => {
22
+ return (value as (MixStreamLike & MixParticipantLike) | null | undefined)?.muted;
23
+ };
24
+
25
+ export interface MixStreamsOptions<
26
+ TStream extends MixStreamLike = Stream,
27
+ TParticipant extends MixParticipantLike = Participant,
28
+ > {
29
+ alVideoStreams: (TStream | TParticipant)[];
30
+ non_alVideoStreams: TParticipant[];
31
+ ref_participants: (TStream | TParticipant)[];
7
32
  }
8
33
 
9
34
  // Export the type definition for the function
10
- export type MixStreamsType = (options: MixStreamsOptions) => Promise<(Stream | Participant)[]>;
35
+ export type MixStreamsType = <
36
+ TStream extends MixStreamLike = Stream,
37
+ TParticipant extends MixParticipantLike = Participant,
38
+ >(options: MixStreamsOptions<TStream, TParticipant>) => Promise<(TStream | TParticipant)[]>;
11
39
 
12
40
  /**
13
41
  * Mixes video and audio streams and participants based on specified parameters.
@@ -30,37 +58,40 @@ export type MixStreamsType = (options: MixStreamsOptions) => Promise<(Stream | P
30
58
  */
31
59
 
32
60
 
33
- export async function mixStreams({
61
+ export async function mixStreams<
62
+ TStream extends MixStreamLike = Stream,
63
+ TParticipant extends MixParticipantLike = Participant,
64
+ >({
34
65
  alVideoStreams,
35
66
  non_alVideoStreams,
36
67
  ref_participants,
37
- }: MixStreamsOptions): Promise<(Stream | Participant)[]> {
68
+ }: MixStreamsOptions<TStream, TParticipant>): Promise<(TStream | TParticipant)[]> {
38
69
  try {
39
70
 
40
- const mixedStreams: (Stream | Participant)[] = [];
71
+ const mixedStreams: (TStream | TParticipant)[] = [];
41
72
 
42
73
  // Find "youyou" or "youyouyou" stream
43
74
  const youyouStream = alVideoStreams.find(
44
- (obj) => obj.producerId === "youyou" || obj.producerId === "youyouyou"
75
+ (obj) => getProducerId(obj) === "youyou" || getProducerId(obj) === "youyouyou"
45
76
  );
46
77
 
47
78
  let remainingAlVideoStreams = alVideoStreams.filter(
48
- (obj) => obj.producerId !== "youyou" && obj.producerId !== "youyouyou"
79
+ (obj) => getProducerId(obj) !== "youyou" && getProducerId(obj) !== "youyouyou"
49
80
  );
50
81
 
51
82
  // Separate unmuted and muted streams
52
83
  const unmutedAlVideoStreams = remainingAlVideoStreams.filter((obj) => {
53
84
  const participant = ref_participants.find(
54
- (p) => p.videoID === obj.producerId
85
+ (p) => getVideoId(p) === getProducerId(obj)
55
86
  );
56
- return !obj.muted && participant && participant.muted === false;
87
+ return !getMuted(obj) && participant && getMuted(participant) === false;
57
88
  });
58
89
 
59
90
  const mutedAlVideoStreams = remainingAlVideoStreams.filter((obj) => {
60
91
  const participant = ref_participants.find(
61
- (p) => p.videoID === obj.producerId
92
+ (p) => getVideoId(p) === getProducerId(obj)
62
93
  );
63
- return obj.muted || (participant && participant.muted === true);
94
+ return !!getMuted(obj) || (participant && getMuted(participant) === true);
64
95
  });
65
96
 
66
97
  const nonAlVideoStreams = [...non_alVideoStreams]; // Create a copy of non_alVideoStreams
@@ -1,6 +1,10 @@
1
- import { ReorderStreamsType, ReorderStreamsParameters, EventType } from "../types/types";
1
+ import { ReorderStreamsParameters, EventType } from "../types/types";
2
2
 
3
- export interface OnScreenChangesParameters extends ReorderStreamsParameters {
3
+ type OpaqueReorderStreamsInvoker = {
4
+ bivarianceHack: (options: any) => Promise<void>;
5
+ }["bivarianceHack"];
6
+
7
+ export interface OnScreenChangesParameters extends ReorderStreamsParameters<any, any, any> {
4
8
  eventType: EventType;
5
9
  shareScreenStarted: boolean;
6
10
  shared: boolean;
@@ -10,18 +14,22 @@ export interface OnScreenChangesParameters extends ReorderStreamsParameters {
10
14
  updateItemPageLimit: (value: number) => void;
11
15
  updateMainHeightWidth: (value: number) => void;
12
16
 
13
- //mediasfu functions
14
- reorderStreams: ReorderStreamsType;
17
+ // mediasfu functions
18
+ reorderStreams: OpaqueReorderStreamsInvoker;
15
19
  [key: string]: any;
16
20
  }
17
21
 
18
- export interface OnScreenChangesOptions {
22
+ export interface OnScreenChangesOptions<
23
+ TParameters extends OnScreenChangesParameters = OnScreenChangesParameters,
24
+ > {
19
25
  changed?: boolean;
20
- parameters: OnScreenChangesParameters;
26
+ parameters: TParameters;
21
27
  }
22
28
 
23
29
  // Export the type definition for the function
24
- export type OnScreenChangesType = (options: OnScreenChangesOptions) => Promise<void>;
30
+ export type OnScreenChangesType = <
31
+ TParameters extends OnScreenChangesParameters = OnScreenChangesParameters,
32
+ >(options: OnScreenChangesOptions<TParameters>) => Promise<void>;
25
33
 
26
34
  /**
27
35
  * Handles changes in screen events such as broadcast, chat, and conference.
@@ -62,13 +70,17 @@ export type OnScreenChangesType = (options: OnScreenChangesOptions) => Promise<v
62
70
  * ```
63
71
  */
64
72
 
65
- export async function onScreenChanges({ changed, parameters }: OnScreenChangesOptions): Promise<void> {
73
+ export async function onScreenChanges<
74
+ TParameters extends OnScreenChangesParameters = OnScreenChangesParameters,
75
+ >({ changed, parameters }: OnScreenChangesOptions<TParameters>): Promise<void> {
66
76
  try {
67
77
  // Destructure parameters
68
78
  let {
69
79
  eventType,
70
80
  shareScreenStarted,
71
81
  shared,
82
+ whiteboardStarted,
83
+ whiteboardEnded,
72
84
  addForBasic,
73
85
  updateMainHeightWidth,
74
86
  updateAddForBasic,
@@ -78,6 +90,7 @@ export async function onScreenChanges({ changed, parameters }: OnScreenChangesOp
78
90
  //mediasfu functions
79
91
  reorderStreams,
80
92
  } = parameters;
93
+ const screenFlowActive = shareScreenStarted || shared || (whiteboardStarted && !whiteboardEnded);
81
94
 
82
95
  // Remove element with id 'controlButtons'
83
96
  addForBasic = false;
@@ -89,9 +102,11 @@ export async function onScreenChanges({ changed, parameters }: OnScreenChangesOp
89
102
 
90
103
  itemPageLimit = eventType === "broadcast" ? 1 : 2;
91
104
  updateItemPageLimit(itemPageLimit);
92
- updateMainHeightWidth(eventType === "broadcast" ? 100 : 0);
105
+ updateMainHeightWidth(screenFlowActive ? 84 : eventType === "broadcast" ? 100 : 0);
106
+ } else if (screenFlowActive) {
107
+ updateMainHeightWidth(84);
93
108
  } else {
94
- if (eventType === "conference" && !(shareScreenStarted || shared)) {
109
+ if (eventType === "conference") {
95
110
  updateMainHeightWidth(0);
96
111
  }
97
112
  }
@@ -1,6 +1,8 @@
1
1
  // Stub export for prepopulateUserMedia
2
2
  // This is a React component in the original and not needed for the shared package
3
3
 
4
+ import { createFrameworkConsumerContractError } from './frameworkConsumerContract';
5
+
4
6
  export interface PrepopulateUserMediaParameters {
5
7
  [key: string]: any;
6
8
  }
@@ -13,6 +15,5 @@ export interface PrepopulateUserMediaOptions {
13
15
  export type PrepopulateUserMediaType = (options: PrepopulateUserMediaOptions) => Promise<void>;
14
16
 
15
17
  export const prepopulateUserMedia: PrepopulateUserMediaType = async () => {
16
- // Stub implementation - actual logic handled in framework-specific packages
17
- console.warn('prepopulateUserMedia called on shared package - should be implemented in framework package');
18
+ throw createFrameworkConsumerContractError('prepopulateUserMedia');
18
19
  };
@@ -1,24 +1,65 @@
1
1
  import { Stream, Participant, Transport, SleepType } from "../types/types";
2
2
 
3
- export interface ProcessConsumerTransportsParameters {
4
- remoteScreenStream: Stream[];
5
- oldAllStreams: (Stream | Participant)[];
6
- newLimitedStreams: (Stream | Participant)[];
3
+ interface ProducerIdCarrier {
4
+ producerId?: string | null;
5
+ }
6
+
7
+ const getProducerId = (value: unknown): string | null | undefined => {
8
+ return (value as ProducerIdCarrier | null | undefined)?.producerId;
9
+ };
10
+
11
+ interface ConsumerLike {
12
+ paused?: boolean;
13
+ kind?: string;
14
+ pause: () => unknown;
15
+ resume: () => unknown;
16
+ }
17
+
18
+ interface SocketLike {
19
+ emit: (
20
+ event: string,
21
+ payload: { serverConsumerId: string },
22
+ callback?: ((payload?: { resumed: boolean }) => void | Promise<unknown>)
23
+ ) => void;
24
+ }
25
+
26
+ interface TransportLike {
27
+ producerId?: string | null;
28
+ consumer?: ConsumerLike;
29
+ socket_: SocketLike;
30
+ serverConsumerTransportId: string;
31
+ }
32
+
33
+ export interface ProcessConsumerTransportsParameters<
34
+ TStreamEntry = Stream,
35
+ TMediaEntry = Stream | Participant,
36
+ > {
37
+ remoteScreenStream: TStreamEntry[];
38
+ oldAllStreams: TMediaEntry[];
39
+ newLimitedStreams: TMediaEntry[];
7
40
 
8
41
  // mediasfu functions
9
42
  sleep: SleepType;
10
- getUpdatedAllParams: () => ProcessConsumerTransportsParameters;
43
+ getUpdatedAllParams: () => ProcessConsumerTransportsParameters<TStreamEntry, TMediaEntry>;
11
44
  [key: string]: any;
12
45
  }
13
46
 
14
- export interface ProcessConsumerTransportsOptions {
15
- consumerTransports: Transport[];
16
- lStreams_: (Stream | Participant)[];
17
- parameters: ProcessConsumerTransportsParameters;
47
+ export interface ProcessConsumerTransportsOptions<
48
+ TTransport extends TransportLike = Transport,
49
+ TStreamEntry = Stream,
50
+ TMediaEntry = Stream | Participant,
51
+ > {
52
+ consumerTransports: TTransport[];
53
+ lStreams_: TMediaEntry[];
54
+ parameters: ProcessConsumerTransportsParameters<TStreamEntry, TMediaEntry>;
18
55
  }
19
56
 
20
57
  // Export the type definition for the function
21
- export type ProcessConsumerTransportsType = (options: ProcessConsumerTransportsOptions) => Promise<void>;
58
+ export type ProcessConsumerTransportsType = <
59
+ TTransport extends TransportLike = Transport,
60
+ TStreamEntry = Stream,
61
+ TMediaEntry = Stream | Participant,
62
+ >(options: ProcessConsumerTransportsOptions<TTransport, TStreamEntry, TMediaEntry>) => Promise<void>;
22
63
 
23
64
  /**
24
65
  * Processes consumer transports by pausing and resuming them based on certain conditions.
@@ -57,11 +98,15 @@ export type ProcessConsumerTransportsType = (options: ProcessConsumerTransportsO
57
98
  * ```
58
99
  */
59
100
 
60
- export async function processConsumerTransports({
101
+ export async function processConsumerTransports<
102
+ TTransport extends TransportLike = Transport,
103
+ TStreamEntry = Stream,
104
+ TMediaEntry = Stream | Participant,
105
+ >({
61
106
  consumerTransports,
62
107
  lStreams_,
63
108
  parameters,
64
- }: ProcessConsumerTransportsOptions): Promise<void> {
109
+ }: ProcessConsumerTransportsOptions<TTransport, TStreamEntry, TMediaEntry>): Promise<void> {
65
110
  try {
66
111
  // Destructure parameters and get updated values
67
112
  parameters = parameters.getUpdatedAllParams();
@@ -74,14 +119,14 @@ export async function processConsumerTransports({
74
119
  } = parameters;
75
120
 
76
121
  // Function to check if the producerId is valid in the given stream arrays
77
- function isValidProducerId(producerId: string, ...streamArrays: (Stream | Participant)[][]): boolean {
122
+ function isValidProducerId(producerId: string | null | undefined, ...streamArrays: unknown[][]): boolean {
78
123
  return (
79
124
  producerId !== null &&
80
125
  producerId !== "" &&
81
126
  streamArrays.some((streamArray) => {
82
127
  return (
83
128
  streamArray.length > 0 &&
84
- streamArray.some((stream) => stream?.producerId === producerId)
129
+ streamArray.some((stream) => getProducerId(stream) === producerId)
85
130
  );
86
131
  })
87
132
  );
@@ -98,7 +143,7 @@ export async function processConsumerTransports({
98
143
  newLimitedStreams
99
144
  ) &&
100
145
  transport.consumer?.paused === true &&
101
- transport.consumer.kind !== "audio"
146
+ transport.consumer?.kind !== "audio"
102
147
  );
103
148
 
104
149
  // Get unpaused consumer transports that are not audio
@@ -108,15 +153,15 @@ export async function processConsumerTransports({
108
153
  transport.producerId !== null &&
109
154
  transport.producerId !== "" &&
110
155
  !lStreams_.some(
111
- (stream) => stream.producerId === transport.producerId
156
+ (stream) => getProducerId(stream) === transport.producerId
112
157
  ) &&
113
158
  transport.consumer &&
114
- transport.consumer.kind &&
159
+ transport.consumer?.kind &&
115
160
  transport.consumer.paused !== true &&
116
161
  transport.consumer.kind !== "audio" &&
117
- !remoteScreenStream.some((stream) => stream.producerId === transport.producerId) &&
118
- !oldAllStreams.some((stream) => stream.producerId === transport.producerId) &&
119
- !newLimitedStreams.some((stream) => stream.producerId === transport.producerId)
162
+ !remoteScreenStream.some((stream) => getProducerId(stream) === transport.producerId) &&
163
+ !oldAllStreams.some((stream) => getProducerId(stream) === transport.producerId) &&
164
+ !newLimitedStreams.some((stream) => getProducerId(stream) === transport.producerId)
120
165
  );
121
166
 
122
167
  // Pause consumer transports after a short delay
@@ -124,7 +169,7 @@ export async function processConsumerTransports({
124
169
 
125
170
  // Emit consumer.pause() for each filtered transport (not audio)
126
171
  for (const transport of consumerTransportsToPause) {
127
- transport.consumer.pause();
172
+ transport.consumer?.pause();
128
173
  transport.socket_.emit(
129
174
  "consumer-pause",
130
175
  { serverConsumerId: transport.serverConsumerTransportId },
@@ -139,9 +184,9 @@ export async function processConsumerTransports({
139
184
  transport.socket_.emit(
140
185
  "consumer-resume",
141
186
  { serverConsumerId: transport.serverConsumerTransportId },
142
- async ({ resumed }: { resumed: boolean }) => {
187
+ async ({ resumed }: { resumed: boolean } = { resumed: false }) => {
143
188
  if (resumed) {
144
- transport.consumer.resume();
189
+ transport.consumer?.resume();
145
190
  }
146
191
  }
147
192
  );
@@ -1,5 +1,119 @@
1
1
  import { Stream, Transport, Participant, SleepType } from "../types/types";
2
2
 
3
+ interface ProducerIdCarrier {
4
+ producerId?: string | null;
5
+ }
6
+
7
+ interface SpeakerTranslationStateLike {
8
+ enabled?: boolean;
9
+ speakerId?: string;
10
+ speakerName?: string;
11
+ originalProducerId?: string;
12
+ }
13
+
14
+ interface ParticipantLike {
15
+ name?: string | null;
16
+ audioID?: string | null;
17
+ }
18
+
19
+ const getProducerId = (value: unknown): string | null | undefined => {
20
+ return (value as ProducerIdCarrier | null | undefined)?.producerId;
21
+ };
22
+
23
+ interface ConsumerLike {
24
+ paused?: boolean;
25
+ kind?: string;
26
+ pause: () => unknown;
27
+ resume: () => unknown;
28
+ }
29
+
30
+ interface SocketLike {
31
+ emit: (
32
+ event: string,
33
+ payload: { serverConsumerId: string },
34
+ callback?: ((payload?: { resumed: boolean }) => void | Promise<unknown>)
35
+ ) => void;
36
+ }
37
+
38
+ interface TransportLike {
39
+ producerId?: string | null;
40
+ consumer?: ConsumerLike;
41
+ socket_: SocketLike;
42
+ serverConsumerTransportId: string;
43
+ }
44
+
45
+ const getSpeakerNameForProducerId = (
46
+ producerId: string,
47
+ parameters: Record<string, any>,
48
+ ): string | undefined => {
49
+ const participants = parameters.participants as ParticipantLike[] | undefined;
50
+ const participant = participants?.find((candidate) => candidate.audioID === producerId);
51
+
52
+ if (participant?.name) {
53
+ return participant.name;
54
+ }
55
+
56
+ const audStreamName = (parameters.audStreamNames as Array<{ producerId?: string; name?: string }> | undefined)
57
+ ?.find((stream) => stream.producerId === producerId && typeof stream.name === 'string');
58
+ if (audStreamName?.name) {
59
+ return audStreamName.name;
60
+ }
61
+
62
+ return (parameters.allAudioStreams as Array<{ producerId?: string; name?: string }> | undefined)
63
+ ?.find((stream) => stream.producerId === producerId && typeof stream.name === 'string')
64
+ ?.name;
65
+ };
66
+
67
+ const isOriginalAudioSuppressedByTranslation = (
68
+ producerId: string | null | undefined,
69
+ parameters: Record<string, any>,
70
+ ): boolean => {
71
+ if (!producerId) {
72
+ return false;
73
+ }
74
+
75
+ const activeTranslationProducerIds = parameters.activeTranslationProducerIds as Set<string> | undefined;
76
+ if (activeTranslationProducerIds?.has(producerId)) {
77
+ return false;
78
+ }
79
+
80
+ const speakerTranslationStates = parameters.speakerTranslationStates as
81
+ | Map<string, SpeakerTranslationStateLike>
82
+ | undefined;
83
+
84
+ if (!speakerTranslationStates?.size) {
85
+ return false;
86
+ }
87
+
88
+ const speakerName = getSpeakerNameForProducerId(producerId, parameters);
89
+
90
+ if (speakerName) {
91
+ const speakerState = speakerTranslationStates.get(speakerName);
92
+ if (speakerState?.enabled) {
93
+ return true;
94
+ }
95
+ }
96
+
97
+ return Array.from(speakerTranslationStates.values()).some((speakerState) => {
98
+ if (!speakerState?.enabled) {
99
+ return false;
100
+ }
101
+
102
+ if (speakerState.originalProducerId === producerId) {
103
+ return true;
104
+ }
105
+
106
+ if (!speakerName) {
107
+ return false;
108
+ }
109
+
110
+ return (
111
+ speakerState.speakerId === speakerName ||
112
+ speakerState.speakerName === speakerName
113
+ );
114
+ });
115
+ };
116
+
3
117
  export interface ProcessConsumerTransportsAudioParameters {
4
118
 
5
119
  // mediasfu functions
@@ -7,16 +121,20 @@ export interface ProcessConsumerTransportsAudioParameters {
7
121
  [key: string]: any;
8
122
  }
9
123
 
10
- export interface ProcessConsumerTransportsAudioOptions {
11
- consumerTransports: Transport[];
12
- lStreams: (Stream | Participant)[];
124
+ export interface ProcessConsumerTransportsAudioOptions<
125
+ TTransport extends TransportLike = Transport,
126
+ TMediaEntry = Stream | Participant,
127
+ > {
128
+ consumerTransports: TTransport[];
129
+ lStreams: TMediaEntry[];
13
130
  parameters: ProcessConsumerTransportsAudioParameters;
14
131
  }
15
132
 
16
133
  // Export the type definition for the function
17
- export type ProcessConsumerTransportsAudioType = (
18
- options: ProcessConsumerTransportsAudioOptions
19
- ) => Promise<void>;
134
+ export type ProcessConsumerTransportsAudioType = <
135
+ TTransport extends TransportLike = Transport,
136
+ TMediaEntry = Stream | Participant,
137
+ >(options: ProcessConsumerTransportsAudioOptions<TTransport, TMediaEntry>) => Promise<void>;
20
138
 
21
139
  /**
22
140
  * Processes consumer transports for audio streams by pausing and resuming them based on their current state and the provided streams.
@@ -43,23 +161,26 @@ export type ProcessConsumerTransportsAudioType = (
43
161
  * ```
44
162
  */
45
163
 
46
- export const processConsumerTransportsAudio = async ({
164
+ export const processConsumerTransportsAudio = async <
165
+ TTransport extends TransportLike = Transport,
166
+ TMediaEntry = Stream | Participant,
167
+ >({
47
168
  consumerTransports,
48
169
  lStreams,
49
170
  parameters,
50
- }: ProcessConsumerTransportsAudioOptions): Promise<void> => {
171
+ }: ProcessConsumerTransportsAudioOptions<TTransport, TMediaEntry>): Promise<void> => {
51
172
  try {
52
173
  const { sleep } = parameters;
53
174
 
54
175
  // Function to check if the producerId is valid in the given stream arrays
55
- const isValidProducerId = (producerId: string, ...streamArrays: (Stream | Participant)[][]): boolean => {
176
+ const isValidProducerId = (producerId: string | null | undefined, ...streamArrays: unknown[][]): boolean => {
56
177
  return (
57
178
  producerId !== null &&
58
179
  producerId !== "" &&
59
180
  streamArrays.some((streamArray) => {
60
181
  return (
61
182
  streamArray.length > 0 &&
62
- streamArray.some((stream) => stream?.producerId === producerId)
183
+ streamArray.some((stream) => getProducerId(stream) === producerId)
63
184
  );
64
185
  })
65
186
  );
@@ -69,8 +190,9 @@ export const processConsumerTransportsAudio = async ({
69
190
  const consumerTransportsToResume = consumerTransports.filter(
70
191
  (transport) =>
71
192
  isValidProducerId(transport.producerId, lStreams) &&
193
+ !isOriginalAudioSuppressedByTranslation(transport.producerId, parameters) &&
72
194
  transport.consumer?.paused === true &&
73
- transport.consumer.kind === "audio"
195
+ transport.consumer?.kind === "audio"
74
196
  );
75
197
 
76
198
  // Get unpaused consumer transports that are audio
@@ -79,11 +201,14 @@ export const processConsumerTransportsAudio = async ({
79
201
  transport.producerId &&
80
202
  transport.producerId !== null &&
81
203
  transport.producerId !== "" &&
82
- !lStreams.some(
83
- (stream) => stream.producerId === transport.producerId
204
+ (
205
+ isOriginalAudioSuppressedByTranslation(transport.producerId, parameters) ||
206
+ !lStreams.some(
207
+ (stream) => getProducerId(stream) === transport.producerId
208
+ )
84
209
  ) &&
85
210
  transport.consumer &&
86
- transport.consumer.kind &&
211
+ transport.consumer?.kind &&
87
212
  transport.consumer.paused !== true &&
88
213
  transport.consumer.kind === "audio"
89
214
  );
@@ -92,7 +217,7 @@ export const processConsumerTransportsAudio = async ({
92
217
 
93
218
  // Emit consumer.pause() for each transport to pause
94
219
  for (const transport of consumerTransportsToPause) {
95
- transport.consumer.pause();
220
+ transport.consumer?.pause();
96
221
  transport.socket_.emit(
97
222
  "consumer-pause",
98
223
  { serverConsumerId: transport.serverConsumerTransportId },
@@ -104,12 +229,16 @@ export const processConsumerTransportsAudio = async ({
104
229
 
105
230
  // Emit consumer.resume() for each transport to resume
106
231
  for (const transport of consumerTransportsToResume) {
232
+ if (isOriginalAudioSuppressedByTranslation(transport.producerId, parameters)) {
233
+ continue;
234
+ }
235
+
107
236
  transport.socket_.emit(
108
237
  "consumer-resume",
109
238
  { serverConsumerId: transport.serverConsumerTransportId },
110
- async ({ resumed }: { resumed: boolean }) => {
239
+ async ({ resumed }: { resumed: boolean } = { resumed: false }) => {
111
240
  if (resumed) {
112
- transport.consumer.resume();
241
+ transport.consumer?.resume();
113
242
  }
114
243
  }
115
244
  );