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