@livedigital/client 3.48.0 → 3.49.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 (165) hide show
  1. package/dist/constants/encodings.d.ts +3 -3
  2. package/dist/constants/encodings.ts +3 -3
  3. package/dist/engine/handlers/ChannelAudioObserverEventHandler.d.ts +3 -1
  4. package/dist/engine/handlers/ChannelAudioObserverMissingProducerRestorer.d.ts +10 -0
  5. package/dist/engine/handlers/MediaEventHandler.d.ts +0 -1
  6. package/dist/engine/index.d.ts +7 -4
  7. package/dist/engine/network/DatachannelHeartbeater.d.ts +2 -2
  8. package/dist/engine/network/NetworkTransportPolicyManager.d.ts +22 -0
  9. package/dist/engine/network/index.d.ts +10 -8
  10. package/dist/index.d.ts +2 -0
  11. package/dist/index.es.js +2 -2
  12. package/dist/index.js +2 -2
  13. package/dist/inversify.tokens.d.ts +3 -1
  14. package/dist/types/network.d.ts +6 -6
  15. package/package.json +2 -3
  16. package/src/ClientMetaProvider.ts +0 -41
  17. package/src/EnhancedEventEmitter.ts +0 -75
  18. package/src/config/ConfigService.ts +0 -66
  19. package/src/constants/common.ts +0 -85
  20. package/src/constants/encodings.ts +0 -26
  21. package/src/constants/events.ts +0 -126
  22. package/src/constants/mutex.ts +0 -6
  23. package/src/constants/stats.ts +0 -1
  24. package/src/constants/videoConstrains.ts +0 -21
  25. package/src/engine/CallState.ts +0 -19
  26. package/src/engine/ChannelStateSynchronizer/ChannelStateSynchronizer.ts +0 -448
  27. package/src/engine/ChannelStateSynchronizer/types.ts +0 -22
  28. package/src/engine/EventsQueue.ts +0 -255
  29. package/src/engine/IntegrationsService.ts +0 -163
  30. package/src/engine/LocalMutex.ts +0 -45
  31. package/src/engine/Logger.ts +0 -234
  32. package/src/engine/MyPeer.ts +0 -25
  33. package/src/engine/Peer.ts +0 -602
  34. package/src/engine/PeerConsumer.ts +0 -276
  35. package/src/engine/PeerProducer.ts +0 -50
  36. package/src/engine/Peers.ts +0 -150
  37. package/src/engine/PeersStorage.ts +0 -45
  38. package/src/engine/RemotePeerTracks.ts +0 -73
  39. package/src/engine/WIDHandler.ts +0 -166
  40. package/src/engine/WebRTCStats/ConnectionStatsManager.ts +0 -31
  41. package/src/engine/WebRTCStats/InboundTrackStatsManager.ts +0 -51
  42. package/src/engine/WebRTCStats/OutboudTrackStatsManager.ts +0 -51
  43. package/src/engine/WebRTCStats/StatsHandler.ts +0 -80
  44. package/src/engine/WebRTCStats/TransportsStatsProvider.ts +0 -123
  45. package/src/engine/WebRTCStats/types.ts +0 -20
  46. package/src/engine/analyticsApiClient/LogApi.ts +0 -24
  47. package/src/engine/analyticsApiClient/MetricsApi.ts +0 -30
  48. package/src/engine/analyticsApiClient/helper.ts +0 -88
  49. package/src/engine/analyticsApiClient/index.ts +0 -42
  50. package/src/engine/analyticsApiClient/types.ts +0 -33
  51. package/src/engine/handlers/ChannelAudioObserverEventHandler.ts +0 -177
  52. package/src/engine/handlers/ChannelEventHandler.ts +0 -268
  53. package/src/engine/handlers/ChannelStateSyncEventHandler/ChannelStateConsistencyCheckResult.ts +0 -31
  54. package/src/engine/handlers/ChannelStateSyncEventHandler/ChannelStateConsistencyChecker.ts +0 -146
  55. package/src/engine/handlers/ChannelStateSyncEventHandler/consts.ts +0 -7
  56. package/src/engine/handlers/ChannelStateSyncEventHandler/index.ts +0 -342
  57. package/src/engine/handlers/ChannelStateSyncEventHandler/types.ts +0 -21
  58. package/src/engine/handlers/MediaEventHandler.ts +0 -273
  59. package/src/engine/index.ts +0 -793
  60. package/src/engine/media/index.ts +0 -574
  61. package/src/engine/media/producer/PendingClosureProducerStorage.ts +0 -37
  62. package/src/engine/media/producer/ProducerCloseManager.ts +0 -115
  63. package/src/engine/media/streamEffects/ProcessorsCache.ts +0 -41
  64. package/src/engine/media/streamEffects/audio/AudioTrackProcessor.ts +0 -7
  65. package/src/engine/media/streamEffects/audio/asdk/ASDKTrackProcessor.ts +0 -275
  66. package/src/engine/media/streamEffects/audio/asdk/atsrb.d.ts +0 -36
  67. package/src/engine/media/streamEffects/audio/asdk/errorBus.d.ts +0 -47
  68. package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionAudioWorkletNode.ts +0 -35
  69. package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionNodeProvider.ts +0 -44
  70. package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionScriptProcessorNode.ts +0 -69
  71. package/src/engine/media/streamEffects/audio/noiseSuppression/RNNoiseTrackProcessor.ts +0 -134
  72. package/src/engine/media/streamEffects/audio/noiseSuppression/WasmModuleCompiler.ts +0 -9
  73. package/src/engine/media/streamEffects/video/esdk/TrackProcessor.ts +0 -386
  74. package/src/engine/media/streamEffects/video/esdk/components/component.d.ts +0 -35
  75. package/src/engine/media/streamEffects/video/esdk/components/countdown/countdown.d.ts +0 -27
  76. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/doubleSlideRect.d.ts +0 -33
  77. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/horizontalMirror.d.ts +0 -29
  78. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/leftTextbox.d.ts +0 -31
  79. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/slideBold.d.ts +0 -41
  80. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/twoSideRects/animatedBox.d.ts +0 -59
  81. package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/twoSideRects/twoSlideRects.d.ts +0 -27
  82. package/src/engine/media/streamEffects/video/esdk/components/lower-third/lowerThird.d.ts +0 -83
  83. package/src/engine/media/streamEffects/video/esdk/components/overlay-screen/overlayScreen.d.ts +0 -40
  84. package/src/engine/media/streamEffects/video/esdk/components/overlay-screen/overlaySprite.d.ts +0 -10
  85. package/src/engine/media/streamEffects/video/esdk/components/stickers/stickerSprite.d.ts +0 -51
  86. package/src/engine/media/streamEffects/video/esdk/components/stickers/stickers.d.ts +0 -54
  87. package/src/engine/media/streamEffects/video/esdk/components/utils/positionHelper.d.ts +0 -14
  88. package/src/engine/media/streamEffects/video/esdk/components/waterMark/waterMark.d.ts +0 -20
  89. package/src/engine/media/streamEffects/video/esdk/tsvb.d.ts +0 -187
  90. package/src/engine/media/streamEffects/video/esdk/utils/errorBus.d.ts +0 -42
  91. package/src/engine/media/tracks/DefaultAudioTrack.ts +0 -178
  92. package/src/engine/media/tracks/DefaultBaseTrack.ts +0 -592
  93. package/src/engine/media/tracks/DefaultVideoTrack.ts +0 -301
  94. package/src/engine/media/tracks/MediaStreamTrackManager.ts +0 -50
  95. package/src/engine/media/tracks/PeerTrack.ts +0 -558
  96. package/src/engine/network/DataChannelsManager.ts +0 -164
  97. package/src/engine/network/DatachannelHeartbeater.ts +0 -122
  98. package/src/engine/network/SignalingHeartbeater.ts +0 -55
  99. package/src/engine/network/index.ts +0 -961
  100. package/src/engine/signalingApiClient/SignalingApiClient.ts +0 -95
  101. package/src/engine/signalingApiClient/api.ts +0 -2289
  102. package/src/engine/system/index.ts +0 -221
  103. package/src/errors/AlreadyConnectedError.ts +0 -11
  104. package/src/errors/AlreadyCreatedError.ts +0 -11
  105. package/src/errors/ForbiddenError.ts +0 -11
  106. package/src/errors/InvalidPayloadError.ts +0 -11
  107. package/src/errors/InvalidRequestError.ts +0 -11
  108. package/src/errors/LivedigitalSDKError.ts +0 -15
  109. package/src/errors/NeedJoinFirstError.ts +0 -11
  110. package/src/errors/NotFoundError.ts +0 -11
  111. package/src/errors/OperationError.ts +0 -47
  112. package/src/errors/RequestError.ts +0 -11
  113. package/src/errors/TimeoutError.ts +0 -11
  114. package/src/errors/TooManyRequestsError.ts +0 -11
  115. package/src/errors/UnauthorizedError.ts +0 -11
  116. package/src/errors/UnsupportedError.ts +0 -15
  117. package/src/errors/signalingApiErrorMapper.ts +0 -143
  118. package/src/helpers/appDataValidator.ts +0 -21
  119. package/src/helpers/browser.ts +0 -37
  120. package/src/helpers/channelMessageConverter.ts +0 -124
  121. package/src/helpers/common.ts +0 -96
  122. package/src/helpers/datetime.ts +0 -11
  123. package/src/helpers/errors.ts +0 -25
  124. package/src/helpers/filterStatsCodecs.ts +0 -3
  125. package/src/helpers/loader.ts +0 -59
  126. package/src/helpers/media.ts +0 -57
  127. package/src/helpers/peer.ts +0 -19
  128. package/src/helpers/randomString.ts +0 -18
  129. package/src/helpers/retry.ts +0 -74
  130. package/src/index.ts +0 -171
  131. package/src/inversify.config.ts +0 -333
  132. package/src/inversify.factories.ts +0 -191
  133. package/src/inversify.tokens.ts +0 -42
  134. package/src/proto/.gitkeep +0 -0
  135. package/src/proto/generated/channel/channel_activity_confirmation_time.ts +0 -110
  136. package/src/proto/generated/channel/channel_management_event.ts +0 -213
  137. package/src/proto/generated/channel/channel_produce_permissions.ts +0 -171
  138. package/src/proto/generated/channel/channel_state.ts +0 -94
  139. package/src/proto/generated/channel/channel_state_short.ts +0 -282
  140. package/src/proto/generated/channel_message/channel_event.ts +0 -401
  141. package/src/proto/generated/channel_message/channel_message.ts +0 -139
  142. package/src/proto/generated/channel_message/media_event.ts +0 -290
  143. package/src/proto/generated/consumer/consumer.ts +0 -167
  144. package/src/proto/generated/google/protobuf/struct.ts +0 -588
  145. package/src/proto/generated/google/protobuf/timestamp.ts +0 -229
  146. package/src/proto/generated/peer/peer.ts +0 -430
  147. package/src/proto/generated/peer/peer_group.ts +0 -48
  148. package/src/proto/generated/peer/peer_role.ts +0 -48
  149. package/src/proto/generated/producer/producer.ts +0 -204
  150. package/src/proto/generated/producer/producer_kind.ts +0 -48
  151. package/src/proto/generated/producer/producer_label.ts +0 -78
  152. package/src/proto/generated/producer/producer_spatial_layer_request.ts +0 -116
  153. package/src/proto/generated/transport/transport_connection_timeout.ts +0 -156
  154. package/src/proto/generated/transport/transport_connection_timeout_reason.ts +0 -48
  155. package/src/proto/generated/transport/transport_direction.ts +0 -48
  156. package/src/types/channelAudioObserver.ts +0 -34
  157. package/src/types/channelStateSyncronizer.ts +0 -22
  158. package/src/types/client.ts +0 -27
  159. package/src/types/common.ts +0 -399
  160. package/src/types/container.ts +0 -31
  161. package/src/types/engine.ts +0 -97
  162. package/src/types/media.ts +0 -146
  163. package/src/types/mediasoup.ts +0 -10
  164. package/src/types/network.ts +0 -10
  165. package/src/types/streamEffects.ts +0 -23
@@ -1,255 +0,0 @@
1
- import { inject, injectable } from 'inversify';
2
- import { DataConsumer } from 'mediasoup-client/lib/DataConsumer';
3
- import { serializeError } from 'serialize-error';
4
- import { Logger } from '../types/common';
5
- import { TOKEN } from '../inversify.tokens';
6
- import { ChannelMessage } from '../proto/generated/channel_message/channel_message';
7
- import { ChannelEvent, channelEventTypeToJSON } from '../proto/generated/channel_message/channel_event';
8
- import { MediaEvent, mediaEventTypeToJSON } from '../proto/generated/channel_message/media_event';
9
-
10
- interface PendingMessage {
11
- total: number;
12
- received: Uint8Array[];
13
- msgId: number;
14
- }
15
-
16
- const CHUNK_HEADER_SIZE = 12;
17
- const CHUNK_HEADER_MSG_ID_OFFSET = 0;
18
- const CHUNK_HEADER_INDEX_OFFSET = 4;
19
- const CHUNK_HEADER_TOTAL_OFFSET = 8;
20
-
21
- @injectable()
22
- export default class EventsQueue {
23
- readonly #queue: ChannelMessage[] = [];
24
-
25
- #paused = false;
26
-
27
- #processing = false;
28
-
29
- #mediaEventHandler?: (event: MediaEvent) => void | Promise<void>;
30
-
31
- #channelEventHandler?: (event: ChannelEvent) => void | Promise<void>;
32
-
33
- readonly #pendingMessagesBuffer = new Map<number, PendingMessage>();
34
- readonly #logger: Logger;
35
-
36
- #processedMessageIds: Set<number> = new Set<number>();
37
-
38
- constructor(@inject(TOKEN.LoggerFactory) loggerFactory: (namespace: string) => Logger) {
39
- this.#logger = loggerFactory('EventsQueue');
40
- }
41
-
42
- setMediaEventHandler(handler: (event: MediaEvent) => void | Promise<void>): void {
43
- this.#mediaEventHandler = handler;
44
- this.#logger.info('Media event handler set', {
45
- case: 'EventsQueue',
46
- });
47
- }
48
-
49
- setChannelEventHandler(handler: (event: ChannelEvent) => void | Promise<void>): void {
50
- this.#channelEventHandler = handler;
51
- this.#logger.info('Channel event handler set', {
52
- case: 'EventsQueue',
53
- });
54
- }
55
-
56
- subscribe(dataChannel: DataConsumer): void {
57
- this.#processedMessageIds = new Set<number>();
58
- let lastReceivedMsgId = 0;
59
-
60
- const onMessage = (raw: ArrayBuffer): void => {
61
- try {
62
- const pendingMessage = this.processMessageChunk(raw);
63
-
64
- if (!pendingMessage || !this.isPendingMessageFullyReceived(pendingMessage)) {
65
- return;
66
- }
67
-
68
- const fullBytes = this.finalizeMessageBytes(pendingMessage);
69
- const message = ChannelMessage.decode(fullBytes);
70
-
71
- if (message.id) {
72
- if (this.#processedMessageIds.has(message.id)) {
73
- this.#logger.warn('Received duplicate message', {
74
- case: 'EventsQueue',
75
- lastReceivedMsgId,
76
- currentReceivedMsgId: message.id,
77
- });
78
- }
79
-
80
- if (message.id > lastReceivedMsgId + 1) {
81
- this.#logger.warn('Received out of order message', {
82
- case: 'EventsQueue',
83
- lastReceivedMsgId,
84
- currentReceivedMsgId: message.id,
85
- });
86
- }
87
- }
88
-
89
- this.#processedMessageIds.add(message.id);
90
- lastReceivedMsgId = message.id;
91
- this.push(message);
92
- } catch (e) {
93
- this.#logger.error('Failed to parse channel message', {
94
- error: serializeError(e),
95
- case: 'EventsQueue',
96
- });
97
- }
98
- };
99
-
100
- const onClose = (): void => {
101
- dataChannel.removeListener('message', onMessage);
102
- dataChannel.removeListener('close', onClose);
103
- };
104
-
105
- dataChannel.on('close', onClose);
106
- dataChannel.on('message', onMessage);
107
-
108
- this.#logger.info('Subscribed to data channel', {
109
- case: 'EventsQueue',
110
- });
111
- }
112
-
113
- private push(message: ChannelMessage): void {
114
- this.#queue.push(message);
115
- void this.process();
116
- }
117
-
118
- private async process(): Promise<void> {
119
- if (this.#paused || this.#processing) {
120
- return;
121
- }
122
-
123
- this.#processing = true;
124
-
125
- while (!this.#paused && this.#queue.length > 0) {
126
- const message = this.#queue.shift();
127
-
128
- if (!message) {
129
- continue;
130
- }
131
-
132
- try {
133
- if (message.channelEvent && this.#channelEventHandler) {
134
- this.#logger.debug('Handle channel event', {
135
- case: 'EventsQueue',
136
- id: message.id,
137
- type: channelEventTypeToJSON(message.channelEvent.eventType),
138
- event: message.channelEvent,
139
- });
140
-
141
- await this.#channelEventHandler(message.channelEvent);
142
- continue;
143
- }
144
-
145
- if (message.mediaEvent && this.#mediaEventHandler) {
146
- this.#logger.debug('Handle media event', {
147
- case: 'EventsQueue',
148
- id: message.id,
149
- type: mediaEventTypeToJSON(message.mediaEvent.eventType),
150
- event: message.mediaEvent,
151
- });
152
-
153
- await this.#mediaEventHandler(message.mediaEvent);
154
- continue;
155
- }
156
-
157
- this.#logger.warn('Received unknown message', { message, case: 'EventsQueue' });
158
- } catch (error) {
159
- this.#logger.error('Failed to handle event', {
160
- case: 'EventsQueue',
161
- id: message.id,
162
- error: serializeError(error),
163
- });
164
- }
165
- }
166
-
167
- this.#processing = false;
168
-
169
- // If new events were pushed during processing, process again
170
- if (!this.#paused && this.#queue.length > 0) {
171
- queueMicrotask(() => void this.process());
172
- }
173
- }
174
-
175
- private processMessageChunk(data: ArrayBuffer): PendingMessage | undefined {
176
- const bytes = new Uint8Array(data);
177
-
178
- if (bytes.length < CHUNK_HEADER_SIZE) {
179
- this.#logger.warn('Chunk too small', {
180
- case: 'EventsQueue',
181
- bytesLength: bytes.length,
182
- });
183
-
184
- return;
185
- }
186
-
187
- const { msgId, index, total } = this.parseMessageChunkHeader(bytes);
188
- const dataPart = bytes.slice(CHUNK_HEADER_SIZE);
189
-
190
- if (!this.#pendingMessagesBuffer.has(msgId)) {
191
- this.#pendingMessagesBuffer.set(msgId, { msgId, total, received: [] });
192
- }
193
-
194
- const entry: PendingMessage | undefined = this.#pendingMessagesBuffer.get(msgId);
195
-
196
- if (!entry) {
197
- this.#logger.warn('Chunk buffer entry not found for msgId', {
198
- msgId,
199
- case: 'EventsQueue',
200
- });
201
-
202
- return;
203
- }
204
-
205
- entry.received[index] = dataPart;
206
- entry.msgId = msgId;
207
-
208
- return entry;
209
- }
210
-
211
- private parseMessageChunkHeader(bytes: Uint8Array): { msgId: number; index: number; total: number } {
212
- const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
213
-
214
- return {
215
- msgId: view.getUint32(CHUNK_HEADER_MSG_ID_OFFSET),
216
- index: view.getUint32(CHUNK_HEADER_INDEX_OFFSET),
217
- total: view.getUint32(CHUNK_HEADER_TOTAL_OFFSET),
218
- };
219
- }
220
-
221
- private isPendingMessageFullyReceived(pendingMessage: PendingMessage): boolean {
222
- return pendingMessage.received.filter(Boolean).length === pendingMessage.total;
223
- }
224
-
225
- private finalizeMessageBytes(entry: PendingMessage): Uint8Array {
226
- const fullBytes = new Uint8Array(entry.received.reduce((sum, arr) => sum + arr.length, 0));
227
- let offset = 0;
228
-
229
- for (const chunk of entry.received) {
230
- fullBytes.set(chunk, offset);
231
- offset += chunk.length;
232
- }
233
-
234
- this.#pendingMessagesBuffer.delete(entry.msgId);
235
-
236
- return fullBytes;
237
- }
238
-
239
- pause(): void {
240
- this.#paused = true;
241
- }
242
-
243
- size(): number {
244
- return this.#queue.length;
245
- }
246
-
247
- resume(): void {
248
- this.#paused = false;
249
- void this.process();
250
- }
251
-
252
- isMessageReceived(messageId: number): boolean {
253
- return this.#processedMessageIds.has(messageId);
254
- }
255
- }
@@ -1,163 +0,0 @@
1
- import { inject, injectable } from 'inversify';
2
- import { URL } from 'url';
3
- import ConfigService from '../config/ConfigService';
4
- import { loadScriptWithFallback } from '../helpers/loader';
5
- import { TOKEN } from '../inversify.tokens';
6
- import { TrackLabel } from '../types/common';
7
- import type { AudioTrackProcessorFactory, LoggerFactory } from '../types/container';
8
- import Logger from './Logger';
9
- import { ASDKTrackProcessor } from './media/streamEffects/audio/asdk/ASDKTrackProcessor';
10
- import { compileWASMModule } from './media/streamEffects/audio/noiseSuppression/WasmModuleCompiler';
11
- import { ProcessorsCache } from './media/streamEffects/ProcessorsCache';
12
-
13
- export type Integrations = 'asdk' | 'rnnoise'; // later 'esdk' should be added
14
- export interface IntegrationContext {
15
- integrated: boolean;
16
- initPromise: Promise<void>;
17
- }
18
-
19
- export interface Integration {
20
- type: Integrations;
21
- enabled: boolean; // flag to show that integration is requested/enabled through ClientParams
22
- isInitialized: boolean;
23
- waitForInitialization: Promise<void>;
24
- }
25
-
26
- @injectable()
27
- export class IntegrationsService {
28
- readonly #integrationsStorage = new Map<Integrations, IntegrationContext>();
29
-
30
- readonly #logger: Logger;
31
-
32
- constructor(
33
- @inject(TOKEN.Config) private readonly config: ConfigService,
34
- @inject(TOKEN.ProcessorsCache) private readonly processorsCache: ProcessorsCache,
35
- @inject(TOKEN.AudioTrackProcessorFactory) private readonly audioTrackProcessorFactory: AudioTrackProcessorFactory,
36
- @inject(TOKEN.LoggerFactory) loggerFactory: LoggerFactory,
37
- ) {
38
- this.#logger = loggerFactory('IntegrationsService');
39
- }
40
-
41
- init(): void { // must not be async
42
- const denoiser = this.config.get('denoiser');
43
-
44
- if (denoiser === 'asdk') {
45
- this.#logger.info('Start integration of ASDK', {
46
- denoiser,
47
- });
48
-
49
- const context: IntegrationContext = {
50
- integrated: false,
51
- initPromise: this.integrateASDK(),
52
- };
53
-
54
- this.#integrationsStorage.set('asdk', context);
55
- } else {
56
- this.#logger.info('Start integration of RNNoise', {
57
- denoiser,
58
- });
59
-
60
- const context: IntegrationContext = {
61
- integrated: false,
62
- initPromise: this.integrateRNNoise(),
63
- };
64
-
65
- this.#integrationsStorage.set('rnnoise', context);
66
- }
67
- }
68
-
69
- private async integrateASDK(): Promise<void> {
70
- const asdkParams = this.config.get('asdk');
71
- const staticFilesPath = this.config.get('staticFilesPath');
72
-
73
- if (!window.atsvb) {
74
- const remoteUrl = `https://effectssdk.ai/sdk/audio/dev/${ asdkParams.version }/atsvb-web.js`;
75
- let localUrl = remoteUrl;
76
-
77
- if (asdkParams.localDir) {
78
- const localPath = `${ asdkParams.localDir }/${ asdkParams.version }/atsvb-web.js`;
79
- const url = new URL(localPath, staticFilesPath);
80
- localUrl = url.href;
81
- }
82
-
83
- await loadScriptWithFallback(localUrl, remoteUrl);
84
- }
85
-
86
- if (!window.atsvb) {
87
- this.#logger.info('Audio Effects SDK is not loaded, skipping initialization', { case: 'initAudioSDK' });
88
-
89
- throw new Error('windows.atsvb is still missing');
90
- }
91
-
92
- const processor = this.audioTrackProcessorFactory({
93
- trackLabel: TrackLabel.Microphone,
94
- }) as ASDKTrackProcessor;
95
-
96
- await processor.init();
97
-
98
- this.processorsCache.add('asdk', TrackLabel.Microphone, processor);
99
-
100
- const context = this.#integrationsStorage.get('asdk');
101
-
102
- if (!context) {
103
- throw Error('IntegrationContext is missing for ASDK');
104
- }
105
-
106
- context.integrated = true;
107
- }
108
-
109
- get audio(): Integration {
110
- const denoiser = this.config.get('denoiser');
111
-
112
- if (denoiser === 'asdk') {
113
- return this.getASDKState();
114
- }
115
-
116
- return this.getRNNoiseState();
117
- }
118
-
119
- private getASDKState(): Integration {
120
- const asdk = this.#integrationsStorage.get('asdk');
121
-
122
- return {
123
- type: 'asdk',
124
- enabled: Boolean(asdk),
125
- isInitialized: asdk?.integrated ?? false,
126
- waitForInitialization: asdk?.initPromise ?? Promise.resolve(),
127
- };
128
- }
129
-
130
- private getRNNoiseState(): Integration {
131
- const rnnoise = this.#integrationsStorage.get('rnnoise');
132
-
133
- return {
134
- type: 'rnnoise',
135
- enabled: Boolean(rnnoise),
136
- isInitialized: rnnoise?.integrated ?? false,
137
- waitForInitialization: rnnoise?.initPromise ?? Promise.resolve(),
138
- };
139
- }
140
-
141
- private async integrateRNNoise(): Promise<void> {
142
- const noiseSuppressor = await compileWASMModule(this.config.get('staticFilesPath'));
143
-
144
- const processor = this.audioTrackProcessorFactory({
145
- trackLabel: TrackLabel.Microphone,
146
- noiseSuppressor,
147
- });
148
-
149
- this.processorsCache.add('rnnoise', TrackLabel.Microphone, processor);
150
-
151
- const context = this.#integrationsStorage.get('rnnoise');
152
-
153
- if (!context) {
154
- throw Error('IntegrationContext is missing for RNNoise');
155
- }
156
-
157
- context.integrated = true;
158
- }
159
-
160
- reset(): void {
161
- this.#integrationsStorage.clear();
162
- }
163
- }
@@ -1,45 +0,0 @@
1
- import { Mutex } from 'async-mutex';
2
- import { injectable } from 'inversify';
3
- import { MutexKey } from '../constants/mutex';
4
-
5
- @injectable()
6
- export default class LocalMutex {
7
- readonly #mutexMap = new Map<MutexKey, Mutex>();
8
-
9
- async lock(key: MutexKey): Promise<() => void> {
10
- let mutex = this.#mutexMap.get(key);
11
-
12
- if (!mutex) {
13
- mutex = new Mutex();
14
- this.#mutexMap.set(key, mutex);
15
- }
16
-
17
- if (mutex.isLocked()) {
18
- await mutex.waitForUnlock();
19
- }
20
-
21
- return await mutex.acquire();
22
- }
23
-
24
- isLocked(key: MutexKey): boolean {
25
- const mutex = this.#mutexMap.get(key);
26
-
27
- if (mutex) {
28
- return mutex.isLocked();
29
- }
30
-
31
- return false;
32
- }
33
-
34
- async waitForUnlock(key: MutexKey): Promise<void> {
35
- const mutex = this.#mutexMap.get(key);
36
-
37
- if (mutex?.isLocked()) {
38
- await mutex.waitForUnlock();
39
-
40
- return;
41
- }
42
-
43
- await Promise.resolve();
44
- }
45
- }
@@ -1,234 +0,0 @@
1
- import debug from 'debug';
2
- import { MessageBatcher } from 'message-batcher';
3
- import { serializeError } from 'serialize-error';
4
- import clientMetaProvider from '../ClientMetaProvider';
5
- import { HALF_SECOND_IN_MS, LogLevels, SECOND_IN_MS } from '../constants/common';
6
- import { isObject } from '../helpers/common';
7
- import type { LogLevel, LogLevelStr, LogMessageHandler } from '../types/common';
8
- import AnalyticsApiClient from './analyticsApiClient';
9
- import { getClientUniqueId } from './analyticsApiClient/helper';
10
-
11
- const APP_NAME = 'LiveDigital';
12
- const BATCH_SIZE = 50;
13
-
14
- export interface RecordMeta {
15
- error?: unknown;
16
- clientTimestamp: string;
17
- from_sdk: boolean;
18
- case?: string;
19
- channelId?: string;
20
- applicationId?: string;
21
- peerId?: string;
22
- [key: string]: unknown;
23
- }
24
-
25
- export interface ClientMeta {
26
- clUId: string;
27
- peerId?: string;
28
- channelId?: string;
29
- appId?: string;
30
- [key: string]: unknown;
31
- }
32
-
33
- export interface LoggerParams {
34
- logLevel: LogLevel;
35
- onLogMessage?: LogMessageHandler;
36
- sendAnalytics: boolean;
37
- }
38
-
39
- export interface LoggerConstructorParams {
40
- namespace: string;
41
- logLevel: LogLevel;
42
- onLogMessage?: LogMessageHandler;
43
- sendAnalytics: boolean;
44
- }
45
-
46
- export type LogRecordMeta = Record<string, unknown> & {
47
- error?: unknown;
48
- case?: string;
49
- channelId?: string;
50
- applicationId?: string;
51
- peerId?: string;
52
- };
53
-
54
- export interface LogToRemotePayload {
55
- level: LogLevel;
56
- message: string;
57
- meta?: LogRecordMeta;
58
- }
59
-
60
- class Logger {
61
- private readonly _debug: debug.Debugger;
62
-
63
- private readonly _info: debug.Debugger;
64
-
65
- private readonly _warn: debug.Debugger;
66
-
67
- private readonly _error: debug.Debugger;
68
-
69
- readonly #namespace: string;
70
-
71
- readonly #logLevel: LogLevel;
72
-
73
- readonly onLogMessage?: LogMessageHandler;
74
-
75
- readonly #logToRemoteBatcher: MessageBatcher;
76
-
77
- readonly #analyticsApi: AnalyticsApiClient;
78
-
79
- readonly #sendAnalytics: boolean;
80
-
81
- constructor(params: LoggerConstructorParams) {
82
- const { logLevel, namespace, onLogMessage } = params;
83
- this.#namespace = namespace;
84
- this.#logLevel = logLevel;
85
- this.onLogMessage = onLogMessage;
86
- this.#analyticsApi = new AnalyticsApiClient();
87
- this.#logToRemoteBatcher = new MessageBatcher({
88
- MaxBatchSize: BATCH_SIZE,
89
- MaxDelay: SECOND_IN_MS,
90
- MinDelay: HALF_SECOND_IN_MS,
91
- });
92
- this.#sendAnalytics = params.sendAnalytics;
93
-
94
- this.#logToRemoteBatcher.on('batch', (logs: LogToRemotePayload[]) => {
95
- this.logToApi(logs).catch((error: unknown) => {
96
- this.error('Failed to log to api', {
97
- case: 'Logger',
98
- error: serializeError(error),
99
- });
100
- });
101
- });
102
-
103
- this._debug = debug(APP_NAME).extend('debug').extend(this.#namespace);
104
- this._info = debug(APP_NAME).extend('info').extend(this.#namespace);
105
- this._warn = debug(APP_NAME).extend('warn').extend(this.#namespace);
106
- this._error = debug(APP_NAME).extend('error').extend(this.#namespace);
107
-
108
- // eslint-disable-next-line no-console
109
- this._debug.log = console.info.bind(console);
110
- // eslint-disable-next-line no-console
111
- this._info.log = console.info.bind(console);
112
- this._warn.log = console.warn.bind(console);
113
- this._error.log = console.error.bind(console);
114
- }
115
-
116
- debug(message: string, meta: Record<string, unknown>): void {
117
- this._debug(message, meta);
118
-
119
- if (this.#sendAnalytics) {
120
- this.#logToRemoteBatcher.Queue({ level: 'debug', message, meta });
121
- }
122
-
123
- if (this.#logLevel >= LogLevels.Debug) {
124
- this.#log('debug', message, meta);
125
- }
126
- }
127
-
128
- info(message: string, meta: Record<string, unknown>): void {
129
- this._info(message, meta);
130
-
131
- if (this.#sendAnalytics) {
132
- this.#logToRemoteBatcher.Queue({ level: 'info', message, meta });
133
- }
134
-
135
- if (this.#logLevel >= LogLevels.Info) {
136
- this.#log('info', message, meta);
137
- }
138
- }
139
-
140
- warn(message: string, meta: Record<string, unknown>): void {
141
- this._warn(message, meta);
142
-
143
- if (this.#sendAnalytics) {
144
- this.#logToRemoteBatcher.Queue({ level: 'warn', message, meta });
145
- }
146
-
147
- if (this.#logLevel >= LogLevels.Warn) {
148
- this.#log('warn', message, meta);
149
- }
150
- }
151
-
152
- error(message: string, meta: Record<string, unknown>): void {
153
- this._error(message, meta);
154
-
155
- if (this.#sendAnalytics) {
156
- this.#logToRemoteBatcher.Queue({ level: 'error', message, meta });
157
- }
158
-
159
- if (this.#logLevel >= LogLevels.Error) {
160
- this.#log('error', message, meta);
161
- }
162
- }
163
-
164
- #log(level: LogLevelStr, message: string, ...args: readonly unknown[]): void {
165
- if (typeof this.onLogMessage === 'function') {
166
- this.onLogMessage(message, ...this.#decirculate(args), level);
167
- }
168
- }
169
-
170
- #decirculate<Input>(object: Input): Input {
171
- const seenObjects = new WeakMap<Record<string, unknown>, readonly string[]>();
172
-
173
- function internalDecirculate<T>(value: T, path: readonly string[] = []): T {
174
- if (!isObject(value)) {
175
- return value;
176
- }
177
-
178
- const existingPath = seenObjects.get(value);
179
-
180
- if (existingPath) {
181
- return `[Circular *${ existingPath.join('.') }]` as unknown as T;
182
- }
183
-
184
- seenObjects.set(value, path);
185
-
186
- const newValue = (Array.isArray(value) ? [] : {}) as T;
187
-
188
- Object.entries(value).forEach(([key, propValue]) => {
189
- newValue[key as keyof T] = internalDecirculate(propValue, [...path, key]) as T[keyof T];
190
- });
191
-
192
- seenObjects.delete(value);
193
-
194
- return newValue;
195
- }
196
-
197
- return internalDecirculate(object);
198
- }
199
-
200
- private async logToApi(logs: LogToRemotePayload[]): Promise<void> {
201
- try {
202
- await this.#analyticsApi.log.batch({
203
- logs: logs.map((log) => this.#decirculate({
204
- ...log,
205
- meta: this.prepareRecordMeta(log.meta),
206
- })),
207
- clientMeta: this.getClientMeta(),
208
- });
209
- } catch (error) {
210
- this._debug('Log request was not successful', { error });
211
- }
212
- }
213
-
214
- private getClientMeta(): ClientMeta {
215
- return {
216
- ...clientMetaProvider.meta,
217
- clUId: getClientUniqueId(),
218
- };
219
- }
220
-
221
- private prepareRecordMeta(metaData?: LogRecordMeta): RecordMeta {
222
- const meta = metaData ?? {};
223
- const { error } = meta;
224
-
225
- return {
226
- ...meta,
227
- clientTimestamp: new Date().toISOString(),
228
- from_sdk: true,
229
- ...(error && typeof error === 'object' ? { error: serializeError(error) } : {}),
230
- };
231
- }
232
- }
233
-
234
- export default Logger;