@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,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;