@livedigital/client 3.36.0 → 3.36.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,8 @@ export declare enum SocketIOEvents {
6
6
  Reconnecting = "reconnecting",
7
7
  Reconnected = "reconnected",
8
8
  ReconnectAttempt = "reconnect_attempt",
9
+ ReconnectFailed = "reconnect_failed",
10
+ ReconnectError = "reconnect_error",
9
11
  NeedToJoinFirst = "need_to_join_first",
10
12
  Disconnect = "disconnect",
11
13
  Disconnected = "disconnected",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@livedigital/client",
3
3
  "author": "vlprojects",
4
4
  "license": "MIT",
5
- "version": "3.36.0",
5
+ "version": "3.36.2",
6
6
  "private": false,
7
7
  "bugs": {
8
8
  "url": "https://github.com/vlprojects/livedigital-sdk/issues"
@@ -85,7 +85,7 @@
85
85
  "@types/sinon-chai": "^3.2.9",
86
86
  "@typescript-eslint/eslint-plugin": "^4.32.0",
87
87
  "@typescript-eslint/parser": "^4.32.0",
88
- "audio-effects-sdk": "^2.4.2",
88
+ "audio-effects-sdk": "^2.4.3",
89
89
  "axios-mock-adapter": "^1.21.2",
90
90
  "chai": "^4.3.7",
91
91
  "chai-as-promised": "^7.1.1",
@@ -21,3 +21,7 @@ export const PEER_APP_DATA_MAX_SIZE_BYTES = 2048;
21
21
  export const SOCKET_ERROR_CODE_UNAUTHORIZED = 'unauthorized';
22
22
 
23
23
  export const MAX_JOIN_ATTEMPTS = 4;
24
+
25
+ export const DEBOUNCE_LIMIT = 3;
26
+
27
+ export const TEN_SECONDS_IN_MS = 10 * 1000;
@@ -596,7 +596,7 @@ class Engine {
596
596
  this.channelEventsHandler.subscribeToEvents();
597
597
  this.mediaSoupEventsHandler.subscribeToEvents();
598
598
  this.state.isJoined = true;
599
- this.#logger.debug('Successfully joined channel', { channelId });
599
+ this.#logger.info('Successfully joined channel', { channelId });
600
600
  await this.dataChannelsManager.createAllDataChannels();
601
601
  clientMetaProvider.setPeerId(peerId);
602
602
  clientMetaProvider.setChannelId(channelId);
@@ -359,6 +359,12 @@ class Media {
359
359
  }
360
360
 
361
361
  async fallbackToRNoise(track: AudioTrack, context: DenoiserFallbackContext) {
362
+ if (this.#denoiserFallbacked) {
363
+ return;
364
+ }
365
+
366
+ this.#denoiserFallbacked = true;
367
+
362
368
  if (this.#denoiser === 'rnnoise') {
363
369
  return;
364
370
  }
@@ -1,8 +1,31 @@
1
1
  import { serializeError } from 'serialize-error';
2
- import type { atsvb, Config } from 'audio-effects-sdk';
2
+ import type { atsvb, Config, ErrorType } from 'audio-effects-sdk';
3
3
  import { LoggerFactory } from '../../../../../types/container';
4
4
  import Logger from '../../../../Logger';
5
5
  import { AudioTrackProcessor } from '../AudioTrackProcessor';
6
+ import { TEN_SECONDS_IN_MS, DEBOUNCE_LIMIT } from '../../../../../constants/common';
7
+
8
+ declare enum ErrorCode {
9
+ PERFORMANCE_STOP = 1001,
10
+ REDUCE_LATENCY = 1002,
11
+ }
12
+ declare enum ErrorEmitter {
13
+ ATSVB = 'atsvb',
14
+ STREAM_PROCESSOR = 'stream_processor',
15
+ ML_INFERENCE = 'ml_inference',
16
+ MODEL = 'model',
17
+ WORKLET = 'worklet',
18
+ WORKER = 'worker',
19
+ MODEL_LOADER = 'model_loader',
20
+ }
21
+ interface ErrorObject {
22
+ message: string;
23
+ type: ErrorType;
24
+ code?: ErrorCode;
25
+ emitter?: ErrorEmitter;
26
+ cause?: Error;
27
+ data?: any;
28
+ }
6
29
 
7
30
  declare global {
8
31
  interface Window {
@@ -30,6 +53,8 @@ export class ASDKTrackProcessor implements AudioTrackProcessor {
30
53
 
31
54
  #sampleRate: Config['sampleRate'] = 16000;
32
55
 
56
+ #debounceCounters = new Map<number, number>();
57
+
33
58
  #track?: MediaStreamTrack;
34
59
 
35
60
  readonly type = 'asdk';
@@ -50,48 +75,12 @@ export class ASDKTrackProcessor implements AudioTrackProcessor {
50
75
  sdk_url: 'https://effectssdk.ai/sdk/audio/',
51
76
  // path to wasm files
52
77
  wasmPaths: {
53
- 'ort-wasm.wasm': 'https://effectssdk.ai/sdk/audio/dev/2.4.2/ort-wasm.wasm',
54
- 'ort-wasm-simd.wasm': 'https://effectssdk.ai/sdk/audio/dev/2.4.2/ort-wasm-simd.wasm',
78
+ 'ort-wasm.wasm': 'https://effectssdk.ai/sdk/audio/dev/2.4.3/ort-wasm.wasm',
79
+ 'ort-wasm-simd.wasm': 'https://effectssdk.ai/sdk/audio/dev/2.4.3/ort-wasm-simd.wasm',
55
80
  },
56
81
  });
57
82
 
58
- this.#atsvb.onError((error) => {
59
- const {
60
- message, type, cause, ...rest
61
- } = error;
62
-
63
- if (rest.code === 1002 || rest.code === 1001) {
64
- this.#onError(`ASDK performance issue(${rest.code}): ${message}`, cause);
65
- }
66
-
67
- if (type === 'error') {
68
- this.#logger.error(message, {
69
- error: serializeError(cause),
70
- cause,
71
- ...rest,
72
- type: this.type,
73
- case: 'Denoiser',
74
- });
75
- this.#onError(`ASDK runtime error: ${message}`, cause);
76
- this.#onError = noop;
77
- }
78
-
79
- if (type === 'warning') {
80
- this.#logger.warn(message, {
81
- ...rest,
82
- type: this.type,
83
- case: 'Denoiser',
84
- });
85
- }
86
-
87
- if (type === 'info') {
88
- this.#logger.info(message, {
89
- ...rest,
90
- type: this.type,
91
- case: 'Denoiser',
92
- });
93
- }
94
- });
83
+ this.#atsvb.onError(this.onError.bind(this));
95
84
  }
96
85
 
97
86
  setOnError(onError: (reason: string, error: Error | undefined) => void): void {
@@ -142,6 +131,12 @@ export class ASDKTrackProcessor implements AudioTrackProcessor {
142
131
 
143
132
  const outTrack = await outTrackPromise;
144
133
 
134
+ this.#logger.info('processTrack()', {
135
+ case: 'Denoiser',
136
+ type: this.type,
137
+ track: track.id,
138
+ });
139
+
145
140
  return outTrack;
146
141
  } catch (error) {
147
142
  this.#logger.error('processTrack()', {
@@ -171,4 +166,67 @@ export class ASDKTrackProcessor implements AudioTrackProcessor {
171
166
  this.#originalTrack = null;
172
167
  }
173
168
  }
169
+
170
+ getUpdatedDebounceCounter(errorCode: number) {
171
+ let value = this.#debounceCounters.get(errorCode) || 0;
172
+
173
+ value += 1;
174
+ this.#debounceCounters.set(errorCode, value);
175
+
176
+ setTimeout(() => {
177
+ const currentValue = this.#debounceCounters.get(errorCode) || 0;
178
+ if (currentValue <= 0) {
179
+ this.#debounceCounters.set(errorCode, 0);
180
+ return;
181
+ }
182
+
183
+ this.#debounceCounters.set(errorCode, currentValue - 1);
184
+ }, TEN_SECONDS_IN_MS);
185
+
186
+ return value;
187
+ }
188
+
189
+ onError(error: ErrorObject) {
190
+ const {
191
+ message, type, cause, ...rest
192
+ } = error;
193
+
194
+ if (type === 'error') {
195
+ this.#logger.error(message, {
196
+ error: serializeError(cause),
197
+ cause,
198
+ ...rest,
199
+ type: this.type,
200
+ case: 'Denoiser',
201
+ });
202
+
203
+ if (rest.code === ErrorCode.REDUCE_LATENCY || rest.code === ErrorCode.PERFORMANCE_STOP) {
204
+ const debounceCounter = this.getUpdatedDebounceCounter(rest.code);
205
+ if (debounceCounter > DEBOUNCE_LIMIT) {
206
+ this.#debounceCounters.set(rest.code, 0);
207
+ this.#onError(`ASDK performance issue(${rest.code}): ${message}`, cause);
208
+ this.#onError = noop;
209
+ }
210
+ } else {
211
+ this.#onError(`ASDK runtime error: ${message}`, cause);
212
+ this.#onError = noop;
213
+ }
214
+ }
215
+
216
+ if (type === 'warning') {
217
+ this.#logger.warn(message, {
218
+ ...rest,
219
+ type: this.type,
220
+ case: 'Denoiser',
221
+ });
222
+ }
223
+
224
+ if (type === 'info') {
225
+ this.#logger.info(message, {
226
+ ...rest,
227
+ type: this.type,
228
+ case: 'Denoiser',
229
+ });
230
+ }
231
+ }
174
232
  }
@@ -1,4 +1,5 @@
1
1
  import { inject, injectable } from 'inversify';
2
+ import { serializeError } from 'serialize-error';
2
3
  import { io, Socket } from 'socket.io-client';
3
4
  import { SIGNALING_API_VERSION } from '../../constants/common';
4
5
  import { MEDIASOUP_MEDIA_ACTIONS_TRACK_EVENTS } from '../../constants/events';
@@ -94,7 +95,9 @@ class SocketIO {
94
95
 
95
96
  connection.on(SocketIOEvents.ConnectError, (error: unknown) => {
96
97
  this.connectionError = error as string;
97
- this.#logger.error(`connection.on('${SocketIOEvents.ConnectError}')`, { error });
98
+ this.#logger.error(`connection.on('${SocketIOEvents.ConnectError}')`, {
99
+ error: serializeError(error),
100
+ });
98
101
  this.observer.safeEmit(SocketIOEvents.State, { state: SocketIOEvents.Error, error });
99
102
 
100
103
  if (this.reconnectingAttempt > this.#maxReconnectingAttempts) {
@@ -106,6 +109,13 @@ class SocketIO {
106
109
  }
107
110
  });
108
111
 
112
+ connection.on(SocketIOEvents.ReconnectError, (error: unknown) => {
113
+ this.#logger.error(`connection.on('${SocketIOEvents.ReconnectError}')`, {
114
+ case: 'SocketReconnect',
115
+ error: serializeError(error),
116
+ });
117
+ });
118
+
109
119
  connection.on(SocketIOEvents.Disconnect, ((reason: string) => {
110
120
  this.isConnected = false;
111
121
  this.setReconnectingAttempt(0);
@@ -1,3 +1,4 @@
1
+ import { serializeError } from 'serialize-error';
1
2
  import DefaultTimeProvider from './datetime';
2
3
  import Logger from '../engine/Logger';
3
4
 
@@ -34,7 +35,7 @@ const retryAsync = async <ReturnType>(
34
35
  opts.logger.info('Action retry failed', {
35
36
  currentAttempt,
36
37
  actionName: opts.actionName,
37
- error: err,
38
+ error: serializeError(err),
38
39
  });
39
40
  }
40
41
 
@@ -160,12 +160,11 @@ export function audioTrackProcessorFactory(context: interfaces.Context): AudioTr
160
160
  return (params: CreateAudioTrackProcessorParams): AudioTrackProcessor => {
161
161
  const denoiser = config.get('denoiser');
162
162
 
163
- if (processorsCache.has(denoiser, params.trackLabel)) {
164
- throw new Error(`Track processor for type:${denoiser}, label:${params.trackLabel} already created`);
163
+ let processor = processorsCache.get(denoiser, params.trackLabel);
164
+ if (processor) {
165
+ return processor;
165
166
  }
166
167
 
167
- let processor;
168
-
169
168
  if (denoiser === 'rnnoise' && params.noiseSuppressor) {
170
169
  processor = new RNNoiseTrackProcessor({
171
170
  noiseSuppressor: params.noiseSuppressor,
@@ -8,6 +8,9 @@ export enum SocketIOEvents {
8
8
  Reconnecting = 'reconnecting',
9
9
  Reconnected = 'reconnected',
10
10
  ReconnectAttempt = 'reconnect_attempt',
11
+ ReconnectFailed = 'reconnect_failed',
12
+ ReconnectError = 'reconnect_error',
13
+
11
14
  NeedToJoinFirst = 'need_to_join_first',
12
15
 
13
16
  Disconnect = 'disconnect',