@stream-io/video-client 1.35.0 → 1.36.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.
- package/CHANGELOG.md +10 -0
- package/dist/index.browser.es.js +217 -236
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +239 -240
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +217 -236
- 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 +3 -2
- package/dist/src/store/CallState.d.ts +1 -1
- package/package.json +4 -3
- package/src/Call.ts +36 -48
- 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 +19 -22
- package/src/rtc/Dispatcher.ts +4 -4
- package/src/rtc/IceTrickleBuffer.ts +5 -5
- package/src/rtc/Publisher.ts +8 -8
- package/src/rtc/Subscriber.ts +12 -16
- package/src/rtc/signal.ts +7 -7
- 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/dist/index.cjs.js
CHANGED
|
@@ -5,12 +5,32 @@ var runtime = require('@protobuf-ts/runtime');
|
|
|
5
5
|
var runtimeRpc = require('@protobuf-ts/runtime-rpc');
|
|
6
6
|
var axios = require('axios');
|
|
7
7
|
var twirpTransport = require('@protobuf-ts/twirp-transport');
|
|
8
|
+
var scopedLogger = require('@stream-io/logger');
|
|
8
9
|
var rxjs = require('rxjs');
|
|
9
10
|
var uaParserJs = require('ua-parser-js');
|
|
10
11
|
var sdpTransform = require('sdp-transform');
|
|
11
12
|
var workerTimer = require('@stream-io/worker-timer');
|
|
12
13
|
var https = require('https');
|
|
13
14
|
|
|
15
|
+
function _interopNamespaceDefault(e) {
|
|
16
|
+
var n = Object.create(null);
|
|
17
|
+
if (e) {
|
|
18
|
+
Object.keys(e).forEach(function (k) {
|
|
19
|
+
if (k !== 'default') {
|
|
20
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
21
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get: function () { return e[k]; }
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
n.default = e;
|
|
29
|
+
return Object.freeze(n);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
var scopedLogger__namespace = /*#__PURE__*/_interopNamespaceDefault(scopedLogger);
|
|
33
|
+
|
|
14
34
|
/* tslint:disable */
|
|
15
35
|
/**
|
|
16
36
|
* @export
|
|
@@ -3727,7 +3747,7 @@ const withRequestLogger = (logger, level) => {
|
|
|
3727
3747
|
return {
|
|
3728
3748
|
interceptUnary: (next, method, input, options) => {
|
|
3729
3749
|
const invocation = next(method, input, options);
|
|
3730
|
-
logger(
|
|
3750
|
+
logger[level](`Invoked SFU RPC method ${method.name}`, {
|
|
3731
3751
|
request: invocation.request,
|
|
3732
3752
|
headers: invocation.requestHeaders,
|
|
3733
3753
|
response: invocation.response,
|
|
@@ -3863,16 +3883,6 @@ const isReactNative = () => {
|
|
|
3863
3883
|
return navigator.product?.toLowerCase() === 'reactnative';
|
|
3864
3884
|
};
|
|
3865
3885
|
|
|
3866
|
-
// log levels, sorted by verbosity
|
|
3867
|
-
const logLevels = Object.freeze({
|
|
3868
|
-
trace: 0,
|
|
3869
|
-
debug: 1,
|
|
3870
|
-
info: 2,
|
|
3871
|
-
warn: 3,
|
|
3872
|
-
error: 4,
|
|
3873
|
-
});
|
|
3874
|
-
let logger;
|
|
3875
|
-
let level = 'info';
|
|
3876
3886
|
const logToConsole = (logLevel, message, ...args) => {
|
|
3877
3887
|
let logMethod;
|
|
3878
3888
|
switch (logLevel) {
|
|
@@ -3904,26 +3914,7 @@ const logToConsole = (logLevel, message, ...args) => {
|
|
|
3904
3914
|
}
|
|
3905
3915
|
logMethod(message, ...args);
|
|
3906
3916
|
};
|
|
3907
|
-
const
|
|
3908
|
-
logger = l;
|
|
3909
|
-
if (lvl) {
|
|
3910
|
-
setLogLevel(lvl);
|
|
3911
|
-
}
|
|
3912
|
-
};
|
|
3913
|
-
const setLogLevel = (l) => {
|
|
3914
|
-
level = l;
|
|
3915
|
-
};
|
|
3916
|
-
const getLogLevel = () => level;
|
|
3917
|
-
const getLogger = (withTags) => {
|
|
3918
|
-
const loggerMethod = logger || logToConsole;
|
|
3919
|
-
const tags = (withTags || []).filter(Boolean).join(':');
|
|
3920
|
-
const result = (logLevel, message, ...args) => {
|
|
3921
|
-
if (logLevels[logLevel] >= logLevels[level]) {
|
|
3922
|
-
loggerMethod(logLevel, `[${tags}]: ${message}`, ...args);
|
|
3923
|
-
}
|
|
3924
|
-
};
|
|
3925
|
-
return result;
|
|
3926
|
-
};
|
|
3917
|
+
const videoLoggerSystem = scopedLogger__namespace.createLoggerSystem();
|
|
3927
3918
|
|
|
3928
3919
|
/**
|
|
3929
3920
|
* Creates a closure which wraps the given RPC call and retries invoking
|
|
@@ -3949,7 +3940,9 @@ const retryable = async (rpc, signal) => {
|
|
|
3949
3940
|
const isAborted = signal?.aborted ?? false;
|
|
3950
3941
|
if (isRequestCancelled || isAborted)
|
|
3951
3942
|
throw err;
|
|
3952
|
-
|
|
3943
|
+
videoLoggerSystem
|
|
3944
|
+
.getLogger('sfu-client', { tags: ['rpc'] })
|
|
3945
|
+
.debug(`rpc failed (${attempt})`, err);
|
|
3953
3946
|
attempt++;
|
|
3954
3947
|
}
|
|
3955
3948
|
} while (!result || result.response.error?.shouldRetry);
|
|
@@ -4020,14 +4013,14 @@ const isSfuEvent = (eventName) => {
|
|
|
4020
4013
|
};
|
|
4021
4014
|
class Dispatcher {
|
|
4022
4015
|
constructor() {
|
|
4023
|
-
this.logger = getLogger(
|
|
4016
|
+
this.logger = videoLoggerSystem.getLogger('Dispatcher');
|
|
4024
4017
|
this.subscribers = {};
|
|
4025
4018
|
this.dispatch = (message, tag = '0') => {
|
|
4026
4019
|
const eventKind = message.eventPayload.oneofKind;
|
|
4027
4020
|
if (!eventKind)
|
|
4028
4021
|
return;
|
|
4029
4022
|
const payload = message.eventPayload[eventKind];
|
|
4030
|
-
this.logger(
|
|
4023
|
+
this.logger.debug(`Dispatching ${eventKind}, tag=${tag}`, payload);
|
|
4031
4024
|
const listeners = this.subscribers[eventKind];
|
|
4032
4025
|
if (!listeners)
|
|
4033
4026
|
return;
|
|
@@ -4036,7 +4029,7 @@ class Dispatcher {
|
|
|
4036
4029
|
fn(payload);
|
|
4037
4030
|
}
|
|
4038
4031
|
catch (e) {
|
|
4039
|
-
this.logger('
|
|
4032
|
+
this.logger.warn('Listener failed with error', e);
|
|
4040
4033
|
}
|
|
4041
4034
|
}
|
|
4042
4035
|
};
|
|
@@ -4072,8 +4065,8 @@ class IceTrickleBuffer {
|
|
|
4072
4065
|
this.publisherCandidates.next(iceCandidate);
|
|
4073
4066
|
}
|
|
4074
4067
|
else {
|
|
4075
|
-
const logger = getLogger(
|
|
4076
|
-
logger(
|
|
4068
|
+
const logger = videoLoggerSystem.getLogger('sfu-client');
|
|
4069
|
+
logger.warn(`ICETrickle, Unknown peer type`, iceTrickle);
|
|
4077
4070
|
}
|
|
4078
4071
|
};
|
|
4079
4072
|
this.dispose = () => {
|
|
@@ -4087,8 +4080,8 @@ const toIceCandidate = (iceTrickle) => {
|
|
|
4087
4080
|
return JSON.parse(iceTrickle.iceCandidate);
|
|
4088
4081
|
}
|
|
4089
4082
|
catch (e) {
|
|
4090
|
-
const logger = getLogger(
|
|
4091
|
-
logger(
|
|
4083
|
+
const logger = videoLoggerSystem.getLogger('sfu-client');
|
|
4084
|
+
logger.error(`Failed to parse ICE Trickle`, e, iceTrickle);
|
|
4092
4085
|
return undefined;
|
|
4093
4086
|
}
|
|
4094
4087
|
};
|
|
@@ -4264,7 +4257,9 @@ const updateValue = (subject, update) => {
|
|
|
4264
4257
|
* @param handler the handler to call when the observable emits a value.
|
|
4265
4258
|
* @param onError an optional error handler.
|
|
4266
4259
|
*/
|
|
4267
|
-
const createSubscription = (observable, handler, onError = (error) =>
|
|
4260
|
+
const createSubscription = (observable, handler, onError = (error) => videoLoggerSystem
|
|
4261
|
+
.getLogger('RxUtils')
|
|
4262
|
+
.warn('An observable emitted an error', error)) => {
|
|
4268
4263
|
const subscription = observable.subscribe({ next: handler, error: onError });
|
|
4269
4264
|
return () => {
|
|
4270
4265
|
subscription.unsubscribe();
|
|
@@ -4384,8 +4379,8 @@ class StreamVideoWriteableStateStore {
|
|
|
4384
4379
|
* @param call the call to remove
|
|
4385
4380
|
*/
|
|
4386
4381
|
this.unregisterCall = (call) => {
|
|
4387
|
-
const logger = getLogger(
|
|
4388
|
-
logger(
|
|
4382
|
+
const logger = videoLoggerSystem.getLogger('client-state');
|
|
4383
|
+
logger.trace(`Unregistering call: ${call.cid}`);
|
|
4389
4384
|
return this.setCalls((calls) => calls.filter((c) => c !== call));
|
|
4390
4385
|
};
|
|
4391
4386
|
/**
|
|
@@ -4400,15 +4395,15 @@ class StreamVideoWriteableStateStore {
|
|
|
4400
4395
|
this.connectedUserSubject.subscribe(async (user) => {
|
|
4401
4396
|
// leave all calls when the user disconnects.
|
|
4402
4397
|
if (!user) {
|
|
4403
|
-
const logger = getLogger(
|
|
4398
|
+
const logger = videoLoggerSystem.getLogger('client-state');
|
|
4404
4399
|
for (const call of this.calls) {
|
|
4405
4400
|
if (call.state.callingState === exports.CallingState.LEFT)
|
|
4406
4401
|
continue;
|
|
4407
|
-
logger(
|
|
4402
|
+
logger.info(`User disconnected, leaving call: ${call.cid}`);
|
|
4408
4403
|
await call
|
|
4409
4404
|
.leave({ message: 'client.disconnectUser() called' })
|
|
4410
4405
|
.catch((err) => {
|
|
4411
|
-
logger(
|
|
4406
|
+
logger.error(`Error leaving call: ${call.cid}`, err);
|
|
4412
4407
|
});
|
|
4413
4408
|
}
|
|
4414
4409
|
}
|
|
@@ -4802,7 +4797,7 @@ class CallState {
|
|
|
4802
4797
|
// We keep these tracks around until we can associate them with a participant.
|
|
4803
4798
|
this.orphanedTracks = [];
|
|
4804
4799
|
this.callGrantsSubject = new rxjs.ReplaySubject(1);
|
|
4805
|
-
this.logger = getLogger(
|
|
4800
|
+
this.logger = videoLoggerSystem.getLogger('CallState');
|
|
4806
4801
|
/**
|
|
4807
4802
|
* A list of comparators that are used to sort the participants.
|
|
4808
4803
|
*/
|
|
@@ -4983,7 +4978,7 @@ class CallState {
|
|
|
4983
4978
|
this.updateParticipant = (sessionId, patch) => {
|
|
4984
4979
|
const participant = this.findParticipantBySessionId(sessionId);
|
|
4985
4980
|
if (!participant) {
|
|
4986
|
-
this.logger(
|
|
4981
|
+
this.logger.warn(`Participant with sessionId ${sessionId} not found`);
|
|
4987
4982
|
return;
|
|
4988
4983
|
}
|
|
4989
4984
|
const thePatch = typeof patch === 'function' ? patch(participant) : patch;
|
|
@@ -5862,7 +5857,7 @@ const getSdkVersion = (sdk) => {
|
|
|
5862
5857
|
return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
|
|
5863
5858
|
};
|
|
5864
5859
|
|
|
5865
|
-
const version = "1.
|
|
5860
|
+
const version = "1.36.0";
|
|
5866
5861
|
const [major, minor, patch] = version.split('.');
|
|
5867
5862
|
let sdkInfo = {
|
|
5868
5863
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -6065,7 +6060,7 @@ var browsers = /*#__PURE__*/Object.freeze({
|
|
|
6065
6060
|
* Creates a new StatsReporter instance that collects metrics about the ongoing call and reports them to the state store
|
|
6066
6061
|
*/
|
|
6067
6062
|
const createStatsReporter = ({ subscriber, publisher, state, datacenter, pollingIntervalInMs = 2000, }) => {
|
|
6068
|
-
const logger = getLogger(
|
|
6063
|
+
const logger = videoLoggerSystem.getLogger('stats');
|
|
6069
6064
|
const getRawStatsForTrack = async (kind, selector) => {
|
|
6070
6065
|
if (kind === 'subscriber' && subscriber) {
|
|
6071
6066
|
return subscriber.getStats(selector);
|
|
@@ -6124,7 +6119,7 @@ const createStatsReporter = ({ subscriber, publisher, state, datacenter, polling
|
|
|
6124
6119
|
participantStats[sessionId] = await getStatsForStream(kind, tracks);
|
|
6125
6120
|
}
|
|
6126
6121
|
catch (e) {
|
|
6127
|
-
logger(
|
|
6122
|
+
logger.warn(`Failed to collect ${kind} stats for ${userId}`, e);
|
|
6128
6123
|
}
|
|
6129
6124
|
}
|
|
6130
6125
|
}
|
|
@@ -6156,7 +6151,7 @@ const createStatsReporter = ({ subscriber, publisher, state, datacenter, polling
|
|
|
6156
6151
|
// (they are expensive) if no one is listening to them
|
|
6157
6152
|
if (state.isCallStatsReportObserved) {
|
|
6158
6153
|
await run().catch((e) => {
|
|
6159
|
-
logger('
|
|
6154
|
+
logger.debug('Failed to collect stats', e);
|
|
6160
6155
|
});
|
|
6161
6156
|
}
|
|
6162
6157
|
timeoutId = setTimeout(loop, pollingIntervalInMs);
|
|
@@ -6302,7 +6297,7 @@ const aggregate = (stats) => {
|
|
|
6302
6297
|
|
|
6303
6298
|
class SfuStatsReporter {
|
|
6304
6299
|
constructor(sfuClient, { options, clientDetails, subscriber, publisher, microphone, camera, state, tracer, unifiedSessionId, }) {
|
|
6305
|
-
this.logger = getLogger(
|
|
6300
|
+
this.logger = videoLoggerSystem.getLogger('SfuStatsReporter');
|
|
6306
6301
|
this.inputDevices = new Map();
|
|
6307
6302
|
this.observeDevice = (device, kind) => {
|
|
6308
6303
|
const { browserPermissionState$ } = device.state;
|
|
@@ -6353,7 +6348,7 @@ class SfuStatsReporter {
|
|
|
6353
6348
|
// intentionally not awaiting the promise here
|
|
6354
6349
|
// to avoid impeding with the ongoing actions.
|
|
6355
6350
|
this.run(telemetryData).catch((err) => {
|
|
6356
|
-
this.logger('
|
|
6351
|
+
this.logger.warn('Failed to send telemetry data', err);
|
|
6357
6352
|
});
|
|
6358
6353
|
};
|
|
6359
6354
|
this.run = async (telemetry) => {
|
|
@@ -6412,7 +6407,7 @@ class SfuStatsReporter {
|
|
|
6412
6407
|
clearInterval(this.intervalId);
|
|
6413
6408
|
this.intervalId = setInterval(() => {
|
|
6414
6409
|
this.run().catch((err) => {
|
|
6415
|
-
this.logger('
|
|
6410
|
+
this.logger.warn('Failed to report stats', err);
|
|
6416
6411
|
});
|
|
6417
6412
|
}, this.options.reporting_interval_ms);
|
|
6418
6413
|
};
|
|
@@ -6429,14 +6424,14 @@ class SfuStatsReporter {
|
|
|
6429
6424
|
};
|
|
6430
6425
|
this.flush = () => {
|
|
6431
6426
|
this.run().catch((err) => {
|
|
6432
|
-
this.logger('
|
|
6427
|
+
this.logger.warn('Failed to flush report stats', err);
|
|
6433
6428
|
});
|
|
6434
6429
|
};
|
|
6435
6430
|
this.scheduleOne = (timeout) => {
|
|
6436
6431
|
clearTimeout(this.timeoutId);
|
|
6437
6432
|
this.timeoutId = setTimeout(() => {
|
|
6438
6433
|
this.run().catch((err) => {
|
|
6439
|
-
this.logger('
|
|
6434
|
+
this.logger.warn('Failed to report stats', err);
|
|
6440
6435
|
});
|
|
6441
6436
|
}, timeout);
|
|
6442
6437
|
};
|
|
@@ -6807,7 +6802,7 @@ class BasePeerConnection {
|
|
|
6807
6802
|
this.tryRestartIce = () => {
|
|
6808
6803
|
this.restartIce().catch((e) => {
|
|
6809
6804
|
const reason = 'restartICE() failed, initiating reconnect';
|
|
6810
|
-
this.logger(
|
|
6805
|
+
this.logger.error(reason, e);
|
|
6811
6806
|
const strategy = e instanceof NegotiationError &&
|
|
6812
6807
|
e.error.code === ErrorCode.PARTICIPANT_SIGNAL_LOST
|
|
6813
6808
|
? WebsocketReconnectStrategy.FAST
|
|
@@ -6825,7 +6820,7 @@ class BasePeerConnection {
|
|
|
6825
6820
|
withoutConcurrency(lockKey, async () => fn(e)).catch((err) => {
|
|
6826
6821
|
if (this.isDisposed)
|
|
6827
6822
|
return;
|
|
6828
|
-
this.logger(
|
|
6823
|
+
this.logger.warn(`Error handling ${event}`, err);
|
|
6829
6824
|
});
|
|
6830
6825
|
}));
|
|
6831
6826
|
};
|
|
@@ -6842,7 +6837,7 @@ class BasePeerConnection {
|
|
|
6842
6837
|
return this.pc.addIceCandidate(candidate).catch((e) => {
|
|
6843
6838
|
if (this.isDisposed)
|
|
6844
6839
|
return;
|
|
6845
|
-
this.logger(
|
|
6840
|
+
this.logger.warn(`ICE candidate error`, e, candidate);
|
|
6846
6841
|
});
|
|
6847
6842
|
});
|
|
6848
6843
|
};
|
|
@@ -6886,7 +6881,7 @@ class BasePeerConnection {
|
|
|
6886
6881
|
this.onIceCandidate = (e) => {
|
|
6887
6882
|
const { candidate } = e;
|
|
6888
6883
|
if (!candidate) {
|
|
6889
|
-
this.logger('
|
|
6884
|
+
this.logger.debug('null ice candidate');
|
|
6890
6885
|
return;
|
|
6891
6886
|
}
|
|
6892
6887
|
const iceCandidate = this.asJSON(candidate);
|
|
@@ -6895,7 +6890,7 @@ class BasePeerConnection {
|
|
|
6895
6890
|
.catch((err) => {
|
|
6896
6891
|
if (this.isDisposed)
|
|
6897
6892
|
return;
|
|
6898
|
-
this.logger(
|
|
6893
|
+
this.logger.warn(`ICETrickle failed`, err);
|
|
6899
6894
|
});
|
|
6900
6895
|
};
|
|
6901
6896
|
/**
|
|
@@ -6916,7 +6911,7 @@ class BasePeerConnection {
|
|
|
6916
6911
|
*/
|
|
6917
6912
|
this.onConnectionStateChange = async () => {
|
|
6918
6913
|
const state = this.pc.connectionState;
|
|
6919
|
-
this.logger(
|
|
6914
|
+
this.logger.debug(`Connection state changed`, state);
|
|
6920
6915
|
if (this.tracer && (state === 'connected' || state === 'failed')) {
|
|
6921
6916
|
try {
|
|
6922
6917
|
const stats = await this.stats.get();
|
|
@@ -6938,7 +6933,7 @@ class BasePeerConnection {
|
|
|
6938
6933
|
*/
|
|
6939
6934
|
this.onIceConnectionStateChange = () => {
|
|
6940
6935
|
const state = this.pc.iceConnectionState;
|
|
6941
|
-
this.logger(
|
|
6936
|
+
this.logger.debug(`ICE connection state changed`, state);
|
|
6942
6937
|
this.handleConnectionStateUpdate(state);
|
|
6943
6938
|
};
|
|
6944
6939
|
this.handleConnectionStateUpdate = (state) => {
|
|
@@ -6953,13 +6948,13 @@ class BasePeerConnection {
|
|
|
6953
6948
|
switch (state) {
|
|
6954
6949
|
case 'failed':
|
|
6955
6950
|
// in the `failed` state, we try to restart ICE immediately
|
|
6956
|
-
this.logger('
|
|
6951
|
+
this.logger.info('restartICE due to failed connection');
|
|
6957
6952
|
this.tryRestartIce();
|
|
6958
6953
|
break;
|
|
6959
6954
|
case 'disconnected':
|
|
6960
6955
|
// in the `disconnected` state, we schedule a restartICE() after a delay
|
|
6961
6956
|
// as the browser might recover the connection in the meantime
|
|
6962
|
-
this.logger('
|
|
6957
|
+
this.logger.info('disconnected connection, scheduling restartICE');
|
|
6963
6958
|
clearTimeout(this.iceRestartTimeout);
|
|
6964
6959
|
this.iceRestartTimeout = setTimeout(() => {
|
|
6965
6960
|
const currentState = this.pc.iceConnectionState;
|
|
@@ -6971,7 +6966,7 @@ class BasePeerConnection {
|
|
|
6971
6966
|
case 'connected':
|
|
6972
6967
|
// in the `connected` state, we clear the ice restart timeout if it exists
|
|
6973
6968
|
if (this.iceRestartTimeout) {
|
|
6974
|
-
this.logger('
|
|
6969
|
+
this.logger.info('connected connection, canceling restartICE');
|
|
6975
6970
|
clearTimeout(this.iceRestartTimeout);
|
|
6976
6971
|
this.iceRestartTimeout = undefined;
|
|
6977
6972
|
}
|
|
@@ -6985,19 +6980,19 @@ class BasePeerConnection {
|
|
|
6985
6980
|
const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent
|
|
6986
6981
|
? `${e.errorCode}: ${e.errorText}`
|
|
6987
6982
|
: e;
|
|
6988
|
-
this.logger('
|
|
6983
|
+
this.logger.debug('ICE Candidate error', errorMessage);
|
|
6989
6984
|
};
|
|
6990
6985
|
/**
|
|
6991
6986
|
* Handles the ICE gathering state change event.
|
|
6992
6987
|
*/
|
|
6993
6988
|
this.onIceGatherChange = () => {
|
|
6994
|
-
this.logger(
|
|
6989
|
+
this.logger.debug(`ICE Gathering State`, this.pc.iceGatheringState);
|
|
6995
6990
|
};
|
|
6996
6991
|
/**
|
|
6997
6992
|
* Handles the signaling state change event.
|
|
6998
6993
|
*/
|
|
6999
6994
|
this.onSignalingChange = () => {
|
|
7000
|
-
this.logger(
|
|
6995
|
+
this.logger.debug(`Signaling state changed`, this.pc.signalingState);
|
|
7001
6996
|
};
|
|
7002
6997
|
this.peerType = peerType;
|
|
7003
6998
|
this.sfuClient = sfuClient;
|
|
@@ -7005,10 +7000,7 @@ class BasePeerConnection {
|
|
|
7005
7000
|
this.dispatcher = dispatcher;
|
|
7006
7001
|
this.iceRestartDelay = iceRestartDelay;
|
|
7007
7002
|
this.onReconnectionNeeded = onReconnectionNeeded;
|
|
7008
|
-
this.logger = getLogger([
|
|
7009
|
-
peerType === PeerType.SUBSCRIBER ? 'Subscriber' : 'Publisher',
|
|
7010
|
-
tag,
|
|
7011
|
-
]);
|
|
7003
|
+
this.logger = videoLoggerSystem.getLogger(peerType === PeerType.SUBSCRIBER ? 'Subscriber' : 'Publisher', { tags: [tag] });
|
|
7012
7004
|
this.pc = this.createPeerConnection(connectionConfig);
|
|
7013
7005
|
this.stats = new StatsTracer(this.pc, peerType, this.trackIdToTrackType);
|
|
7014
7006
|
if (enableTracing) {
|
|
@@ -7131,7 +7123,7 @@ class TransceiverCache {
|
|
|
7131
7123
|
}
|
|
7132
7124
|
|
|
7133
7125
|
const ensureExhausted = (x, message) => {
|
|
7134
|
-
getLogger(
|
|
7126
|
+
videoLoggerSystem.getLogger('helpers').warn(message, x);
|
|
7135
7127
|
};
|
|
7136
7128
|
|
|
7137
7129
|
const trackTypeToParticipantStreamKey = (trackType) => {
|
|
@@ -7470,7 +7462,7 @@ class Publisher extends BasePeerConnection {
|
|
|
7470
7462
|
params.degradationPreference = 'maintain-framerate';
|
|
7471
7463
|
await transceiver.sender.setParameters(params);
|
|
7472
7464
|
const trackType = publishOption.trackType;
|
|
7473
|
-
this.logger(
|
|
7465
|
+
this.logger.debug(`Added ${TrackType[trackType]} transceiver`);
|
|
7474
7466
|
this.transceiverCache.add({ publishOption, transceiver, options });
|
|
7475
7467
|
this.trackIdToTrackType.set(track.id, trackType);
|
|
7476
7468
|
await this.negotiate();
|
|
@@ -7590,16 +7582,16 @@ class Publisher extends BasePeerConnection {
|
|
|
7590
7582
|
const { trackType, layers, publishOptionId } = videoSender;
|
|
7591
7583
|
const enabledLayers = layers.filter((l) => l.active);
|
|
7592
7584
|
const tag = 'Update publish quality:';
|
|
7593
|
-
this.logger(
|
|
7585
|
+
this.logger.info(`${tag} requested layers by SFU:`, enabledLayers);
|
|
7594
7586
|
const transceiverId = this.transceiverCache.find((t) => t.publishOption.id === publishOptionId &&
|
|
7595
7587
|
t.publishOption.trackType === trackType);
|
|
7596
7588
|
const sender = transceiverId?.transceiver.sender;
|
|
7597
7589
|
if (!sender) {
|
|
7598
|
-
return this.logger(
|
|
7590
|
+
return this.logger.warn(`${tag} no video sender found.`);
|
|
7599
7591
|
}
|
|
7600
7592
|
const params = sender.getParameters();
|
|
7601
7593
|
if (params.encodings.length === 0) {
|
|
7602
|
-
return this.logger(
|
|
7594
|
+
return this.logger.warn(`${tag} there are no encodings set.`);
|
|
7603
7595
|
}
|
|
7604
7596
|
const codecInUse = transceiverId?.publishOption.codec?.name;
|
|
7605
7597
|
const usesSvcCodec = codecInUse && isSvcCodec(codecInUse);
|
|
@@ -7643,19 +7635,19 @@ class Publisher extends BasePeerConnection {
|
|
|
7643
7635
|
}
|
|
7644
7636
|
const activeEncoders = params.encodings.filter((e) => e.active);
|
|
7645
7637
|
if (!changed) {
|
|
7646
|
-
return this.logger(
|
|
7638
|
+
return this.logger.info(`${tag} no change:`, activeEncoders);
|
|
7647
7639
|
}
|
|
7648
7640
|
await sender.setParameters(params);
|
|
7649
|
-
this.logger(
|
|
7641
|
+
this.logger.info(`${tag} enabled rids:`, activeEncoders);
|
|
7650
7642
|
};
|
|
7651
7643
|
/**
|
|
7652
7644
|
* Restarts the ICE connection and renegotiates with the SFU.
|
|
7653
7645
|
*/
|
|
7654
7646
|
this.restartIce = async () => {
|
|
7655
|
-
this.logger('
|
|
7647
|
+
this.logger.debug('Restarting ICE connection');
|
|
7656
7648
|
const signalingState = this.pc.signalingState;
|
|
7657
7649
|
if (this.isIceRestarting || signalingState === 'have-local-offer') {
|
|
7658
|
-
this.logger('
|
|
7650
|
+
this.logger.debug('ICE restart is already in progress');
|
|
7659
7651
|
return;
|
|
7660
7652
|
}
|
|
7661
7653
|
await this.negotiate({ iceRestart: true });
|
|
@@ -7817,13 +7809,13 @@ class Subscriber extends BasePeerConnection {
|
|
|
7817
7809
|
* Restarts the ICE connection and renegotiates with the SFU.
|
|
7818
7810
|
*/
|
|
7819
7811
|
this.restartIce = async () => {
|
|
7820
|
-
this.logger('
|
|
7812
|
+
this.logger.debug('Restarting ICE connection');
|
|
7821
7813
|
if (this.pc.signalingState === 'have-remote-offer') {
|
|
7822
|
-
this.logger('
|
|
7814
|
+
this.logger.debug('ICE restart is already in progress');
|
|
7823
7815
|
return;
|
|
7824
7816
|
}
|
|
7825
7817
|
if (this.pc.connectionState === 'new') {
|
|
7826
|
-
this.logger(
|
|
7818
|
+
this.logger.debug(`ICE connection is not yet established, skipping restart.`);
|
|
7827
7819
|
return;
|
|
7828
7820
|
}
|
|
7829
7821
|
const previousIsIceRestarting = this.isIceRestarting;
|
|
@@ -7846,25 +7838,25 @@ class Subscriber extends BasePeerConnection {
|
|
|
7846
7838
|
// example: `e3f6aaf8-b03d-4911-be36-83f47d37a76a:TRACK_TYPE_VIDEO`
|
|
7847
7839
|
const [trackId, rawTrackType] = primaryStream.id.split(':');
|
|
7848
7840
|
const participantToUpdate = this.state.participants.find((p) => p.trackLookupPrefix === trackId);
|
|
7849
|
-
this.logger(
|
|
7841
|
+
this.logger.debug(`[onTrack]: Got remote ${rawTrackType} track for userId: ${participantToUpdate?.userId}`, e.track.id, e.track);
|
|
7850
7842
|
const trackDebugInfo = `${participantToUpdate?.userId} ${rawTrackType}:${trackId}`;
|
|
7851
7843
|
e.track.addEventListener('mute', () => {
|
|
7852
|
-
this.logger(
|
|
7844
|
+
this.logger.info(`[onTrack]: Track muted: ${trackDebugInfo}`);
|
|
7853
7845
|
});
|
|
7854
7846
|
e.track.addEventListener('unmute', () => {
|
|
7855
|
-
this.logger(
|
|
7847
|
+
this.logger.info(`[onTrack]: Track unmuted: ${trackDebugInfo}`);
|
|
7856
7848
|
});
|
|
7857
7849
|
e.track.addEventListener('ended', () => {
|
|
7858
|
-
this.logger(
|
|
7850
|
+
this.logger.info(`[onTrack]: Track ended: ${trackDebugInfo}`);
|
|
7859
7851
|
this.state.removeOrphanedTrack(primaryStream.id);
|
|
7860
7852
|
});
|
|
7861
7853
|
const trackType = toTrackType(rawTrackType);
|
|
7862
7854
|
if (!trackType) {
|
|
7863
|
-
return this.logger(
|
|
7855
|
+
return this.logger.error(`Unknown track type: ${rawTrackType}`);
|
|
7864
7856
|
}
|
|
7865
7857
|
this.trackIdToTrackType.set(e.track.id, trackType);
|
|
7866
7858
|
if (!participantToUpdate) {
|
|
7867
|
-
this.logger(
|
|
7859
|
+
this.logger.warn(`[onTrack]: Received track for unknown participant: ${trackId}`, e);
|
|
7868
7860
|
this.state.registerOrphanedTrack({
|
|
7869
7861
|
id: primaryStream.id,
|
|
7870
7862
|
trackLookupPrefix: trackId,
|
|
@@ -7875,7 +7867,7 @@ class Subscriber extends BasePeerConnection {
|
|
|
7875
7867
|
}
|
|
7876
7868
|
const streamKindProp = trackTypeToParticipantStreamKey(trackType);
|
|
7877
7869
|
if (!streamKindProp) {
|
|
7878
|
-
this.logger(
|
|
7870
|
+
this.logger.error(`Unknown track type: ${rawTrackType}`);
|
|
7879
7871
|
return;
|
|
7880
7872
|
}
|
|
7881
7873
|
// get the previous stream to dispose it later
|
|
@@ -7888,7 +7880,7 @@ class Subscriber extends BasePeerConnection {
|
|
|
7888
7880
|
});
|
|
7889
7881
|
// now, dispose the previous stream if it exists
|
|
7890
7882
|
if (previousStream) {
|
|
7891
|
-
this.logger(
|
|
7883
|
+
this.logger.info(`[onTrack]: Cleaning up previous remote ${e.track.kind} tracks for userId: ${participantToUpdate.userId}`);
|
|
7892
7884
|
previousStream.getTracks().forEach((t) => {
|
|
7893
7885
|
t.stop();
|
|
7894
7886
|
previousStream.removeTrack(t);
|
|
@@ -7915,7 +7907,7 @@ class Subscriber extends BasePeerConnection {
|
|
|
7915
7907
|
this.pc.addEventListener('track', this.handleOnTrack);
|
|
7916
7908
|
this.on('subscriberOffer', async (subscriberOffer) => {
|
|
7917
7909
|
return this.negotiate(subscriberOffer).catch((err) => {
|
|
7918
|
-
this.logger(
|
|
7910
|
+
this.logger.error(`Negotiation failed.`, err);
|
|
7919
7911
|
});
|
|
7920
7912
|
});
|
|
7921
7913
|
}
|
|
@@ -7932,20 +7924,20 @@ class Subscriber extends BasePeerConnection {
|
|
|
7932
7924
|
|
|
7933
7925
|
const createWebSocketSignalChannel = (opts) => {
|
|
7934
7926
|
const { endpoint, onMessage, tag, tracer } = opts;
|
|
7935
|
-
const logger = getLogger(
|
|
7936
|
-
logger('
|
|
7927
|
+
const logger = videoLoggerSystem.getLogger('SfuClientWS', { tags: [tag] });
|
|
7928
|
+
logger.debug('Creating signaling WS channel:', endpoint);
|
|
7937
7929
|
const ws = new WebSocket(endpoint);
|
|
7938
7930
|
ws.binaryType = 'arraybuffer'; // do we need this?
|
|
7939
7931
|
ws.addEventListener('error', (e) => {
|
|
7940
|
-
logger('
|
|
7932
|
+
logger.error('Signaling WS channel error', e);
|
|
7941
7933
|
tracer?.trace('signal.ws.error', e);
|
|
7942
7934
|
});
|
|
7943
7935
|
ws.addEventListener('close', (e) => {
|
|
7944
|
-
logger('
|
|
7936
|
+
logger.info('Signaling WS channel is closed', e);
|
|
7945
7937
|
tracer?.trace('signal.ws.close', e);
|
|
7946
7938
|
});
|
|
7947
7939
|
ws.addEventListener('open', (e) => {
|
|
7948
|
-
logger('
|
|
7940
|
+
logger.info('Signaling WS channel is open', e);
|
|
7949
7941
|
tracer?.trace('signal.ws.open', e);
|
|
7950
7942
|
});
|
|
7951
7943
|
ws.addEventListener('message', (e) => {
|
|
@@ -7957,7 +7949,7 @@ const createWebSocketSignalChannel = (opts) => {
|
|
|
7957
7949
|
}
|
|
7958
7950
|
catch (err) {
|
|
7959
7951
|
const message = 'Failed to decode a message. Check whether the Proto models match.';
|
|
7960
|
-
logger(
|
|
7952
|
+
logger.error(message, { event: e, error: err });
|
|
7961
7953
|
tracer?.trace('signal.ws.message.error', message);
|
|
7962
7954
|
}
|
|
7963
7955
|
});
|
|
@@ -8158,14 +8150,14 @@ class StreamSfuClient {
|
|
|
8158
8150
|
this.close = (code = StreamSfuClient.NORMAL_CLOSURE, reason) => {
|
|
8159
8151
|
this.isClosingClean = code !== StreamSfuClient.ERROR_CONNECTION_UNHEALTHY;
|
|
8160
8152
|
if (this.signalWs.readyState === WebSocket.OPEN) {
|
|
8161
|
-
this.logger(
|
|
8153
|
+
this.logger.debug(`Closing SFU WS connection: ${code} - ${reason}`);
|
|
8162
8154
|
this.signalWs.close(code, `js-client: ${reason}`);
|
|
8163
8155
|
this.signalWs.removeEventListener('close', this.handleWebSocketClose);
|
|
8164
8156
|
}
|
|
8165
8157
|
this.dispose();
|
|
8166
8158
|
};
|
|
8167
8159
|
this.dispose = () => {
|
|
8168
|
-
this.logger('
|
|
8160
|
+
this.logger.debug('Disposing SFU client');
|
|
8169
8161
|
this.unsubscribeIceTrickle();
|
|
8170
8162
|
this.unsubscribeNetworkChanged();
|
|
8171
8163
|
clearInterval(this.keepAliveInterval);
|
|
@@ -8185,7 +8177,7 @@ class StreamSfuClient {
|
|
|
8185
8177
|
await this.notifyLeave(reason);
|
|
8186
8178
|
}
|
|
8187
8179
|
catch (err) {
|
|
8188
|
-
this.logger('
|
|
8180
|
+
this.logger.debug('Error notifying SFU about leaving call', err);
|
|
8189
8181
|
}
|
|
8190
8182
|
this.close(StreamSfuClient.NORMAL_CLOSURE, reason.substring(0, 115));
|
|
8191
8183
|
};
|
|
@@ -8306,10 +8298,10 @@ class StreamSfuClient {
|
|
|
8306
8298
|
await this.signalReady(); // wait for the signal ws to be open
|
|
8307
8299
|
const msgJson = SfuRequest.toJson(message);
|
|
8308
8300
|
if (this.signalWs.readyState !== WebSocket.OPEN) {
|
|
8309
|
-
this.logger('
|
|
8301
|
+
this.logger.debug('Signal WS is not open. Skipping message', msgJson);
|
|
8310
8302
|
return;
|
|
8311
8303
|
}
|
|
8312
|
-
this.logger(
|
|
8304
|
+
this.logger.debug(`Sending message to: ${this.edgeName}`, msgJson);
|
|
8313
8305
|
this.signalWs.send(SfuRequest.toBinary(message));
|
|
8314
8306
|
};
|
|
8315
8307
|
this.keepAlive = () => {
|
|
@@ -8317,7 +8309,7 @@ class StreamSfuClient {
|
|
|
8317
8309
|
timers.clearInterval(this.keepAliveInterval);
|
|
8318
8310
|
this.keepAliveInterval = timers.setInterval(() => {
|
|
8319
8311
|
this.ping().catch((e) => {
|
|
8320
|
-
this.logger('
|
|
8312
|
+
this.logger.error('Error sending healthCheckRequest to SFU', e);
|
|
8321
8313
|
});
|
|
8322
8314
|
}, this.pingIntervalInMs);
|
|
8323
8315
|
};
|
|
@@ -8340,7 +8332,7 @@ class StreamSfuClient {
|
|
|
8340
8332
|
this.edgeName = server.edge_name;
|
|
8341
8333
|
this.joinResponseTimeout = joinResponseTimeout;
|
|
8342
8334
|
this.tag = tag;
|
|
8343
|
-
this.logger = getLogger(
|
|
8335
|
+
this.logger = videoLoggerSystem.getLogger('SfuClient', { tags: [tag] });
|
|
8344
8336
|
this.tracer = enableTracing
|
|
8345
8337
|
? new Tracer(`${tag}-${this.edgeName}`)
|
|
8346
8338
|
: undefined;
|
|
@@ -8349,7 +8341,8 @@ class StreamSfuClient {
|
|
|
8349
8341
|
interceptors: [
|
|
8350
8342
|
withHeaders({ Authorization: `Bearer ${token}` }),
|
|
8351
8343
|
this.tracer && withRequestTracer(this.tracer.trace),
|
|
8352
|
-
getLogLevel() === 'trace' &&
|
|
8344
|
+
this.logger.getLogLevel() === 'trace' &&
|
|
8345
|
+
withRequestLogger(this.logger, 'trace'),
|
|
8353
8346
|
].filter((v) => !!v),
|
|
8354
8347
|
});
|
|
8355
8348
|
// Special handling for the ICETrickle kind of events.
|
|
@@ -8437,13 +8430,13 @@ const watchCallRejected = (call) => {
|
|
|
8437
8430
|
const { call: eventCall } = event;
|
|
8438
8431
|
const { session: callSession } = eventCall;
|
|
8439
8432
|
if (!callSession) {
|
|
8440
|
-
call.logger('
|
|
8433
|
+
call.logger.warn('No call session provided. Ignoring call.rejected event.', event);
|
|
8441
8434
|
return;
|
|
8442
8435
|
}
|
|
8443
8436
|
const rejectedBy = callSession.rejected_by;
|
|
8444
8437
|
const { members, callingState } = call.state;
|
|
8445
8438
|
if (callingState !== exports.CallingState.RINGING) {
|
|
8446
|
-
call.logger('
|
|
8439
|
+
call.logger.info('Call is not in ringing mode (it is either accepted or rejected already). Ignoring call.rejected event.', event);
|
|
8447
8440
|
return;
|
|
8448
8441
|
}
|
|
8449
8442
|
if (call.isCreatedByMe) {
|
|
@@ -8451,7 +8444,7 @@ const watchCallRejected = (call) => {
|
|
|
8451
8444
|
.filter((m) => m.user_id !== call.currentUserId)
|
|
8452
8445
|
.every((m) => rejectedBy[m.user_id]);
|
|
8453
8446
|
if (everyoneElseRejected) {
|
|
8454
|
-
call.logger('
|
|
8447
|
+
call.logger.info('everyone rejected, leaving the call');
|
|
8455
8448
|
await call.leave({
|
|
8456
8449
|
reject: true,
|
|
8457
8450
|
reason: 'cancel',
|
|
@@ -8461,7 +8454,7 @@ const watchCallRejected = (call) => {
|
|
|
8461
8454
|
}
|
|
8462
8455
|
else {
|
|
8463
8456
|
if (rejectedBy[eventCall.created_by.id]) {
|
|
8464
|
-
call.logger('
|
|
8457
|
+
call.logger.info('call creator rejected, leaving call');
|
|
8465
8458
|
await call.leave({ message: 'ring: creator rejected' });
|
|
8466
8459
|
}
|
|
8467
8460
|
}
|
|
@@ -8478,7 +8471,7 @@ const watchCallEnded = (call) => {
|
|
|
8478
8471
|
call
|
|
8479
8472
|
.leave({ message: 'call.ended event received', reject: false })
|
|
8480
8473
|
.catch((err) => {
|
|
8481
|
-
call.logger('
|
|
8474
|
+
call.logger.error('Failed to leave call after call.ended ', err);
|
|
8482
8475
|
});
|
|
8483
8476
|
}
|
|
8484
8477
|
};
|
|
@@ -8506,7 +8499,7 @@ const watchSfuCallEnded = (call) => {
|
|
|
8506
8499
|
await call.leave({ message: `callEnded received: ${reason}` });
|
|
8507
8500
|
}
|
|
8508
8501
|
catch (err) {
|
|
8509
|
-
call.logger('
|
|
8502
|
+
call.logger.error('Failed to leave call after being ended by the SFU', err);
|
|
8510
8503
|
}
|
|
8511
8504
|
});
|
|
8512
8505
|
};
|
|
@@ -8589,7 +8582,7 @@ const watchLiveEnded = (dispatcher, call) => {
|
|
|
8589
8582
|
call.state.setBackstage(true);
|
|
8590
8583
|
if (!call.permissionsContext.hasPermission(OwnCapability.JOIN_BACKSTAGE)) {
|
|
8591
8584
|
call.leave({ message: 'live ended' }).catch((err) => {
|
|
8592
|
-
call.logger('
|
|
8585
|
+
call.logger.error('Failed to leave call after live ended', err);
|
|
8593
8586
|
});
|
|
8594
8587
|
}
|
|
8595
8588
|
});
|
|
@@ -8601,9 +8594,9 @@ const watchSfuErrorReports = (dispatcher) => {
|
|
|
8601
8594
|
return dispatcher.on('error', (e) => {
|
|
8602
8595
|
if (!e.error)
|
|
8603
8596
|
return;
|
|
8604
|
-
const logger = getLogger(
|
|
8597
|
+
const logger = videoLoggerSystem.getLogger('SfuClient');
|
|
8605
8598
|
const { error, reconnectStrategy } = e;
|
|
8606
|
-
logger('
|
|
8599
|
+
logger.error('SFU reported error', {
|
|
8607
8600
|
code: ErrorCode[error.code],
|
|
8608
8601
|
reconnectStrategy: WebsocketReconnectStrategy[reconnectStrategy],
|
|
8609
8602
|
message: error.message,
|
|
@@ -8657,7 +8650,7 @@ const handleRemoteSoftMute = (call) => {
|
|
|
8657
8650
|
if (cause === TrackUnpublishReason.MODERATION &&
|
|
8658
8651
|
sessionId === localParticipant?.sessionId) {
|
|
8659
8652
|
const logger = call.logger;
|
|
8660
|
-
logger(
|
|
8653
|
+
logger.info(`Local participant's ${TrackType[type]} track is muted remotely`);
|
|
8661
8654
|
try {
|
|
8662
8655
|
if (type === TrackType.VIDEO) {
|
|
8663
8656
|
await call.camera.disable();
|
|
@@ -8670,11 +8663,11 @@ const handleRemoteSoftMute = (call) => {
|
|
|
8670
8663
|
await call.screenShare.disable();
|
|
8671
8664
|
}
|
|
8672
8665
|
else {
|
|
8673
|
-
logger('
|
|
8666
|
+
logger.warn('Unsupported track type to soft mute', TrackType[type]);
|
|
8674
8667
|
}
|
|
8675
8668
|
}
|
|
8676
8669
|
catch (error) {
|
|
8677
|
-
logger('
|
|
8670
|
+
logger.error('Failed to stop publishing', error);
|
|
8678
8671
|
}
|
|
8679
8672
|
}
|
|
8680
8673
|
});
|
|
@@ -8995,7 +8988,7 @@ class DynascaleManager {
|
|
|
8995
8988
|
* The viewport tracker instance.
|
|
8996
8989
|
*/
|
|
8997
8990
|
this.viewportTracker = new ViewportTracker();
|
|
8998
|
-
this.logger = getLogger(
|
|
8991
|
+
this.logger = videoLoggerSystem.getLogger('DynascaleManager');
|
|
8999
8992
|
this.pendingSubscriptionsUpdate = null;
|
|
9000
8993
|
this.videoTrackSubscriptionOverridesSubject = new rxjs.BehaviorSubject({});
|
|
9001
8994
|
this.videoTrackSubscriptionOverrides$ = this.videoTrackSubscriptionOverridesSubject.asObservable();
|
|
@@ -9052,7 +9045,7 @@ class DynascaleManager {
|
|
|
9052
9045
|
this.sfuClient
|
|
9053
9046
|
?.updateSubscriptions(this.trackSubscriptions)
|
|
9054
9047
|
.catch((err) => {
|
|
9055
|
-
this.logger(
|
|
9048
|
+
this.logger.debug(`Failed to update track subscriptions`, err);
|
|
9056
9049
|
});
|
|
9057
9050
|
};
|
|
9058
9051
|
if (debounceType) {
|
|
@@ -9141,7 +9134,7 @@ class DynascaleManager {
|
|
|
9141
9134
|
// is not visible (e.g., has display: none).
|
|
9142
9135
|
// we treat this as "unsubscription" as we don't want to keep
|
|
9143
9136
|
// consuming bandwidth for a video that is not visible on the screen.
|
|
9144
|
-
this.logger(
|
|
9137
|
+
this.logger.debug(`Ignoring 0x0 dimension`, boundParticipant);
|
|
9145
9138
|
dimension = undefined;
|
|
9146
9139
|
}
|
|
9147
9140
|
this.callState.updateParticipantTracks(trackType, {
|
|
@@ -9246,7 +9239,7 @@ class DynascaleManager {
|
|
|
9246
9239
|
setTimeout(() => {
|
|
9247
9240
|
videoElement.srcObject = source ?? null;
|
|
9248
9241
|
videoElement.play().catch((e) => {
|
|
9249
|
-
this.logger(
|
|
9242
|
+
this.logger.warn(`Failed to play stream`, e);
|
|
9250
9243
|
});
|
|
9251
9244
|
// we add extra delay until we attempt to force-play
|
|
9252
9245
|
// the participant's media stream in Firefox and Safari,
|
|
@@ -9283,13 +9276,13 @@ class DynascaleManager {
|
|
|
9283
9276
|
return;
|
|
9284
9277
|
if ('setSinkId' in audioElement) {
|
|
9285
9278
|
audioElement.setSinkId(deviceId).catch((e) => {
|
|
9286
|
-
this.logger(
|
|
9279
|
+
this.logger.warn(`Can't to set AudioElement sinkId`, e);
|
|
9287
9280
|
});
|
|
9288
9281
|
}
|
|
9289
9282
|
if (audioContext && 'setSinkId' in audioContext) {
|
|
9290
9283
|
// @ts-expect-error setSinkId is not available in all browsers
|
|
9291
9284
|
audioContext.setSinkId(deviceId).catch((e) => {
|
|
9292
|
-
this.logger(
|
|
9285
|
+
this.logger.warn(`Can't to set AudioContext sinkId`, e);
|
|
9293
9286
|
});
|
|
9294
9287
|
}
|
|
9295
9288
|
};
|
|
@@ -9331,7 +9324,7 @@ class DynascaleManager {
|
|
|
9331
9324
|
// we will play audio directly through the audio element in other browsers
|
|
9332
9325
|
audioElement.muted = false;
|
|
9333
9326
|
audioElement.play().catch((e) => {
|
|
9334
|
-
this.logger(
|
|
9327
|
+
this.logger.warn(`Failed to play audio stream`, e);
|
|
9335
9328
|
});
|
|
9336
9329
|
}
|
|
9337
9330
|
const { selectedDevice } = this.speaker.state;
|
|
@@ -9383,7 +9376,7 @@ class DynascaleManager {
|
|
|
9383
9376
|
if (this.audioContext?.state === 'suspended') {
|
|
9384
9377
|
this.audioContext
|
|
9385
9378
|
.resume()
|
|
9386
|
-
.catch((err) => this.logger(
|
|
9379
|
+
.catch((err) => this.logger.warn(`Can't resume audio context`, err))
|
|
9387
9380
|
.then(() => {
|
|
9388
9381
|
document.removeEventListener('click', this.resumeAudioContext);
|
|
9389
9382
|
});
|
|
@@ -9620,7 +9613,7 @@ class BrowserPermission {
|
|
|
9620
9613
|
this.disposeController = new AbortController();
|
|
9621
9614
|
this.wasPrompted = false;
|
|
9622
9615
|
this.listeners = new Set();
|
|
9623
|
-
this.logger = getLogger(
|
|
9616
|
+
this.logger = videoLoggerSystem.getLogger('permissions');
|
|
9624
9617
|
const signal = this.disposeController.signal;
|
|
9625
9618
|
this.ready = (async () => {
|
|
9626
9619
|
const assumeGranted = () => {
|
|
@@ -9646,7 +9639,7 @@ class BrowserPermission {
|
|
|
9646
9639
|
}
|
|
9647
9640
|
}
|
|
9648
9641
|
catch (err) {
|
|
9649
|
-
this.logger('
|
|
9642
|
+
this.logger.debug('Failed to query permission status', err);
|
|
9650
9643
|
assumeGranted();
|
|
9651
9644
|
}
|
|
9652
9645
|
})();
|
|
@@ -9685,7 +9678,7 @@ class BrowserPermission {
|
|
|
9685
9678
|
typeof e === 'object' &&
|
|
9686
9679
|
'name' in e &&
|
|
9687
9680
|
(e.name === 'NotAllowedError' || e.name === 'SecurityError')) {
|
|
9688
|
-
this.logger('
|
|
9681
|
+
this.logger.info('Browser permission was not granted', {
|
|
9689
9682
|
permission: this.permission,
|
|
9690
9683
|
});
|
|
9691
9684
|
this.setState('denied');
|
|
@@ -9694,7 +9687,7 @@ class BrowserPermission {
|
|
|
9694
9687
|
}
|
|
9695
9688
|
return false;
|
|
9696
9689
|
}
|
|
9697
|
-
this.logger(
|
|
9690
|
+
this.logger.error(`Failed to getUserMedia`, {
|
|
9698
9691
|
error: e,
|
|
9699
9692
|
permission: this.permission,
|
|
9700
9693
|
});
|
|
@@ -9915,10 +9908,12 @@ const getAudioStream = async (trackConstraints, tracer) => {
|
|
|
9915
9908
|
if (isNotFoundOrOverconstrainedError(error) && trackConstraints?.deviceId) {
|
|
9916
9909
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9917
9910
|
const { deviceId, ...relaxedConstraints } = trackConstraints;
|
|
9918
|
-
|
|
9911
|
+
videoLoggerSystem
|
|
9912
|
+
.getLogger('devices')
|
|
9913
|
+
.warn('Failed to get audio stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
|
|
9919
9914
|
return getAudioStream(relaxedConstraints);
|
|
9920
9915
|
}
|
|
9921
|
-
getLogger(
|
|
9916
|
+
videoLoggerSystem.getLogger('devices').error('Failed to get audio stream', {
|
|
9922
9917
|
error,
|
|
9923
9918
|
constraints,
|
|
9924
9919
|
});
|
|
@@ -9951,10 +9946,12 @@ const getVideoStream = async (trackConstraints, tracer) => {
|
|
|
9951
9946
|
if (isNotFoundOrOverconstrainedError(error) && trackConstraints?.deviceId) {
|
|
9952
9947
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9953
9948
|
const { deviceId, ...relaxedConstraints } = trackConstraints;
|
|
9954
|
-
|
|
9949
|
+
videoLoggerSystem
|
|
9950
|
+
.getLogger('devices')
|
|
9951
|
+
.warn('Failed to get video stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
|
|
9955
9952
|
return getVideoStream(relaxedConstraints);
|
|
9956
9953
|
}
|
|
9957
|
-
getLogger(
|
|
9954
|
+
videoLoggerSystem.getLogger('devices').error('Failed to get video stream', {
|
|
9958
9955
|
error,
|
|
9959
9956
|
constraints,
|
|
9960
9957
|
});
|
|
@@ -10003,7 +10000,9 @@ const getScreenShareStream = async (options, tracer) => {
|
|
|
10003
10000
|
}
|
|
10004
10001
|
catch (e) {
|
|
10005
10002
|
tracer?.trace(`${tag}OnFailure`, e.name);
|
|
10006
|
-
|
|
10003
|
+
videoLoggerSystem
|
|
10004
|
+
.getLogger('devices')
|
|
10005
|
+
.error('Failed to get screen share stream', e);
|
|
10007
10006
|
throw e;
|
|
10008
10007
|
}
|
|
10009
10008
|
};
|
|
@@ -10065,7 +10064,7 @@ class DeviceManager {
|
|
|
10065
10064
|
this.call = call;
|
|
10066
10065
|
this.state = state;
|
|
10067
10066
|
this.trackType = trackType;
|
|
10068
|
-
this.logger = getLogger(
|
|
10067
|
+
this.logger = videoLoggerSystem.getLogger(`${TrackType[trackType].toLowerCase()} manager`);
|
|
10069
10068
|
this.setup();
|
|
10070
10069
|
}
|
|
10071
10070
|
setup() {
|
|
@@ -10228,6 +10227,7 @@ class DeviceManager {
|
|
|
10228
10227
|
}
|
|
10229
10228
|
}
|
|
10230
10229
|
async applySettingsToStream() {
|
|
10230
|
+
console.log('applySettingsToStream ');
|
|
10231
10231
|
await withCancellation(this.statusChangeConcurrencyTag, async (signal) => {
|
|
10232
10232
|
if (this.enabled) {
|
|
10233
10233
|
try {
|
|
@@ -10260,7 +10260,7 @@ class DeviceManager {
|
|
|
10260
10260
|
const mediaStream = this.state.mediaStream;
|
|
10261
10261
|
if (!mediaStream)
|
|
10262
10262
|
return;
|
|
10263
|
-
this.logger(
|
|
10263
|
+
this.logger.debug(`${stopTracks ? 'Stopping' : 'Disabling'} stream`);
|
|
10264
10264
|
if (this.call.state.callingState === exports.CallingState.JOINED) {
|
|
10265
10265
|
await this.stopPublishStream();
|
|
10266
10266
|
}
|
|
@@ -10306,7 +10306,7 @@ class DeviceManager {
|
|
|
10306
10306
|
}
|
|
10307
10307
|
}
|
|
10308
10308
|
async unmuteStream() {
|
|
10309
|
-
this.logger('
|
|
10309
|
+
this.logger.debug('Starting stream');
|
|
10310
10310
|
let stream;
|
|
10311
10311
|
let rootStream;
|
|
10312
10312
|
if (this.state.mediaStream &&
|
|
@@ -10387,7 +10387,7 @@ class DeviceManager {
|
|
|
10387
10387
|
return output;
|
|
10388
10388
|
})
|
|
10389
10389
|
.then(chainWith(parent), (error) => {
|
|
10390
|
-
this.logger('
|
|
10390
|
+
this.logger.warn('Filter failed to start and will be ignored', error);
|
|
10391
10391
|
return parent;
|
|
10392
10392
|
}), rootStream);
|
|
10393
10393
|
}
|
|
@@ -10410,7 +10410,7 @@ class DeviceManager {
|
|
|
10410
10410
|
if (!isMobile() || this.trackType !== TrackType.VIDEO)
|
|
10411
10411
|
return;
|
|
10412
10412
|
this.call.notifyTrackMuteState(muted, this.trackType).catch((err) => {
|
|
10413
|
-
this.logger('
|
|
10413
|
+
this.logger.warn('Error while notifying track mute state', err);
|
|
10414
10414
|
});
|
|
10415
10415
|
};
|
|
10416
10416
|
stream.getTracks().forEach((track) => {
|
|
@@ -10474,7 +10474,7 @@ class DeviceManager {
|
|
|
10474
10474
|
}
|
|
10475
10475
|
}
|
|
10476
10476
|
catch (err) {
|
|
10477
|
-
this.logger('
|
|
10477
|
+
this.logger.warn('Unexpected error while handling disconnected or replaced device', err);
|
|
10478
10478
|
}
|
|
10479
10479
|
}));
|
|
10480
10480
|
}
|
|
@@ -10681,7 +10681,7 @@ class CameraManager extends DeviceManager {
|
|
|
10681
10681
|
*/
|
|
10682
10682
|
async selectDirection(direction) {
|
|
10683
10683
|
if (!this.isDirectionSupportedByDevice()) {
|
|
10684
|
-
this.logger('
|
|
10684
|
+
this.logger.warn('Setting direction is not supported on this device');
|
|
10685
10685
|
return;
|
|
10686
10686
|
}
|
|
10687
10687
|
if (isReactNative()) {
|
|
@@ -10732,7 +10732,7 @@ class CameraManager extends DeviceManager {
|
|
|
10732
10732
|
}
|
|
10733
10733
|
catch (error) {
|
|
10734
10734
|
// couldn't enable device, target resolution will be applied the next time user attempts to start the device
|
|
10735
|
-
this.logger('
|
|
10735
|
+
this.logger.warn('could not apply target resolution', error);
|
|
10736
10736
|
}
|
|
10737
10737
|
}
|
|
10738
10738
|
if (this.enabled && this.state.mediaStream) {
|
|
@@ -10743,7 +10743,7 @@ class CameraManager extends DeviceManager {
|
|
|
10743
10743
|
if (width !== this.targetResolution.width ||
|
|
10744
10744
|
height !== this.targetResolution.height) {
|
|
10745
10745
|
await this.applySettingsToStream();
|
|
10746
|
-
this.logger(
|
|
10746
|
+
this.logger.debug(`${width}x${height} target resolution applied to media stream`);
|
|
10747
10747
|
}
|
|
10748
10748
|
}
|
|
10749
10749
|
}
|
|
@@ -11007,8 +11007,8 @@ class RNSpeechDetector {
|
|
|
11007
11007
|
};
|
|
11008
11008
|
}
|
|
11009
11009
|
catch (error) {
|
|
11010
|
-
const logger = getLogger(
|
|
11011
|
-
logger('error
|
|
11010
|
+
const logger = videoLoggerSystem.getLogger('RNSpeechDetector');
|
|
11011
|
+
logger.error('error handling permissions: ', error);
|
|
11012
11012
|
return () => { };
|
|
11013
11013
|
}
|
|
11014
11014
|
}
|
|
@@ -11092,8 +11092,8 @@ class RNSpeechDetector {
|
|
|
11092
11092
|
}
|
|
11093
11093
|
}
|
|
11094
11094
|
catch (error) {
|
|
11095
|
-
const logger = getLogger(
|
|
11096
|
-
logger('error
|
|
11095
|
+
const logger = videoLoggerSystem.getLogger('RNSpeechDetector');
|
|
11096
|
+
logger.error('error checking audio level from stats', error);
|
|
11097
11097
|
}
|
|
11098
11098
|
};
|
|
11099
11099
|
// Call checkAudioLevel periodically (every 100ms)
|
|
@@ -11153,7 +11153,7 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
11153
11153
|
}
|
|
11154
11154
|
}
|
|
11155
11155
|
catch (err) {
|
|
11156
|
-
this.logger('
|
|
11156
|
+
this.logger.warn('Could not enable speaking while muted', err);
|
|
11157
11157
|
}
|
|
11158
11158
|
}));
|
|
11159
11159
|
this.subscriptions.push(createSubscription(this.call.state.callingState$, (callingState) => {
|
|
@@ -11176,7 +11176,7 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
11176
11176
|
}
|
|
11177
11177
|
})
|
|
11178
11178
|
.catch((err) => {
|
|
11179
|
-
this.logger(
|
|
11179
|
+
this.logger.warn(`Failed to enable noise cancellation`, err);
|
|
11180
11180
|
return this.call.notifyNoiseCancellationStopped();
|
|
11181
11181
|
});
|
|
11182
11182
|
}
|
|
@@ -11184,7 +11184,7 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
11184
11184
|
this.noiseCancellationRegistration
|
|
11185
11185
|
.then(() => this.noiseCancellation?.disable())
|
|
11186
11186
|
.catch((err) => {
|
|
11187
|
-
this.logger(
|
|
11187
|
+
this.logger.warn(`Failed to disable noise cancellation`, err);
|
|
11188
11188
|
});
|
|
11189
11189
|
}
|
|
11190
11190
|
}));
|
|
@@ -11213,12 +11213,12 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
11213
11213
|
this.call.tracer.trace('noiseCancellation.enabled', enabled);
|
|
11214
11214
|
if (enabled) {
|
|
11215
11215
|
this.call.notifyNoiseCancellationStarting().catch((err) => {
|
|
11216
|
-
this.logger(
|
|
11216
|
+
this.logger.warn(`notifyNoiseCancellationStart failed`, err);
|
|
11217
11217
|
});
|
|
11218
11218
|
}
|
|
11219
11219
|
else {
|
|
11220
11220
|
this.call.notifyNoiseCancellationStopped().catch((err) => {
|
|
11221
|
-
this.logger(
|
|
11221
|
+
this.logger.warn(`notifyNoiseCancellationStop failed`, err);
|
|
11222
11222
|
});
|
|
11223
11223
|
}
|
|
11224
11224
|
});
|
|
@@ -11247,9 +11247,9 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
11247
11247
|
}
|
|
11248
11248
|
}
|
|
11249
11249
|
catch (e) {
|
|
11250
|
-
this.logger('
|
|
11250
|
+
this.logger.warn('Failed to enable noise cancellation', e);
|
|
11251
11251
|
await this.disableNoiseCancellation().catch((err) => {
|
|
11252
|
-
this.logger('
|
|
11252
|
+
this.logger.warn('Failed to disable noise cancellation', err);
|
|
11253
11253
|
});
|
|
11254
11254
|
throw e;
|
|
11255
11255
|
}
|
|
@@ -11262,7 +11262,7 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
11262
11262
|
.then(() => this.noiseCancellation?.disable())
|
|
11263
11263
|
.then(() => this.noiseCancellationChangeUnsubscribe?.())
|
|
11264
11264
|
.catch((err) => {
|
|
11265
|
-
this.logger('
|
|
11265
|
+
this.logger.warn('Failed to unregister noise cancellation', err);
|
|
11266
11266
|
});
|
|
11267
11267
|
this.call.tracer.trace('noiseCancellation.disabled', true);
|
|
11268
11268
|
await this.call.notifyNoiseCancellationStopped();
|
|
@@ -11770,9 +11770,9 @@ class Call {
|
|
|
11770
11770
|
return;
|
|
11771
11771
|
const currentUserId = this.currentUserId;
|
|
11772
11772
|
if (currentUserId && blockedUserIds.includes(currentUserId)) {
|
|
11773
|
-
this.logger('
|
|
11773
|
+
this.logger.info('Leaving call because of being blocked');
|
|
11774
11774
|
await this.leave({ message: 'user blocked' }).catch((err) => {
|
|
11775
|
-
this.logger('
|
|
11775
|
+
this.logger.error('Error leaving call after being blocked', err);
|
|
11776
11776
|
});
|
|
11777
11777
|
}
|
|
11778
11778
|
}));
|
|
@@ -11808,7 +11808,7 @@ class Call {
|
|
|
11808
11808
|
if ((isAcceptedElsewhere || isRejectedByMe) &&
|
|
11809
11809
|
!hasPending(this.joinLeaveConcurrencyTag)) {
|
|
11810
11810
|
this.leave().catch(() => {
|
|
11811
|
-
this.logger('
|
|
11811
|
+
this.logger.error('Could not leave a call that was accepted or rejected elsewhere');
|
|
11812
11812
|
});
|
|
11813
11813
|
}
|
|
11814
11814
|
}));
|
|
@@ -11888,7 +11888,7 @@ class Call {
|
|
|
11888
11888
|
}
|
|
11889
11889
|
}
|
|
11890
11890
|
catch (err) {
|
|
11891
|
-
this.logger(
|
|
11891
|
+
this.logger.error(`Can't disable mic/camera/screenshare after revoked permissions`, err);
|
|
11892
11892
|
}
|
|
11893
11893
|
}
|
|
11894
11894
|
};
|
|
@@ -12149,13 +12149,13 @@ class Call {
|
|
|
12149
12149
|
maxJoinRetries = Math.max(maxJoinRetries, 1);
|
|
12150
12150
|
for (let attempt = 0; attempt < maxJoinRetries; attempt++) {
|
|
12151
12151
|
try {
|
|
12152
|
-
this.logger(
|
|
12152
|
+
this.logger.trace(`Joining call (${attempt})`, this.cid);
|
|
12153
12153
|
await this.doJoin(data);
|
|
12154
12154
|
delete joinData.migrating_from;
|
|
12155
12155
|
break;
|
|
12156
12156
|
}
|
|
12157
12157
|
catch (err) {
|
|
12158
|
-
this.logger(
|
|
12158
|
+
this.logger.warn(`Failed to join call (${attempt})`, this.cid);
|
|
12159
12159
|
if (err instanceof ErrorFromResponse && err.unrecoverable) {
|
|
12160
12160
|
// if the error is unrecoverable, we should not retry as that signals
|
|
12161
12161
|
// that connectivity is good, but the coordinator doesn't allow the user
|
|
@@ -12185,7 +12185,7 @@ class Call {
|
|
|
12185
12185
|
const connectStartTime = Date.now();
|
|
12186
12186
|
const callingState = this.state.callingState;
|
|
12187
12187
|
this.joinCallData = data;
|
|
12188
|
-
this.logger('
|
|
12188
|
+
this.logger.debug('Starting join flow');
|
|
12189
12189
|
this.state.setCallingState(exports.CallingState.JOINING);
|
|
12190
12190
|
const performingMigration = this.reconnectStrategy === WebsocketReconnectStrategy.MIGRATE;
|
|
12191
12191
|
const performingRejoin = this.reconnectStrategy === WebsocketReconnectStrategy.REJOIN;
|
|
@@ -12270,7 +12270,7 @@ class Call {
|
|
|
12270
12270
|
}
|
|
12271
12271
|
}
|
|
12272
12272
|
catch (error) {
|
|
12273
|
-
this.logger('
|
|
12273
|
+
this.logger.warn('Join SFU request failed', error);
|
|
12274
12274
|
sfuClient.close(StreamSfuClient.JOIN_FAILED, 'Join request failed, connection considered unhealthy');
|
|
12275
12275
|
// restore the previous call state if the join-flow fails
|
|
12276
12276
|
this.state.setCallingState(callingState);
|
|
@@ -12327,7 +12327,7 @@ class Call {
|
|
|
12327
12327
|
// reset the reconnect strategy to unspecified after a successful reconnection
|
|
12328
12328
|
this.reconnectStrategy = WebsocketReconnectStrategy.UNSPECIFIED;
|
|
12329
12329
|
this.reconnectReason = '';
|
|
12330
|
-
this.logger(
|
|
12330
|
+
this.logger.info(`Joined call ${this.cid}`);
|
|
12331
12331
|
};
|
|
12332
12332
|
/**
|
|
12333
12333
|
* Prepares Reconnect Details object.
|
|
@@ -12440,7 +12440,7 @@ class Call {
|
|
|
12440
12440
|
onReconnectionNeeded: (kind, reason) => {
|
|
12441
12441
|
this.reconnect(kind, reason).catch((err) => {
|
|
12442
12442
|
const message = `[Reconnect] Error reconnecting after a subscriber error: ${reason}`;
|
|
12443
|
-
this.logger(
|
|
12443
|
+
this.logger.warn(message, err);
|
|
12444
12444
|
});
|
|
12445
12445
|
},
|
|
12446
12446
|
});
|
|
@@ -12462,7 +12462,7 @@ class Call {
|
|
|
12462
12462
|
onReconnectionNeeded: (kind, reason) => {
|
|
12463
12463
|
this.reconnect(kind, reason).catch((err) => {
|
|
12464
12464
|
const message = `[Reconnect] Error reconnecting after a publisher error: ${reason}`;
|
|
12465
|
-
this.logger(
|
|
12465
|
+
this.logger.warn(message, err);
|
|
12466
12466
|
});
|
|
12467
12467
|
},
|
|
12468
12468
|
});
|
|
@@ -12531,7 +12531,7 @@ class Call {
|
|
|
12531
12531
|
* @param reason the reason for the closure.
|
|
12532
12532
|
*/
|
|
12533
12533
|
this.handleSfuSignalClose = (sfuClient, reason) => {
|
|
12534
|
-
this.logger('
|
|
12534
|
+
this.logger.debug('[Reconnect] SFU signal connection closed');
|
|
12535
12535
|
const { callingState } = this.state;
|
|
12536
12536
|
if (
|
|
12537
12537
|
// SFU WS closed before we finished current join,
|
|
@@ -12552,7 +12552,7 @@ class Call {
|
|
|
12552
12552
|
? WebsocketReconnectStrategy.FAST
|
|
12553
12553
|
: WebsocketReconnectStrategy.REJOIN;
|
|
12554
12554
|
this.reconnect(strategy, reason).catch((err) => {
|
|
12555
|
-
this.logger('
|
|
12555
|
+
this.logger.warn('[Reconnect] Error reconnecting', err);
|
|
12556
12556
|
});
|
|
12557
12557
|
};
|
|
12558
12558
|
/**
|
|
@@ -12588,7 +12588,7 @@ class Call {
|
|
|
12588
12588
|
const shouldGiveUpReconnecting = this.disconnectionTimeoutSeconds > 0 &&
|
|
12589
12589
|
reconnectingTime / 1000 > this.disconnectionTimeoutSeconds;
|
|
12590
12590
|
if (shouldGiveUpReconnecting) {
|
|
12591
|
-
this.logger('
|
|
12591
|
+
this.logger.warn('[Reconnect] Stopping reconnection attempts after reaching disconnection timeout');
|
|
12592
12592
|
await markAsReconnectingFailed();
|
|
12593
12593
|
return;
|
|
12594
12594
|
}
|
|
@@ -12600,11 +12600,11 @@ class Call {
|
|
|
12600
12600
|
try {
|
|
12601
12601
|
// wait until the network is available
|
|
12602
12602
|
await this.networkAvailableTask?.promise;
|
|
12603
|
-
this.logger(
|
|
12603
|
+
this.logger.info(`[Reconnect] Reconnecting with strategy ${WebsocketReconnectStrategy[this.reconnectStrategy]}`);
|
|
12604
12604
|
switch (this.reconnectStrategy) {
|
|
12605
12605
|
case WebsocketReconnectStrategy.UNSPECIFIED:
|
|
12606
12606
|
case WebsocketReconnectStrategy.DISCONNECT:
|
|
12607
|
-
this.logger(
|
|
12607
|
+
this.logger.debug(`[Reconnect] No-op strategy ${currentStrategy}`);
|
|
12608
12608
|
break;
|
|
12609
12609
|
case WebsocketReconnectStrategy.FAST:
|
|
12610
12610
|
await this.reconnectFast();
|
|
@@ -12623,13 +12623,13 @@ class Call {
|
|
|
12623
12623
|
}
|
|
12624
12624
|
catch (error) {
|
|
12625
12625
|
if (this.state.callingState === exports.CallingState.OFFLINE) {
|
|
12626
|
-
this.logger(
|
|
12626
|
+
this.logger.debug(`[Reconnect] Can't reconnect while offline, stopping reconnection attempts`);
|
|
12627
12627
|
break;
|
|
12628
12628
|
// we don't need to handle the error if the call is offline
|
|
12629
12629
|
// network change event will trigger the reconnection
|
|
12630
12630
|
}
|
|
12631
12631
|
if (error instanceof ErrorFromResponse && error.unrecoverable) {
|
|
12632
|
-
this.logger(
|
|
12632
|
+
this.logger.warn(`[Reconnect] Can't reconnect due to coordinator unrecoverable error`, error);
|
|
12633
12633
|
await markAsReconnectingFailed();
|
|
12634
12634
|
return;
|
|
12635
12635
|
}
|
|
@@ -12650,12 +12650,12 @@ class Call {
|
|
|
12650
12650
|
? WebsocketReconnectStrategy.REJOIN
|
|
12651
12651
|
: WebsocketReconnectStrategy.FAST;
|
|
12652
12652
|
this.reconnectStrategy = nextStrategy;
|
|
12653
|
-
this.logger(
|
|
12653
|
+
this.logger.info(`[Reconnect] ${currentStrategy} (${this.reconnectAttempts}) failed. Attempting with ${WebsocketReconnectStrategy[nextStrategy]}`, error);
|
|
12654
12654
|
}
|
|
12655
12655
|
} while (this.state.callingState !== exports.CallingState.JOINED &&
|
|
12656
12656
|
this.state.callingState !== exports.CallingState.RECONNECTING_FAILED &&
|
|
12657
12657
|
this.state.callingState !== exports.CallingState.LEFT);
|
|
12658
|
-
this.logger('
|
|
12658
|
+
this.logger.info('[Reconnect] Reconnection flow finished');
|
|
12659
12659
|
});
|
|
12660
12660
|
};
|
|
12661
12661
|
/**
|
|
@@ -12737,7 +12737,7 @@ class Call {
|
|
|
12737
12737
|
this.registerReconnectHandlers = () => {
|
|
12738
12738
|
// handles the legacy "goAway" event
|
|
12739
12739
|
const unregisterGoAway = this.on('goAway', () => {
|
|
12740
|
-
this.reconnect(WebsocketReconnectStrategy.MIGRATE, 'goAway').catch((err) => this.logger('
|
|
12740
|
+
this.reconnect(WebsocketReconnectStrategy.MIGRATE, 'goAway').catch((err) => this.logger.warn('[Reconnect] Error reconnecting', err));
|
|
12741
12741
|
});
|
|
12742
12742
|
// handles the "error" event, through which the SFU can request a reconnect
|
|
12743
12743
|
const unregisterOnError = this.on('error', (e) => {
|
|
@@ -12746,19 +12746,19 @@ class Call {
|
|
|
12746
12746
|
return;
|
|
12747
12747
|
if (strategy === WebsocketReconnectStrategy.DISCONNECT) {
|
|
12748
12748
|
this.leave({ message: 'SFU instructed to disconnect' }).catch((err) => {
|
|
12749
|
-
this.logger(
|
|
12749
|
+
this.logger.warn(`Can't leave call after disconnect request`, err);
|
|
12750
12750
|
});
|
|
12751
12751
|
}
|
|
12752
12752
|
else {
|
|
12753
12753
|
this.reconnect(strategy, error?.message || 'SFU Error').catch((err) => {
|
|
12754
|
-
this.logger('
|
|
12754
|
+
this.logger.warn('[Reconnect] Error reconnecting', err);
|
|
12755
12755
|
});
|
|
12756
12756
|
}
|
|
12757
12757
|
});
|
|
12758
12758
|
const unregisterNetworkChanged = this.streamClient.on('network.changed', (e) => {
|
|
12759
12759
|
this.tracer.trace('network.changed', e);
|
|
12760
12760
|
if (!e.online) {
|
|
12761
|
-
this.logger('
|
|
12761
|
+
this.logger.debug('[Reconnect] Going offline');
|
|
12762
12762
|
if (!this.hasJoinedOnce)
|
|
12763
12763
|
return;
|
|
12764
12764
|
this.lastOfflineTimestamp = Date.now();
|
|
@@ -12775,7 +12775,7 @@ class Call {
|
|
|
12775
12775
|
}
|
|
12776
12776
|
}
|
|
12777
12777
|
this.reconnect(strategy, 'Going online').catch((err) => {
|
|
12778
|
-
this.logger('
|
|
12778
|
+
this.logger.warn('[Reconnect] Error reconnecting after going online', err);
|
|
12779
12779
|
});
|
|
12780
12780
|
});
|
|
12781
12781
|
this.networkAvailableTask = networkAvailableTask;
|
|
@@ -12783,7 +12783,7 @@ class Call {
|
|
|
12783
12783
|
this.state.setCallingState(exports.CallingState.OFFLINE);
|
|
12784
12784
|
}
|
|
12785
12785
|
else {
|
|
12786
|
-
this.logger('
|
|
12786
|
+
this.logger.debug('[Reconnect] Going online');
|
|
12787
12787
|
this.sfuClient?.close(StreamSfuClient.DISPOSE_OLD_SOCKET, 'Closing WS to reconnect after going online');
|
|
12788
12788
|
// we went online, release the previous waiters and reset the state
|
|
12789
12789
|
this.networkAvailableTask?.resolve();
|
|
@@ -12945,10 +12945,10 @@ class Call {
|
|
|
12945
12945
|
* @param options the options to use.
|
|
12946
12946
|
*/
|
|
12947
12947
|
this.updatePublishOptions = (options) => {
|
|
12948
|
-
this.logger('
|
|
12948
|
+
this.logger.warn('[call.updatePublishOptions]: You are manually overriding the publish options for this call. ' +
|
|
12949
12949
|
'This is not recommended, and it can cause call stability/compatibility issues. Use with caution.');
|
|
12950
12950
|
if (this.state.callingState === exports.CallingState.JOINED) {
|
|
12951
|
-
this.logger('
|
|
12951
|
+
this.logger.warn('Updating publish options after joining the call does not have an effect');
|
|
12952
12952
|
}
|
|
12953
12953
|
this.clientPublishOptions = { ...this.clientPublishOptions, ...options };
|
|
12954
12954
|
};
|
|
@@ -12959,7 +12959,7 @@ class Call {
|
|
|
12959
12959
|
*/
|
|
12960
12960
|
this.notifyNoiseCancellationStarting = async () => {
|
|
12961
12961
|
return this.sfuClient?.startNoiseCancellation().catch((err) => {
|
|
12962
|
-
this.logger('
|
|
12962
|
+
this.logger.warn('Failed to notify start of noise cancellation', err);
|
|
12963
12963
|
});
|
|
12964
12964
|
};
|
|
12965
12965
|
/**
|
|
@@ -12969,7 +12969,7 @@ class Call {
|
|
|
12969
12969
|
*/
|
|
12970
12970
|
this.notifyNoiseCancellationStopped = async () => {
|
|
12971
12971
|
return this.sfuClient?.stopNoiseCancellation().catch((err) => {
|
|
12972
|
-
this.logger('
|
|
12972
|
+
this.logger.warn('Failed to notify stop of noise cancellation', err);
|
|
12973
12973
|
});
|
|
12974
12974
|
};
|
|
12975
12975
|
/**
|
|
@@ -13403,7 +13403,7 @@ class Call {
|
|
|
13403
13403
|
reason: 'timeout',
|
|
13404
13404
|
message: `ringing timeout - ${this.isCreatedByMe ? 'no one accepted' : `user didn't interact with incoming call screen`}`,
|
|
13405
13405
|
}).catch((err) => {
|
|
13406
|
-
this.logger('
|
|
13406
|
+
this.logger.error('Failed to drop call', err);
|
|
13407
13407
|
});
|
|
13408
13408
|
}, timeoutInMs);
|
|
13409
13409
|
};
|
|
@@ -13515,10 +13515,10 @@ class Call {
|
|
|
13515
13515
|
*/
|
|
13516
13516
|
this.applyDeviceConfig = async (settings, publish) => {
|
|
13517
13517
|
await this.camera.apply(settings.video, publish).catch((err) => {
|
|
13518
|
-
this.logger('
|
|
13518
|
+
this.logger.warn('Camera init failed', err);
|
|
13519
13519
|
});
|
|
13520
13520
|
await this.microphone.apply(settings.audio, publish).catch((err) => {
|
|
13521
|
-
this.logger('
|
|
13521
|
+
this.logger.warn('Mic init failed', err);
|
|
13522
13522
|
});
|
|
13523
13523
|
};
|
|
13524
13524
|
/**
|
|
@@ -13670,7 +13670,7 @@ class Call {
|
|
|
13670
13670
|
this.streamClient = streamClient;
|
|
13671
13671
|
this.clientStore = clientStore;
|
|
13672
13672
|
this.streamClientBasePath = `/call/${this.type}/${this.id}`;
|
|
13673
|
-
this.logger = getLogger(
|
|
13673
|
+
this.logger = videoLoggerSystem.getLogger('Call');
|
|
13674
13674
|
const callTypeConfig = CallTypes.get(type);
|
|
13675
13675
|
const participantSorter = sortParticipantsBy || callTypeConfig.options.sortParticipantsBy;
|
|
13676
13676
|
if (participantSorter) {
|
|
@@ -13757,7 +13757,7 @@ const APIErrorCodes = {
|
|
|
13757
13757
|
class StableWSConnection {
|
|
13758
13758
|
constructor(client) {
|
|
13759
13759
|
this._log = (msg, extra = {}, level = 'info') => {
|
|
13760
|
-
this.client.logger(
|
|
13760
|
+
this.client.logger[level](`connection:${msg}`, extra);
|
|
13761
13761
|
};
|
|
13762
13762
|
this.setClient = (client) => {
|
|
13763
13763
|
this.client = client;
|
|
@@ -13803,12 +13803,12 @@ class StableWSConnection {
|
|
|
13803
13803
|
return;
|
|
13804
13804
|
const user = this.client.user;
|
|
13805
13805
|
if (!user) {
|
|
13806
|
-
this.client.logger(
|
|
13806
|
+
this.client.logger.error(`User not set, can't connect to WS`);
|
|
13807
13807
|
return;
|
|
13808
13808
|
}
|
|
13809
13809
|
const token = this.client._getToken();
|
|
13810
13810
|
if (!token) {
|
|
13811
|
-
this.client.logger(
|
|
13811
|
+
this.client.logger.error(`Token not set, can't connect authenticate`);
|
|
13812
13812
|
return;
|
|
13813
13813
|
}
|
|
13814
13814
|
const authMessage = JSON.stringify({
|
|
@@ -14445,7 +14445,7 @@ class TokenManager {
|
|
|
14445
14445
|
}
|
|
14446
14446
|
|
|
14447
14447
|
const getLocationHint = async (hintUrl = `https://hint.stream-io-video.com/`, timeout = 2000, maxAttempts = 3) => {
|
|
14448
|
-
const logger = getLogger(
|
|
14448
|
+
const logger = videoLoggerSystem.getLogger('location-hint');
|
|
14449
14449
|
let attempt = 0;
|
|
14450
14450
|
let locationHint = 'ERR';
|
|
14451
14451
|
do {
|
|
@@ -14457,11 +14457,11 @@ const getLocationHint = async (hintUrl = `https://hint.stream-io-video.com/`, ti
|
|
|
14457
14457
|
signal: abortController.signal,
|
|
14458
14458
|
});
|
|
14459
14459
|
const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
|
|
14460
|
-
logger(
|
|
14460
|
+
logger.debug(`Location header: ${awsPop}`);
|
|
14461
14461
|
locationHint = awsPop.substring(0, 3); // AMS1-P2 -> AMS
|
|
14462
14462
|
}
|
|
14463
14463
|
catch (e) {
|
|
14464
|
-
logger(
|
|
14464
|
+
logger.warn(`Failed to get location hint from ${hintUrl}`, e);
|
|
14465
14465
|
locationHint = 'ERR';
|
|
14466
14466
|
}
|
|
14467
14467
|
finally {
|
|
@@ -14522,14 +14522,14 @@ class StreamClient {
|
|
|
14522
14522
|
* If the user id remains the same we don't throw error
|
|
14523
14523
|
*/
|
|
14524
14524
|
if (this.userID === user.id && this.connectUserTask) {
|
|
14525
|
-
this.logger('
|
|
14525
|
+
this.logger.warn('Consecutive calls to connectUser is detected, ideally you should only call this function once in your app.');
|
|
14526
14526
|
return this.connectUserTask;
|
|
14527
14527
|
}
|
|
14528
14528
|
if (this.userID) {
|
|
14529
14529
|
throw new Error('Use client.disconnect() before trying to connect as a different user. connectUser was called twice.');
|
|
14530
14530
|
}
|
|
14531
14531
|
if ((this.secret || this.node) && !this.options.allowServerSideConnect) {
|
|
14532
|
-
this.logger('
|
|
14532
|
+
this.logger.warn('Please do not use connectUser server side. Use our @stream-io/node-sdk instead: https://getstream.io/video/docs/api/');
|
|
14533
14533
|
}
|
|
14534
14534
|
// we generate the client id client side
|
|
14535
14535
|
this.userID = user.id;
|
|
@@ -14587,11 +14587,11 @@ class StreamClient {
|
|
|
14587
14587
|
}
|
|
14588
14588
|
const wsPromise = this.wsPromiseSafe?.();
|
|
14589
14589
|
if (this.wsConnection?.isConnecting && wsPromise) {
|
|
14590
|
-
this.logger('
|
|
14590
|
+
this.logger.info('client:openConnection() - connection already in progress');
|
|
14591
14591
|
return await wsPromise;
|
|
14592
14592
|
}
|
|
14593
14593
|
if (this.wsConnection?.isHealthy && this._hasConnectionID()) {
|
|
14594
|
-
this.logger('
|
|
14594
|
+
this.logger.info('client:openConnection() - openConnection called twice, healthy connection already exists');
|
|
14595
14595
|
return;
|
|
14596
14596
|
}
|
|
14597
14597
|
this._setupConnectionIdPromise();
|
|
@@ -14607,7 +14607,7 @@ class StreamClient {
|
|
|
14607
14607
|
* https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
|
|
14608
14608
|
*/
|
|
14609
14609
|
this.disconnectUser = async (timeout) => {
|
|
14610
|
-
this.logger('
|
|
14610
|
+
this.logger.info('client:disconnect() - Disconnecting the client');
|
|
14611
14611
|
// remove the user specific fields
|
|
14612
14612
|
delete this.user;
|
|
14613
14613
|
delete this._user;
|
|
@@ -14654,7 +14654,7 @@ class StreamClient {
|
|
|
14654
14654
|
if (!this.listeners[eventName]) {
|
|
14655
14655
|
this.listeners[eventName] = [];
|
|
14656
14656
|
}
|
|
14657
|
-
this.logger(
|
|
14657
|
+
this.logger.debug(`Adding listener for ${eventName} event`);
|
|
14658
14658
|
this.listeners[eventName]?.push(callback);
|
|
14659
14659
|
return () => {
|
|
14660
14660
|
this.off(eventName, callback);
|
|
@@ -14667,7 +14667,7 @@ class StreamClient {
|
|
|
14667
14667
|
if (!this.listeners[eventName]) {
|
|
14668
14668
|
this.listeners[eventName] = [];
|
|
14669
14669
|
}
|
|
14670
|
-
this.logger(
|
|
14670
|
+
this.logger.debug(`Removing listener for ${eventName} event`);
|
|
14671
14671
|
this.listeners[eventName] = this.listeners[eventName]?.filter((value) => value !== callback);
|
|
14672
14672
|
};
|
|
14673
14673
|
/**
|
|
@@ -14681,17 +14681,17 @@ class StreamClient {
|
|
|
14681
14681
|
}));
|
|
14682
14682
|
};
|
|
14683
14683
|
this._logApiRequest = (type, url, data, config) => {
|
|
14684
|
-
if (getLogLevel() !== 'trace')
|
|
14684
|
+
if (this.logger.getLogLevel() !== 'trace')
|
|
14685
14685
|
return;
|
|
14686
|
-
this.logger(
|
|
14686
|
+
this.logger.trace(`client: ${type} - Request - ${url}`, {
|
|
14687
14687
|
payload: data,
|
|
14688
14688
|
config,
|
|
14689
14689
|
});
|
|
14690
14690
|
};
|
|
14691
14691
|
this._logApiResponse = (type, url, response) => {
|
|
14692
|
-
if (getLogLevel() !== 'trace')
|
|
14692
|
+
if (this.logger.getLogLevel() !== 'trace')
|
|
14693
14693
|
return;
|
|
14694
|
-
this.logger(
|
|
14694
|
+
this.logger.trace(`client:${type} - Response - url: ${url} > status ${response.status}`, {
|
|
14695
14695
|
response,
|
|
14696
14696
|
});
|
|
14697
14697
|
};
|
|
@@ -14748,13 +14748,13 @@ class StreamClient {
|
|
|
14748
14748
|
this.consecutiveFailures += 1;
|
|
14749
14749
|
const { response } = e;
|
|
14750
14750
|
if (!response || !isErrorResponse(response)) {
|
|
14751
|
-
this.logger(
|
|
14751
|
+
this.logger.error(`client:${type} url: ${url}`, e);
|
|
14752
14752
|
throw e;
|
|
14753
14753
|
}
|
|
14754
14754
|
const { data: responseData, status } = response;
|
|
14755
14755
|
const isTokenExpired = responseData.code === KnownCodes.TOKEN_EXPIRED;
|
|
14756
14756
|
if (isTokenExpired && !this.tokenManager.isStatic()) {
|
|
14757
|
-
this.logger(
|
|
14757
|
+
this.logger.warn(`client:${type}: url: ${url}`, response);
|
|
14758
14758
|
if (this.consecutiveFailures > 1) {
|
|
14759
14759
|
await sleep(retryInterval(this.consecutiveFailures));
|
|
14760
14760
|
}
|
|
@@ -14763,7 +14763,7 @@ class StreamClient {
|
|
|
14763
14763
|
return await this.doAxiosRequest(type, url, data, options);
|
|
14764
14764
|
}
|
|
14765
14765
|
else {
|
|
14766
|
-
this.logger(
|
|
14766
|
+
this.logger.error(`client:${type} url: ${url}`, response);
|
|
14767
14767
|
throw new ErrorFromResponse({
|
|
14768
14768
|
message: `Stream error code ${responseData.code}: ${responseData.message}`,
|
|
14769
14769
|
code: responseData.code ?? null,
|
|
@@ -14794,7 +14794,7 @@ class StreamClient {
|
|
|
14794
14794
|
});
|
|
14795
14795
|
};
|
|
14796
14796
|
this.dispatchEvent = (event) => {
|
|
14797
|
-
this.logger(
|
|
14797
|
+
this.logger.debug(`Dispatching event: ${event.type}`, event);
|
|
14798
14798
|
if (!this.listeners)
|
|
14799
14799
|
return;
|
|
14800
14800
|
// call generic listeners
|
|
@@ -14819,13 +14819,13 @@ class StreamClient {
|
|
|
14819
14819
|
throw Error('clientID is not set');
|
|
14820
14820
|
// The StableWSConnection handles all the reconnection logic.
|
|
14821
14821
|
this.wsConnection = new StableWSConnection(this);
|
|
14822
|
-
this.logger('
|
|
14822
|
+
this.logger.info('StreamClient.connect: this.wsConnection.connect()');
|
|
14823
14823
|
return await this.wsConnection.connect(this.defaultWSTimeout);
|
|
14824
14824
|
};
|
|
14825
14825
|
this.getUserAgent = () => {
|
|
14826
14826
|
if (!this.cachedUserAgent) {
|
|
14827
14827
|
const { clientAppIdentifier = {} } = this.options;
|
|
14828
|
-
const { sdkName = 'js', sdkVersion = "1.
|
|
14828
|
+
const { sdkName = 'js', sdkVersion = "1.36.0", ...extras } = clientAppIdentifier;
|
|
14829
14829
|
this.cachedUserAgent = [
|
|
14830
14830
|
`stream-video-${sdkName}-v${sdkVersion}`,
|
|
14831
14831
|
...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
|
|
@@ -14876,11 +14876,11 @@ class StreamClient {
|
|
|
14876
14876
|
};
|
|
14877
14877
|
this.updateNetworkConnectionStatus = (event) => {
|
|
14878
14878
|
if (event.type === 'offline') {
|
|
14879
|
-
this.logger('
|
|
14879
|
+
this.logger.debug('device went offline');
|
|
14880
14880
|
this.dispatchEvent({ type: 'network.changed', online: false });
|
|
14881
14881
|
}
|
|
14882
14882
|
else if (event.type === 'online') {
|
|
14883
|
-
this.logger('
|
|
14883
|
+
this.logger.debug('device went online');
|
|
14884
14884
|
this.dispatchEvent({ type: 'network.changed', online: true });
|
|
14885
14885
|
}
|
|
14886
14886
|
};
|
|
@@ -14928,9 +14928,7 @@ class StreamClient {
|
|
|
14928
14928
|
this.tokenManager = new TokenManager(this.secret);
|
|
14929
14929
|
this.consecutiveFailures = 0;
|
|
14930
14930
|
this.defaultWSTimeout = this.options.defaultWsTimeout ?? 15000;
|
|
14931
|
-
this.logger =
|
|
14932
|
-
? inputOptions.logger
|
|
14933
|
-
: () => null;
|
|
14931
|
+
this.logger = videoLoggerSystem.getLogger('coordinator');
|
|
14934
14932
|
}
|
|
14935
14933
|
get connectionIdPromise() {
|
|
14936
14934
|
return this.connectionIdPromiseSafe?.();
|
|
@@ -14975,12 +14973,10 @@ const getClientAppIdentifier = (options) => {
|
|
|
14975
14973
|
*/
|
|
14976
14974
|
const createCoordinatorClient = (apiKey, options) => {
|
|
14977
14975
|
const clientAppIdentifier = getClientAppIdentifier(options);
|
|
14978
|
-
const coordinatorLogger = getLogger(['coordinator']);
|
|
14979
14976
|
return new StreamClient(apiKey, {
|
|
14980
14977
|
persistUserOnConnectionFailure: true,
|
|
14981
14978
|
...options,
|
|
14982
14979
|
clientAppIdentifier,
|
|
14983
|
-
logger: coordinatorLogger,
|
|
14984
14980
|
});
|
|
14985
14981
|
};
|
|
14986
14982
|
/**
|
|
@@ -15018,7 +15014,7 @@ class StreamVideoClient {
|
|
|
15018
15014
|
this.registerClientInstance = (apiKey, user) => {
|
|
15019
15015
|
const instanceKey = getInstanceKey(apiKey, user);
|
|
15020
15016
|
if (StreamVideoClient._instances.has(instanceKey)) {
|
|
15021
|
-
this.logger(
|
|
15017
|
+
this.logger.warn(`A StreamVideoClient already exists for ${user.id}; Prefer using getOrCreateInstance method`);
|
|
15022
15018
|
}
|
|
15023
15019
|
StreamVideoClient._instances.set(instanceKey, this);
|
|
15024
15020
|
};
|
|
@@ -15033,13 +15029,13 @@ class StreamVideoClient {
|
|
|
15033
15029
|
.map((call) => call.cid);
|
|
15034
15030
|
if (callsToReWatch.length <= 0)
|
|
15035
15031
|
return;
|
|
15036
|
-
this.logger(
|
|
15032
|
+
this.logger.info(`Rewatching calls ${callsToReWatch.join(', ')}`);
|
|
15037
15033
|
this.queryCalls({
|
|
15038
15034
|
watch: true,
|
|
15039
15035
|
filter_conditions: { cid: { $in: callsToReWatch } },
|
|
15040
15036
|
sort: [{ field: 'cid', direction: 1 }],
|
|
15041
15037
|
}).catch((err) => {
|
|
15042
|
-
this.logger('
|
|
15038
|
+
this.logger.error('Failed to re-watch calls', err);
|
|
15043
15039
|
});
|
|
15044
15040
|
}));
|
|
15045
15041
|
this.effectsRegistered = true;
|
|
@@ -15050,7 +15046,7 @@ class StreamVideoClient {
|
|
|
15050
15046
|
*/
|
|
15051
15047
|
this.initCallFromEvent = async (e) => {
|
|
15052
15048
|
if (this.state.connectedUser?.id === e.call.created_by.id) {
|
|
15053
|
-
this.logger(
|
|
15049
|
+
this.logger.debug(`Ignoring ${e.type} event sent by the current user`);
|
|
15054
15050
|
return;
|
|
15055
15051
|
}
|
|
15056
15052
|
try {
|
|
@@ -15061,7 +15057,7 @@ class StreamVideoClient {
|
|
|
15061
15057
|
if (call) {
|
|
15062
15058
|
if (ringing) {
|
|
15063
15059
|
if (this.shouldRejectCall(call.cid)) {
|
|
15064
|
-
this.logger(
|
|
15060
|
+
this.logger.info(`Leaving call with busy reject reason ${call.cid} because user is busy`);
|
|
15065
15061
|
// remove the instance from the state store
|
|
15066
15062
|
await call.leave();
|
|
15067
15063
|
// explicitly reject the call with busy reason as calling state was not ringing before and leave would not call it therefore
|
|
@@ -15086,7 +15082,7 @@ class StreamVideoClient {
|
|
|
15086
15082
|
});
|
|
15087
15083
|
if (ringing) {
|
|
15088
15084
|
if (this.shouldRejectCall(call.cid)) {
|
|
15089
|
-
this.logger(
|
|
15085
|
+
this.logger.info(`Rejecting call ${call.cid} because user is busy`);
|
|
15090
15086
|
// call is not in the state store yet, so just reject api is enough
|
|
15091
15087
|
await call.reject('busy');
|
|
15092
15088
|
}
|
|
@@ -15098,12 +15094,12 @@ class StreamVideoClient {
|
|
|
15098
15094
|
else {
|
|
15099
15095
|
call.state.updateFromCallResponse(e.call);
|
|
15100
15096
|
this.writeableStateStore.registerCall(call);
|
|
15101
|
-
this.logger(
|
|
15097
|
+
this.logger.info(`New call created and registered: ${call.cid}`);
|
|
15102
15098
|
}
|
|
15103
15099
|
});
|
|
15104
15100
|
}
|
|
15105
15101
|
catch (err) {
|
|
15106
|
-
this.logger(
|
|
15102
|
+
this.logger.error(`Failed to init call from event ${e.type}`, err);
|
|
15107
15103
|
}
|
|
15108
15104
|
};
|
|
15109
15105
|
/**
|
|
@@ -15127,13 +15123,13 @@ class StreamVideoClient {
|
|
|
15127
15123
|
const errorQueue = [];
|
|
15128
15124
|
for (let attempt = 0; attempt < maxConnectUserRetries; attempt++) {
|
|
15129
15125
|
try {
|
|
15130
|
-
this.logger(
|
|
15126
|
+
this.logger.trace(`Connecting user (${attempt})`, user);
|
|
15131
15127
|
return user.type === 'guest'
|
|
15132
15128
|
? await client.connectGuestUser(user)
|
|
15133
15129
|
: await client.connectUser(user, tokenOrProvider);
|
|
15134
15130
|
}
|
|
15135
15131
|
catch (err) {
|
|
15136
|
-
this.logger(
|
|
15132
|
+
this.logger.warn(`Failed to connect a user (${attempt})`, err);
|
|
15137
15133
|
errorQueue.push(err);
|
|
15138
15134
|
if (attempt === maxConnectUserRetries - 1) {
|
|
15139
15135
|
onConnectUserError?.(err, errorQueue);
|
|
@@ -15378,8 +15374,11 @@ class StreamVideoClient {
|
|
|
15378
15374
|
if (clientOptions?.enableTimerWorker)
|
|
15379
15375
|
enableTimerWorker();
|
|
15380
15376
|
const rootLogger = clientOptions?.logger || logToConsole;
|
|
15381
|
-
|
|
15382
|
-
|
|
15377
|
+
videoLoggerSystem.configureLoggers({
|
|
15378
|
+
default: { sink: rootLogger, level: clientOptions?.logLevel || 'warn' },
|
|
15379
|
+
...clientOptions?.logOptions,
|
|
15380
|
+
});
|
|
15381
|
+
this.logger = videoLoggerSystem.getLogger('client');
|
|
15383
15382
|
this.rejectCallWhenBusy = clientOptions?.rejectCallWhenBusy ?? false;
|
|
15384
15383
|
this.streamClient = createCoordinatorClient(apiKey, clientOptions);
|
|
15385
15384
|
this.writeableStateStore = new StreamVideoWriteableStateStore();
|
|
@@ -15392,7 +15391,7 @@ class StreamVideoClient {
|
|
|
15392
15391
|
this.registerClientInstance(apiKey, user);
|
|
15393
15392
|
const tokenOrProvider = createTokenOrProvider(apiKeyOrArgs);
|
|
15394
15393
|
this.connectUser(user, tokenOrProvider).catch((err) => {
|
|
15395
|
-
this.logger('
|
|
15394
|
+
this.logger.error('Failed to connect', err);
|
|
15396
15395
|
});
|
|
15397
15396
|
}
|
|
15398
15397
|
}
|
|
@@ -15426,6 +15425,10 @@ Object.defineProperty(exports, "AxiosError", {
|
|
|
15426
15425
|
enumerable: true,
|
|
15427
15426
|
get: function () { return axios.AxiosError; }
|
|
15428
15427
|
});
|
|
15428
|
+
Object.defineProperty(exports, "LogLevelEnum", {
|
|
15429
|
+
enumerable: true,
|
|
15430
|
+
get: function () { return scopedLogger.LogLevelEnum; }
|
|
15431
|
+
});
|
|
15429
15432
|
exports.AudioSettingsRequestDefaultDeviceEnum = AudioSettingsRequestDefaultDeviceEnum;
|
|
15430
15433
|
exports.AudioSettingsResponseDefaultDeviceEnum = AudioSettingsResponseDefaultDeviceEnum;
|
|
15431
15434
|
exports.Browsers = browsers;
|
|
@@ -15493,8 +15496,6 @@ exports.getAudioOutputDevices = getAudioOutputDevices;
|
|
|
15493
15496
|
exports.getAudioStream = getAudioStream;
|
|
15494
15497
|
exports.getClientDetails = getClientDetails;
|
|
15495
15498
|
exports.getDeviceState = getDeviceState;
|
|
15496
|
-
exports.getLogLevel = getLogLevel;
|
|
15497
|
-
exports.getLogger = getLogger;
|
|
15498
15499
|
exports.getScreenShareStream = getScreenShareStream;
|
|
15499
15500
|
exports.getSdkInfo = getSdkInfo;
|
|
15500
15501
|
exports.getVideoBrowserPermission = getVideoBrowserPermission;
|
|
@@ -15508,7 +15509,6 @@ exports.hasScreenShareAudio = hasScreenShareAudio;
|
|
|
15508
15509
|
exports.hasVideo = hasVideo;
|
|
15509
15510
|
exports.isPinned = isPinned;
|
|
15510
15511
|
exports.livestreamOrAudioRoomSortPreset = livestreamOrAudioRoomSortPreset;
|
|
15511
|
-
exports.logLevels = logLevels;
|
|
15512
15512
|
exports.logToConsole = logToConsole;
|
|
15513
15513
|
exports.name = name;
|
|
15514
15514
|
exports.noopComparator = noopComparator;
|
|
@@ -15521,8 +15521,6 @@ exports.resolveDeviceId = resolveDeviceId;
|
|
|
15521
15521
|
exports.role = role;
|
|
15522
15522
|
exports.screenSharing = screenSharing;
|
|
15523
15523
|
exports.setDeviceInfo = setDeviceInfo;
|
|
15524
|
-
exports.setLogLevel = setLogLevel;
|
|
15525
|
-
exports.setLogger = setLogger;
|
|
15526
15524
|
exports.setOSInfo = setOSInfo;
|
|
15527
15525
|
exports.setPowerState = setPowerState;
|
|
15528
15526
|
exports.setSdkInfo = setSdkInfo;
|
|
@@ -15530,5 +15528,6 @@ exports.setThermalState = setThermalState;
|
|
|
15530
15528
|
exports.setWebRTCInfo = setWebRTCInfo;
|
|
15531
15529
|
exports.speakerLayoutSortPreset = speakerLayoutSortPreset;
|
|
15532
15530
|
exports.speaking = speaking;
|
|
15531
|
+
exports.videoLoggerSystem = videoLoggerSystem;
|
|
15533
15532
|
exports.withParticipantSource = withParticipantSource;
|
|
15534
15533
|
//# sourceMappingURL=index.cjs.js.map
|