@stream-io/video-client 1.35.1 → 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 +6 -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 +3 -2
- 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.es.js
CHANGED
|
@@ -4,6 +4,8 @@ import { ServiceType, stackIntercept, RpcError } from '@protobuf-ts/runtime-rpc'
|
|
|
4
4
|
import axios from 'axios';
|
|
5
5
|
export { AxiosError } from 'axios';
|
|
6
6
|
import { TwirpFetchTransport, TwirpErrorCode } from '@protobuf-ts/twirp-transport';
|
|
7
|
+
import * as scopedLogger from '@stream-io/logger';
|
|
8
|
+
export { LogLevelEnum } from '@stream-io/logger';
|
|
7
9
|
import { ReplaySubject, combineLatest, BehaviorSubject, shareReplay, map, distinctUntilChanged, startWith, takeWhile, distinctUntilKeyChanged, fromEventPattern, concatMap, merge, from, fromEvent, tap, debounceTime, pairwise, of } from 'rxjs';
|
|
8
10
|
import { UAParser } from 'ua-parser-js';
|
|
9
11
|
import { parse, write } from 'sdp-transform';
|
|
@@ -3726,7 +3728,7 @@ const withRequestLogger = (logger, level) => {
|
|
|
3726
3728
|
return {
|
|
3727
3729
|
interceptUnary: (next, method, input, options) => {
|
|
3728
3730
|
const invocation = next(method, input, options);
|
|
3729
|
-
logger(
|
|
3731
|
+
logger[level](`Invoked SFU RPC method ${method.name}`, {
|
|
3730
3732
|
request: invocation.request,
|
|
3731
3733
|
headers: invocation.requestHeaders,
|
|
3732
3734
|
response: invocation.response,
|
|
@@ -3862,16 +3864,6 @@ const isReactNative = () => {
|
|
|
3862
3864
|
return navigator.product?.toLowerCase() === 'reactnative';
|
|
3863
3865
|
};
|
|
3864
3866
|
|
|
3865
|
-
// log levels, sorted by verbosity
|
|
3866
|
-
const logLevels = Object.freeze({
|
|
3867
|
-
trace: 0,
|
|
3868
|
-
debug: 1,
|
|
3869
|
-
info: 2,
|
|
3870
|
-
warn: 3,
|
|
3871
|
-
error: 4,
|
|
3872
|
-
});
|
|
3873
|
-
let logger;
|
|
3874
|
-
let level = 'info';
|
|
3875
3867
|
const logToConsole = (logLevel, message, ...args) => {
|
|
3876
3868
|
let logMethod;
|
|
3877
3869
|
switch (logLevel) {
|
|
@@ -3903,26 +3895,7 @@ const logToConsole = (logLevel, message, ...args) => {
|
|
|
3903
3895
|
}
|
|
3904
3896
|
logMethod(message, ...args);
|
|
3905
3897
|
};
|
|
3906
|
-
const
|
|
3907
|
-
logger = l;
|
|
3908
|
-
if (lvl) {
|
|
3909
|
-
setLogLevel(lvl);
|
|
3910
|
-
}
|
|
3911
|
-
};
|
|
3912
|
-
const setLogLevel = (l) => {
|
|
3913
|
-
level = l;
|
|
3914
|
-
};
|
|
3915
|
-
const getLogLevel = () => level;
|
|
3916
|
-
const getLogger = (withTags) => {
|
|
3917
|
-
const loggerMethod = logger || logToConsole;
|
|
3918
|
-
const tags = (withTags || []).filter(Boolean).join(':');
|
|
3919
|
-
const result = (logLevel, message, ...args) => {
|
|
3920
|
-
if (logLevels[logLevel] >= logLevels[level]) {
|
|
3921
|
-
loggerMethod(logLevel, `[${tags}]: ${message}`, ...args);
|
|
3922
|
-
}
|
|
3923
|
-
};
|
|
3924
|
-
return result;
|
|
3925
|
-
};
|
|
3898
|
+
const videoLoggerSystem = scopedLogger.createLoggerSystem();
|
|
3926
3899
|
|
|
3927
3900
|
/**
|
|
3928
3901
|
* Creates a closure which wraps the given RPC call and retries invoking
|
|
@@ -3948,7 +3921,9 @@ const retryable = async (rpc, signal) => {
|
|
|
3948
3921
|
const isAborted = signal?.aborted ?? false;
|
|
3949
3922
|
if (isRequestCancelled || isAborted)
|
|
3950
3923
|
throw err;
|
|
3951
|
-
|
|
3924
|
+
videoLoggerSystem
|
|
3925
|
+
.getLogger('sfu-client', { tags: ['rpc'] })
|
|
3926
|
+
.debug(`rpc failed (${attempt})`, err);
|
|
3952
3927
|
attempt++;
|
|
3953
3928
|
}
|
|
3954
3929
|
} while (!result || result.response.error?.shouldRetry);
|
|
@@ -4019,14 +3994,14 @@ const isSfuEvent = (eventName) => {
|
|
|
4019
3994
|
};
|
|
4020
3995
|
class Dispatcher {
|
|
4021
3996
|
constructor() {
|
|
4022
|
-
this.logger = getLogger(
|
|
3997
|
+
this.logger = videoLoggerSystem.getLogger('Dispatcher');
|
|
4023
3998
|
this.subscribers = {};
|
|
4024
3999
|
this.dispatch = (message, tag = '0') => {
|
|
4025
4000
|
const eventKind = message.eventPayload.oneofKind;
|
|
4026
4001
|
if (!eventKind)
|
|
4027
4002
|
return;
|
|
4028
4003
|
const payload = message.eventPayload[eventKind];
|
|
4029
|
-
this.logger(
|
|
4004
|
+
this.logger.debug(`Dispatching ${eventKind}, tag=${tag}`, payload);
|
|
4030
4005
|
const listeners = this.subscribers[eventKind];
|
|
4031
4006
|
if (!listeners)
|
|
4032
4007
|
return;
|
|
@@ -4035,7 +4010,7 @@ class Dispatcher {
|
|
|
4035
4010
|
fn(payload);
|
|
4036
4011
|
}
|
|
4037
4012
|
catch (e) {
|
|
4038
|
-
this.logger('
|
|
4013
|
+
this.logger.warn('Listener failed with error', e);
|
|
4039
4014
|
}
|
|
4040
4015
|
}
|
|
4041
4016
|
};
|
|
@@ -4071,8 +4046,8 @@ class IceTrickleBuffer {
|
|
|
4071
4046
|
this.publisherCandidates.next(iceCandidate);
|
|
4072
4047
|
}
|
|
4073
4048
|
else {
|
|
4074
|
-
const logger = getLogger(
|
|
4075
|
-
logger(
|
|
4049
|
+
const logger = videoLoggerSystem.getLogger('sfu-client');
|
|
4050
|
+
logger.warn(`ICETrickle, Unknown peer type`, iceTrickle);
|
|
4076
4051
|
}
|
|
4077
4052
|
};
|
|
4078
4053
|
this.dispose = () => {
|
|
@@ -4086,8 +4061,8 @@ const toIceCandidate = (iceTrickle) => {
|
|
|
4086
4061
|
return JSON.parse(iceTrickle.iceCandidate);
|
|
4087
4062
|
}
|
|
4088
4063
|
catch (e) {
|
|
4089
|
-
const logger = getLogger(
|
|
4090
|
-
logger(
|
|
4064
|
+
const logger = videoLoggerSystem.getLogger('sfu-client');
|
|
4065
|
+
logger.error(`Failed to parse ICE Trickle`, e, iceTrickle);
|
|
4091
4066
|
return undefined;
|
|
4092
4067
|
}
|
|
4093
4068
|
};
|
|
@@ -4263,7 +4238,9 @@ const updateValue = (subject, update) => {
|
|
|
4263
4238
|
* @param handler the handler to call when the observable emits a value.
|
|
4264
4239
|
* @param onError an optional error handler.
|
|
4265
4240
|
*/
|
|
4266
|
-
const createSubscription = (observable, handler, onError = (error) =>
|
|
4241
|
+
const createSubscription = (observable, handler, onError = (error) => videoLoggerSystem
|
|
4242
|
+
.getLogger('RxUtils')
|
|
4243
|
+
.warn('An observable emitted an error', error)) => {
|
|
4267
4244
|
const subscription = observable.subscribe({ next: handler, error: onError });
|
|
4268
4245
|
return () => {
|
|
4269
4246
|
subscription.unsubscribe();
|
|
@@ -4383,8 +4360,8 @@ class StreamVideoWriteableStateStore {
|
|
|
4383
4360
|
* @param call the call to remove
|
|
4384
4361
|
*/
|
|
4385
4362
|
this.unregisterCall = (call) => {
|
|
4386
|
-
const logger = getLogger(
|
|
4387
|
-
logger(
|
|
4363
|
+
const logger = videoLoggerSystem.getLogger('client-state');
|
|
4364
|
+
logger.trace(`Unregistering call: ${call.cid}`);
|
|
4388
4365
|
return this.setCalls((calls) => calls.filter((c) => c !== call));
|
|
4389
4366
|
};
|
|
4390
4367
|
/**
|
|
@@ -4399,15 +4376,15 @@ class StreamVideoWriteableStateStore {
|
|
|
4399
4376
|
this.connectedUserSubject.subscribe(async (user) => {
|
|
4400
4377
|
// leave all calls when the user disconnects.
|
|
4401
4378
|
if (!user) {
|
|
4402
|
-
const logger = getLogger(
|
|
4379
|
+
const logger = videoLoggerSystem.getLogger('client-state');
|
|
4403
4380
|
for (const call of this.calls) {
|
|
4404
4381
|
if (call.state.callingState === CallingState.LEFT)
|
|
4405
4382
|
continue;
|
|
4406
|
-
logger(
|
|
4383
|
+
logger.info(`User disconnected, leaving call: ${call.cid}`);
|
|
4407
4384
|
await call
|
|
4408
4385
|
.leave({ message: 'client.disconnectUser() called' })
|
|
4409
4386
|
.catch((err) => {
|
|
4410
|
-
logger(
|
|
4387
|
+
logger.error(`Error leaving call: ${call.cid}`, err);
|
|
4411
4388
|
});
|
|
4412
4389
|
}
|
|
4413
4390
|
}
|
|
@@ -4801,7 +4778,7 @@ class CallState {
|
|
|
4801
4778
|
// We keep these tracks around until we can associate them with a participant.
|
|
4802
4779
|
this.orphanedTracks = [];
|
|
4803
4780
|
this.callGrantsSubject = new ReplaySubject(1);
|
|
4804
|
-
this.logger = getLogger(
|
|
4781
|
+
this.logger = videoLoggerSystem.getLogger('CallState');
|
|
4805
4782
|
/**
|
|
4806
4783
|
* A list of comparators that are used to sort the participants.
|
|
4807
4784
|
*/
|
|
@@ -4982,7 +4959,7 @@ class CallState {
|
|
|
4982
4959
|
this.updateParticipant = (sessionId, patch) => {
|
|
4983
4960
|
const participant = this.findParticipantBySessionId(sessionId);
|
|
4984
4961
|
if (!participant) {
|
|
4985
|
-
this.logger(
|
|
4962
|
+
this.logger.warn(`Participant with sessionId ${sessionId} not found`);
|
|
4986
4963
|
return;
|
|
4987
4964
|
}
|
|
4988
4965
|
const thePatch = typeof patch === 'function' ? patch(participant) : patch;
|
|
@@ -5861,7 +5838,7 @@ const getSdkVersion = (sdk) => {
|
|
|
5861
5838
|
return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
|
|
5862
5839
|
};
|
|
5863
5840
|
|
|
5864
|
-
const version = "1.
|
|
5841
|
+
const version = "1.36.0";
|
|
5865
5842
|
const [major, minor, patch] = version.split('.');
|
|
5866
5843
|
let sdkInfo = {
|
|
5867
5844
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -6064,7 +6041,7 @@ var browsers = /*#__PURE__*/Object.freeze({
|
|
|
6064
6041
|
* Creates a new StatsReporter instance that collects metrics about the ongoing call and reports them to the state store
|
|
6065
6042
|
*/
|
|
6066
6043
|
const createStatsReporter = ({ subscriber, publisher, state, datacenter, pollingIntervalInMs = 2000, }) => {
|
|
6067
|
-
const logger = getLogger(
|
|
6044
|
+
const logger = videoLoggerSystem.getLogger('stats');
|
|
6068
6045
|
const getRawStatsForTrack = async (kind, selector) => {
|
|
6069
6046
|
if (kind === 'subscriber' && subscriber) {
|
|
6070
6047
|
return subscriber.getStats(selector);
|
|
@@ -6123,7 +6100,7 @@ const createStatsReporter = ({ subscriber, publisher, state, datacenter, polling
|
|
|
6123
6100
|
participantStats[sessionId] = await getStatsForStream(kind, tracks);
|
|
6124
6101
|
}
|
|
6125
6102
|
catch (e) {
|
|
6126
|
-
logger(
|
|
6103
|
+
logger.warn(`Failed to collect ${kind} stats for ${userId}`, e);
|
|
6127
6104
|
}
|
|
6128
6105
|
}
|
|
6129
6106
|
}
|
|
@@ -6155,7 +6132,7 @@ const createStatsReporter = ({ subscriber, publisher, state, datacenter, polling
|
|
|
6155
6132
|
// (they are expensive) if no one is listening to them
|
|
6156
6133
|
if (state.isCallStatsReportObserved) {
|
|
6157
6134
|
await run().catch((e) => {
|
|
6158
|
-
logger('
|
|
6135
|
+
logger.debug('Failed to collect stats', e);
|
|
6159
6136
|
});
|
|
6160
6137
|
}
|
|
6161
6138
|
timeoutId = setTimeout(loop, pollingIntervalInMs);
|
|
@@ -6301,7 +6278,7 @@ const aggregate = (stats) => {
|
|
|
6301
6278
|
|
|
6302
6279
|
class SfuStatsReporter {
|
|
6303
6280
|
constructor(sfuClient, { options, clientDetails, subscriber, publisher, microphone, camera, state, tracer, unifiedSessionId, }) {
|
|
6304
|
-
this.logger = getLogger(
|
|
6281
|
+
this.logger = videoLoggerSystem.getLogger('SfuStatsReporter');
|
|
6305
6282
|
this.inputDevices = new Map();
|
|
6306
6283
|
this.observeDevice = (device, kind) => {
|
|
6307
6284
|
const { browserPermissionState$ } = device.state;
|
|
@@ -6352,7 +6329,7 @@ class SfuStatsReporter {
|
|
|
6352
6329
|
// intentionally not awaiting the promise here
|
|
6353
6330
|
// to avoid impeding with the ongoing actions.
|
|
6354
6331
|
this.run(telemetryData).catch((err) => {
|
|
6355
|
-
this.logger('
|
|
6332
|
+
this.logger.warn('Failed to send telemetry data', err);
|
|
6356
6333
|
});
|
|
6357
6334
|
};
|
|
6358
6335
|
this.run = async (telemetry) => {
|
|
@@ -6411,7 +6388,7 @@ class SfuStatsReporter {
|
|
|
6411
6388
|
clearInterval(this.intervalId);
|
|
6412
6389
|
this.intervalId = setInterval(() => {
|
|
6413
6390
|
this.run().catch((err) => {
|
|
6414
|
-
this.logger('
|
|
6391
|
+
this.logger.warn('Failed to report stats', err);
|
|
6415
6392
|
});
|
|
6416
6393
|
}, this.options.reporting_interval_ms);
|
|
6417
6394
|
};
|
|
@@ -6428,14 +6405,14 @@ class SfuStatsReporter {
|
|
|
6428
6405
|
};
|
|
6429
6406
|
this.flush = () => {
|
|
6430
6407
|
this.run().catch((err) => {
|
|
6431
|
-
this.logger('
|
|
6408
|
+
this.logger.warn('Failed to flush report stats', err);
|
|
6432
6409
|
});
|
|
6433
6410
|
};
|
|
6434
6411
|
this.scheduleOne = (timeout) => {
|
|
6435
6412
|
clearTimeout(this.timeoutId);
|
|
6436
6413
|
this.timeoutId = setTimeout(() => {
|
|
6437
6414
|
this.run().catch((err) => {
|
|
6438
|
-
this.logger('
|
|
6415
|
+
this.logger.warn('Failed to report stats', err);
|
|
6439
6416
|
});
|
|
6440
6417
|
}, timeout);
|
|
6441
6418
|
};
|
|
@@ -6806,7 +6783,7 @@ class BasePeerConnection {
|
|
|
6806
6783
|
this.tryRestartIce = () => {
|
|
6807
6784
|
this.restartIce().catch((e) => {
|
|
6808
6785
|
const reason = 'restartICE() failed, initiating reconnect';
|
|
6809
|
-
this.logger(
|
|
6786
|
+
this.logger.error(reason, e);
|
|
6810
6787
|
const strategy = e instanceof NegotiationError &&
|
|
6811
6788
|
e.error.code === ErrorCode.PARTICIPANT_SIGNAL_LOST
|
|
6812
6789
|
? WebsocketReconnectStrategy.FAST
|
|
@@ -6824,7 +6801,7 @@ class BasePeerConnection {
|
|
|
6824
6801
|
withoutConcurrency(lockKey, async () => fn(e)).catch((err) => {
|
|
6825
6802
|
if (this.isDisposed)
|
|
6826
6803
|
return;
|
|
6827
|
-
this.logger(
|
|
6804
|
+
this.logger.warn(`Error handling ${event}`, err);
|
|
6828
6805
|
});
|
|
6829
6806
|
}));
|
|
6830
6807
|
};
|
|
@@ -6841,7 +6818,7 @@ class BasePeerConnection {
|
|
|
6841
6818
|
return this.pc.addIceCandidate(candidate).catch((e) => {
|
|
6842
6819
|
if (this.isDisposed)
|
|
6843
6820
|
return;
|
|
6844
|
-
this.logger(
|
|
6821
|
+
this.logger.warn(`ICE candidate error`, e, candidate);
|
|
6845
6822
|
});
|
|
6846
6823
|
});
|
|
6847
6824
|
};
|
|
@@ -6885,7 +6862,7 @@ class BasePeerConnection {
|
|
|
6885
6862
|
this.onIceCandidate = (e) => {
|
|
6886
6863
|
const { candidate } = e;
|
|
6887
6864
|
if (!candidate) {
|
|
6888
|
-
this.logger('
|
|
6865
|
+
this.logger.debug('null ice candidate');
|
|
6889
6866
|
return;
|
|
6890
6867
|
}
|
|
6891
6868
|
const iceCandidate = this.asJSON(candidate);
|
|
@@ -6894,7 +6871,7 @@ class BasePeerConnection {
|
|
|
6894
6871
|
.catch((err) => {
|
|
6895
6872
|
if (this.isDisposed)
|
|
6896
6873
|
return;
|
|
6897
|
-
this.logger(
|
|
6874
|
+
this.logger.warn(`ICETrickle failed`, err);
|
|
6898
6875
|
});
|
|
6899
6876
|
};
|
|
6900
6877
|
/**
|
|
@@ -6915,7 +6892,7 @@ class BasePeerConnection {
|
|
|
6915
6892
|
*/
|
|
6916
6893
|
this.onConnectionStateChange = async () => {
|
|
6917
6894
|
const state = this.pc.connectionState;
|
|
6918
|
-
this.logger(
|
|
6895
|
+
this.logger.debug(`Connection state changed`, state);
|
|
6919
6896
|
if (this.tracer && (state === 'connected' || state === 'failed')) {
|
|
6920
6897
|
try {
|
|
6921
6898
|
const stats = await this.stats.get();
|
|
@@ -6937,7 +6914,7 @@ class BasePeerConnection {
|
|
|
6937
6914
|
*/
|
|
6938
6915
|
this.onIceConnectionStateChange = () => {
|
|
6939
6916
|
const state = this.pc.iceConnectionState;
|
|
6940
|
-
this.logger(
|
|
6917
|
+
this.logger.debug(`ICE connection state changed`, state);
|
|
6941
6918
|
this.handleConnectionStateUpdate(state);
|
|
6942
6919
|
};
|
|
6943
6920
|
this.handleConnectionStateUpdate = (state) => {
|
|
@@ -6952,13 +6929,13 @@ class BasePeerConnection {
|
|
|
6952
6929
|
switch (state) {
|
|
6953
6930
|
case 'failed':
|
|
6954
6931
|
// in the `failed` state, we try to restart ICE immediately
|
|
6955
|
-
this.logger('
|
|
6932
|
+
this.logger.info('restartICE due to failed connection');
|
|
6956
6933
|
this.tryRestartIce();
|
|
6957
6934
|
break;
|
|
6958
6935
|
case 'disconnected':
|
|
6959
6936
|
// in the `disconnected` state, we schedule a restartICE() after a delay
|
|
6960
6937
|
// as the browser might recover the connection in the meantime
|
|
6961
|
-
this.logger('
|
|
6938
|
+
this.logger.info('disconnected connection, scheduling restartICE');
|
|
6962
6939
|
clearTimeout(this.iceRestartTimeout);
|
|
6963
6940
|
this.iceRestartTimeout = setTimeout(() => {
|
|
6964
6941
|
const currentState = this.pc.iceConnectionState;
|
|
@@ -6970,7 +6947,7 @@ class BasePeerConnection {
|
|
|
6970
6947
|
case 'connected':
|
|
6971
6948
|
// in the `connected` state, we clear the ice restart timeout if it exists
|
|
6972
6949
|
if (this.iceRestartTimeout) {
|
|
6973
|
-
this.logger('
|
|
6950
|
+
this.logger.info('connected connection, canceling restartICE');
|
|
6974
6951
|
clearTimeout(this.iceRestartTimeout);
|
|
6975
6952
|
this.iceRestartTimeout = undefined;
|
|
6976
6953
|
}
|
|
@@ -6984,19 +6961,19 @@ class BasePeerConnection {
|
|
|
6984
6961
|
const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent
|
|
6985
6962
|
? `${e.errorCode}: ${e.errorText}`
|
|
6986
6963
|
: e;
|
|
6987
|
-
this.logger('
|
|
6964
|
+
this.logger.debug('ICE Candidate error', errorMessage);
|
|
6988
6965
|
};
|
|
6989
6966
|
/**
|
|
6990
6967
|
* Handles the ICE gathering state change event.
|
|
6991
6968
|
*/
|
|
6992
6969
|
this.onIceGatherChange = () => {
|
|
6993
|
-
this.logger(
|
|
6970
|
+
this.logger.debug(`ICE Gathering State`, this.pc.iceGatheringState);
|
|
6994
6971
|
};
|
|
6995
6972
|
/**
|
|
6996
6973
|
* Handles the signaling state change event.
|
|
6997
6974
|
*/
|
|
6998
6975
|
this.onSignalingChange = () => {
|
|
6999
|
-
this.logger(
|
|
6976
|
+
this.logger.debug(`Signaling state changed`, this.pc.signalingState);
|
|
7000
6977
|
};
|
|
7001
6978
|
this.peerType = peerType;
|
|
7002
6979
|
this.sfuClient = sfuClient;
|
|
@@ -7004,10 +6981,7 @@ class BasePeerConnection {
|
|
|
7004
6981
|
this.dispatcher = dispatcher;
|
|
7005
6982
|
this.iceRestartDelay = iceRestartDelay;
|
|
7006
6983
|
this.onReconnectionNeeded = onReconnectionNeeded;
|
|
7007
|
-
this.logger = getLogger([
|
|
7008
|
-
peerType === PeerType.SUBSCRIBER ? 'Subscriber' : 'Publisher',
|
|
7009
|
-
tag,
|
|
7010
|
-
]);
|
|
6984
|
+
this.logger = videoLoggerSystem.getLogger(peerType === PeerType.SUBSCRIBER ? 'Subscriber' : 'Publisher', { tags: [tag] });
|
|
7011
6985
|
this.pc = this.createPeerConnection(connectionConfig);
|
|
7012
6986
|
this.stats = new StatsTracer(this.pc, peerType, this.trackIdToTrackType);
|
|
7013
6987
|
if (enableTracing) {
|
|
@@ -7130,7 +7104,7 @@ class TransceiverCache {
|
|
|
7130
7104
|
}
|
|
7131
7105
|
|
|
7132
7106
|
const ensureExhausted = (x, message) => {
|
|
7133
|
-
getLogger(
|
|
7107
|
+
videoLoggerSystem.getLogger('helpers').warn(message, x);
|
|
7134
7108
|
};
|
|
7135
7109
|
|
|
7136
7110
|
const trackTypeToParticipantStreamKey = (trackType) => {
|
|
@@ -7469,7 +7443,7 @@ class Publisher extends BasePeerConnection {
|
|
|
7469
7443
|
params.degradationPreference = 'maintain-framerate';
|
|
7470
7444
|
await transceiver.sender.setParameters(params);
|
|
7471
7445
|
const trackType = publishOption.trackType;
|
|
7472
|
-
this.logger(
|
|
7446
|
+
this.logger.debug(`Added ${TrackType[trackType]} transceiver`);
|
|
7473
7447
|
this.transceiverCache.add({ publishOption, transceiver, options });
|
|
7474
7448
|
this.trackIdToTrackType.set(track.id, trackType);
|
|
7475
7449
|
await this.negotiate();
|
|
@@ -7589,16 +7563,16 @@ class Publisher extends BasePeerConnection {
|
|
|
7589
7563
|
const { trackType, layers, publishOptionId } = videoSender;
|
|
7590
7564
|
const enabledLayers = layers.filter((l) => l.active);
|
|
7591
7565
|
const tag = 'Update publish quality:';
|
|
7592
|
-
this.logger(
|
|
7566
|
+
this.logger.info(`${tag} requested layers by SFU:`, enabledLayers);
|
|
7593
7567
|
const transceiverId = this.transceiverCache.find((t) => t.publishOption.id === publishOptionId &&
|
|
7594
7568
|
t.publishOption.trackType === trackType);
|
|
7595
7569
|
const sender = transceiverId?.transceiver.sender;
|
|
7596
7570
|
if (!sender) {
|
|
7597
|
-
return this.logger(
|
|
7571
|
+
return this.logger.warn(`${tag} no video sender found.`);
|
|
7598
7572
|
}
|
|
7599
7573
|
const params = sender.getParameters();
|
|
7600
7574
|
if (params.encodings.length === 0) {
|
|
7601
|
-
return this.logger(
|
|
7575
|
+
return this.logger.warn(`${tag} there are no encodings set.`);
|
|
7602
7576
|
}
|
|
7603
7577
|
const codecInUse = transceiverId?.publishOption.codec?.name;
|
|
7604
7578
|
const usesSvcCodec = codecInUse && isSvcCodec(codecInUse);
|
|
@@ -7642,19 +7616,19 @@ class Publisher extends BasePeerConnection {
|
|
|
7642
7616
|
}
|
|
7643
7617
|
const activeEncoders = params.encodings.filter((e) => e.active);
|
|
7644
7618
|
if (!changed) {
|
|
7645
|
-
return this.logger(
|
|
7619
|
+
return this.logger.info(`${tag} no change:`, activeEncoders);
|
|
7646
7620
|
}
|
|
7647
7621
|
await sender.setParameters(params);
|
|
7648
|
-
this.logger(
|
|
7622
|
+
this.logger.info(`${tag} enabled rids:`, activeEncoders);
|
|
7649
7623
|
};
|
|
7650
7624
|
/**
|
|
7651
7625
|
* Restarts the ICE connection and renegotiates with the SFU.
|
|
7652
7626
|
*/
|
|
7653
7627
|
this.restartIce = async () => {
|
|
7654
|
-
this.logger('
|
|
7628
|
+
this.logger.debug('Restarting ICE connection');
|
|
7655
7629
|
const signalingState = this.pc.signalingState;
|
|
7656
7630
|
if (this.isIceRestarting || signalingState === 'have-local-offer') {
|
|
7657
|
-
this.logger('
|
|
7631
|
+
this.logger.debug('ICE restart is already in progress');
|
|
7658
7632
|
return;
|
|
7659
7633
|
}
|
|
7660
7634
|
await this.negotiate({ iceRestart: true });
|
|
@@ -7816,13 +7790,13 @@ class Subscriber extends BasePeerConnection {
|
|
|
7816
7790
|
* Restarts the ICE connection and renegotiates with the SFU.
|
|
7817
7791
|
*/
|
|
7818
7792
|
this.restartIce = async () => {
|
|
7819
|
-
this.logger('
|
|
7793
|
+
this.logger.debug('Restarting ICE connection');
|
|
7820
7794
|
if (this.pc.signalingState === 'have-remote-offer') {
|
|
7821
|
-
this.logger('
|
|
7795
|
+
this.logger.debug('ICE restart is already in progress');
|
|
7822
7796
|
return;
|
|
7823
7797
|
}
|
|
7824
7798
|
if (this.pc.connectionState === 'new') {
|
|
7825
|
-
this.logger(
|
|
7799
|
+
this.logger.debug(`ICE connection is not yet established, skipping restart.`);
|
|
7826
7800
|
return;
|
|
7827
7801
|
}
|
|
7828
7802
|
const previousIsIceRestarting = this.isIceRestarting;
|
|
@@ -7845,25 +7819,25 @@ class Subscriber extends BasePeerConnection {
|
|
|
7845
7819
|
// example: `e3f6aaf8-b03d-4911-be36-83f47d37a76a:TRACK_TYPE_VIDEO`
|
|
7846
7820
|
const [trackId, rawTrackType] = primaryStream.id.split(':');
|
|
7847
7821
|
const participantToUpdate = this.state.participants.find((p) => p.trackLookupPrefix === trackId);
|
|
7848
|
-
this.logger(
|
|
7822
|
+
this.logger.debug(`[onTrack]: Got remote ${rawTrackType} track for userId: ${participantToUpdate?.userId}`, e.track.id, e.track);
|
|
7849
7823
|
const trackDebugInfo = `${participantToUpdate?.userId} ${rawTrackType}:${trackId}`;
|
|
7850
7824
|
e.track.addEventListener('mute', () => {
|
|
7851
|
-
this.logger(
|
|
7825
|
+
this.logger.info(`[onTrack]: Track muted: ${trackDebugInfo}`);
|
|
7852
7826
|
});
|
|
7853
7827
|
e.track.addEventListener('unmute', () => {
|
|
7854
|
-
this.logger(
|
|
7828
|
+
this.logger.info(`[onTrack]: Track unmuted: ${trackDebugInfo}`);
|
|
7855
7829
|
});
|
|
7856
7830
|
e.track.addEventListener('ended', () => {
|
|
7857
|
-
this.logger(
|
|
7831
|
+
this.logger.info(`[onTrack]: Track ended: ${trackDebugInfo}`);
|
|
7858
7832
|
this.state.removeOrphanedTrack(primaryStream.id);
|
|
7859
7833
|
});
|
|
7860
7834
|
const trackType = toTrackType(rawTrackType);
|
|
7861
7835
|
if (!trackType) {
|
|
7862
|
-
return this.logger(
|
|
7836
|
+
return this.logger.error(`Unknown track type: ${rawTrackType}`);
|
|
7863
7837
|
}
|
|
7864
7838
|
this.trackIdToTrackType.set(e.track.id, trackType);
|
|
7865
7839
|
if (!participantToUpdate) {
|
|
7866
|
-
this.logger(
|
|
7840
|
+
this.logger.warn(`[onTrack]: Received track for unknown participant: ${trackId}`, e);
|
|
7867
7841
|
this.state.registerOrphanedTrack({
|
|
7868
7842
|
id: primaryStream.id,
|
|
7869
7843
|
trackLookupPrefix: trackId,
|
|
@@ -7874,7 +7848,7 @@ class Subscriber extends BasePeerConnection {
|
|
|
7874
7848
|
}
|
|
7875
7849
|
const streamKindProp = trackTypeToParticipantStreamKey(trackType);
|
|
7876
7850
|
if (!streamKindProp) {
|
|
7877
|
-
this.logger(
|
|
7851
|
+
this.logger.error(`Unknown track type: ${rawTrackType}`);
|
|
7878
7852
|
return;
|
|
7879
7853
|
}
|
|
7880
7854
|
// get the previous stream to dispose it later
|
|
@@ -7887,7 +7861,7 @@ class Subscriber extends BasePeerConnection {
|
|
|
7887
7861
|
});
|
|
7888
7862
|
// now, dispose the previous stream if it exists
|
|
7889
7863
|
if (previousStream) {
|
|
7890
|
-
this.logger(
|
|
7864
|
+
this.logger.info(`[onTrack]: Cleaning up previous remote ${e.track.kind} tracks for userId: ${participantToUpdate.userId}`);
|
|
7891
7865
|
previousStream.getTracks().forEach((t) => {
|
|
7892
7866
|
t.stop();
|
|
7893
7867
|
previousStream.removeTrack(t);
|
|
@@ -7914,7 +7888,7 @@ class Subscriber extends BasePeerConnection {
|
|
|
7914
7888
|
this.pc.addEventListener('track', this.handleOnTrack);
|
|
7915
7889
|
this.on('subscriberOffer', async (subscriberOffer) => {
|
|
7916
7890
|
return this.negotiate(subscriberOffer).catch((err) => {
|
|
7917
|
-
this.logger(
|
|
7891
|
+
this.logger.error(`Negotiation failed.`, err);
|
|
7918
7892
|
});
|
|
7919
7893
|
});
|
|
7920
7894
|
}
|
|
@@ -7931,20 +7905,20 @@ class Subscriber extends BasePeerConnection {
|
|
|
7931
7905
|
|
|
7932
7906
|
const createWebSocketSignalChannel = (opts) => {
|
|
7933
7907
|
const { endpoint, onMessage, tag, tracer } = opts;
|
|
7934
|
-
const logger = getLogger(
|
|
7935
|
-
logger('
|
|
7908
|
+
const logger = videoLoggerSystem.getLogger('SfuClientWS', { tags: [tag] });
|
|
7909
|
+
logger.debug('Creating signaling WS channel:', endpoint);
|
|
7936
7910
|
const ws = new WebSocket(endpoint);
|
|
7937
7911
|
ws.binaryType = 'arraybuffer'; // do we need this?
|
|
7938
7912
|
ws.addEventListener('error', (e) => {
|
|
7939
|
-
logger('
|
|
7913
|
+
logger.error('Signaling WS channel error', e);
|
|
7940
7914
|
tracer?.trace('signal.ws.error', e);
|
|
7941
7915
|
});
|
|
7942
7916
|
ws.addEventListener('close', (e) => {
|
|
7943
|
-
logger('
|
|
7917
|
+
logger.info('Signaling WS channel is closed', e);
|
|
7944
7918
|
tracer?.trace('signal.ws.close', e);
|
|
7945
7919
|
});
|
|
7946
7920
|
ws.addEventListener('open', (e) => {
|
|
7947
|
-
logger('
|
|
7921
|
+
logger.info('Signaling WS channel is open', e);
|
|
7948
7922
|
tracer?.trace('signal.ws.open', e);
|
|
7949
7923
|
});
|
|
7950
7924
|
ws.addEventListener('message', (e) => {
|
|
@@ -7956,7 +7930,7 @@ const createWebSocketSignalChannel = (opts) => {
|
|
|
7956
7930
|
}
|
|
7957
7931
|
catch (err) {
|
|
7958
7932
|
const message = 'Failed to decode a message. Check whether the Proto models match.';
|
|
7959
|
-
logger(
|
|
7933
|
+
logger.error(message, { event: e, error: err });
|
|
7960
7934
|
tracer?.trace('signal.ws.message.error', message);
|
|
7961
7935
|
}
|
|
7962
7936
|
});
|
|
@@ -8157,14 +8131,14 @@ class StreamSfuClient {
|
|
|
8157
8131
|
this.close = (code = StreamSfuClient.NORMAL_CLOSURE, reason) => {
|
|
8158
8132
|
this.isClosingClean = code !== StreamSfuClient.ERROR_CONNECTION_UNHEALTHY;
|
|
8159
8133
|
if (this.signalWs.readyState === WebSocket.OPEN) {
|
|
8160
|
-
this.logger(
|
|
8134
|
+
this.logger.debug(`Closing SFU WS connection: ${code} - ${reason}`);
|
|
8161
8135
|
this.signalWs.close(code, `js-client: ${reason}`);
|
|
8162
8136
|
this.signalWs.removeEventListener('close', this.handleWebSocketClose);
|
|
8163
8137
|
}
|
|
8164
8138
|
this.dispose();
|
|
8165
8139
|
};
|
|
8166
8140
|
this.dispose = () => {
|
|
8167
|
-
this.logger('
|
|
8141
|
+
this.logger.debug('Disposing SFU client');
|
|
8168
8142
|
this.unsubscribeIceTrickle();
|
|
8169
8143
|
this.unsubscribeNetworkChanged();
|
|
8170
8144
|
clearInterval(this.keepAliveInterval);
|
|
@@ -8184,7 +8158,7 @@ class StreamSfuClient {
|
|
|
8184
8158
|
await this.notifyLeave(reason);
|
|
8185
8159
|
}
|
|
8186
8160
|
catch (err) {
|
|
8187
|
-
this.logger('
|
|
8161
|
+
this.logger.debug('Error notifying SFU about leaving call', err);
|
|
8188
8162
|
}
|
|
8189
8163
|
this.close(StreamSfuClient.NORMAL_CLOSURE, reason.substring(0, 115));
|
|
8190
8164
|
};
|
|
@@ -8305,10 +8279,10 @@ class StreamSfuClient {
|
|
|
8305
8279
|
await this.signalReady(); // wait for the signal ws to be open
|
|
8306
8280
|
const msgJson = SfuRequest.toJson(message);
|
|
8307
8281
|
if (this.signalWs.readyState !== WebSocket.OPEN) {
|
|
8308
|
-
this.logger('
|
|
8282
|
+
this.logger.debug('Signal WS is not open. Skipping message', msgJson);
|
|
8309
8283
|
return;
|
|
8310
8284
|
}
|
|
8311
|
-
this.logger(
|
|
8285
|
+
this.logger.debug(`Sending message to: ${this.edgeName}`, msgJson);
|
|
8312
8286
|
this.signalWs.send(SfuRequest.toBinary(message));
|
|
8313
8287
|
};
|
|
8314
8288
|
this.keepAlive = () => {
|
|
@@ -8316,7 +8290,7 @@ class StreamSfuClient {
|
|
|
8316
8290
|
timers.clearInterval(this.keepAliveInterval);
|
|
8317
8291
|
this.keepAliveInterval = timers.setInterval(() => {
|
|
8318
8292
|
this.ping().catch((e) => {
|
|
8319
|
-
this.logger('
|
|
8293
|
+
this.logger.error('Error sending healthCheckRequest to SFU', e);
|
|
8320
8294
|
});
|
|
8321
8295
|
}, this.pingIntervalInMs);
|
|
8322
8296
|
};
|
|
@@ -8339,7 +8313,7 @@ class StreamSfuClient {
|
|
|
8339
8313
|
this.edgeName = server.edge_name;
|
|
8340
8314
|
this.joinResponseTimeout = joinResponseTimeout;
|
|
8341
8315
|
this.tag = tag;
|
|
8342
|
-
this.logger = getLogger(
|
|
8316
|
+
this.logger = videoLoggerSystem.getLogger('SfuClient', { tags: [tag] });
|
|
8343
8317
|
this.tracer = enableTracing
|
|
8344
8318
|
? new Tracer(`${tag}-${this.edgeName}`)
|
|
8345
8319
|
: undefined;
|
|
@@ -8348,7 +8322,8 @@ class StreamSfuClient {
|
|
|
8348
8322
|
interceptors: [
|
|
8349
8323
|
withHeaders({ Authorization: `Bearer ${token}` }),
|
|
8350
8324
|
this.tracer && withRequestTracer(this.tracer.trace),
|
|
8351
|
-
getLogLevel() === 'trace' &&
|
|
8325
|
+
this.logger.getLogLevel() === 'trace' &&
|
|
8326
|
+
withRequestLogger(this.logger, 'trace'),
|
|
8352
8327
|
].filter((v) => !!v),
|
|
8353
8328
|
});
|
|
8354
8329
|
// Special handling for the ICETrickle kind of events.
|
|
@@ -8436,13 +8411,13 @@ const watchCallRejected = (call) => {
|
|
|
8436
8411
|
const { call: eventCall } = event;
|
|
8437
8412
|
const { session: callSession } = eventCall;
|
|
8438
8413
|
if (!callSession) {
|
|
8439
|
-
call.logger('
|
|
8414
|
+
call.logger.warn('No call session provided. Ignoring call.rejected event.', event);
|
|
8440
8415
|
return;
|
|
8441
8416
|
}
|
|
8442
8417
|
const rejectedBy = callSession.rejected_by;
|
|
8443
8418
|
const { members, callingState } = call.state;
|
|
8444
8419
|
if (callingState !== CallingState.RINGING) {
|
|
8445
|
-
call.logger('
|
|
8420
|
+
call.logger.info('Call is not in ringing mode (it is either accepted or rejected already). Ignoring call.rejected event.', event);
|
|
8446
8421
|
return;
|
|
8447
8422
|
}
|
|
8448
8423
|
if (call.isCreatedByMe) {
|
|
@@ -8450,7 +8425,7 @@ const watchCallRejected = (call) => {
|
|
|
8450
8425
|
.filter((m) => m.user_id !== call.currentUserId)
|
|
8451
8426
|
.every((m) => rejectedBy[m.user_id]);
|
|
8452
8427
|
if (everyoneElseRejected) {
|
|
8453
|
-
call.logger('
|
|
8428
|
+
call.logger.info('everyone rejected, leaving the call');
|
|
8454
8429
|
await call.leave({
|
|
8455
8430
|
reject: true,
|
|
8456
8431
|
reason: 'cancel',
|
|
@@ -8460,7 +8435,7 @@ const watchCallRejected = (call) => {
|
|
|
8460
8435
|
}
|
|
8461
8436
|
else {
|
|
8462
8437
|
if (rejectedBy[eventCall.created_by.id]) {
|
|
8463
|
-
call.logger('
|
|
8438
|
+
call.logger.info('call creator rejected, leaving call');
|
|
8464
8439
|
await call.leave({ message: 'ring: creator rejected' });
|
|
8465
8440
|
}
|
|
8466
8441
|
}
|
|
@@ -8477,7 +8452,7 @@ const watchCallEnded = (call) => {
|
|
|
8477
8452
|
call
|
|
8478
8453
|
.leave({ message: 'call.ended event received', reject: false })
|
|
8479
8454
|
.catch((err) => {
|
|
8480
|
-
call.logger('
|
|
8455
|
+
call.logger.error('Failed to leave call after call.ended ', err);
|
|
8481
8456
|
});
|
|
8482
8457
|
}
|
|
8483
8458
|
};
|
|
@@ -8505,7 +8480,7 @@ const watchSfuCallEnded = (call) => {
|
|
|
8505
8480
|
await call.leave({ message: `callEnded received: ${reason}` });
|
|
8506
8481
|
}
|
|
8507
8482
|
catch (err) {
|
|
8508
|
-
call.logger('
|
|
8483
|
+
call.logger.error('Failed to leave call after being ended by the SFU', err);
|
|
8509
8484
|
}
|
|
8510
8485
|
});
|
|
8511
8486
|
};
|
|
@@ -8588,7 +8563,7 @@ const watchLiveEnded = (dispatcher, call) => {
|
|
|
8588
8563
|
call.state.setBackstage(true);
|
|
8589
8564
|
if (!call.permissionsContext.hasPermission(OwnCapability.JOIN_BACKSTAGE)) {
|
|
8590
8565
|
call.leave({ message: 'live ended' }).catch((err) => {
|
|
8591
|
-
call.logger('
|
|
8566
|
+
call.logger.error('Failed to leave call after live ended', err);
|
|
8592
8567
|
});
|
|
8593
8568
|
}
|
|
8594
8569
|
});
|
|
@@ -8600,9 +8575,9 @@ const watchSfuErrorReports = (dispatcher) => {
|
|
|
8600
8575
|
return dispatcher.on('error', (e) => {
|
|
8601
8576
|
if (!e.error)
|
|
8602
8577
|
return;
|
|
8603
|
-
const logger = getLogger(
|
|
8578
|
+
const logger = videoLoggerSystem.getLogger('SfuClient');
|
|
8604
8579
|
const { error, reconnectStrategy } = e;
|
|
8605
|
-
logger('
|
|
8580
|
+
logger.error('SFU reported error', {
|
|
8606
8581
|
code: ErrorCode[error.code],
|
|
8607
8582
|
reconnectStrategy: WebsocketReconnectStrategy[reconnectStrategy],
|
|
8608
8583
|
message: error.message,
|
|
@@ -8656,7 +8631,7 @@ const handleRemoteSoftMute = (call) => {
|
|
|
8656
8631
|
if (cause === TrackUnpublishReason.MODERATION &&
|
|
8657
8632
|
sessionId === localParticipant?.sessionId) {
|
|
8658
8633
|
const logger = call.logger;
|
|
8659
|
-
logger(
|
|
8634
|
+
logger.info(`Local participant's ${TrackType[type]} track is muted remotely`);
|
|
8660
8635
|
try {
|
|
8661
8636
|
if (type === TrackType.VIDEO) {
|
|
8662
8637
|
await call.camera.disable();
|
|
@@ -8669,11 +8644,11 @@ const handleRemoteSoftMute = (call) => {
|
|
|
8669
8644
|
await call.screenShare.disable();
|
|
8670
8645
|
}
|
|
8671
8646
|
else {
|
|
8672
|
-
logger('
|
|
8647
|
+
logger.warn('Unsupported track type to soft mute', TrackType[type]);
|
|
8673
8648
|
}
|
|
8674
8649
|
}
|
|
8675
8650
|
catch (error) {
|
|
8676
|
-
logger('
|
|
8651
|
+
logger.error('Failed to stop publishing', error);
|
|
8677
8652
|
}
|
|
8678
8653
|
}
|
|
8679
8654
|
});
|
|
@@ -8994,7 +8969,7 @@ class DynascaleManager {
|
|
|
8994
8969
|
* The viewport tracker instance.
|
|
8995
8970
|
*/
|
|
8996
8971
|
this.viewportTracker = new ViewportTracker();
|
|
8997
|
-
this.logger = getLogger(
|
|
8972
|
+
this.logger = videoLoggerSystem.getLogger('DynascaleManager');
|
|
8998
8973
|
this.pendingSubscriptionsUpdate = null;
|
|
8999
8974
|
this.videoTrackSubscriptionOverridesSubject = new BehaviorSubject({});
|
|
9000
8975
|
this.videoTrackSubscriptionOverrides$ = this.videoTrackSubscriptionOverridesSubject.asObservable();
|
|
@@ -9051,7 +9026,7 @@ class DynascaleManager {
|
|
|
9051
9026
|
this.sfuClient
|
|
9052
9027
|
?.updateSubscriptions(this.trackSubscriptions)
|
|
9053
9028
|
.catch((err) => {
|
|
9054
|
-
this.logger(
|
|
9029
|
+
this.logger.debug(`Failed to update track subscriptions`, err);
|
|
9055
9030
|
});
|
|
9056
9031
|
};
|
|
9057
9032
|
if (debounceType) {
|
|
@@ -9140,7 +9115,7 @@ class DynascaleManager {
|
|
|
9140
9115
|
// is not visible (e.g., has display: none).
|
|
9141
9116
|
// we treat this as "unsubscription" as we don't want to keep
|
|
9142
9117
|
// consuming bandwidth for a video that is not visible on the screen.
|
|
9143
|
-
this.logger(
|
|
9118
|
+
this.logger.debug(`Ignoring 0x0 dimension`, boundParticipant);
|
|
9144
9119
|
dimension = undefined;
|
|
9145
9120
|
}
|
|
9146
9121
|
this.callState.updateParticipantTracks(trackType, {
|
|
@@ -9245,7 +9220,7 @@ class DynascaleManager {
|
|
|
9245
9220
|
setTimeout(() => {
|
|
9246
9221
|
videoElement.srcObject = source ?? null;
|
|
9247
9222
|
videoElement.play().catch((e) => {
|
|
9248
|
-
this.logger(
|
|
9223
|
+
this.logger.warn(`Failed to play stream`, e);
|
|
9249
9224
|
});
|
|
9250
9225
|
// we add extra delay until we attempt to force-play
|
|
9251
9226
|
// the participant's media stream in Firefox and Safari,
|
|
@@ -9282,13 +9257,13 @@ class DynascaleManager {
|
|
|
9282
9257
|
return;
|
|
9283
9258
|
if ('setSinkId' in audioElement) {
|
|
9284
9259
|
audioElement.setSinkId(deviceId).catch((e) => {
|
|
9285
|
-
this.logger(
|
|
9260
|
+
this.logger.warn(`Can't to set AudioElement sinkId`, e);
|
|
9286
9261
|
});
|
|
9287
9262
|
}
|
|
9288
9263
|
if (audioContext && 'setSinkId' in audioContext) {
|
|
9289
9264
|
// @ts-expect-error setSinkId is not available in all browsers
|
|
9290
9265
|
audioContext.setSinkId(deviceId).catch((e) => {
|
|
9291
|
-
this.logger(
|
|
9266
|
+
this.logger.warn(`Can't to set AudioContext sinkId`, e);
|
|
9292
9267
|
});
|
|
9293
9268
|
}
|
|
9294
9269
|
};
|
|
@@ -9330,7 +9305,7 @@ class DynascaleManager {
|
|
|
9330
9305
|
// we will play audio directly through the audio element in other browsers
|
|
9331
9306
|
audioElement.muted = false;
|
|
9332
9307
|
audioElement.play().catch((e) => {
|
|
9333
|
-
this.logger(
|
|
9308
|
+
this.logger.warn(`Failed to play audio stream`, e);
|
|
9334
9309
|
});
|
|
9335
9310
|
}
|
|
9336
9311
|
const { selectedDevice } = this.speaker.state;
|
|
@@ -9382,7 +9357,7 @@ class DynascaleManager {
|
|
|
9382
9357
|
if (this.audioContext?.state === 'suspended') {
|
|
9383
9358
|
this.audioContext
|
|
9384
9359
|
.resume()
|
|
9385
|
-
.catch((err) => this.logger(
|
|
9360
|
+
.catch((err) => this.logger.warn(`Can't resume audio context`, err))
|
|
9386
9361
|
.then(() => {
|
|
9387
9362
|
document.removeEventListener('click', this.resumeAudioContext);
|
|
9388
9363
|
});
|
|
@@ -9619,7 +9594,7 @@ class BrowserPermission {
|
|
|
9619
9594
|
this.disposeController = new AbortController();
|
|
9620
9595
|
this.wasPrompted = false;
|
|
9621
9596
|
this.listeners = new Set();
|
|
9622
|
-
this.logger = getLogger(
|
|
9597
|
+
this.logger = videoLoggerSystem.getLogger('permissions');
|
|
9623
9598
|
const signal = this.disposeController.signal;
|
|
9624
9599
|
this.ready = (async () => {
|
|
9625
9600
|
const assumeGranted = () => {
|
|
@@ -9645,7 +9620,7 @@ class BrowserPermission {
|
|
|
9645
9620
|
}
|
|
9646
9621
|
}
|
|
9647
9622
|
catch (err) {
|
|
9648
|
-
this.logger('
|
|
9623
|
+
this.logger.debug('Failed to query permission status', err);
|
|
9649
9624
|
assumeGranted();
|
|
9650
9625
|
}
|
|
9651
9626
|
})();
|
|
@@ -9684,7 +9659,7 @@ class BrowserPermission {
|
|
|
9684
9659
|
typeof e === 'object' &&
|
|
9685
9660
|
'name' in e &&
|
|
9686
9661
|
(e.name === 'NotAllowedError' || e.name === 'SecurityError')) {
|
|
9687
|
-
this.logger('
|
|
9662
|
+
this.logger.info('Browser permission was not granted', {
|
|
9688
9663
|
permission: this.permission,
|
|
9689
9664
|
});
|
|
9690
9665
|
this.setState('denied');
|
|
@@ -9693,7 +9668,7 @@ class BrowserPermission {
|
|
|
9693
9668
|
}
|
|
9694
9669
|
return false;
|
|
9695
9670
|
}
|
|
9696
|
-
this.logger(
|
|
9671
|
+
this.logger.error(`Failed to getUserMedia`, {
|
|
9697
9672
|
error: e,
|
|
9698
9673
|
permission: this.permission,
|
|
9699
9674
|
});
|
|
@@ -9914,10 +9889,12 @@ const getAudioStream = async (trackConstraints, tracer) => {
|
|
|
9914
9889
|
if (isNotFoundOrOverconstrainedError(error) && trackConstraints?.deviceId) {
|
|
9915
9890
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9916
9891
|
const { deviceId, ...relaxedConstraints } = trackConstraints;
|
|
9917
|
-
|
|
9892
|
+
videoLoggerSystem
|
|
9893
|
+
.getLogger('devices')
|
|
9894
|
+
.warn('Failed to get audio stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
|
|
9918
9895
|
return getAudioStream(relaxedConstraints);
|
|
9919
9896
|
}
|
|
9920
|
-
getLogger(
|
|
9897
|
+
videoLoggerSystem.getLogger('devices').error('Failed to get audio stream', {
|
|
9921
9898
|
error,
|
|
9922
9899
|
constraints,
|
|
9923
9900
|
});
|
|
@@ -9950,10 +9927,12 @@ const getVideoStream = async (trackConstraints, tracer) => {
|
|
|
9950
9927
|
if (isNotFoundOrOverconstrainedError(error) && trackConstraints?.deviceId) {
|
|
9951
9928
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9952
9929
|
const { deviceId, ...relaxedConstraints } = trackConstraints;
|
|
9953
|
-
|
|
9930
|
+
videoLoggerSystem
|
|
9931
|
+
.getLogger('devices')
|
|
9932
|
+
.warn('Failed to get video stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
|
|
9954
9933
|
return getVideoStream(relaxedConstraints);
|
|
9955
9934
|
}
|
|
9956
|
-
getLogger(
|
|
9935
|
+
videoLoggerSystem.getLogger('devices').error('Failed to get video stream', {
|
|
9957
9936
|
error,
|
|
9958
9937
|
constraints,
|
|
9959
9938
|
});
|
|
@@ -10002,7 +9981,9 @@ const getScreenShareStream = async (options, tracer) => {
|
|
|
10002
9981
|
}
|
|
10003
9982
|
catch (e) {
|
|
10004
9983
|
tracer?.trace(`${tag}OnFailure`, e.name);
|
|
10005
|
-
|
|
9984
|
+
videoLoggerSystem
|
|
9985
|
+
.getLogger('devices')
|
|
9986
|
+
.error('Failed to get screen share stream', e);
|
|
10006
9987
|
throw e;
|
|
10007
9988
|
}
|
|
10008
9989
|
};
|
|
@@ -10064,7 +10045,7 @@ class DeviceManager {
|
|
|
10064
10045
|
this.call = call;
|
|
10065
10046
|
this.state = state;
|
|
10066
10047
|
this.trackType = trackType;
|
|
10067
|
-
this.logger = getLogger(
|
|
10048
|
+
this.logger = videoLoggerSystem.getLogger(`${TrackType[trackType].toLowerCase()} manager`);
|
|
10068
10049
|
this.setup();
|
|
10069
10050
|
}
|
|
10070
10051
|
setup() {
|
|
@@ -10227,6 +10208,7 @@ class DeviceManager {
|
|
|
10227
10208
|
}
|
|
10228
10209
|
}
|
|
10229
10210
|
async applySettingsToStream() {
|
|
10211
|
+
console.log('applySettingsToStream ');
|
|
10230
10212
|
await withCancellation(this.statusChangeConcurrencyTag, async (signal) => {
|
|
10231
10213
|
if (this.enabled) {
|
|
10232
10214
|
try {
|
|
@@ -10259,7 +10241,7 @@ class DeviceManager {
|
|
|
10259
10241
|
const mediaStream = this.state.mediaStream;
|
|
10260
10242
|
if (!mediaStream)
|
|
10261
10243
|
return;
|
|
10262
|
-
this.logger(
|
|
10244
|
+
this.logger.debug(`${stopTracks ? 'Stopping' : 'Disabling'} stream`);
|
|
10263
10245
|
if (this.call.state.callingState === CallingState.JOINED) {
|
|
10264
10246
|
await this.stopPublishStream();
|
|
10265
10247
|
}
|
|
@@ -10305,7 +10287,7 @@ class DeviceManager {
|
|
|
10305
10287
|
}
|
|
10306
10288
|
}
|
|
10307
10289
|
async unmuteStream() {
|
|
10308
|
-
this.logger('
|
|
10290
|
+
this.logger.debug('Starting stream');
|
|
10309
10291
|
let stream;
|
|
10310
10292
|
let rootStream;
|
|
10311
10293
|
if (this.state.mediaStream &&
|
|
@@ -10386,7 +10368,7 @@ class DeviceManager {
|
|
|
10386
10368
|
return output;
|
|
10387
10369
|
})
|
|
10388
10370
|
.then(chainWith(parent), (error) => {
|
|
10389
|
-
this.logger('
|
|
10371
|
+
this.logger.warn('Filter failed to start and will be ignored', error);
|
|
10390
10372
|
return parent;
|
|
10391
10373
|
}), rootStream);
|
|
10392
10374
|
}
|
|
@@ -10409,7 +10391,7 @@ class DeviceManager {
|
|
|
10409
10391
|
if (!isMobile() || this.trackType !== TrackType.VIDEO)
|
|
10410
10392
|
return;
|
|
10411
10393
|
this.call.notifyTrackMuteState(muted, this.trackType).catch((err) => {
|
|
10412
|
-
this.logger('
|
|
10394
|
+
this.logger.warn('Error while notifying track mute state', err);
|
|
10413
10395
|
});
|
|
10414
10396
|
};
|
|
10415
10397
|
stream.getTracks().forEach((track) => {
|
|
@@ -10473,7 +10455,7 @@ class DeviceManager {
|
|
|
10473
10455
|
}
|
|
10474
10456
|
}
|
|
10475
10457
|
catch (err) {
|
|
10476
|
-
this.logger('
|
|
10458
|
+
this.logger.warn('Unexpected error while handling disconnected or replaced device', err);
|
|
10477
10459
|
}
|
|
10478
10460
|
}));
|
|
10479
10461
|
}
|
|
@@ -10680,7 +10662,7 @@ class CameraManager extends DeviceManager {
|
|
|
10680
10662
|
*/
|
|
10681
10663
|
async selectDirection(direction) {
|
|
10682
10664
|
if (!this.isDirectionSupportedByDevice()) {
|
|
10683
|
-
this.logger('
|
|
10665
|
+
this.logger.warn('Setting direction is not supported on this device');
|
|
10684
10666
|
return;
|
|
10685
10667
|
}
|
|
10686
10668
|
if (isReactNative()) {
|
|
@@ -10731,7 +10713,7 @@ class CameraManager extends DeviceManager {
|
|
|
10731
10713
|
}
|
|
10732
10714
|
catch (error) {
|
|
10733
10715
|
// couldn't enable device, target resolution will be applied the next time user attempts to start the device
|
|
10734
|
-
this.logger('
|
|
10716
|
+
this.logger.warn('could not apply target resolution', error);
|
|
10735
10717
|
}
|
|
10736
10718
|
}
|
|
10737
10719
|
if (this.enabled && this.state.mediaStream) {
|
|
@@ -10742,7 +10724,7 @@ class CameraManager extends DeviceManager {
|
|
|
10742
10724
|
if (width !== this.targetResolution.width ||
|
|
10743
10725
|
height !== this.targetResolution.height) {
|
|
10744
10726
|
await this.applySettingsToStream();
|
|
10745
|
-
this.logger(
|
|
10727
|
+
this.logger.debug(`${width}x${height} target resolution applied to media stream`);
|
|
10746
10728
|
}
|
|
10747
10729
|
}
|
|
10748
10730
|
}
|
|
@@ -11006,8 +10988,8 @@ class RNSpeechDetector {
|
|
|
11006
10988
|
};
|
|
11007
10989
|
}
|
|
11008
10990
|
catch (error) {
|
|
11009
|
-
const logger = getLogger(
|
|
11010
|
-
logger('error
|
|
10991
|
+
const logger = videoLoggerSystem.getLogger('RNSpeechDetector');
|
|
10992
|
+
logger.error('error handling permissions: ', error);
|
|
11011
10993
|
return () => { };
|
|
11012
10994
|
}
|
|
11013
10995
|
}
|
|
@@ -11091,8 +11073,8 @@ class RNSpeechDetector {
|
|
|
11091
11073
|
}
|
|
11092
11074
|
}
|
|
11093
11075
|
catch (error) {
|
|
11094
|
-
const logger = getLogger(
|
|
11095
|
-
logger('error
|
|
11076
|
+
const logger = videoLoggerSystem.getLogger('RNSpeechDetector');
|
|
11077
|
+
logger.error('error checking audio level from stats', error);
|
|
11096
11078
|
}
|
|
11097
11079
|
};
|
|
11098
11080
|
// Call checkAudioLevel periodically (every 100ms)
|
|
@@ -11152,7 +11134,7 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
11152
11134
|
}
|
|
11153
11135
|
}
|
|
11154
11136
|
catch (err) {
|
|
11155
|
-
this.logger('
|
|
11137
|
+
this.logger.warn('Could not enable speaking while muted', err);
|
|
11156
11138
|
}
|
|
11157
11139
|
}));
|
|
11158
11140
|
this.subscriptions.push(createSubscription(this.call.state.callingState$, (callingState) => {
|
|
@@ -11175,7 +11157,7 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
11175
11157
|
}
|
|
11176
11158
|
})
|
|
11177
11159
|
.catch((err) => {
|
|
11178
|
-
this.logger(
|
|
11160
|
+
this.logger.warn(`Failed to enable noise cancellation`, err);
|
|
11179
11161
|
return this.call.notifyNoiseCancellationStopped();
|
|
11180
11162
|
});
|
|
11181
11163
|
}
|
|
@@ -11183,7 +11165,7 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
11183
11165
|
this.noiseCancellationRegistration
|
|
11184
11166
|
.then(() => this.noiseCancellation?.disable())
|
|
11185
11167
|
.catch((err) => {
|
|
11186
|
-
this.logger(
|
|
11168
|
+
this.logger.warn(`Failed to disable noise cancellation`, err);
|
|
11187
11169
|
});
|
|
11188
11170
|
}
|
|
11189
11171
|
}));
|
|
@@ -11212,12 +11194,12 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
11212
11194
|
this.call.tracer.trace('noiseCancellation.enabled', enabled);
|
|
11213
11195
|
if (enabled) {
|
|
11214
11196
|
this.call.notifyNoiseCancellationStarting().catch((err) => {
|
|
11215
|
-
this.logger(
|
|
11197
|
+
this.logger.warn(`notifyNoiseCancellationStart failed`, err);
|
|
11216
11198
|
});
|
|
11217
11199
|
}
|
|
11218
11200
|
else {
|
|
11219
11201
|
this.call.notifyNoiseCancellationStopped().catch((err) => {
|
|
11220
|
-
this.logger(
|
|
11202
|
+
this.logger.warn(`notifyNoiseCancellationStop failed`, err);
|
|
11221
11203
|
});
|
|
11222
11204
|
}
|
|
11223
11205
|
});
|
|
@@ -11246,9 +11228,9 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
11246
11228
|
}
|
|
11247
11229
|
}
|
|
11248
11230
|
catch (e) {
|
|
11249
|
-
this.logger('
|
|
11231
|
+
this.logger.warn('Failed to enable noise cancellation', e);
|
|
11250
11232
|
await this.disableNoiseCancellation().catch((err) => {
|
|
11251
|
-
this.logger('
|
|
11233
|
+
this.logger.warn('Failed to disable noise cancellation', err);
|
|
11252
11234
|
});
|
|
11253
11235
|
throw e;
|
|
11254
11236
|
}
|
|
@@ -11261,7 +11243,7 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
11261
11243
|
.then(() => this.noiseCancellation?.disable())
|
|
11262
11244
|
.then(() => this.noiseCancellationChangeUnsubscribe?.())
|
|
11263
11245
|
.catch((err) => {
|
|
11264
|
-
this.logger('
|
|
11246
|
+
this.logger.warn('Failed to unregister noise cancellation', err);
|
|
11265
11247
|
});
|
|
11266
11248
|
this.call.tracer.trace('noiseCancellation.disabled', true);
|
|
11267
11249
|
await this.call.notifyNoiseCancellationStopped();
|
|
@@ -11769,9 +11751,9 @@ class Call {
|
|
|
11769
11751
|
return;
|
|
11770
11752
|
const currentUserId = this.currentUserId;
|
|
11771
11753
|
if (currentUserId && blockedUserIds.includes(currentUserId)) {
|
|
11772
|
-
this.logger('
|
|
11754
|
+
this.logger.info('Leaving call because of being blocked');
|
|
11773
11755
|
await this.leave({ message: 'user blocked' }).catch((err) => {
|
|
11774
|
-
this.logger('
|
|
11756
|
+
this.logger.error('Error leaving call after being blocked', err);
|
|
11775
11757
|
});
|
|
11776
11758
|
}
|
|
11777
11759
|
}));
|
|
@@ -11807,7 +11789,7 @@ class Call {
|
|
|
11807
11789
|
if ((isAcceptedElsewhere || isRejectedByMe) &&
|
|
11808
11790
|
!hasPending(this.joinLeaveConcurrencyTag)) {
|
|
11809
11791
|
this.leave().catch(() => {
|
|
11810
|
-
this.logger('
|
|
11792
|
+
this.logger.error('Could not leave a call that was accepted or rejected elsewhere');
|
|
11811
11793
|
});
|
|
11812
11794
|
}
|
|
11813
11795
|
}));
|
|
@@ -11887,7 +11869,7 @@ class Call {
|
|
|
11887
11869
|
}
|
|
11888
11870
|
}
|
|
11889
11871
|
catch (err) {
|
|
11890
|
-
this.logger(
|
|
11872
|
+
this.logger.error(`Can't disable mic/camera/screenshare after revoked permissions`, err);
|
|
11891
11873
|
}
|
|
11892
11874
|
}
|
|
11893
11875
|
};
|
|
@@ -12148,13 +12130,13 @@ class Call {
|
|
|
12148
12130
|
maxJoinRetries = Math.max(maxJoinRetries, 1);
|
|
12149
12131
|
for (let attempt = 0; attempt < maxJoinRetries; attempt++) {
|
|
12150
12132
|
try {
|
|
12151
|
-
this.logger(
|
|
12133
|
+
this.logger.trace(`Joining call (${attempt})`, this.cid);
|
|
12152
12134
|
await this.doJoin(data);
|
|
12153
12135
|
delete joinData.migrating_from;
|
|
12154
12136
|
break;
|
|
12155
12137
|
}
|
|
12156
12138
|
catch (err) {
|
|
12157
|
-
this.logger(
|
|
12139
|
+
this.logger.warn(`Failed to join call (${attempt})`, this.cid);
|
|
12158
12140
|
if (err instanceof ErrorFromResponse && err.unrecoverable) {
|
|
12159
12141
|
// if the error is unrecoverable, we should not retry as that signals
|
|
12160
12142
|
// that connectivity is good, but the coordinator doesn't allow the user
|
|
@@ -12184,7 +12166,7 @@ class Call {
|
|
|
12184
12166
|
const connectStartTime = Date.now();
|
|
12185
12167
|
const callingState = this.state.callingState;
|
|
12186
12168
|
this.joinCallData = data;
|
|
12187
|
-
this.logger('
|
|
12169
|
+
this.logger.debug('Starting join flow');
|
|
12188
12170
|
this.state.setCallingState(CallingState.JOINING);
|
|
12189
12171
|
const performingMigration = this.reconnectStrategy === WebsocketReconnectStrategy.MIGRATE;
|
|
12190
12172
|
const performingRejoin = this.reconnectStrategy === WebsocketReconnectStrategy.REJOIN;
|
|
@@ -12269,7 +12251,7 @@ class Call {
|
|
|
12269
12251
|
}
|
|
12270
12252
|
}
|
|
12271
12253
|
catch (error) {
|
|
12272
|
-
this.logger('
|
|
12254
|
+
this.logger.warn('Join SFU request failed', error);
|
|
12273
12255
|
sfuClient.close(StreamSfuClient.JOIN_FAILED, 'Join request failed, connection considered unhealthy');
|
|
12274
12256
|
// restore the previous call state if the join-flow fails
|
|
12275
12257
|
this.state.setCallingState(callingState);
|
|
@@ -12326,7 +12308,7 @@ class Call {
|
|
|
12326
12308
|
// reset the reconnect strategy to unspecified after a successful reconnection
|
|
12327
12309
|
this.reconnectStrategy = WebsocketReconnectStrategy.UNSPECIFIED;
|
|
12328
12310
|
this.reconnectReason = '';
|
|
12329
|
-
this.logger(
|
|
12311
|
+
this.logger.info(`Joined call ${this.cid}`);
|
|
12330
12312
|
};
|
|
12331
12313
|
/**
|
|
12332
12314
|
* Prepares Reconnect Details object.
|
|
@@ -12439,7 +12421,7 @@ class Call {
|
|
|
12439
12421
|
onReconnectionNeeded: (kind, reason) => {
|
|
12440
12422
|
this.reconnect(kind, reason).catch((err) => {
|
|
12441
12423
|
const message = `[Reconnect] Error reconnecting after a subscriber error: ${reason}`;
|
|
12442
|
-
this.logger(
|
|
12424
|
+
this.logger.warn(message, err);
|
|
12443
12425
|
});
|
|
12444
12426
|
},
|
|
12445
12427
|
});
|
|
@@ -12461,7 +12443,7 @@ class Call {
|
|
|
12461
12443
|
onReconnectionNeeded: (kind, reason) => {
|
|
12462
12444
|
this.reconnect(kind, reason).catch((err) => {
|
|
12463
12445
|
const message = `[Reconnect] Error reconnecting after a publisher error: ${reason}`;
|
|
12464
|
-
this.logger(
|
|
12446
|
+
this.logger.warn(message, err);
|
|
12465
12447
|
});
|
|
12466
12448
|
},
|
|
12467
12449
|
});
|
|
@@ -12530,7 +12512,7 @@ class Call {
|
|
|
12530
12512
|
* @param reason the reason for the closure.
|
|
12531
12513
|
*/
|
|
12532
12514
|
this.handleSfuSignalClose = (sfuClient, reason) => {
|
|
12533
|
-
this.logger('
|
|
12515
|
+
this.logger.debug('[Reconnect] SFU signal connection closed');
|
|
12534
12516
|
const { callingState } = this.state;
|
|
12535
12517
|
if (
|
|
12536
12518
|
// SFU WS closed before we finished current join,
|
|
@@ -12551,7 +12533,7 @@ class Call {
|
|
|
12551
12533
|
? WebsocketReconnectStrategy.FAST
|
|
12552
12534
|
: WebsocketReconnectStrategy.REJOIN;
|
|
12553
12535
|
this.reconnect(strategy, reason).catch((err) => {
|
|
12554
|
-
this.logger('
|
|
12536
|
+
this.logger.warn('[Reconnect] Error reconnecting', err);
|
|
12555
12537
|
});
|
|
12556
12538
|
};
|
|
12557
12539
|
/**
|
|
@@ -12587,7 +12569,7 @@ class Call {
|
|
|
12587
12569
|
const shouldGiveUpReconnecting = this.disconnectionTimeoutSeconds > 0 &&
|
|
12588
12570
|
reconnectingTime / 1000 > this.disconnectionTimeoutSeconds;
|
|
12589
12571
|
if (shouldGiveUpReconnecting) {
|
|
12590
|
-
this.logger('
|
|
12572
|
+
this.logger.warn('[Reconnect] Stopping reconnection attempts after reaching disconnection timeout');
|
|
12591
12573
|
await markAsReconnectingFailed();
|
|
12592
12574
|
return;
|
|
12593
12575
|
}
|
|
@@ -12599,11 +12581,11 @@ class Call {
|
|
|
12599
12581
|
try {
|
|
12600
12582
|
// wait until the network is available
|
|
12601
12583
|
await this.networkAvailableTask?.promise;
|
|
12602
|
-
this.logger(
|
|
12584
|
+
this.logger.info(`[Reconnect] Reconnecting with strategy ${WebsocketReconnectStrategy[this.reconnectStrategy]}`);
|
|
12603
12585
|
switch (this.reconnectStrategy) {
|
|
12604
12586
|
case WebsocketReconnectStrategy.UNSPECIFIED:
|
|
12605
12587
|
case WebsocketReconnectStrategy.DISCONNECT:
|
|
12606
|
-
this.logger(
|
|
12588
|
+
this.logger.debug(`[Reconnect] No-op strategy ${currentStrategy}`);
|
|
12607
12589
|
break;
|
|
12608
12590
|
case WebsocketReconnectStrategy.FAST:
|
|
12609
12591
|
await this.reconnectFast();
|
|
@@ -12622,13 +12604,13 @@ class Call {
|
|
|
12622
12604
|
}
|
|
12623
12605
|
catch (error) {
|
|
12624
12606
|
if (this.state.callingState === CallingState.OFFLINE) {
|
|
12625
|
-
this.logger(
|
|
12607
|
+
this.logger.debug(`[Reconnect] Can't reconnect while offline, stopping reconnection attempts`);
|
|
12626
12608
|
break;
|
|
12627
12609
|
// we don't need to handle the error if the call is offline
|
|
12628
12610
|
// network change event will trigger the reconnection
|
|
12629
12611
|
}
|
|
12630
12612
|
if (error instanceof ErrorFromResponse && error.unrecoverable) {
|
|
12631
|
-
this.logger(
|
|
12613
|
+
this.logger.warn(`[Reconnect] Can't reconnect due to coordinator unrecoverable error`, error);
|
|
12632
12614
|
await markAsReconnectingFailed();
|
|
12633
12615
|
return;
|
|
12634
12616
|
}
|
|
@@ -12649,12 +12631,12 @@ class Call {
|
|
|
12649
12631
|
? WebsocketReconnectStrategy.REJOIN
|
|
12650
12632
|
: WebsocketReconnectStrategy.FAST;
|
|
12651
12633
|
this.reconnectStrategy = nextStrategy;
|
|
12652
|
-
this.logger(
|
|
12634
|
+
this.logger.info(`[Reconnect] ${currentStrategy} (${this.reconnectAttempts}) failed. Attempting with ${WebsocketReconnectStrategy[nextStrategy]}`, error);
|
|
12653
12635
|
}
|
|
12654
12636
|
} while (this.state.callingState !== CallingState.JOINED &&
|
|
12655
12637
|
this.state.callingState !== CallingState.RECONNECTING_FAILED &&
|
|
12656
12638
|
this.state.callingState !== CallingState.LEFT);
|
|
12657
|
-
this.logger('
|
|
12639
|
+
this.logger.info('[Reconnect] Reconnection flow finished');
|
|
12658
12640
|
});
|
|
12659
12641
|
};
|
|
12660
12642
|
/**
|
|
@@ -12736,7 +12718,7 @@ class Call {
|
|
|
12736
12718
|
this.registerReconnectHandlers = () => {
|
|
12737
12719
|
// handles the legacy "goAway" event
|
|
12738
12720
|
const unregisterGoAway = this.on('goAway', () => {
|
|
12739
|
-
this.reconnect(WebsocketReconnectStrategy.MIGRATE, 'goAway').catch((err) => this.logger('
|
|
12721
|
+
this.reconnect(WebsocketReconnectStrategy.MIGRATE, 'goAway').catch((err) => this.logger.warn('[Reconnect] Error reconnecting', err));
|
|
12740
12722
|
});
|
|
12741
12723
|
// handles the "error" event, through which the SFU can request a reconnect
|
|
12742
12724
|
const unregisterOnError = this.on('error', (e) => {
|
|
@@ -12745,19 +12727,19 @@ class Call {
|
|
|
12745
12727
|
return;
|
|
12746
12728
|
if (strategy === WebsocketReconnectStrategy.DISCONNECT) {
|
|
12747
12729
|
this.leave({ message: 'SFU instructed to disconnect' }).catch((err) => {
|
|
12748
|
-
this.logger(
|
|
12730
|
+
this.logger.warn(`Can't leave call after disconnect request`, err);
|
|
12749
12731
|
});
|
|
12750
12732
|
}
|
|
12751
12733
|
else {
|
|
12752
12734
|
this.reconnect(strategy, error?.message || 'SFU Error').catch((err) => {
|
|
12753
|
-
this.logger('
|
|
12735
|
+
this.logger.warn('[Reconnect] Error reconnecting', err);
|
|
12754
12736
|
});
|
|
12755
12737
|
}
|
|
12756
12738
|
});
|
|
12757
12739
|
const unregisterNetworkChanged = this.streamClient.on('network.changed', (e) => {
|
|
12758
12740
|
this.tracer.trace('network.changed', e);
|
|
12759
12741
|
if (!e.online) {
|
|
12760
|
-
this.logger('
|
|
12742
|
+
this.logger.debug('[Reconnect] Going offline');
|
|
12761
12743
|
if (!this.hasJoinedOnce)
|
|
12762
12744
|
return;
|
|
12763
12745
|
this.lastOfflineTimestamp = Date.now();
|
|
@@ -12774,7 +12756,7 @@ class Call {
|
|
|
12774
12756
|
}
|
|
12775
12757
|
}
|
|
12776
12758
|
this.reconnect(strategy, 'Going online').catch((err) => {
|
|
12777
|
-
this.logger('
|
|
12759
|
+
this.logger.warn('[Reconnect] Error reconnecting after going online', err);
|
|
12778
12760
|
});
|
|
12779
12761
|
});
|
|
12780
12762
|
this.networkAvailableTask = networkAvailableTask;
|
|
@@ -12782,7 +12764,7 @@ class Call {
|
|
|
12782
12764
|
this.state.setCallingState(CallingState.OFFLINE);
|
|
12783
12765
|
}
|
|
12784
12766
|
else {
|
|
12785
|
-
this.logger('
|
|
12767
|
+
this.logger.debug('[Reconnect] Going online');
|
|
12786
12768
|
this.sfuClient?.close(StreamSfuClient.DISPOSE_OLD_SOCKET, 'Closing WS to reconnect after going online');
|
|
12787
12769
|
// we went online, release the previous waiters and reset the state
|
|
12788
12770
|
this.networkAvailableTask?.resolve();
|
|
@@ -12944,10 +12926,10 @@ class Call {
|
|
|
12944
12926
|
* @param options the options to use.
|
|
12945
12927
|
*/
|
|
12946
12928
|
this.updatePublishOptions = (options) => {
|
|
12947
|
-
this.logger('
|
|
12929
|
+
this.logger.warn('[call.updatePublishOptions]: You are manually overriding the publish options for this call. ' +
|
|
12948
12930
|
'This is not recommended, and it can cause call stability/compatibility issues. Use with caution.');
|
|
12949
12931
|
if (this.state.callingState === CallingState.JOINED) {
|
|
12950
|
-
this.logger('
|
|
12932
|
+
this.logger.warn('Updating publish options after joining the call does not have an effect');
|
|
12951
12933
|
}
|
|
12952
12934
|
this.clientPublishOptions = { ...this.clientPublishOptions, ...options };
|
|
12953
12935
|
};
|
|
@@ -12958,7 +12940,7 @@ class Call {
|
|
|
12958
12940
|
*/
|
|
12959
12941
|
this.notifyNoiseCancellationStarting = async () => {
|
|
12960
12942
|
return this.sfuClient?.startNoiseCancellation().catch((err) => {
|
|
12961
|
-
this.logger('
|
|
12943
|
+
this.logger.warn('Failed to notify start of noise cancellation', err);
|
|
12962
12944
|
});
|
|
12963
12945
|
};
|
|
12964
12946
|
/**
|
|
@@ -12968,7 +12950,7 @@ class Call {
|
|
|
12968
12950
|
*/
|
|
12969
12951
|
this.notifyNoiseCancellationStopped = async () => {
|
|
12970
12952
|
return this.sfuClient?.stopNoiseCancellation().catch((err) => {
|
|
12971
|
-
this.logger('
|
|
12953
|
+
this.logger.warn('Failed to notify stop of noise cancellation', err);
|
|
12972
12954
|
});
|
|
12973
12955
|
};
|
|
12974
12956
|
/**
|
|
@@ -13402,7 +13384,7 @@ class Call {
|
|
|
13402
13384
|
reason: 'timeout',
|
|
13403
13385
|
message: `ringing timeout - ${this.isCreatedByMe ? 'no one accepted' : `user didn't interact with incoming call screen`}`,
|
|
13404
13386
|
}).catch((err) => {
|
|
13405
|
-
this.logger('
|
|
13387
|
+
this.logger.error('Failed to drop call', err);
|
|
13406
13388
|
});
|
|
13407
13389
|
}, timeoutInMs);
|
|
13408
13390
|
};
|
|
@@ -13514,10 +13496,10 @@ class Call {
|
|
|
13514
13496
|
*/
|
|
13515
13497
|
this.applyDeviceConfig = async (settings, publish) => {
|
|
13516
13498
|
await this.camera.apply(settings.video, publish).catch((err) => {
|
|
13517
|
-
this.logger('
|
|
13499
|
+
this.logger.warn('Camera init failed', err);
|
|
13518
13500
|
});
|
|
13519
13501
|
await this.microphone.apply(settings.audio, publish).catch((err) => {
|
|
13520
|
-
this.logger('
|
|
13502
|
+
this.logger.warn('Mic init failed', err);
|
|
13521
13503
|
});
|
|
13522
13504
|
};
|
|
13523
13505
|
/**
|
|
@@ -13669,7 +13651,7 @@ class Call {
|
|
|
13669
13651
|
this.streamClient = streamClient;
|
|
13670
13652
|
this.clientStore = clientStore;
|
|
13671
13653
|
this.streamClientBasePath = `/call/${this.type}/${this.id}`;
|
|
13672
|
-
this.logger = getLogger(
|
|
13654
|
+
this.logger = videoLoggerSystem.getLogger('Call');
|
|
13673
13655
|
const callTypeConfig = CallTypes.get(type);
|
|
13674
13656
|
const participantSorter = sortParticipantsBy || callTypeConfig.options.sortParticipantsBy;
|
|
13675
13657
|
if (participantSorter) {
|
|
@@ -13756,7 +13738,7 @@ const APIErrorCodes = {
|
|
|
13756
13738
|
class StableWSConnection {
|
|
13757
13739
|
constructor(client) {
|
|
13758
13740
|
this._log = (msg, extra = {}, level = 'info') => {
|
|
13759
|
-
this.client.logger(
|
|
13741
|
+
this.client.logger[level](`connection:${msg}`, extra);
|
|
13760
13742
|
};
|
|
13761
13743
|
this.setClient = (client) => {
|
|
13762
13744
|
this.client = client;
|
|
@@ -13802,12 +13784,12 @@ class StableWSConnection {
|
|
|
13802
13784
|
return;
|
|
13803
13785
|
const user = this.client.user;
|
|
13804
13786
|
if (!user) {
|
|
13805
|
-
this.client.logger(
|
|
13787
|
+
this.client.logger.error(`User not set, can't connect to WS`);
|
|
13806
13788
|
return;
|
|
13807
13789
|
}
|
|
13808
13790
|
const token = this.client._getToken();
|
|
13809
13791
|
if (!token) {
|
|
13810
|
-
this.client.logger(
|
|
13792
|
+
this.client.logger.error(`Token not set, can't connect authenticate`);
|
|
13811
13793
|
return;
|
|
13812
13794
|
}
|
|
13813
13795
|
const authMessage = JSON.stringify({
|
|
@@ -14444,7 +14426,7 @@ class TokenManager {
|
|
|
14444
14426
|
}
|
|
14445
14427
|
|
|
14446
14428
|
const getLocationHint = async (hintUrl = `https://hint.stream-io-video.com/`, timeout = 2000, maxAttempts = 3) => {
|
|
14447
|
-
const logger = getLogger(
|
|
14429
|
+
const logger = videoLoggerSystem.getLogger('location-hint');
|
|
14448
14430
|
let attempt = 0;
|
|
14449
14431
|
let locationHint = 'ERR';
|
|
14450
14432
|
do {
|
|
@@ -14456,11 +14438,11 @@ const getLocationHint = async (hintUrl = `https://hint.stream-io-video.com/`, ti
|
|
|
14456
14438
|
signal: abortController.signal,
|
|
14457
14439
|
});
|
|
14458
14440
|
const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
|
|
14459
|
-
logger(
|
|
14441
|
+
logger.debug(`Location header: ${awsPop}`);
|
|
14460
14442
|
locationHint = awsPop.substring(0, 3); // AMS1-P2 -> AMS
|
|
14461
14443
|
}
|
|
14462
14444
|
catch (e) {
|
|
14463
|
-
logger(
|
|
14445
|
+
logger.warn(`Failed to get location hint from ${hintUrl}`, e);
|
|
14464
14446
|
locationHint = 'ERR';
|
|
14465
14447
|
}
|
|
14466
14448
|
finally {
|
|
@@ -14521,14 +14503,14 @@ class StreamClient {
|
|
|
14521
14503
|
* If the user id remains the same we don't throw error
|
|
14522
14504
|
*/
|
|
14523
14505
|
if (this.userID === user.id && this.connectUserTask) {
|
|
14524
|
-
this.logger('
|
|
14506
|
+
this.logger.warn('Consecutive calls to connectUser is detected, ideally you should only call this function once in your app.');
|
|
14525
14507
|
return this.connectUserTask;
|
|
14526
14508
|
}
|
|
14527
14509
|
if (this.userID) {
|
|
14528
14510
|
throw new Error('Use client.disconnect() before trying to connect as a different user. connectUser was called twice.');
|
|
14529
14511
|
}
|
|
14530
14512
|
if ((this.secret || this.node) && !this.options.allowServerSideConnect) {
|
|
14531
|
-
this.logger('
|
|
14513
|
+
this.logger.warn('Please do not use connectUser server side. Use our @stream-io/node-sdk instead: https://getstream.io/video/docs/api/');
|
|
14532
14514
|
}
|
|
14533
14515
|
// we generate the client id client side
|
|
14534
14516
|
this.userID = user.id;
|
|
@@ -14586,11 +14568,11 @@ class StreamClient {
|
|
|
14586
14568
|
}
|
|
14587
14569
|
const wsPromise = this.wsPromiseSafe?.();
|
|
14588
14570
|
if (this.wsConnection?.isConnecting && wsPromise) {
|
|
14589
|
-
this.logger('
|
|
14571
|
+
this.logger.info('client:openConnection() - connection already in progress');
|
|
14590
14572
|
return await wsPromise;
|
|
14591
14573
|
}
|
|
14592
14574
|
if (this.wsConnection?.isHealthy && this._hasConnectionID()) {
|
|
14593
|
-
this.logger('
|
|
14575
|
+
this.logger.info('client:openConnection() - openConnection called twice, healthy connection already exists');
|
|
14594
14576
|
return;
|
|
14595
14577
|
}
|
|
14596
14578
|
this._setupConnectionIdPromise();
|
|
@@ -14606,7 +14588,7 @@ class StreamClient {
|
|
|
14606
14588
|
* https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
|
|
14607
14589
|
*/
|
|
14608
14590
|
this.disconnectUser = async (timeout) => {
|
|
14609
|
-
this.logger('
|
|
14591
|
+
this.logger.info('client:disconnect() - Disconnecting the client');
|
|
14610
14592
|
// remove the user specific fields
|
|
14611
14593
|
delete this.user;
|
|
14612
14594
|
delete this._user;
|
|
@@ -14653,7 +14635,7 @@ class StreamClient {
|
|
|
14653
14635
|
if (!this.listeners[eventName]) {
|
|
14654
14636
|
this.listeners[eventName] = [];
|
|
14655
14637
|
}
|
|
14656
|
-
this.logger(
|
|
14638
|
+
this.logger.debug(`Adding listener for ${eventName} event`);
|
|
14657
14639
|
this.listeners[eventName]?.push(callback);
|
|
14658
14640
|
return () => {
|
|
14659
14641
|
this.off(eventName, callback);
|
|
@@ -14666,7 +14648,7 @@ class StreamClient {
|
|
|
14666
14648
|
if (!this.listeners[eventName]) {
|
|
14667
14649
|
this.listeners[eventName] = [];
|
|
14668
14650
|
}
|
|
14669
|
-
this.logger(
|
|
14651
|
+
this.logger.debug(`Removing listener for ${eventName} event`);
|
|
14670
14652
|
this.listeners[eventName] = this.listeners[eventName]?.filter((value) => value !== callback);
|
|
14671
14653
|
};
|
|
14672
14654
|
/**
|
|
@@ -14680,17 +14662,17 @@ class StreamClient {
|
|
|
14680
14662
|
}));
|
|
14681
14663
|
};
|
|
14682
14664
|
this._logApiRequest = (type, url, data, config) => {
|
|
14683
|
-
if (getLogLevel() !== 'trace')
|
|
14665
|
+
if (this.logger.getLogLevel() !== 'trace')
|
|
14684
14666
|
return;
|
|
14685
|
-
this.logger(
|
|
14667
|
+
this.logger.trace(`client: ${type} - Request - ${url}`, {
|
|
14686
14668
|
payload: data,
|
|
14687
14669
|
config,
|
|
14688
14670
|
});
|
|
14689
14671
|
};
|
|
14690
14672
|
this._logApiResponse = (type, url, response) => {
|
|
14691
|
-
if (getLogLevel() !== 'trace')
|
|
14673
|
+
if (this.logger.getLogLevel() !== 'trace')
|
|
14692
14674
|
return;
|
|
14693
|
-
this.logger(
|
|
14675
|
+
this.logger.trace(`client:${type} - Response - url: ${url} > status ${response.status}`, {
|
|
14694
14676
|
response,
|
|
14695
14677
|
});
|
|
14696
14678
|
};
|
|
@@ -14747,13 +14729,13 @@ class StreamClient {
|
|
|
14747
14729
|
this.consecutiveFailures += 1;
|
|
14748
14730
|
const { response } = e;
|
|
14749
14731
|
if (!response || !isErrorResponse(response)) {
|
|
14750
|
-
this.logger(
|
|
14732
|
+
this.logger.error(`client:${type} url: ${url}`, e);
|
|
14751
14733
|
throw e;
|
|
14752
14734
|
}
|
|
14753
14735
|
const { data: responseData, status } = response;
|
|
14754
14736
|
const isTokenExpired = responseData.code === KnownCodes.TOKEN_EXPIRED;
|
|
14755
14737
|
if (isTokenExpired && !this.tokenManager.isStatic()) {
|
|
14756
|
-
this.logger(
|
|
14738
|
+
this.logger.warn(`client:${type}: url: ${url}`, response);
|
|
14757
14739
|
if (this.consecutiveFailures > 1) {
|
|
14758
14740
|
await sleep(retryInterval(this.consecutiveFailures));
|
|
14759
14741
|
}
|
|
@@ -14762,7 +14744,7 @@ class StreamClient {
|
|
|
14762
14744
|
return await this.doAxiosRequest(type, url, data, options);
|
|
14763
14745
|
}
|
|
14764
14746
|
else {
|
|
14765
|
-
this.logger(
|
|
14747
|
+
this.logger.error(`client:${type} url: ${url}`, response);
|
|
14766
14748
|
throw new ErrorFromResponse({
|
|
14767
14749
|
message: `Stream error code ${responseData.code}: ${responseData.message}`,
|
|
14768
14750
|
code: responseData.code ?? null,
|
|
@@ -14793,7 +14775,7 @@ class StreamClient {
|
|
|
14793
14775
|
});
|
|
14794
14776
|
};
|
|
14795
14777
|
this.dispatchEvent = (event) => {
|
|
14796
|
-
this.logger(
|
|
14778
|
+
this.logger.debug(`Dispatching event: ${event.type}`, event);
|
|
14797
14779
|
if (!this.listeners)
|
|
14798
14780
|
return;
|
|
14799
14781
|
// call generic listeners
|
|
@@ -14818,13 +14800,13 @@ class StreamClient {
|
|
|
14818
14800
|
throw Error('clientID is not set');
|
|
14819
14801
|
// The StableWSConnection handles all the reconnection logic.
|
|
14820
14802
|
this.wsConnection = new StableWSConnection(this);
|
|
14821
|
-
this.logger('
|
|
14803
|
+
this.logger.info('StreamClient.connect: this.wsConnection.connect()');
|
|
14822
14804
|
return await this.wsConnection.connect(this.defaultWSTimeout);
|
|
14823
14805
|
};
|
|
14824
14806
|
this.getUserAgent = () => {
|
|
14825
14807
|
if (!this.cachedUserAgent) {
|
|
14826
14808
|
const { clientAppIdentifier = {} } = this.options;
|
|
14827
|
-
const { sdkName = 'js', sdkVersion = "1.
|
|
14809
|
+
const { sdkName = 'js', sdkVersion = "1.36.0", ...extras } = clientAppIdentifier;
|
|
14828
14810
|
this.cachedUserAgent = [
|
|
14829
14811
|
`stream-video-${sdkName}-v${sdkVersion}`,
|
|
14830
14812
|
...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
|
|
@@ -14875,11 +14857,11 @@ class StreamClient {
|
|
|
14875
14857
|
};
|
|
14876
14858
|
this.updateNetworkConnectionStatus = (event) => {
|
|
14877
14859
|
if (event.type === 'offline') {
|
|
14878
|
-
this.logger('
|
|
14860
|
+
this.logger.debug('device went offline');
|
|
14879
14861
|
this.dispatchEvent({ type: 'network.changed', online: false });
|
|
14880
14862
|
}
|
|
14881
14863
|
else if (event.type === 'online') {
|
|
14882
|
-
this.logger('
|
|
14864
|
+
this.logger.debug('device went online');
|
|
14883
14865
|
this.dispatchEvent({ type: 'network.changed', online: true });
|
|
14884
14866
|
}
|
|
14885
14867
|
};
|
|
@@ -14927,9 +14909,7 @@ class StreamClient {
|
|
|
14927
14909
|
this.tokenManager = new TokenManager(this.secret);
|
|
14928
14910
|
this.consecutiveFailures = 0;
|
|
14929
14911
|
this.defaultWSTimeout = this.options.defaultWsTimeout ?? 15000;
|
|
14930
|
-
this.logger =
|
|
14931
|
-
? inputOptions.logger
|
|
14932
|
-
: () => null;
|
|
14912
|
+
this.logger = videoLoggerSystem.getLogger('coordinator');
|
|
14933
14913
|
}
|
|
14934
14914
|
get connectionIdPromise() {
|
|
14935
14915
|
return this.connectionIdPromiseSafe?.();
|
|
@@ -14974,12 +14954,10 @@ const getClientAppIdentifier = (options) => {
|
|
|
14974
14954
|
*/
|
|
14975
14955
|
const createCoordinatorClient = (apiKey, options) => {
|
|
14976
14956
|
const clientAppIdentifier = getClientAppIdentifier(options);
|
|
14977
|
-
const coordinatorLogger = getLogger(['coordinator']);
|
|
14978
14957
|
return new StreamClient(apiKey, {
|
|
14979
14958
|
persistUserOnConnectionFailure: true,
|
|
14980
14959
|
...options,
|
|
14981
14960
|
clientAppIdentifier,
|
|
14982
|
-
logger: coordinatorLogger,
|
|
14983
14961
|
});
|
|
14984
14962
|
};
|
|
14985
14963
|
/**
|
|
@@ -15017,7 +14995,7 @@ class StreamVideoClient {
|
|
|
15017
14995
|
this.registerClientInstance = (apiKey, user) => {
|
|
15018
14996
|
const instanceKey = getInstanceKey(apiKey, user);
|
|
15019
14997
|
if (StreamVideoClient._instances.has(instanceKey)) {
|
|
15020
|
-
this.logger(
|
|
14998
|
+
this.logger.warn(`A StreamVideoClient already exists for ${user.id}; Prefer using getOrCreateInstance method`);
|
|
15021
14999
|
}
|
|
15022
15000
|
StreamVideoClient._instances.set(instanceKey, this);
|
|
15023
15001
|
};
|
|
@@ -15032,13 +15010,13 @@ class StreamVideoClient {
|
|
|
15032
15010
|
.map((call) => call.cid);
|
|
15033
15011
|
if (callsToReWatch.length <= 0)
|
|
15034
15012
|
return;
|
|
15035
|
-
this.logger(
|
|
15013
|
+
this.logger.info(`Rewatching calls ${callsToReWatch.join(', ')}`);
|
|
15036
15014
|
this.queryCalls({
|
|
15037
15015
|
watch: true,
|
|
15038
15016
|
filter_conditions: { cid: { $in: callsToReWatch } },
|
|
15039
15017
|
sort: [{ field: 'cid', direction: 1 }],
|
|
15040
15018
|
}).catch((err) => {
|
|
15041
|
-
this.logger('
|
|
15019
|
+
this.logger.error('Failed to re-watch calls', err);
|
|
15042
15020
|
});
|
|
15043
15021
|
}));
|
|
15044
15022
|
this.effectsRegistered = true;
|
|
@@ -15049,7 +15027,7 @@ class StreamVideoClient {
|
|
|
15049
15027
|
*/
|
|
15050
15028
|
this.initCallFromEvent = async (e) => {
|
|
15051
15029
|
if (this.state.connectedUser?.id === e.call.created_by.id) {
|
|
15052
|
-
this.logger(
|
|
15030
|
+
this.logger.debug(`Ignoring ${e.type} event sent by the current user`);
|
|
15053
15031
|
return;
|
|
15054
15032
|
}
|
|
15055
15033
|
try {
|
|
@@ -15060,7 +15038,7 @@ class StreamVideoClient {
|
|
|
15060
15038
|
if (call) {
|
|
15061
15039
|
if (ringing) {
|
|
15062
15040
|
if (this.shouldRejectCall(call.cid)) {
|
|
15063
|
-
this.logger(
|
|
15041
|
+
this.logger.info(`Leaving call with busy reject reason ${call.cid} because user is busy`);
|
|
15064
15042
|
// remove the instance from the state store
|
|
15065
15043
|
await call.leave();
|
|
15066
15044
|
// explicitly reject the call with busy reason as calling state was not ringing before and leave would not call it therefore
|
|
@@ -15085,7 +15063,7 @@ class StreamVideoClient {
|
|
|
15085
15063
|
});
|
|
15086
15064
|
if (ringing) {
|
|
15087
15065
|
if (this.shouldRejectCall(call.cid)) {
|
|
15088
|
-
this.logger(
|
|
15066
|
+
this.logger.info(`Rejecting call ${call.cid} because user is busy`);
|
|
15089
15067
|
// call is not in the state store yet, so just reject api is enough
|
|
15090
15068
|
await call.reject('busy');
|
|
15091
15069
|
}
|
|
@@ -15097,12 +15075,12 @@ class StreamVideoClient {
|
|
|
15097
15075
|
else {
|
|
15098
15076
|
call.state.updateFromCallResponse(e.call);
|
|
15099
15077
|
this.writeableStateStore.registerCall(call);
|
|
15100
|
-
this.logger(
|
|
15078
|
+
this.logger.info(`New call created and registered: ${call.cid}`);
|
|
15101
15079
|
}
|
|
15102
15080
|
});
|
|
15103
15081
|
}
|
|
15104
15082
|
catch (err) {
|
|
15105
|
-
this.logger(
|
|
15083
|
+
this.logger.error(`Failed to init call from event ${e.type}`, err);
|
|
15106
15084
|
}
|
|
15107
15085
|
};
|
|
15108
15086
|
/**
|
|
@@ -15126,13 +15104,13 @@ class StreamVideoClient {
|
|
|
15126
15104
|
const errorQueue = [];
|
|
15127
15105
|
for (let attempt = 0; attempt < maxConnectUserRetries; attempt++) {
|
|
15128
15106
|
try {
|
|
15129
|
-
this.logger(
|
|
15107
|
+
this.logger.trace(`Connecting user (${attempt})`, user);
|
|
15130
15108
|
return user.type === 'guest'
|
|
15131
15109
|
? await client.connectGuestUser(user)
|
|
15132
15110
|
: await client.connectUser(user, tokenOrProvider);
|
|
15133
15111
|
}
|
|
15134
15112
|
catch (err) {
|
|
15135
|
-
this.logger(
|
|
15113
|
+
this.logger.warn(`Failed to connect a user (${attempt})`, err);
|
|
15136
15114
|
errorQueue.push(err);
|
|
15137
15115
|
if (attempt === maxConnectUserRetries - 1) {
|
|
15138
15116
|
onConnectUserError?.(err, errorQueue);
|
|
@@ -15377,8 +15355,11 @@ class StreamVideoClient {
|
|
|
15377
15355
|
if (clientOptions?.enableTimerWorker)
|
|
15378
15356
|
enableTimerWorker();
|
|
15379
15357
|
const rootLogger = clientOptions?.logger || logToConsole;
|
|
15380
|
-
|
|
15381
|
-
|
|
15358
|
+
videoLoggerSystem.configureLoggers({
|
|
15359
|
+
default: { sink: rootLogger, level: clientOptions?.logLevel || 'warn' },
|
|
15360
|
+
...clientOptions?.logOptions,
|
|
15361
|
+
});
|
|
15362
|
+
this.logger = videoLoggerSystem.getLogger('client');
|
|
15382
15363
|
this.rejectCallWhenBusy = clientOptions?.rejectCallWhenBusy ?? false;
|
|
15383
15364
|
this.streamClient = createCoordinatorClient(apiKey, clientOptions);
|
|
15384
15365
|
this.writeableStateStore = new StreamVideoWriteableStateStore();
|
|
@@ -15391,7 +15372,7 @@ class StreamVideoClient {
|
|
|
15391
15372
|
this.registerClientInstance(apiKey, user);
|
|
15392
15373
|
const tokenOrProvider = createTokenOrProvider(apiKeyOrArgs);
|
|
15393
15374
|
this.connectUser(user, tokenOrProvider).catch((err) => {
|
|
15394
|
-
this.logger('
|
|
15375
|
+
this.logger.error('Failed to connect', err);
|
|
15395
15376
|
});
|
|
15396
15377
|
}
|
|
15397
15378
|
}
|
|
@@ -15421,5 +15402,5 @@ class StreamVideoClient {
|
|
|
15421
15402
|
}
|
|
15422
15403
|
StreamVideoClient._instances = new Map();
|
|
15423
15404
|
|
|
15424
|
-
export { AudioSettingsRequestDefaultDeviceEnum, AudioSettingsResponseDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, CreateDeviceRequestPushProviderEnum, DebounceType, DeviceManager, DeviceManagerState, DynascaleManager, ErrorFromResponse, FrameRecordingSettingsRequestModeEnum, FrameRecordingSettingsRequestQualityEnum, FrameRecordingSettingsResponseModeEnum, IngressAudioEncodingOptionsRequestChannelsEnum, IngressSourceRequestFpsEnum, IngressVideoLayerRequestCodecEnum, LayoutSettingsRequestNameEnum, MicrophoneManager, MicrophoneManagerState, NoiseCancellationSettingsModeEnum, OwnCapability, RNSpeechDetector, RTMPBroadcastRequestQualityEnum, RTMPSettingsRequestQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, StartClosedCaptionsRequestLanguageEnum, StartTranscriptionRequestLanguageEnum, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsRequestClosedCaptionModeEnum, TranscriptionSettingsRequestLanguageEnum, TranscriptionSettingsRequestModeEnum, TranscriptionSettingsResponseClosedCaptionModeEnum, TranscriptionSettingsResponseLanguageEnum, TranscriptionSettingsResponseModeEnum, VideoSettingsRequestCameraFacingEnum, VideoSettingsResponseCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, deviceIds$, disposeOfMediaStream, dominantSpeaker, getAudioBrowserPermission, getAudioDevices, getAudioOutputDevices, getAudioStream, getClientDetails, getDeviceState,
|
|
15405
|
+
export { AudioSettingsRequestDefaultDeviceEnum, AudioSettingsResponseDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, CreateDeviceRequestPushProviderEnum, DebounceType, DeviceManager, DeviceManagerState, DynascaleManager, ErrorFromResponse, FrameRecordingSettingsRequestModeEnum, FrameRecordingSettingsRequestQualityEnum, FrameRecordingSettingsResponseModeEnum, IngressAudioEncodingOptionsRequestChannelsEnum, IngressSourceRequestFpsEnum, IngressVideoLayerRequestCodecEnum, LayoutSettingsRequestNameEnum, MicrophoneManager, MicrophoneManagerState, NoiseCancellationSettingsModeEnum, OwnCapability, RNSpeechDetector, RTMPBroadcastRequestQualityEnum, RTMPSettingsRequestQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, StartClosedCaptionsRequestLanguageEnum, StartTranscriptionRequestLanguageEnum, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsRequestClosedCaptionModeEnum, TranscriptionSettingsRequestLanguageEnum, TranscriptionSettingsRequestModeEnum, TranscriptionSettingsResponseClosedCaptionModeEnum, TranscriptionSettingsResponseLanguageEnum, TranscriptionSettingsResponseModeEnum, VideoSettingsRequestCameraFacingEnum, VideoSettingsResponseCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, deviceIds$, disposeOfMediaStream, dominantSpeaker, getAudioBrowserPermission, getAudioDevices, getAudioOutputDevices, getAudioStream, getClientDetails, getDeviceState, getScreenShareStream, getSdkInfo, getVideoBrowserPermission, getVideoDevices, getVideoStream, getWebRTCInfo, hasAudio, hasPausedTrack, hasScreenShare, hasScreenShareAudio, hasVideo, isPinned, livestreamOrAudioRoomSortPreset, logToConsole, name, noopComparator, paginatedLayoutSortPreset, pinned, publishingAudio, publishingVideo, reactionType, resolveDeviceId, role, screenSharing, setDeviceInfo, setOSInfo, setPowerState, setSdkInfo, setThermalState, setWebRTCInfo, speakerLayoutSortPreset, speaking, videoLoggerSystem, withParticipantSource };
|
|
15425
15406
|
//# sourceMappingURL=index.es.js.map
|