@stream-io/video-client 1.35.1 → 1.36.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.
- package/CHANGELOG.md +10 -0
- package/dist/index.browser.es.js +382 -329
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +404 -333
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +382 -329
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +3 -2
- package/dist/src/StreamVideoClient.d.ts +3 -2
- package/dist/src/coordinator/connection/client.d.ts +3 -2
- package/dist/src/coordinator/connection/connection.d.ts +2 -1
- package/dist/src/coordinator/connection/types.d.ts +17 -1
- package/dist/src/devices/DeviceManager.d.ts +2 -2
- package/dist/src/logger.d.ts +9 -6
- package/dist/src/rpc/createClient.d.ts +3 -2
- package/dist/src/rtc/BasePeerConnection.d.ts +7 -4
- package/dist/src/rtc/Publisher.d.ts +3 -3
- package/dist/src/rtc/codecs.d.ts +3 -1
- package/dist/src/rtc/helpers/sdp.d.ts +8 -0
- package/dist/src/rtc/types.d.ts +4 -5
- package/dist/src/store/CallState.d.ts +1 -1
- package/dist/src/types.d.ts +6 -0
- package/package.json +3 -2
- package/src/Call.ts +49 -68
- package/src/StreamSfuClient.ts +11 -11
- package/src/StreamVideoClient.ts +19 -21
- package/src/coordinator/connection/client.ts +21 -30
- package/src/coordinator/connection/connection.ts +5 -4
- package/src/coordinator/connection/location.ts +4 -4
- package/src/coordinator/connection/types.ts +21 -2
- package/src/devices/BrowserPermission.ts +5 -5
- package/src/devices/CameraManager.ts +3 -4
- package/src/devices/DeviceManager.ts +11 -11
- package/src/devices/MicrophoneManager.ts +8 -8
- package/src/devices/devices.ts +18 -14
- package/src/events/call.ts +6 -9
- package/src/events/internal.ts +4 -4
- package/src/events/mutes.ts +3 -8
- package/src/helpers/DynascaleManager.ts +9 -9
- package/src/helpers/RNSpeechDetector.ts +5 -5
- package/src/helpers/clientUtils.ts +1 -3
- package/src/helpers/ensureExhausted.ts +2 -2
- package/src/logger.ts +9 -34
- package/src/rpc/__tests__/createClient.test.ts +5 -1
- package/src/rpc/createClient.ts +4 -3
- package/src/rpc/retryable.ts +4 -2
- package/src/rtc/BasePeerConnection.ts +26 -24
- package/src/rtc/Dispatcher.ts +4 -4
- package/src/rtc/IceTrickleBuffer.ts +5 -5
- package/src/rtc/Publisher.ts +21 -13
- package/src/rtc/Subscriber.ts +22 -17
- package/src/rtc/__tests__/Publisher.test.ts +12 -8
- package/src/rtc/codecs.ts +13 -2
- package/src/rtc/helpers/__tests__/sdp.codecs.test.ts +628 -0
- package/src/rtc/helpers/sdp.ts +82 -0
- package/src/rtc/signal.ts +7 -7
- package/src/rtc/types.ts +4 -4
- package/src/stats/CallStateStatsReporter.ts +4 -4
- package/src/stats/SfuStatsReporter.ts +6 -6
- package/src/store/CallState.ts +3 -3
- package/src/store/rxUtils.ts +4 -2
- package/src/store/stateStore.ts +6 -6
- package/src/types.ts +6 -0
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
addConnectionEventListeners,
|
|
12
12
|
generateUUIDv4,
|
|
13
13
|
isErrorResponse,
|
|
14
|
-
isFunction,
|
|
15
14
|
KnownCodes,
|
|
16
15
|
removeConnectionEventListeners,
|
|
17
16
|
retryInterval,
|
|
@@ -24,7 +23,6 @@ import {
|
|
|
24
23
|
ClientEventListener,
|
|
25
24
|
ConnectAPIResponse,
|
|
26
25
|
ErrorFromResponse,
|
|
27
|
-
Logger,
|
|
28
26
|
StreamClientOptions,
|
|
29
27
|
StreamVideoEvent,
|
|
30
28
|
TokenOrProvider,
|
|
@@ -38,7 +36,7 @@ import {
|
|
|
38
36
|
CreateGuestResponse,
|
|
39
37
|
} from '../../gen/coordinator';
|
|
40
38
|
import { makeSafePromise, type SafePromise } from '../../helpers/promise';
|
|
41
|
-
import {
|
|
39
|
+
import { ScopedLogger, videoLoggerSystem } from '../../logger';
|
|
42
40
|
|
|
43
41
|
export class StreamClient {
|
|
44
42
|
_user?: UserWithId;
|
|
@@ -52,7 +50,7 @@ export class StreamClient {
|
|
|
52
50
|
listeners: Partial<
|
|
53
51
|
Record<AllClientEventTypes, ClientEventListener<any>[] | undefined>
|
|
54
52
|
> = {};
|
|
55
|
-
logger:
|
|
53
|
+
logger: ScopedLogger;
|
|
56
54
|
|
|
57
55
|
private locationHint: Promise<string> | undefined;
|
|
58
56
|
|
|
@@ -150,9 +148,7 @@ export class StreamClient {
|
|
|
150
148
|
|
|
151
149
|
this.defaultWSTimeout = this.options.defaultWsTimeout ?? 15000;
|
|
152
150
|
|
|
153
|
-
this.logger =
|
|
154
|
-
? inputOptions.logger
|
|
155
|
-
: () => null;
|
|
151
|
+
this.logger = videoLoggerSystem.getLogger('coordinator');
|
|
156
152
|
}
|
|
157
153
|
|
|
158
154
|
getAuthType = () => {
|
|
@@ -206,8 +202,7 @@ export class StreamClient {
|
|
|
206
202
|
* If the user id remains the same we don't throw error
|
|
207
203
|
*/
|
|
208
204
|
if (this.userID === user.id && this.connectUserTask) {
|
|
209
|
-
this.logger(
|
|
210
|
-
'warn',
|
|
205
|
+
this.logger.warn(
|
|
211
206
|
'Consecutive calls to connectUser is detected, ideally you should only call this function once in your app.',
|
|
212
207
|
);
|
|
213
208
|
return this.connectUserTask;
|
|
@@ -220,8 +215,7 @@ export class StreamClient {
|
|
|
220
215
|
}
|
|
221
216
|
|
|
222
217
|
if ((this.secret || this.node) && !this.options.allowServerSideConnect) {
|
|
223
|
-
this.logger(
|
|
224
|
-
'warn',
|
|
218
|
+
this.logger.warn(
|
|
225
219
|
'Please do not use connectUser server side. Use our @stream-io/node-sdk instead: https://getstream.io/video/docs/api/',
|
|
226
220
|
);
|
|
227
221
|
}
|
|
@@ -288,16 +282,14 @@ export class StreamClient {
|
|
|
288
282
|
|
|
289
283
|
const wsPromise = this.wsPromiseSafe?.();
|
|
290
284
|
if (this.wsConnection?.isConnecting && wsPromise) {
|
|
291
|
-
this.logger(
|
|
292
|
-
'info',
|
|
285
|
+
this.logger.info(
|
|
293
286
|
'client:openConnection() - connection already in progress',
|
|
294
287
|
);
|
|
295
288
|
return await wsPromise;
|
|
296
289
|
}
|
|
297
290
|
|
|
298
291
|
if (this.wsConnection?.isHealthy && this._hasConnectionID()) {
|
|
299
|
-
this.logger(
|
|
300
|
-
'info',
|
|
292
|
+
this.logger.info(
|
|
301
293
|
'client:openConnection() - openConnection called twice, healthy connection already exists',
|
|
302
294
|
);
|
|
303
295
|
|
|
@@ -319,7 +311,7 @@ export class StreamClient {
|
|
|
319
311
|
* https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
|
|
320
312
|
*/
|
|
321
313
|
disconnectUser = async (timeout?: number) => {
|
|
322
|
-
this.logger('
|
|
314
|
+
this.logger.info('client:disconnect() - Disconnecting the client');
|
|
323
315
|
|
|
324
316
|
// remove the user specific fields
|
|
325
317
|
delete this.user;
|
|
@@ -390,7 +382,7 @@ export class StreamClient {
|
|
|
390
382
|
this.listeners[eventName] = [];
|
|
391
383
|
}
|
|
392
384
|
|
|
393
|
-
this.logger(
|
|
385
|
+
this.logger.debug(`Adding listener for ${eventName} event`);
|
|
394
386
|
this.listeners[eventName]?.push(callback as ClientEventListener<any>);
|
|
395
387
|
return () => {
|
|
396
388
|
this.off(eventName, callback);
|
|
@@ -408,7 +400,7 @@ export class StreamClient {
|
|
|
408
400
|
this.listeners[eventName] = [];
|
|
409
401
|
}
|
|
410
402
|
|
|
411
|
-
this.logger(
|
|
403
|
+
this.logger.debug(`Removing listener for ${eventName} event`);
|
|
412
404
|
this.listeners[eventName] = this.listeners[eventName]?.filter(
|
|
413
405
|
(value) => value !== callback,
|
|
414
406
|
);
|
|
@@ -447,8 +439,8 @@ export class StreamClient {
|
|
|
447
439
|
config?: AxiosRequestConfig & { maxBodyLength?: number };
|
|
448
440
|
},
|
|
449
441
|
) => {
|
|
450
|
-
if (getLogLevel() !== 'trace') return;
|
|
451
|
-
this.logger(
|
|
442
|
+
if (this.logger.getLogLevel() !== 'trace') return;
|
|
443
|
+
this.logger.trace(`client: ${type} - Request - ${url}`, {
|
|
452
444
|
payload: data,
|
|
453
445
|
config,
|
|
454
446
|
});
|
|
@@ -459,9 +451,8 @@ export class StreamClient {
|
|
|
459
451
|
url: string,
|
|
460
452
|
response: AxiosResponse<T>,
|
|
461
453
|
) => {
|
|
462
|
-
if (getLogLevel() !== 'trace') return;
|
|
463
|
-
this.logger(
|
|
464
|
-
'trace',
|
|
454
|
+
if (this.logger.getLogLevel() !== 'trace') return;
|
|
455
|
+
this.logger.trace(
|
|
465
456
|
`client:${type} - Response - url: ${url} > status ${response.status}`,
|
|
466
457
|
{
|
|
467
458
|
response,
|
|
@@ -529,14 +520,14 @@ export class StreamClient {
|
|
|
529
520
|
this.consecutiveFailures += 1;
|
|
530
521
|
const { response } = e;
|
|
531
522
|
if (!response || !isErrorResponse(response)) {
|
|
532
|
-
this.logger(
|
|
523
|
+
this.logger.error(`client:${type} url: ${url}`, e);
|
|
533
524
|
throw e as AxiosError<APIErrorResponse>;
|
|
534
525
|
}
|
|
535
526
|
|
|
536
527
|
const { data: responseData, status } = response;
|
|
537
528
|
const isTokenExpired = responseData.code === KnownCodes.TOKEN_EXPIRED;
|
|
538
529
|
if (isTokenExpired && !this.tokenManager.isStatic()) {
|
|
539
|
-
this.logger(
|
|
530
|
+
this.logger.warn(`client:${type}: url: ${url}`, response);
|
|
540
531
|
if (this.consecutiveFailures > 1) {
|
|
541
532
|
await sleep(retryInterval(this.consecutiveFailures));
|
|
542
533
|
}
|
|
@@ -544,7 +535,7 @@ export class StreamClient {
|
|
|
544
535
|
await this.tokenManager.loadToken();
|
|
545
536
|
return await this.doAxiosRequest<T, D>(type, url, data, options);
|
|
546
537
|
} else {
|
|
547
|
-
this.logger(
|
|
538
|
+
this.logger.error(`client:${type} url: ${url}`, response);
|
|
548
539
|
throw new ErrorFromResponse<APIErrorResponse>({
|
|
549
540
|
message: `Stream error code ${responseData.code}: ${responseData.message}`,
|
|
550
541
|
code: responseData.code ?? null,
|
|
@@ -593,7 +584,7 @@ export class StreamClient {
|
|
|
593
584
|
};
|
|
594
585
|
|
|
595
586
|
dispatchEvent = (event: StreamVideoEvent) => {
|
|
596
|
-
this.logger(
|
|
587
|
+
this.logger.debug(`Dispatching event: ${event.type}`, event);
|
|
597
588
|
if (!this.listeners) return;
|
|
598
589
|
|
|
599
590
|
// call generic listeners
|
|
@@ -622,7 +613,7 @@ export class StreamClient {
|
|
|
622
613
|
// The StableWSConnection handles all the reconnection logic.
|
|
623
614
|
this.wsConnection = new StableWSConnection(this);
|
|
624
615
|
|
|
625
|
-
this.logger('
|
|
616
|
+
this.logger.info('StreamClient.connect: this.wsConnection.connect()');
|
|
626
617
|
return await this.wsConnection.connect(this.defaultWSTimeout);
|
|
627
618
|
};
|
|
628
619
|
|
|
@@ -704,10 +695,10 @@ export class StreamClient {
|
|
|
704
695
|
event: { type: 'online' | 'offline' } | Event,
|
|
705
696
|
) => {
|
|
706
697
|
if (event.type === 'offline') {
|
|
707
|
-
this.logger('
|
|
698
|
+
this.logger.debug('device went offline');
|
|
708
699
|
this.dispatchEvent({ type: 'network.changed', online: false });
|
|
709
700
|
} else if (event.type === 'online') {
|
|
710
|
-
this.logger('
|
|
701
|
+
this.logger.debug('device went online');
|
|
711
702
|
this.dispatchEvent({ type: 'network.changed', online: true });
|
|
712
703
|
}
|
|
713
704
|
};
|
|
@@ -7,7 +7,8 @@ import {
|
|
|
7
7
|
retryInterval,
|
|
8
8
|
sleep,
|
|
9
9
|
} from './utils';
|
|
10
|
-
import type {
|
|
10
|
+
import type { StreamVideoEvent, UR } from './types';
|
|
11
|
+
import type { LogLevel } from '@stream-io/logger';
|
|
11
12
|
import type {
|
|
12
13
|
ConnectedEvent,
|
|
13
14
|
ConnectionErrorEvent,
|
|
@@ -88,7 +89,7 @@ export class StableWSConnection {
|
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
_log = (msg: string, extra: UR = {}, level: LogLevel = 'info') => {
|
|
91
|
-
this.client.logger(
|
|
92
|
+
this.client.logger[level](`connection:${msg}`, extra);
|
|
92
93
|
};
|
|
93
94
|
|
|
94
95
|
setClient = (client: StreamClient) => {
|
|
@@ -442,13 +443,13 @@ export class StableWSConnection {
|
|
|
442
443
|
|
|
443
444
|
const user = this.client.user;
|
|
444
445
|
if (!user) {
|
|
445
|
-
this.client.logger(
|
|
446
|
+
this.client.logger.error(`User not set, can't connect to WS`);
|
|
446
447
|
return;
|
|
447
448
|
}
|
|
448
449
|
|
|
449
450
|
const token = this.client._getToken();
|
|
450
451
|
if (!token) {
|
|
451
|
-
this.client.logger(
|
|
452
|
+
this.client.logger.error(`Token not set, can't connect authenticate`);
|
|
452
453
|
return;
|
|
453
454
|
}
|
|
454
455
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { videoLoggerSystem } from '../../logger';
|
|
2
2
|
|
|
3
3
|
export const getLocationHint = async (
|
|
4
4
|
hintUrl = `https://hint.stream-io-video.com/`,
|
|
5
5
|
timeout = 2000,
|
|
6
6
|
maxAttempts = 3,
|
|
7
7
|
): Promise<string> => {
|
|
8
|
-
const logger = getLogger(
|
|
8
|
+
const logger = videoLoggerSystem.getLogger('location-hint');
|
|
9
9
|
|
|
10
10
|
let attempt = 0;
|
|
11
11
|
let locationHint = 'ERR';
|
|
@@ -18,10 +18,10 @@ export const getLocationHint = async (
|
|
|
18
18
|
signal: abortController.signal,
|
|
19
19
|
});
|
|
20
20
|
const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
|
|
21
|
-
logger(
|
|
21
|
+
logger.debug(`Location header: ${awsPop}`);
|
|
22
22
|
locationHint = awsPop.substring(0, 3); // AMS1-P2 -> AMS
|
|
23
23
|
} catch (e) {
|
|
24
|
-
logger(
|
|
24
|
+
logger.warn(`Failed to get location hint from ${hintUrl}`, e);
|
|
25
25
|
locationHint = 'ERR';
|
|
26
26
|
} finally {
|
|
27
27
|
clearTimeout(timeoutId);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
2
2
|
import { ConnectedEvent, UserRequest, VideoEvent } from '../../gen/coordinator';
|
|
3
3
|
import { AllSfuEvents } from '../../rtc';
|
|
4
|
+
import type { ConfigureLoggersOptions, LogLevel } from '@stream-io/logger';
|
|
4
5
|
|
|
5
6
|
export type UR = Record<string, unknown>;
|
|
6
7
|
|
|
@@ -24,8 +25,6 @@ export type { OwnUserResponse } from '../../gen/coordinator';
|
|
|
24
25
|
|
|
25
26
|
export type ConnectAPIResponse = Promise<void | ConnectedEvent>;
|
|
26
27
|
|
|
27
|
-
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error';
|
|
28
|
-
|
|
29
28
|
type ErrorResponseDetails = {
|
|
30
29
|
code: number;
|
|
31
30
|
messages: string[];
|
|
@@ -156,8 +155,28 @@ export type StreamClientOptions = Partial<AxiosRequestConfig> & {
|
|
|
156
155
|
*/
|
|
157
156
|
baseURL?: string;
|
|
158
157
|
browser?: boolean;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @deprecated Use `logOptions` instead.
|
|
161
|
+
* Custom logger instance used to handle log messages.
|
|
162
|
+
* Will be removed in a future release.
|
|
163
|
+
*/
|
|
159
164
|
logger?: Logger;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @deprecated Use `logOptions` instead.
|
|
168
|
+
* Sets the minimum log level for all logs.
|
|
169
|
+
* Will be removed in a future release.
|
|
170
|
+
*/
|
|
160
171
|
logLevel?: LogLevel;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Configuration options where keys are logger scopes.
|
|
175
|
+
* The `default` scope is reserved is used to set defaults for all loggers.
|
|
176
|
+
*
|
|
177
|
+
*/
|
|
178
|
+
logOptions?: ConfigureLoggersOptions;
|
|
179
|
+
|
|
161
180
|
/**
|
|
162
181
|
* The URL to use for the location hint.
|
|
163
182
|
*/
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { fromEventPattern, map } from 'rxjs';
|
|
2
2
|
import { isReactNative } from '../helpers/platforms';
|
|
3
|
-
import { getLogger } from '../logger';
|
|
4
3
|
import { disposeOfMediaStream } from './utils';
|
|
5
4
|
import { withoutConcurrency } from '../helpers/concurrency';
|
|
5
|
+
import { videoLoggerSystem } from '../logger';
|
|
6
6
|
|
|
7
7
|
interface BrowserPermissionConfig {
|
|
8
8
|
constraints: DisplayMediaStreamOptions;
|
|
@@ -17,7 +17,7 @@ export class BrowserPermission {
|
|
|
17
17
|
private state: BrowserPermissionState | undefined;
|
|
18
18
|
private wasPrompted: boolean = false;
|
|
19
19
|
private listeners = new Set<(state: BrowserPermissionState) => void>();
|
|
20
|
-
private logger = getLogger(
|
|
20
|
+
private logger = videoLoggerSystem.getLogger('permissions');
|
|
21
21
|
|
|
22
22
|
constructor(private readonly permission: BrowserPermissionConfig) {
|
|
23
23
|
const signal = this.disposeController.signal;
|
|
@@ -47,7 +47,7 @@ export class BrowserPermission {
|
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
49
|
} catch (err) {
|
|
50
|
-
this.logger('
|
|
50
|
+
this.logger.debug('Failed to query permission status', err);
|
|
51
51
|
assumeGranted();
|
|
52
52
|
}
|
|
53
53
|
})();
|
|
@@ -104,7 +104,7 @@ export class BrowserPermission {
|
|
|
104
104
|
'name' in e &&
|
|
105
105
|
(e.name === 'NotAllowedError' || e.name === 'SecurityError')
|
|
106
106
|
) {
|
|
107
|
-
this.logger('
|
|
107
|
+
this.logger.info('Browser permission was not granted', {
|
|
108
108
|
permission: this.permission,
|
|
109
109
|
});
|
|
110
110
|
this.setState('denied');
|
|
@@ -116,7 +116,7 @@ export class BrowserPermission {
|
|
|
116
116
|
return false;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
this.logger(
|
|
119
|
+
this.logger.error(`Failed to getUserMedia`, {
|
|
120
120
|
error: e,
|
|
121
121
|
permission: this.permission,
|
|
122
122
|
});
|
|
@@ -34,7 +34,7 @@ export class CameraManager extends DeviceManager<CameraManagerState> {
|
|
|
34
34
|
*/
|
|
35
35
|
async selectDirection(direction: Exclude<CameraDirection, undefined>) {
|
|
36
36
|
if (!this.isDirectionSupportedByDevice()) {
|
|
37
|
-
this.logger('
|
|
37
|
+
this.logger.warn('Setting direction is not supported on this device');
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -86,7 +86,7 @@ export class CameraManager extends DeviceManager<CameraManagerState> {
|
|
|
86
86
|
await this.statusChangeSettled();
|
|
87
87
|
} catch (error) {
|
|
88
88
|
// couldn't enable device, target resolution will be applied the next time user attempts to start the device
|
|
89
|
-
this.logger('
|
|
89
|
+
this.logger.warn('could not apply target resolution', error);
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
if (this.enabled && this.state.mediaStream) {
|
|
@@ -98,8 +98,7 @@ export class CameraManager extends DeviceManager<CameraManagerState> {
|
|
|
98
98
|
height !== this.targetResolution.height
|
|
99
99
|
) {
|
|
100
100
|
await this.applySettingsToStream();
|
|
101
|
-
this.logger(
|
|
102
|
-
'debug',
|
|
101
|
+
this.logger.debug(
|
|
103
102
|
`${width}x${height} target resolution applied to media stream`,
|
|
104
103
|
);
|
|
105
104
|
}
|
|
@@ -6,8 +6,7 @@ import { createSubscription } from '../store/rxUtils';
|
|
|
6
6
|
import { DeviceManagerState } from './DeviceManagerState';
|
|
7
7
|
import { isMobile } from '../helpers/compatibility';
|
|
8
8
|
import { isReactNative } from '../helpers/platforms';
|
|
9
|
-
import {
|
|
10
|
-
import { getLogger } from '../logger';
|
|
9
|
+
import { ScopedLogger, videoLoggerSystem } from '../logger';
|
|
11
10
|
import { TrackType } from '../gen/video/sfu/models/models';
|
|
12
11
|
import { deviceIds$ } from './devices';
|
|
13
12
|
import {
|
|
@@ -29,7 +28,7 @@ export abstract class DeviceManager<
|
|
|
29
28
|
* if true, stops the media stream when call is left
|
|
30
29
|
*/
|
|
31
30
|
stopOnLeave = true;
|
|
32
|
-
logger:
|
|
31
|
+
logger: ScopedLogger;
|
|
33
32
|
|
|
34
33
|
state: S;
|
|
35
34
|
|
|
@@ -48,7 +47,9 @@ export abstract class DeviceManager<
|
|
|
48
47
|
this.call = call;
|
|
49
48
|
this.state = state;
|
|
50
49
|
this.trackType = trackType;
|
|
51
|
-
this.logger = getLogger(
|
|
50
|
+
this.logger = videoLoggerSystem.getLogger(
|
|
51
|
+
`${TrackType[trackType].toLowerCase()} manager`,
|
|
52
|
+
);
|
|
52
53
|
this.setup();
|
|
53
54
|
}
|
|
54
55
|
|
|
@@ -257,6 +258,7 @@ export abstract class DeviceManager<
|
|
|
257
258
|
};
|
|
258
259
|
|
|
259
260
|
protected async applySettingsToStream() {
|
|
261
|
+
console.log('applySettingsToStream ');
|
|
260
262
|
await withCancellation(this.statusChangeConcurrencyTag, async (signal) => {
|
|
261
263
|
if (this.enabled) {
|
|
262
264
|
try {
|
|
@@ -300,7 +302,7 @@ export abstract class DeviceManager<
|
|
|
300
302
|
protected async muteStream(stopTracks: boolean = true) {
|
|
301
303
|
const mediaStream = this.state.mediaStream;
|
|
302
304
|
if (!mediaStream) return;
|
|
303
|
-
this.logger(
|
|
305
|
+
this.logger.debug(`${stopTracks ? 'Stopping' : 'Disabling'} stream`);
|
|
304
306
|
if (this.call.state.callingState === CallingState.JOINED) {
|
|
305
307
|
await this.stopPublishStream();
|
|
306
308
|
}
|
|
@@ -347,7 +349,7 @@ export abstract class DeviceManager<
|
|
|
347
349
|
}
|
|
348
350
|
|
|
349
351
|
protected async unmuteStream() {
|
|
350
|
-
this.logger('
|
|
352
|
+
this.logger.debug('Starting stream');
|
|
351
353
|
let stream: MediaStream;
|
|
352
354
|
let rootStream: Promise<MediaStream> | undefined;
|
|
353
355
|
if (
|
|
@@ -435,8 +437,7 @@ export abstract class DeviceManager<
|
|
|
435
437
|
return output;
|
|
436
438
|
})
|
|
437
439
|
.then(chainWith(parent), (error) => {
|
|
438
|
-
this.logger(
|
|
439
|
-
'warn',
|
|
440
|
+
this.logger.warn(
|
|
440
441
|
'Filter failed to start and will be ignored',
|
|
441
442
|
error,
|
|
442
443
|
);
|
|
@@ -463,7 +464,7 @@ export abstract class DeviceManager<
|
|
|
463
464
|
const createTrackMuteHandler = (muted: boolean) => () => {
|
|
464
465
|
if (!isMobile() || this.trackType !== TrackType.VIDEO) return;
|
|
465
466
|
this.call.notifyTrackMuteState(muted, this.trackType).catch((err) => {
|
|
466
|
-
this.logger('
|
|
467
|
+
this.logger.warn('Error while notifying track mute state', err);
|
|
467
468
|
});
|
|
468
469
|
};
|
|
469
470
|
stream.getTracks().forEach((track) => {
|
|
@@ -534,8 +535,7 @@ export abstract class DeviceManager<
|
|
|
534
535
|
}
|
|
535
536
|
}
|
|
536
537
|
} catch (err) {
|
|
537
|
-
this.logger(
|
|
538
|
-
'warn',
|
|
538
|
+
this.logger.warn(
|
|
539
539
|
'Unexpected error while handling disconnected or replaced device',
|
|
540
540
|
err,
|
|
541
541
|
);
|
|
@@ -66,7 +66,7 @@ export class MicrophoneManager extends AudioDeviceManager<MicrophoneManagerState
|
|
|
66
66
|
await this.stopSpeakingWhileMutedDetection();
|
|
67
67
|
}
|
|
68
68
|
} catch (err) {
|
|
69
|
-
this.logger('
|
|
69
|
+
this.logger.warn('Could not enable speaking while muted', err);
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
72
|
),
|
|
@@ -96,14 +96,14 @@ export class MicrophoneManager extends AudioDeviceManager<MicrophoneManagerState
|
|
|
96
96
|
}
|
|
97
97
|
})
|
|
98
98
|
.catch((err) => {
|
|
99
|
-
this.logger(
|
|
99
|
+
this.logger.warn(`Failed to enable noise cancellation`, err);
|
|
100
100
|
return this.call.notifyNoiseCancellationStopped();
|
|
101
101
|
});
|
|
102
102
|
} else if (callingState === CallingState.LEFT) {
|
|
103
103
|
this.noiseCancellationRegistration
|
|
104
104
|
.then(() => this.noiseCancellation?.disable())
|
|
105
105
|
.catch((err) => {
|
|
106
|
-
this.logger(
|
|
106
|
+
this.logger.warn(`Failed to disable noise cancellation`, err);
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
109
|
}),
|
|
@@ -141,11 +141,11 @@ export class MicrophoneManager extends AudioDeviceManager<MicrophoneManagerState
|
|
|
141
141
|
this.call.tracer.trace('noiseCancellation.enabled', enabled);
|
|
142
142
|
if (enabled) {
|
|
143
143
|
this.call.notifyNoiseCancellationStarting().catch((err) => {
|
|
144
|
-
this.logger(
|
|
144
|
+
this.logger.warn(`notifyNoiseCancellationStart failed`, err);
|
|
145
145
|
});
|
|
146
146
|
} else {
|
|
147
147
|
this.call.notifyNoiseCancellationStopped().catch((err) => {
|
|
148
|
-
this.logger(
|
|
148
|
+
this.logger.warn(`notifyNoiseCancellationStop failed`, err);
|
|
149
149
|
});
|
|
150
150
|
}
|
|
151
151
|
},
|
|
@@ -179,9 +179,9 @@ export class MicrophoneManager extends AudioDeviceManager<MicrophoneManagerState
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
} catch (e) {
|
|
182
|
-
this.logger('
|
|
182
|
+
this.logger.warn('Failed to enable noise cancellation', e);
|
|
183
183
|
await this.disableNoiseCancellation().catch((err) => {
|
|
184
|
-
this.logger('
|
|
184
|
+
this.logger.warn('Failed to disable noise cancellation', err);
|
|
185
185
|
});
|
|
186
186
|
throw e;
|
|
187
187
|
}
|
|
@@ -195,7 +195,7 @@ export class MicrophoneManager extends AudioDeviceManager<MicrophoneManagerState
|
|
|
195
195
|
.then(() => this.noiseCancellation?.disable())
|
|
196
196
|
.then(() => this.noiseCancellationChangeUnsubscribe?.())
|
|
197
197
|
.catch((err) => {
|
|
198
|
-
this.logger('
|
|
198
|
+
this.logger.warn('Failed to unregister noise cancellation', err);
|
|
199
199
|
});
|
|
200
200
|
|
|
201
201
|
this.call.tracer.trace('noiseCancellation.disabled', true);
|
package/src/devices/devices.ts
CHANGED
|
@@ -9,12 +9,12 @@ import {
|
|
|
9
9
|
startWith,
|
|
10
10
|
tap,
|
|
11
11
|
} from 'rxjs';
|
|
12
|
-
import { getLogger } from '../logger';
|
|
13
12
|
import { BrowserPermission } from './BrowserPermission';
|
|
14
13
|
import { lazy } from '../helpers/lazy';
|
|
15
14
|
import { isFirefox } from '../helpers/browsers';
|
|
16
15
|
import { dumpStream, Tracer } from '../stats';
|
|
17
16
|
import { getCurrentValue } from '../store/rxUtils';
|
|
17
|
+
import { videoLoggerSystem } from '../logger';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Returns an Observable that emits the list of available devices
|
|
@@ -266,15 +266,16 @@ export const getAudioStream = async (
|
|
|
266
266
|
if (isNotFoundOrOverconstrainedError(error) && trackConstraints?.deviceId) {
|
|
267
267
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
268
268
|
const { deviceId, ...relaxedConstraints } = trackConstraints;
|
|
269
|
-
|
|
270
|
-
'
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
269
|
+
videoLoggerSystem
|
|
270
|
+
.getLogger('devices')
|
|
271
|
+
.warn(
|
|
272
|
+
'Failed to get audio stream, will try again with relaxed constraints',
|
|
273
|
+
{ error, constraints, relaxedConstraints },
|
|
274
|
+
);
|
|
274
275
|
return getAudioStream(relaxedConstraints);
|
|
275
276
|
}
|
|
276
277
|
|
|
277
|
-
getLogger(
|
|
278
|
+
videoLoggerSystem.getLogger('devices').error('Failed to get audio stream', {
|
|
278
279
|
error,
|
|
279
280
|
constraints,
|
|
280
281
|
});
|
|
@@ -310,15 +311,16 @@ export const getVideoStream = async (
|
|
|
310
311
|
if (isNotFoundOrOverconstrainedError(error) && trackConstraints?.deviceId) {
|
|
311
312
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
312
313
|
const { deviceId, ...relaxedConstraints } = trackConstraints;
|
|
313
|
-
|
|
314
|
-
'
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
314
|
+
videoLoggerSystem
|
|
315
|
+
.getLogger('devices')
|
|
316
|
+
.warn(
|
|
317
|
+
'Failed to get video stream, will try again with relaxed constraints',
|
|
318
|
+
{ error, constraints, relaxedConstraints },
|
|
319
|
+
);
|
|
318
320
|
return getVideoStream(relaxedConstraints);
|
|
319
321
|
}
|
|
320
322
|
|
|
321
|
-
getLogger(
|
|
323
|
+
videoLoggerSystem.getLogger('devices').error('Failed to get video stream', {
|
|
322
324
|
error,
|
|
323
325
|
constraints,
|
|
324
326
|
});
|
|
@@ -373,7 +375,9 @@ export const getScreenShareStream = async (
|
|
|
373
375
|
return stream;
|
|
374
376
|
} catch (e) {
|
|
375
377
|
tracer?.trace(`${tag}OnFailure`, (e as Error).name);
|
|
376
|
-
|
|
378
|
+
videoLoggerSystem
|
|
379
|
+
.getLogger('devices')
|
|
380
|
+
.error('Failed to get screen share stream', e);
|
|
377
381
|
throw e;
|
|
378
382
|
}
|
|
379
383
|
};
|
package/src/events/call.ts
CHANGED
|
@@ -38,8 +38,7 @@ export const watchCallRejected = (call: Call) => {
|
|
|
38
38
|
const { session: callSession } = eventCall;
|
|
39
39
|
|
|
40
40
|
if (!callSession) {
|
|
41
|
-
call.logger(
|
|
42
|
-
'warn',
|
|
41
|
+
call.logger.warn(
|
|
43
42
|
'No call session provided. Ignoring call.rejected event.',
|
|
44
43
|
event,
|
|
45
44
|
);
|
|
@@ -49,8 +48,7 @@ export const watchCallRejected = (call: Call) => {
|
|
|
49
48
|
const rejectedBy = callSession.rejected_by;
|
|
50
49
|
const { members, callingState } = call.state;
|
|
51
50
|
if (callingState !== CallingState.RINGING) {
|
|
52
|
-
call.logger(
|
|
53
|
-
'info',
|
|
51
|
+
call.logger.info(
|
|
54
52
|
'Call is not in ringing mode (it is either accepted or rejected already). Ignoring call.rejected event.',
|
|
55
53
|
event,
|
|
56
54
|
);
|
|
@@ -61,7 +59,7 @@ export const watchCallRejected = (call: Call) => {
|
|
|
61
59
|
.filter((m) => m.user_id !== call.currentUserId)
|
|
62
60
|
.every((m) => rejectedBy[m.user_id]);
|
|
63
61
|
if (everyoneElseRejected) {
|
|
64
|
-
call.logger('
|
|
62
|
+
call.logger.info('everyone rejected, leaving the call');
|
|
65
63
|
await call.leave({
|
|
66
64
|
reject: true,
|
|
67
65
|
reason: 'cancel',
|
|
@@ -70,7 +68,7 @@ export const watchCallRejected = (call: Call) => {
|
|
|
70
68
|
}
|
|
71
69
|
} else {
|
|
72
70
|
if (rejectedBy[eventCall.created_by.id]) {
|
|
73
|
-
call.logger('
|
|
71
|
+
call.logger.info('call creator rejected, leaving call');
|
|
74
72
|
await call.leave({ message: 'ring: creator rejected' });
|
|
75
73
|
}
|
|
76
74
|
}
|
|
@@ -90,7 +88,7 @@ export const watchCallEnded = (call: Call) => {
|
|
|
90
88
|
call
|
|
91
89
|
.leave({ message: 'call.ended event received', reject: false })
|
|
92
90
|
.catch((err) => {
|
|
93
|
-
call.logger('
|
|
91
|
+
call.logger.error('Failed to leave call after call.ended ', err);
|
|
94
92
|
});
|
|
95
93
|
}
|
|
96
94
|
};
|
|
@@ -117,8 +115,7 @@ export const watchSfuCallEnded = (call: Call) => {
|
|
|
117
115
|
const reason = CallEndedReason[e.reason];
|
|
118
116
|
await call.leave({ message: `callEnded received: ${reason}` });
|
|
119
117
|
} catch (err) {
|
|
120
|
-
call.logger(
|
|
121
|
-
'error',
|
|
118
|
+
call.logger.error(
|
|
122
119
|
'Failed to leave call after being ended by the SFU',
|
|
123
120
|
err,
|
|
124
121
|
);
|
package/src/events/internal.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { Dispatcher } from '../rtc';
|
|
|
2
2
|
import { Call } from '../Call';
|
|
3
3
|
import { CallState } from '../store';
|
|
4
4
|
import { StreamVideoParticipantPatches } from '../types';
|
|
5
|
-
import { getLogger } from '../logger';
|
|
6
5
|
import { pushToIfMissing, removeFromIfPresent } from '../helpers/array';
|
|
7
6
|
import type {
|
|
8
7
|
InboundStateNotification,
|
|
@@ -13,6 +12,7 @@ import {
|
|
|
13
12
|
WebsocketReconnectStrategy,
|
|
14
13
|
} from '../gen/video/sfu/models/models';
|
|
15
14
|
import { OwnCapability } from '../gen/coordinator';
|
|
15
|
+
import { videoLoggerSystem } from '../logger';
|
|
16
16
|
|
|
17
17
|
export const watchConnectionQualityChanged = (
|
|
18
18
|
dispatcher: Dispatcher,
|
|
@@ -60,7 +60,7 @@ export const watchLiveEnded = (dispatcher: Dispatcher, call: Call) => {
|
|
|
60
60
|
call.state.setBackstage(true);
|
|
61
61
|
if (!call.permissionsContext.hasPermission(OwnCapability.JOIN_BACKSTAGE)) {
|
|
62
62
|
call.leave({ message: 'live ended' }).catch((err) => {
|
|
63
|
-
call.logger('
|
|
63
|
+
call.logger.error('Failed to leave call after live ended', err);
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
66
|
});
|
|
@@ -72,9 +72,9 @@ export const watchLiveEnded = (dispatcher: Dispatcher, call: Call) => {
|
|
|
72
72
|
export const watchSfuErrorReports = (dispatcher: Dispatcher) => {
|
|
73
73
|
return dispatcher.on('error', (e) => {
|
|
74
74
|
if (!e.error) return;
|
|
75
|
-
const logger = getLogger(
|
|
75
|
+
const logger = videoLoggerSystem.getLogger('SfuClient');
|
|
76
76
|
const { error, reconnectStrategy } = e;
|
|
77
|
-
logger('
|
|
77
|
+
logger.error('SFU reported error', {
|
|
78
78
|
code: ErrorCode[error.code],
|
|
79
79
|
reconnectStrategy: WebsocketReconnectStrategy[reconnectStrategy],
|
|
80
80
|
message: error.message,
|