@livedigital/client 3.48.0 → 3.49.1

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 (166) hide show
  1. package/LICENSE +1 -1
  2. package/dist/constants/encodings.d.ts +3 -3
  3. package/dist/constants/encodings.ts +3 -3
  4. package/dist/engine/handlers/ChannelAudioObserverEventHandler.d.ts +3 -1
  5. package/dist/engine/handlers/ChannelAudioObserverMissingProducerRestorer.d.ts +10 -0
  6. package/dist/engine/handlers/MediaEventHandler.d.ts +0 -1
  7. package/dist/engine/index.d.ts +7 -4
  8. package/dist/engine/network/DatachannelHeartbeater.d.ts +2 -2
  9. package/dist/engine/network/NetworkTransportPolicyManager.d.ts +22 -0
  10. package/dist/engine/network/index.d.ts +10 -8
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.es.js +2 -2
  13. package/dist/index.js +2 -2
  14. package/dist/inversify.tokens.d.ts +3 -1
  15. package/dist/types/network.d.ts +6 -6
  16. package/package.json +2 -3
  17. package/src/ClientMetaProvider.ts +0 -41
  18. package/src/EnhancedEventEmitter.ts +0 -75
  19. package/src/config/ConfigService.ts +0 -66
  20. package/src/constants/common.ts +0 -85
  21. package/src/constants/encodings.ts +0 -26
  22. package/src/constants/events.ts +0 -126
  23. package/src/constants/mutex.ts +0 -6
  24. package/src/constants/stats.ts +0 -1
  25. package/src/constants/videoConstrains.ts +0 -21
  26. package/src/engine/CallState.ts +0 -19
  27. package/src/engine/ChannelStateSynchronizer/ChannelStateSynchronizer.ts +0 -448
  28. package/src/engine/ChannelStateSynchronizer/types.ts +0 -22
  29. package/src/engine/EventsQueue.ts +0 -255
  30. package/src/engine/IntegrationsService.ts +0 -163
  31. package/src/engine/LocalMutex.ts +0 -45
  32. package/src/engine/Logger.ts +0 -234
  33. package/src/engine/MyPeer.ts +0 -25
  34. package/src/engine/Peer.ts +0 -602
  35. package/src/engine/PeerConsumer.ts +0 -276
  36. package/src/engine/PeerProducer.ts +0 -50
  37. package/src/engine/Peers.ts +0 -150
  38. package/src/engine/PeersStorage.ts +0 -45
  39. package/src/engine/RemotePeerTracks.ts +0 -73
  40. package/src/engine/WIDHandler.ts +0 -166
  41. package/src/engine/WebRTCStats/ConnectionStatsManager.ts +0 -31
  42. package/src/engine/WebRTCStats/InboundTrackStatsManager.ts +0 -51
  43. package/src/engine/WebRTCStats/OutboudTrackStatsManager.ts +0 -51
  44. package/src/engine/WebRTCStats/StatsHandler.ts +0 -80
  45. package/src/engine/WebRTCStats/TransportsStatsProvider.ts +0 -123
  46. package/src/engine/WebRTCStats/types.ts +0 -20
  47. package/src/engine/analyticsApiClient/LogApi.ts +0 -24
  48. package/src/engine/analyticsApiClient/MetricsApi.ts +0 -30
  49. package/src/engine/analyticsApiClient/helper.ts +0 -88
  50. package/src/engine/analyticsApiClient/index.ts +0 -42
  51. package/src/engine/analyticsApiClient/types.ts +0 -33
  52. package/src/engine/handlers/ChannelAudioObserverEventHandler.ts +0 -177
  53. package/src/engine/handlers/ChannelEventHandler.ts +0 -268
  54. package/src/engine/handlers/ChannelStateSyncEventHandler/ChannelStateConsistencyCheckResult.ts +0 -31
  55. package/src/engine/handlers/ChannelStateSyncEventHandler/ChannelStateConsistencyChecker.ts +0 -146
  56. package/src/engine/handlers/ChannelStateSyncEventHandler/consts.ts +0 -7
  57. package/src/engine/handlers/ChannelStateSyncEventHandler/index.ts +0 -342
  58. package/src/engine/handlers/ChannelStateSyncEventHandler/types.ts +0 -21
  59. package/src/engine/handlers/MediaEventHandler.ts +0 -273
  60. package/src/engine/index.ts +0 -793
  61. package/src/engine/media/index.ts +0 -574
  62. package/src/engine/media/producer/PendingClosureProducerStorage.ts +0 -37
  63. package/src/engine/media/producer/ProducerCloseManager.ts +0 -115
  64. package/src/engine/media/streamEffects/ProcessorsCache.ts +0 -41
  65. package/src/engine/media/streamEffects/audio/AudioTrackProcessor.ts +0 -7
  66. package/src/engine/media/streamEffects/audio/asdk/ASDKTrackProcessor.ts +0 -275
  67. package/src/engine/media/streamEffects/audio/asdk/atsrb.d.ts +0 -36
  68. package/src/engine/media/streamEffects/audio/asdk/errorBus.d.ts +0 -47
  69. package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionAudioWorkletNode.ts +0 -35
  70. package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionNodeProvider.ts +0 -44
  71. package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionScriptProcessorNode.ts +0 -69
  72. package/src/engine/media/streamEffects/audio/noiseSuppression/RNNoiseTrackProcessor.ts +0 -134
  73. package/src/engine/media/streamEffects/audio/noiseSuppression/WasmModuleCompiler.ts +0 -9
  74. package/src/engine/media/streamEffects/video/esdk/TrackProcessor.ts +0 -386
  75. package/src/engine/media/streamEffects/video/esdk/components/component.d.ts +0 -35
  76. package/src/engine/media/streamEffects/video/esdk/components/countdown/countdown.d.ts +0 -27
  77. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/doubleSlideRect.d.ts +0 -33
  78. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/horizontalMirror.d.ts +0 -29
  79. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/leftTextbox.d.ts +0 -31
  80. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/slideBold.d.ts +0 -41
  81. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/twoSideRects/animatedBox.d.ts +0 -59
  82. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/twoSideRects/twoSlideRects.d.ts +0 -27
  83. package/src/engine/media/streamEffects/video/esdk/components/lower-third/lowerThird.d.ts +0 -83
  84. package/src/engine/media/streamEffects/video/esdk/components/overlay-screen/overlayScreen.d.ts +0 -40
  85. package/src/engine/media/streamEffects/video/esdk/components/overlay-screen/overlaySprite.d.ts +0 -10
  86. package/src/engine/media/streamEffects/video/esdk/components/stickers/stickerSprite.d.ts +0 -51
  87. package/src/engine/media/streamEffects/video/esdk/components/stickers/stickers.d.ts +0 -54
  88. package/src/engine/media/streamEffects/video/esdk/components/utils/positionHelper.d.ts +0 -14
  89. package/src/engine/media/streamEffects/video/esdk/components/waterMark/waterMark.d.ts +0 -20
  90. package/src/engine/media/streamEffects/video/esdk/tsvb.d.ts +0 -187
  91. package/src/engine/media/streamEffects/video/esdk/utils/errorBus.d.ts +0 -42
  92. package/src/engine/media/tracks/DefaultAudioTrack.ts +0 -178
  93. package/src/engine/media/tracks/DefaultBaseTrack.ts +0 -592
  94. package/src/engine/media/tracks/DefaultVideoTrack.ts +0 -301
  95. package/src/engine/media/tracks/MediaStreamTrackManager.ts +0 -50
  96. package/src/engine/media/tracks/PeerTrack.ts +0 -558
  97. package/src/engine/network/DataChannelsManager.ts +0 -164
  98. package/src/engine/network/DatachannelHeartbeater.ts +0 -122
  99. package/src/engine/network/SignalingHeartbeater.ts +0 -55
  100. package/src/engine/network/index.ts +0 -961
  101. package/src/engine/signalingApiClient/SignalingApiClient.ts +0 -95
  102. package/src/engine/signalingApiClient/api.ts +0 -2289
  103. package/src/engine/system/index.ts +0 -221
  104. package/src/errors/AlreadyConnectedError.ts +0 -11
  105. package/src/errors/AlreadyCreatedError.ts +0 -11
  106. package/src/errors/ForbiddenError.ts +0 -11
  107. package/src/errors/InvalidPayloadError.ts +0 -11
  108. package/src/errors/InvalidRequestError.ts +0 -11
  109. package/src/errors/LivedigitalSDKError.ts +0 -15
  110. package/src/errors/NeedJoinFirstError.ts +0 -11
  111. package/src/errors/NotFoundError.ts +0 -11
  112. package/src/errors/OperationError.ts +0 -47
  113. package/src/errors/RequestError.ts +0 -11
  114. package/src/errors/TimeoutError.ts +0 -11
  115. package/src/errors/TooManyRequestsError.ts +0 -11
  116. package/src/errors/UnauthorizedError.ts +0 -11
  117. package/src/errors/UnsupportedError.ts +0 -15
  118. package/src/errors/signalingApiErrorMapper.ts +0 -143
  119. package/src/helpers/appDataValidator.ts +0 -21
  120. package/src/helpers/browser.ts +0 -37
  121. package/src/helpers/channelMessageConverter.ts +0 -124
  122. package/src/helpers/common.ts +0 -96
  123. package/src/helpers/datetime.ts +0 -11
  124. package/src/helpers/errors.ts +0 -25
  125. package/src/helpers/filterStatsCodecs.ts +0 -3
  126. package/src/helpers/loader.ts +0 -59
  127. package/src/helpers/media.ts +0 -57
  128. package/src/helpers/peer.ts +0 -19
  129. package/src/helpers/randomString.ts +0 -18
  130. package/src/helpers/retry.ts +0 -74
  131. package/src/index.ts +0 -171
  132. package/src/inversify.config.ts +0 -333
  133. package/src/inversify.factories.ts +0 -191
  134. package/src/inversify.tokens.ts +0 -42
  135. package/src/proto/.gitkeep +0 -0
  136. package/src/proto/generated/channel/channel_activity_confirmation_time.ts +0 -110
  137. package/src/proto/generated/channel/channel_management_event.ts +0 -213
  138. package/src/proto/generated/channel/channel_produce_permissions.ts +0 -171
  139. package/src/proto/generated/channel/channel_state.ts +0 -94
  140. package/src/proto/generated/channel/channel_state_short.ts +0 -282
  141. package/src/proto/generated/channel_message/channel_event.ts +0 -401
  142. package/src/proto/generated/channel_message/channel_message.ts +0 -139
  143. package/src/proto/generated/channel_message/media_event.ts +0 -290
  144. package/src/proto/generated/consumer/consumer.ts +0 -167
  145. package/src/proto/generated/google/protobuf/struct.ts +0 -588
  146. package/src/proto/generated/google/protobuf/timestamp.ts +0 -229
  147. package/src/proto/generated/peer/peer.ts +0 -430
  148. package/src/proto/generated/peer/peer_group.ts +0 -48
  149. package/src/proto/generated/peer/peer_role.ts +0 -48
  150. package/src/proto/generated/producer/producer.ts +0 -204
  151. package/src/proto/generated/producer/producer_kind.ts +0 -48
  152. package/src/proto/generated/producer/producer_label.ts +0 -78
  153. package/src/proto/generated/producer/producer_spatial_layer_request.ts +0 -116
  154. package/src/proto/generated/transport/transport_connection_timeout.ts +0 -156
  155. package/src/proto/generated/transport/transport_connection_timeout_reason.ts +0 -48
  156. package/src/proto/generated/transport/transport_direction.ts +0 -48
  157. package/src/types/channelAudioObserver.ts +0 -34
  158. package/src/types/channelStateSyncronizer.ts +0 -22
  159. package/src/types/client.ts +0 -27
  160. package/src/types/common.ts +0 -399
  161. package/src/types/container.ts +0 -31
  162. package/src/types/engine.ts +0 -97
  163. package/src/types/media.ts +0 -146
  164. package/src/types/mediasoup.ts +0 -10
  165. package/src/types/network.ts +0 -10
  166. package/src/types/streamEffects.ts +0 -23
@@ -1,25 +0,0 @@
1
- import { injectable } from 'inversify';
2
- import Peer from './Peer';
3
-
4
- @injectable()
5
- export class MyPeer {
6
- id?: Peer['id'];
7
-
8
- private peer?: Peer;
9
-
10
- get(): Peer | undefined {
11
- return this.peer;
12
- }
13
-
14
- set(peer: Peer): void {
15
- this.peer = peer;
16
- }
17
-
18
- delete(): void {
19
- this.peer = undefined;
20
- }
21
-
22
- get canPublish(): boolean {
23
- return this.peer?.role === 'host';
24
- }
25
- }
@@ -1,602 +0,0 @@
1
- import { serializeError } from 'serialize-error';
2
- import {
3
- CHANNEL_EVENTS, MEDIASOUP_EVENTS, PEER_EVENTS,
4
- } from '../constants/events';
5
- import EnhancedEventEmitter from '../EnhancedEventEmitter';
6
- import OperationError from '../errors/OperationError';
7
- import validateAppData from '../helpers/appDataValidator';
8
- import { logResponse } from '../helpers/peer';
9
- import {
10
- type ChangePreferredLayersPayload, type PayloadOfPublishedMedia,
11
- type PayloadOfUnpublishedMedia, type PeerGroup, type PeerInfo, type PeerShortData, type ProducerData,
12
- type ProducerSetMaxSpatialLayer, type Role, type SubscribeOptions, TrackLabel, type TrackLabelString,
13
- } from '../types/common';
14
- import type { PeerConsumerFactory } from '../types/container';
15
- import type { GroupsChangedPayload, ProducePermissionsChangedPayload } from '../types/engine';
16
- import type { CallState } from './CallState';
17
- import type Logger from './Logger';
18
- import type Media from './media';
19
- import type PeerTrack from './media/tracks/PeerTrack';
20
- import type { MyPeer } from './MyPeer';
21
- import type Network from './network';
22
- import type PeerConsumer from './PeerConsumer';
23
- import PeerProducer from './PeerProducer';
24
- import type { Peers } from './Peers';
25
- import type { RemotePeerTracks } from './RemotePeerTracks';
26
-
27
- export interface PeerDependencies {
28
- callState: CallState;
29
- loggerFactory: (namespace: string) => Logger;
30
- media: Media;
31
- myPeer: MyPeer;
32
- network: Network;
33
- peers: Peers;
34
- remotePeerTracks: RemotePeerTracks;
35
- peerConsumerFactory: PeerConsumerFactory;
36
- }
37
-
38
- interface PeerConstructor extends PeerDependencies {
39
- id: string;
40
- channelIds: string[];
41
- groups: PeerGroup[];
42
- producePermissions: TrackLabel[];
43
- appId: string;
44
- producers: ProducerData[];
45
- videoConsumer?: PeerConsumer;
46
- audioConsumer?: PeerConsumer;
47
- soundLevel?: number;
48
- loginDate: Date;
49
- uid?: string;
50
- appData?: Record<string, unknown>;
51
- role: Role;
52
- }
53
-
54
- export interface PeerObserverEvents {
55
- [PEER_EVENTS.mediaPublished]: [PayloadOfPublishedMedia];
56
- [PEER_EVENTS.appDataUpdated]: [Record<string, unknown>];
57
- [PEER_EVENTS.connectionQualityChanged]: [{ connectionQuality: number }];
58
- [PEER_EVENTS.publisherPaused]: [PayloadOfPublishedMedia];
59
- [PEER_EVENTS.publisherResumed]: [PayloadOfPublishedMedia];
60
- [PEER_EVENTS.mediaUnPublished]: [PayloadOfUnpublishedMedia];
61
- [PEER_EVENTS.trackStart]: [PeerTrack];
62
- [PEER_EVENTS.trackEnd]: [PeerTrack];
63
- [PEER_EVENTS.trackResumed]: [PeerTrack];
64
- [PEER_EVENTS.trackPaused]: [PeerTrack];
65
- [PEER_EVENTS.trackFailed]: [PeerTrack];
66
- [PEER_EVENTS.producePermissionsChanged]: [ProducePermissionsChangedPayload];
67
- [PEER_EVENTS.groupsChanged]: [GroupsChangedPayload];
68
- [MEDIASOUP_EVENTS.producerClose]: [ProducerData];
69
- [MEDIASOUP_EVENTS.newProducer]: [ProducerData];
70
- [MEDIASOUP_EVENTS.closeConsumer]: [consumerId: string];
71
- [MEDIASOUP_EVENTS.pauseConsumer]: [consumerId: string];
72
- [MEDIASOUP_EVENTS.resumeConsumer]: [consumerId: string];
73
- [MEDIASOUP_EVENTS.consumerChangePreferredLayers]: [ChangePreferredLayersPayload];
74
- [MEDIASOUP_EVENTS.producerSetMaxSpatialLayer]: [ProducerSetMaxSpatialLayer];
75
- [CHANNEL_EVENTS.updatePeerAppData]: [Record<string, unknown>];
76
- [event: string]: unknown[];
77
- }
78
-
79
- class Peer {
80
- public id: string;
81
-
82
- public channelIds: string[];
83
-
84
- public groups: PeerGroup[];
85
-
86
- public producePermissions: TrackLabel[];
87
-
88
- public appId: string;
89
-
90
- public loginDate: Date;
91
-
92
- public uid?: string;
93
-
94
- private applicationData: Record<string, unknown>;
95
-
96
- public role: Role;
97
-
98
- producers = new Map<string, PeerProducer>();
99
-
100
- public readonly tracks = new Map<string, PeerTrack>();
101
-
102
- readonly #peers: Peers;
103
-
104
- readonly #remotePeerTracks: RemotePeerTracks;
105
-
106
- readonly #network: Network;
107
-
108
- readonly #media: Media;
109
-
110
- readonly #myPeer: MyPeer;
111
-
112
- readonly #callState: CallState;
113
-
114
- readonly #peerConsumerFactory: PeerConsumerFactory;
115
-
116
- readonly #logger: Logger;
117
-
118
- private readonly _observer = new EnhancedEventEmitter<PeerObserverEvents>();
119
-
120
- constructor({
121
- id,
122
- channelIds,
123
- groups,
124
- producePermissions,
125
- appId,
126
- loginDate,
127
- producers = [],
128
- appData,
129
- uid,
130
- role,
131
- loggerFactory,
132
- myPeer,
133
- callState,
134
- peers,
135
- remotePeerTracks,
136
- media,
137
- network,
138
- peerConsumerFactory,
139
- }: PeerConstructor) {
140
- this.id = id;
141
- this.channelIds = channelIds;
142
- this.groups = groups;
143
- this.producePermissions = producePermissions;
144
- this.appId = appId;
145
- this.loginDate = loginDate;
146
- this.applicationData = appData ?? {};
147
- this.uid = uid;
148
- this.role = role;
149
- this.#myPeer = myPeer;
150
- this.#callState = callState;
151
- this.#peers = peers;
152
- this.#remotePeerTracks = remotePeerTracks;
153
- this.#peerConsumerFactory = peerConsumerFactory;
154
- this.#network = network;
155
- this.#media = media;
156
- this.#logger = loggerFactory('Peer');
157
- producers.forEach(this.handleNewProducer.bind(this));
158
- this.handlePeerEvents();
159
- }
160
-
161
- get appData(): Record<string, unknown> {
162
- return this.applicationData;
163
- }
164
-
165
- get observer(): EnhancedEventEmitter<PeerObserverEvents> {
166
- return this._observer;
167
- }
168
-
169
- public get isMe(): boolean {
170
- return this.id === this.#myPeer.id;
171
- }
172
-
173
- public get isModerator(): boolean {
174
- return this.groups.includes('moderator');
175
- }
176
-
177
- public get isUser(): boolean {
178
- return this.groups.includes('user');
179
- }
180
-
181
- public get publishedMedia(): PayloadOfPublishedMedia[] {
182
- return Array.from(this.producers.values()).map((producer) => ({
183
- producerId: producer.id,
184
- kind: producer.kind,
185
- label: producer.label,
186
- paused: producer.paused,
187
- }));
188
- }
189
-
190
- get shortData(): PeerShortData {
191
- return {
192
- id: this.id,
193
- producers: Array.from(this.producers.values()).map((producer) => ({
194
- id: producer.id,
195
- paused: producer.paused,
196
- })),
197
- appData: this.appData,
198
- };
199
- }
200
-
201
- public hasPermission(producePermission: TrackLabel): boolean {
202
- return this.producePermissions.includes(producePermission);
203
- }
204
-
205
- public hasGroup(group: PeerGroup): boolean {
206
- return this.groups.includes(group);
207
- }
208
-
209
- public async subscribe({ producerId, muted = false }: SubscribeOptions): Promise<void> {
210
- try {
211
- const producer = this.producers.get(producerId);
212
-
213
- if (!producer) {
214
- this.#logger.warn('subscribe()',
215
- { message: 'Peer does not have a producer', peer: logResponse(this), producerId });
216
-
217
- return;
218
- }
219
-
220
- const peerConsumer = this.getAllConsumers().find((item) => item.producerId === producerId);
221
-
222
- if (peerConsumer) {
223
- this.#logger.debug('subscribe()',
224
- { message: 'Already subscribed to producer', peer: logResponse(this), producerId });
225
-
226
- return;
227
- }
228
-
229
- const { consumer, isProducerPaused } = await this.#network.createConsumer({
230
- producerId: producer.id,
231
- rtpCapabilities: this.#media.mediasoupDevice.rtpCapabilities,
232
- producerPeerId: this.id,
233
- appId: this.#callState.appId,
234
- channelId: this.#callState.channelId,
235
- });
236
-
237
- // it happens when moderator removes permissions for a track during the creating of a consumer
238
- if (!this.producePermissions.includes(producer.label) && Object.values(TrackLabel).includes(producer.label)) {
239
- this.#logger.debug('subscribe()',
240
- { message: 'Producer is not allowed anymore', peer: logResponse(this), producerId });
241
-
242
- return;
243
- }
244
-
245
- const track = this.#remotePeerTracks.create({
246
- mediaStreamTrack: consumer.track,
247
- label: producer.label,
248
- consumer: this.#peerConsumerFactory({
249
- consumer,
250
- }),
251
- muted,
252
- paused: isProducerPaused,
253
- peerEventEmitter: this.observer,
254
- });
255
-
256
- if (!muted) {
257
- await track.unmute();
258
- }
259
-
260
- this.tracks.set(track.label, track);
261
- this.#logger.debug(`Subscribed for ${ producer.kind }`, { peer: logResponse(this) });
262
- } catch (error) {
263
- this.#logger.error('subscribe()', { producerId, error, peer: logResponse(this) });
264
- throw new OperationError('peer_subscribe_failed', error);
265
- }
266
- }
267
-
268
- public async unsubscribe(producerId: string): Promise<void> {
269
- try {
270
- const consumer = this.getConsumerByProducerId(producerId);
271
-
272
- if (!consumer) {
273
- return;
274
- }
275
-
276
- const track = this.getTrackByConsumerId(consumer.id);
277
-
278
- if (!track) {
279
- return;
280
- }
281
-
282
- await track.close();
283
- this.tracks.delete(track.label);
284
- this.#logger.debug(`Unsubscribed consumer ${ consumer.kind }`, { peer: logResponse(this) });
285
- } catch (error) {
286
- this.#logger.error('unsubscribe()', { producerId, error });
287
- throw new OperationError('peer_unsubscribe_failed', error);
288
- }
289
- }
290
-
291
- public async setProducePermissions(producePermissions: TrackLabelString[]): Promise<void> {
292
- this.throwIfIamNotModerator();
293
-
294
- try {
295
- await this.#network.changePeerProducePermissions(this.id, producePermissions);
296
- } catch (error) {
297
- throw new OperationError('peer_set_produce_permissions_failed', error);
298
- }
299
-
300
- this.#logger.debug('Produce permissions changed', { peerId: this.id, producePermissions });
301
- }
302
-
303
- public async addProducePermission(label: TrackLabelString): Promise<void> {
304
- this.throwIfIamNotModerator();
305
-
306
- try {
307
- await this.#network.addPeerProducePermission(this.id, label);
308
- } catch (error) {
309
- throw new OperationError('peer_add_produce_permission_failed', error);
310
- }
311
-
312
- this.#logger.debug('Add produce permission requested', { peerId: this.id, label });
313
- }
314
-
315
- public async removeProducePermission(label: TrackLabelString): Promise<void> {
316
- this.throwIfIamNotModerator();
317
-
318
- try {
319
- await this.#network.removePeerProducePermission(this.id, label);
320
- } catch (error) {
321
- throw new OperationError('peer_remove_produce_permission_failed', error);
322
- }
323
-
324
- this.#logger.debug('Remove produce permission requested', { peerId: this.id, label });
325
- }
326
-
327
- async getInfo(): Promise<PeerInfo> {
328
- try {
329
- return {
330
- id: this.id,
331
- appData: this.appData,
332
- role: this.role,
333
- channelIds: this.channelIds,
334
- appId: this.appId,
335
- uid: this.uid,
336
- loginDate: this.loginDate,
337
- tracks: await Promise.all(Array.from(this.tracks.values()).map(async (track) => await track.getInfo())),
338
- };
339
- } catch (error) {
340
- this.#logger.error('getInfo()', { peer: logResponse(this), error });
341
- throw new OperationError('peer_get_info_failed', error);
342
- }
343
- }
344
-
345
- getProducers(): PeerProducer[] {
346
- return Array.from(this.producers.values());
347
- }
348
-
349
- getConsumersState(): Array<{ id: string; producerId: string; paused: boolean }> {
350
- return this.getAllConsumers().map((consumer) => ({
351
- id: consumer.id,
352
- paused: consumer.paused,
353
- producerId: consumer.producerId,
354
- }));
355
- }
356
-
357
- private handleNewProducer(producerData: ProducerData): void {
358
- if (this.producers.get(producerData.id)) {
359
- return;
360
- }
361
-
362
- const producer = new PeerProducer(producerData);
363
- this.producers.set(producer.id, producer);
364
- this.#logger.debug('Peer published media:', { peer: logResponse(this), producer });
365
- const payload: PayloadOfPublishedMedia = {
366
- producerId: producer.id,
367
- kind: producer.kind,
368
- label: producer.label,
369
- paused: producer.paused,
370
- };
371
- this.observer.safeEmit(PEER_EVENTS.mediaPublished, payload);
372
- }
373
-
374
- private handlePeerEvents(): void {
375
- this.observer.on(MEDIASOUP_EVENTS.newProducer, this.handleNewProducer.bind(this));
376
-
377
- this.observer.on(MEDIASOUP_EVENTS.producerClose, async (producer: ProducerData): Promise<void> => {
378
- this.producers.delete(producer.id);
379
- this.#logger.debug('Peer unpublished media:', { peer: logResponse(this), producer });
380
- this.observer.safeEmit(PEER_EVENTS.mediaUnPublished, {
381
- producerId: producer.id,
382
- kind: producer.kind,
383
- label: producer.label,
384
- paused: producer.paused,
385
- });
386
-
387
- const track = this.tracks.get(producer.label);
388
-
389
- if (!track) {
390
- return;
391
- }
392
-
393
- try {
394
- await track.close();
395
- } catch (error) {
396
- this.#logger.warn('Failed to close peer track due to producer closed', {
397
- label: track.label,
398
- peerId: this.id,
399
- error: serializeError(error),
400
- });
401
- }
402
- });
403
-
404
- this.observer.on(MEDIASOUP_EVENTS.closeConsumer, async (consumerId): Promise<void> => {
405
- const track = this.getTrackByConsumerId(consumerId);
406
-
407
- if (!track) {
408
- return;
409
- }
410
-
411
- await track.close();
412
- this.tracks.delete(track.label);
413
- this.#logger.debug('Peer video track was ended:', { peer: logResponse(this), track: track.logCtx });
414
- });
415
-
416
- this.observer.on(MEDIASOUP_EVENTS.pauseConsumer, async (consumerId): Promise<void> => {
417
- const track = this.getTrackByConsumerId(consumerId);
418
-
419
- if (!track) {
420
- return;
421
- }
422
-
423
- await track.pause(false);
424
- });
425
-
426
- this.observer.on(MEDIASOUP_EVENTS.resumeConsumer, async (consumerId): Promise<void> => {
427
- const track = this.getTrackByConsumerId(consumerId);
428
-
429
- if (!track) {
430
- return;
431
- }
432
-
433
- await track.resume(false);
434
- });
435
-
436
- this.observer.on(MEDIASOUP_EVENTS.consumerChangePreferredLayers, (payload: ChangePreferredLayersPayload): void => {
437
- const consumer = this.getConsumerById(payload.consumerId);
438
-
439
- if (consumer?.isVideo) {
440
- consumer.applyLayersUpdate({
441
- spatialLayer: payload.spatialLayer,
442
- temporalLayer: payload.temporalLayer,
443
- });
444
-
445
- if (payload.spatialLayer === consumer.requestedSpatialLayer) {
446
- consumer.setRequestedSpatialLayer(undefined);
447
- }
448
-
449
- this.#logger.debug('consumerChangePreferredLayers()', { ...payload });
450
- }
451
- });
452
-
453
- this.observer.on(MEDIASOUP_EVENTS.producerSetMaxSpatialLayer, async (
454
- payload: ProducerSetMaxSpatialLayer,
455
- ): Promise<void> => {
456
- const { producerId, spatialLayer } = payload;
457
- const consumer = this.getConsumerByProducerId(producerId);
458
-
459
- if (!consumer) {
460
- this.#logger.debug('producerSetMaxSpatialLayer()', {
461
- message: 'Consumer for producer not created, ignore MaxSpatialLayer change',
462
- });
463
-
464
- return;
465
- }
466
-
467
- consumer.setCurrentMaxSpatialLayer(spatialLayer);
468
- this.#logger.debug('producerSetMaxSpatialLayer()', {
469
- producerId,
470
- consumerId: consumer.id,
471
- spatialLayer,
472
- });
473
-
474
- if (consumer.requestedSpatialLayer !== spatialLayer) {
475
- this.#logger.debug('producerSetMaxSpatialLayer()', {
476
- message: 'No need to request new preferred layer',
477
- currentMaxSpatialLayer: spatialLayer,
478
- requestedMaxSpatialLayer: consumer.requestedSpatialLayer,
479
- });
480
-
481
- return;
482
- }
483
-
484
- await this.#network.updateConsumerPreferredLayers(consumer.id, spatialLayer);
485
-
486
- this.#logger.debug('requestVideoPreferredLayers()', {
487
- producerId,
488
- consumerId: consumer.id,
489
- spatialLayer,
490
- });
491
- });
492
-
493
- this.observer.on(CHANNEL_EVENTS.updatePeerAppData, (appData: Record<string, unknown>): void => {
494
- try {
495
- validateAppData(appData);
496
- this.setAppData(appData);
497
- this.observer.emit(PEER_EVENTS.appDataUpdated, appData);
498
- this.#logger.debug('updatePeerAppData', { peer: logResponse(this), appData });
499
- } catch (error) {
500
- this.#logger.error('updatePeerAppData', { peer: logResponse(this), appData, error });
501
- }
502
- });
503
- }
504
-
505
- async reset(): Promise<void> {
506
- this.producers.clear();
507
-
508
- await Promise.all(Array.from(this.tracks.values()).map(async (track): Promise<void> => await track.close()));
509
- this.tracks.clear();
510
-
511
- const eventNames = [
512
- MEDIASOUP_EVENTS.newProducer,
513
- MEDIASOUP_EVENTS.producerClose,
514
- MEDIASOUP_EVENTS.closeConsumer,
515
- MEDIASOUP_EVENTS.pauseConsumer,
516
- MEDIASOUP_EVENTS.resumeConsumer,
517
- MEDIASOUP_EVENTS.consumerChangePreferredLayers,
518
- MEDIASOUP_EVENTS.producerSetMaxSpatialLayer,
519
- CHANNEL_EVENTS.updatePeerAppData,
520
- ];
521
-
522
- eventNames.forEach((x): EnhancedEventEmitter<PeerObserverEvents> => this.observer.removeAllListeners(x));
523
- }
524
-
525
- getActiveTracksCount(): number {
526
- return Array.from(this.tracks.values())
527
- .map((track) => track.consumer)
528
- .filter((consumer) => !consumer?.paused)
529
- .length;
530
- }
531
-
532
- getActivePublishersCount(): number {
533
- return Array.from(this.producers.values())
534
- .filter((producer) => !producer.paused)
535
- .length;
536
- }
537
-
538
- handleProducePermissionsChange(producePermissions: TrackLabel[]): void {
539
- this.producePermissions = producePermissions;
540
-
541
- // close tracks that are no longer allowed
542
- Object.values(TrackLabel)
543
- .filter((label) => !this.producePermissions.includes(label))
544
- .forEach((label) => {
545
- const track = this.tracks.get(label);
546
-
547
- if (track) {
548
- this.tracks.delete(track.label);
549
- track.close().catch((error: unknown) => {
550
- this.#logger.error('Failed to close track', {
551
- case: 'Peer',
552
- error: serializeError(error),
553
- });
554
- });
555
- }
556
- });
557
-
558
- // notify about changes in permissions
559
- this.observer.safeEmit(PEER_EVENTS.producePermissionsChanged, {
560
- labels: this.producePermissions,
561
- });
562
- }
563
-
564
- handleGroupsChange(groups: PeerGroup[]): void {
565
- this.groups = groups;
566
- this.observer.safeEmit(PEER_EVENTS.groupsChanged, { groups });
567
- }
568
-
569
- private getAllConsumers(): PeerConsumer[] {
570
- return Array.from(this.tracks.values())
571
- .map((track) => track.consumer)
572
- .filter((item): item is PeerConsumer => !!item);
573
- }
574
-
575
- private getConsumerByProducerId(producerId: string): PeerConsumer | undefined {
576
- return this.getAllConsumers().find((consumer) => consumer.producerId === producerId);
577
- }
578
-
579
- private getConsumerById(id: string): PeerConsumer | undefined {
580
- return this.getAllConsumers().find((consumer) => consumer.id === id);
581
- }
582
-
583
- private getTrackByConsumerId(id: string): PeerTrack | undefined {
584
- return Array.from(this.tracks.values()).find((track) => track.consumerId === id);
585
- }
586
-
587
- private setAppData(appData: Record<string, unknown>): void {
588
- this.applicationData = appData;
589
- }
590
-
591
- private throwIfIamNotModerator(): void {
592
- const isIamModerator = this.#peers.isModerator(this.#myPeer.id);
593
-
594
- if (isIamModerator) {
595
- return;
596
- }
597
-
598
- throw new OperationError('not_enough_access', new Error('Not enough access'));
599
- }
600
- }
601
-
602
- export default Peer;