@stream-io/video-client 0.0.27 → 0.0.29
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 +14 -0
- package/dist/index.browser.es.js +2517 -1760
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +2537 -1758
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +2517 -1760
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +7 -8
- package/dist/src/StreamSfuClient.d.ts +23 -10
- package/dist/src/StreamVideoClient.d.ts +1 -4
- package/dist/src/client-details.d.ts +2 -1
- package/dist/src/coordinator/connection/types.d.ts +2 -2
- package/dist/src/coordinator/connection/utils.d.ts +1 -0
- package/dist/src/events/internal.d.ts +4 -0
- package/dist/src/gen/coordinator/index.d.ts +6 -0
- package/dist/src/gen/google/protobuf/struct.d.ts +8 -15
- package/dist/src/gen/google/protobuf/timestamp.d.ts +2 -9
- package/dist/src/gen/video/sfu/event/events.d.ts +121 -1
- package/dist/src/gen/video/sfu/models/models.d.ts +38 -1
- package/dist/src/gen/video/sfu/signal_rpc/signal.client.d.ts +3 -14
- package/dist/src/gen/video/sfu/signal_rpc/signal.d.ts +4 -12
- package/dist/src/logger.d.ts +4 -2
- package/dist/src/rtc/Dispatcher.d.ts +1 -2
- package/dist/src/rtc/{publisher.d.ts → Publisher.d.ts} +49 -15
- package/dist/src/rtc/Subscriber.d.ts +58 -0
- package/dist/src/rtc/__tests__/Subscriber.test.d.ts +1 -0
- package/dist/src/rtc/flows/join.d.ts +8 -1
- package/dist/src/rtc/index.d.ts +2 -2
- package/dist/src/rtc/signal.d.ts +1 -0
- package/dist/src/stats/state-store-stats-reporter.d.ts +3 -4
- package/dist/src/store/CallState.d.ts +10 -0
- package/package.json +3 -1
- package/src/Call.ts +218 -214
- package/src/StreamSfuClient.ts +48 -21
- package/src/StreamVideoClient.ts +7 -24
- package/src/client-details.ts +33 -1
- package/src/coordinator/connection/client.ts +6 -8
- package/src/coordinator/connection/types.ts +2 -3
- package/src/coordinator/connection/utils.ts +1 -0
- package/src/events/call.ts +0 -1
- package/src/events/callEventHandlers.ts +2 -0
- package/src/events/internal.ts +20 -0
- package/src/events/sessions.ts +0 -1
- package/src/gen/coordinator/index.ts +6 -0
- package/src/gen/google/protobuf/struct.ts +541 -333
- package/src/gen/google/protobuf/timestamp.ts +214 -148
- package/src/gen/video/sfu/event/events.ts +353 -3
- package/src/gen/video/sfu/models/models.ts +37 -0
- package/src/gen/video/sfu/signal_rpc/signal.client.ts +160 -94
- package/src/gen/video/sfu/signal_rpc/signal.ts +1214 -731
- package/src/logger.ts +43 -30
- package/src/rtc/Dispatcher.ts +5 -9
- package/src/rtc/{publisher.ts → Publisher.ts} +245 -111
- package/src/rtc/Subscriber.ts +304 -0
- package/src/rtc/__tests__/{publisher.test.ts → Publisher.test.ts} +77 -9
- package/src/rtc/__tests__/Subscriber.test.ts +121 -0
- package/src/rtc/__tests__/mocks/webrtc.mocks.ts +20 -0
- package/src/rtc/flows/join.ts +43 -2
- package/src/rtc/index.ts +2 -2
- package/src/rtc/signal.ts +6 -5
- package/src/rtc/videoLayers.ts +1 -4
- package/src/stats/state-store-stats-reporter.ts +3 -5
- package/src/store/CallState.ts +20 -0
- package/src/types.ts +0 -1
- package/dist/src/rtc/subscriber.d.ts +0 -9
- package/src/rtc/subscriber.ts +0 -107
- /package/dist/src/rtc/__tests__/{publisher.test.d.ts → Publisher.test.d.ts} +0 -0
package/src/StreamSfuClient.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { WebSocket } from 'ws';
|
|
1
2
|
import type {
|
|
2
3
|
FinishedUnaryCall,
|
|
3
4
|
MethodInfo,
|
|
@@ -30,6 +31,7 @@ import {
|
|
|
30
31
|
retryInterval,
|
|
31
32
|
sleep,
|
|
32
33
|
} from './coordinator/connection/utils';
|
|
34
|
+
import { SFUResponse } from './gen/coordinator';
|
|
33
35
|
import { Logger } from './coordinator/connection/types';
|
|
34
36
|
import { getLogger } from './logger';
|
|
35
37
|
|
|
@@ -40,14 +42,9 @@ export type StreamSfuClientConstructor = {
|
|
|
40
42
|
dispatcher: Dispatcher;
|
|
41
43
|
|
|
42
44
|
/**
|
|
43
|
-
* The
|
|
45
|
+
* The SFU server to connect to.
|
|
44
46
|
*/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* The WebSocket endpoint of the SFU to connect to.
|
|
49
|
-
*/
|
|
50
|
-
wsEndpoint: string;
|
|
47
|
+
sfuServer: SFUResponse;
|
|
51
48
|
|
|
52
49
|
/**
|
|
53
50
|
* The JWT token to use for authentication.
|
|
@@ -75,6 +72,21 @@ export class StreamSfuClient {
|
|
|
75
72
|
*/
|
|
76
73
|
readonly sessionId: string;
|
|
77
74
|
|
|
75
|
+
/**
|
|
76
|
+
* The `edgeName` representing the edge the client is connected to.
|
|
77
|
+
*/
|
|
78
|
+
readonly edgeName: string;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The current token used for authenticating against the SFU.
|
|
82
|
+
*/
|
|
83
|
+
readonly token: string;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The SFU server details the current client is connected to.
|
|
87
|
+
*/
|
|
88
|
+
readonly sfuServer: SFUResponse;
|
|
89
|
+
|
|
78
90
|
/**
|
|
79
91
|
* Holds the current WebSocket connection to the SFU.
|
|
80
92
|
*/
|
|
@@ -85,8 +97,13 @@ export class StreamSfuClient {
|
|
|
85
97
|
*/
|
|
86
98
|
signalReady: Promise<WebSocket>;
|
|
87
99
|
|
|
100
|
+
/**
|
|
101
|
+
* A flag indicating whether the client is currently migrating away
|
|
102
|
+
* from this SFU.
|
|
103
|
+
*/
|
|
104
|
+
isMigratingAway = false;
|
|
105
|
+
|
|
88
106
|
private readonly rpc: SignalServerClient;
|
|
89
|
-
private readonly token: string;
|
|
90
107
|
private keepAliveInterval?: NodeJS.Timeout;
|
|
91
108
|
private connectionCheckTimeout?: NodeJS.Timeout;
|
|
92
109
|
private pingIntervalInMs = 25 * 1000;
|
|
@@ -99,19 +116,19 @@ export class StreamSfuClient {
|
|
|
99
116
|
* Constructs a new SFU client.
|
|
100
117
|
*
|
|
101
118
|
* @param dispatcher the event dispatcher to use.
|
|
102
|
-
* @param
|
|
103
|
-
* @param wsEndpoint the WebSocket endpoint of the SFU.
|
|
119
|
+
* @param sfuServer the SFU server to connect to.
|
|
104
120
|
* @param token the JWT token to use for authentication.
|
|
105
121
|
* @param sessionId the `sessionId` of the currently connected participant.
|
|
106
122
|
*/
|
|
107
123
|
constructor({
|
|
108
124
|
dispatcher,
|
|
109
|
-
|
|
110
|
-
wsEndpoint,
|
|
125
|
+
sfuServer,
|
|
111
126
|
token,
|
|
112
127
|
sessionId,
|
|
113
128
|
}: StreamSfuClientConstructor) {
|
|
114
129
|
this.sessionId = sessionId || generateUUIDv4();
|
|
130
|
+
this.sfuServer = sfuServer;
|
|
131
|
+
this.edgeName = sfuServer.edge_name;
|
|
115
132
|
this.token = token;
|
|
116
133
|
this.logger = getLogger(['sfu-client']);
|
|
117
134
|
const logger = this.logger;
|
|
@@ -122,13 +139,15 @@ export class StreamSfuClient {
|
|
|
122
139
|
input: object,
|
|
123
140
|
options: RpcOptions,
|
|
124
141
|
): UnaryCall {
|
|
125
|
-
logger('
|
|
126
|
-
|
|
142
|
+
logger('trace', `Calling SFU RPC method ${method.name}`, {
|
|
143
|
+
input,
|
|
144
|
+
options,
|
|
145
|
+
});
|
|
127
146
|
return next(method, input, options);
|
|
128
147
|
},
|
|
129
148
|
};
|
|
130
149
|
this.rpc = createSignalClient({
|
|
131
|
-
baseUrl: url,
|
|
150
|
+
baseUrl: sfuServer.url,
|
|
132
151
|
interceptors: [
|
|
133
152
|
withHeaders({
|
|
134
153
|
Authorization: `Bearer ${token}`,
|
|
@@ -149,7 +168,7 @@ export class StreamSfuClient {
|
|
|
149
168
|
});
|
|
150
169
|
|
|
151
170
|
this.signalWs = createWebSocketSignalChannel({
|
|
152
|
-
endpoint:
|
|
171
|
+
endpoint: sfuServer.ws_endpoint,
|
|
153
172
|
onMessage: (message) => {
|
|
154
173
|
this.lastMessageTimestamp = new Date();
|
|
155
174
|
this.scheduleConnectionCheck();
|
|
@@ -158,10 +177,12 @@ export class StreamSfuClient {
|
|
|
158
177
|
});
|
|
159
178
|
|
|
160
179
|
this.signalReady = new Promise((resolve) => {
|
|
161
|
-
|
|
180
|
+
const onOpen = () => {
|
|
181
|
+
this.signalWs.removeEventListener('open', onOpen);
|
|
162
182
|
this.keepAlive();
|
|
163
183
|
resolve(this.signalWs);
|
|
164
|
-
}
|
|
184
|
+
};
|
|
185
|
+
this.signalWs.addEventListener('open', onOpen);
|
|
165
186
|
});
|
|
166
187
|
}
|
|
167
188
|
|
|
@@ -262,6 +283,11 @@ export class StreamSfuClient {
|
|
|
262
283
|
|
|
263
284
|
send = (message: SfuRequest) => {
|
|
264
285
|
return this.signalReady.then((signal) => {
|
|
286
|
+
this.logger(
|
|
287
|
+
'debug',
|
|
288
|
+
`Sending message to: ${this.edgeName}`,
|
|
289
|
+
SfuRequest.toJson(message),
|
|
290
|
+
);
|
|
265
291
|
signal.send(SfuRequest.toBinary(message));
|
|
266
292
|
});
|
|
267
293
|
};
|
|
@@ -271,7 +297,7 @@ export class StreamSfuClient {
|
|
|
271
297
|
clearInterval(this.keepAliveInterval);
|
|
272
298
|
}
|
|
273
299
|
this.keepAliveInterval = setInterval(() => {
|
|
274
|
-
this.logger('
|
|
300
|
+
this.logger('trace', 'Sending healthCheckRequest to SFU');
|
|
275
301
|
const message = SfuRequest.create({
|
|
276
302
|
requestPayload: {
|
|
277
303
|
oneofKind: 'healthCheckRequest',
|
|
@@ -326,6 +352,7 @@ const MAX_RETRIES = 5;
|
|
|
326
352
|
* request bursts towards the SFU.
|
|
327
353
|
*
|
|
328
354
|
* @param rpc the closure around the RPC call to execute.
|
|
355
|
+
* @param logger a logger instance to use.
|
|
329
356
|
* @param <I> the type of the request object.
|
|
330
357
|
* @param <O> the type of the response object.
|
|
331
358
|
*/
|
|
@@ -343,10 +370,10 @@ const retryable = async <I extends object, O extends SfuResponseWithError>(
|
|
|
343
370
|
|
|
344
371
|
rpcCallResult = await rpc();
|
|
345
372
|
logger(
|
|
346
|
-
'
|
|
373
|
+
'trace',
|
|
347
374
|
`SFU RPC response received for ${rpcCallResult.method.name}`,
|
|
375
|
+
rpcCallResult,
|
|
348
376
|
);
|
|
349
|
-
logger('debug', `Response payload`, rpcCallResult);
|
|
350
377
|
|
|
351
378
|
// if the RPC call failed, log the error and retry
|
|
352
379
|
if (rpcCallResult.response.error) {
|
package/src/StreamVideoClient.ts
CHANGED
|
@@ -24,8 +24,8 @@ import type {
|
|
|
24
24
|
ConnectionChangedEvent,
|
|
25
25
|
EventHandler,
|
|
26
26
|
EventTypes,
|
|
27
|
-
LogLevel,
|
|
28
27
|
Logger,
|
|
28
|
+
LogLevel,
|
|
29
29
|
StreamClientOptions,
|
|
30
30
|
TokenOrProvider,
|
|
31
31
|
TokenProvider,
|
|
@@ -44,7 +44,6 @@ export class StreamVideoClient {
|
|
|
44
44
|
readonly readOnlyStateStore: StreamVideoReadOnlyStateStore;
|
|
45
45
|
readonly user?: User;
|
|
46
46
|
readonly token?: TokenOrProvider;
|
|
47
|
-
readonly logLevel: LogLevel = 'warn';
|
|
48
47
|
readonly logger: Logger;
|
|
49
48
|
|
|
50
49
|
private readonly writeableStateStore: StreamVideoWriteableStateStore;
|
|
@@ -53,7 +52,6 @@ export class StreamVideoClient {
|
|
|
53
52
|
private eventHandlersToUnregister: Array<() => void> = [];
|
|
54
53
|
private connectionPromise: Promise<void | ConnectedEvent> | undefined;
|
|
55
54
|
private disconnectionPromise: Promise<void> | undefined;
|
|
56
|
-
private logLevels: LogLevel[] = ['debug', 'info', 'warn', 'error'];
|
|
57
55
|
|
|
58
56
|
/**
|
|
59
57
|
* You should create only one instance of `StreamVideoClient`.
|
|
@@ -79,29 +77,30 @@ export class StreamVideoClient {
|
|
|
79
77
|
opts?: StreamClientOptions,
|
|
80
78
|
) {
|
|
81
79
|
let logger: Logger = logToConsole;
|
|
80
|
+
let logLevel: LogLevel = 'warn';
|
|
82
81
|
if (typeof apiKeyOrArgs === 'string') {
|
|
83
|
-
|
|
82
|
+
logLevel = opts?.logLevel || logLevel;
|
|
84
83
|
logger = opts?.logger || logger;
|
|
85
84
|
} else {
|
|
86
|
-
|
|
85
|
+
logLevel = apiKeyOrArgs.options?.logLevel || logLevel;
|
|
87
86
|
logger = apiKeyOrArgs.options?.logger || logger;
|
|
88
87
|
}
|
|
89
88
|
|
|
90
|
-
setLogger(
|
|
89
|
+
setLogger(logger, logLevel);
|
|
91
90
|
this.logger = getLogger(['client']);
|
|
92
91
|
|
|
93
92
|
if (typeof apiKeyOrArgs === 'string') {
|
|
94
93
|
this.streamClient = new StreamClient(apiKeyOrArgs, {
|
|
95
94
|
persistUserOnConnectionFailure: true,
|
|
96
95
|
...opts,
|
|
97
|
-
logLevel
|
|
96
|
+
logLevel,
|
|
98
97
|
logger: this.logger,
|
|
99
98
|
});
|
|
100
99
|
} else {
|
|
101
100
|
this.streamClient = new StreamClient(apiKeyOrArgs.apiKey, {
|
|
102
101
|
persistUserOnConnectionFailure: true,
|
|
103
102
|
...apiKeyOrArgs.options,
|
|
104
|
-
logLevel
|
|
103
|
+
logLevel,
|
|
105
104
|
logger: this.logger,
|
|
106
105
|
});
|
|
107
106
|
|
|
@@ -504,20 +503,4 @@ export class StreamVideoClient {
|
|
|
504
503
|
this.connectionPromise.finally(() => (this.connectionPromise = undefined));
|
|
505
504
|
return this.connectionPromise;
|
|
506
505
|
};
|
|
507
|
-
|
|
508
|
-
private filterLogs = (logMethod: Logger) => {
|
|
509
|
-
return (
|
|
510
|
-
logLevel: LogLevel,
|
|
511
|
-
messeage: string,
|
|
512
|
-
extraData?: Record<string, unknown>,
|
|
513
|
-
tags?: string[],
|
|
514
|
-
) => {
|
|
515
|
-
if (
|
|
516
|
-
this.logLevels.indexOf(logLevel) >=
|
|
517
|
-
this.logLevels.indexOf(this.logLevel)
|
|
518
|
-
) {
|
|
519
|
-
logMethod(logLevel, messeage, extraData, tags);
|
|
520
|
-
}
|
|
521
|
-
};
|
|
522
|
-
};
|
|
523
506
|
}
|
package/src/client-details.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { Device, OS, Sdk } from './gen/video/sfu/models/models';
|
|
1
|
+
import { ClientDetails, Device, OS, Sdk } from './gen/video/sfu/models/models';
|
|
2
|
+
import { isReactNative } from './helpers/platforms';
|
|
3
|
+
import { UAParser } from 'ua-parser-js';
|
|
2
4
|
|
|
3
5
|
let sdkInfo: Sdk | undefined;
|
|
4
6
|
let osInfo: OS | undefined;
|
|
@@ -27,3 +29,33 @@ export const setDeviceInfo = (info: Device) => {
|
|
|
27
29
|
export const getDeviceInfo = () => {
|
|
28
30
|
return deviceInfo;
|
|
29
31
|
};
|
|
32
|
+
|
|
33
|
+
export const getClientDetails = (): ClientDetails => {
|
|
34
|
+
if (isReactNative()) {
|
|
35
|
+
// Since RN doesn't support web, sharing browser info is not required
|
|
36
|
+
return {
|
|
37
|
+
sdk: getSdkInfo(),
|
|
38
|
+
os: getOSInfo(),
|
|
39
|
+
device: getDeviceInfo(),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const userAgent = new UAParser(navigator.userAgent);
|
|
44
|
+
const { browser, os, device, cpu } = userAgent.getResult();
|
|
45
|
+
return {
|
|
46
|
+
sdk: getSdkInfo(),
|
|
47
|
+
browser: {
|
|
48
|
+
name: browser.name || navigator.userAgent,
|
|
49
|
+
version: browser.version || '',
|
|
50
|
+
},
|
|
51
|
+
os: {
|
|
52
|
+
name: os.name || '',
|
|
53
|
+
version: os.version || '',
|
|
54
|
+
architecture: cpu.architecture || '',
|
|
55
|
+
},
|
|
56
|
+
device: {
|
|
57
|
+
name: `${device.vendor || ''} ${device.model || ''} ${device.type || ''}`,
|
|
58
|
+
version: '',
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
};
|
|
@@ -134,8 +134,8 @@ export class StreamClient {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
this.axiosInstance = axios.create({
|
|
137
|
-
baseURL: this.baseURL,
|
|
138
137
|
...this.options,
|
|
138
|
+
baseURL: this.baseURL,
|
|
139
139
|
});
|
|
140
140
|
|
|
141
141
|
// WS connection is initialized when setUser is called
|
|
@@ -457,7 +457,7 @@ export class StreamClient {
|
|
|
457
457
|
this.listeners[key] = [];
|
|
458
458
|
}
|
|
459
459
|
|
|
460
|
-
this.logger('
|
|
460
|
+
this.logger('debug', `Removing listener for ${key} event`);
|
|
461
461
|
this.listeners[key] = this.listeners[key].filter(
|
|
462
462
|
(value) => value !== callback,
|
|
463
463
|
);
|
|
@@ -471,8 +471,7 @@ export class StreamClient {
|
|
|
471
471
|
config?: AxiosRequestConfig & { maxBodyLength?: number };
|
|
472
472
|
},
|
|
473
473
|
) {
|
|
474
|
-
this.logger('
|
|
475
|
-
this.logger('debug', `client: ${type} - Request payload`, {
|
|
474
|
+
this.logger('trace', `client: ${type} - Request - ${url}`, {
|
|
476
475
|
payload: data,
|
|
477
476
|
config,
|
|
478
477
|
});
|
|
@@ -480,13 +479,13 @@ export class StreamClient {
|
|
|
480
479
|
|
|
481
480
|
_logApiResponse<T>(type: string, url: string, response: AxiosResponse<T>) {
|
|
482
481
|
this.logger(
|
|
483
|
-
'
|
|
482
|
+
'trace',
|
|
484
483
|
`client:${type} - Response - url: ${url} > status ${response.status}`,
|
|
485
484
|
{
|
|
486
485
|
response,
|
|
487
486
|
},
|
|
488
487
|
);
|
|
489
|
-
this.logger('
|
|
488
|
+
this.logger('trace', `client:${type} - Response payload`, {
|
|
490
489
|
response,
|
|
491
490
|
});
|
|
492
491
|
}
|
|
@@ -617,8 +616,7 @@ export class StreamClient {
|
|
|
617
616
|
dispatchEvent = (event: StreamVideoEvent) => {
|
|
618
617
|
if (!event.received_at) event.received_at = new Date();
|
|
619
618
|
|
|
620
|
-
this.logger('
|
|
621
|
-
this.logger('debug', 'Event payload:', event);
|
|
619
|
+
this.logger('debug', `Dispatching event: ${event.type}`, event);
|
|
622
620
|
this._callClientListeners(event);
|
|
623
621
|
};
|
|
624
622
|
|
|
@@ -24,7 +24,7 @@ export type { OwnUserResponse } from '../../gen/coordinator';
|
|
|
24
24
|
|
|
25
25
|
export type ConnectAPIResponse = Promise<void | ConnectedEvent>;
|
|
26
26
|
|
|
27
|
-
export type LogLevel = 'debug' | 'info' | '
|
|
27
|
+
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error';
|
|
28
28
|
|
|
29
29
|
type ErrorResponseDetails = {
|
|
30
30
|
code: number;
|
|
@@ -81,8 +81,7 @@ export type CallEventTypes = StreamCallEvent['type'];
|
|
|
81
81
|
export type Logger = (
|
|
82
82
|
logLevel: LogLevel,
|
|
83
83
|
message: string,
|
|
84
|
-
|
|
85
|
-
tags?: string[],
|
|
84
|
+
...args: unknown[]
|
|
86
85
|
) => void;
|
|
87
86
|
|
|
88
87
|
export type StreamClientOptions = Partial<AxiosRequestConfig> & {
|
package/src/events/call.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { CallingState, CallState } from '../store';
|
|
2
2
|
import { StreamVideoEvent } from '../coordinator/connection/types';
|
|
3
3
|
import { Call } from '../Call';
|
|
4
|
-
import { getLogger } from '../logger';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Event handler that watched the delivery of `call.accepted`.
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
watchParticipantCountChanged,
|
|
32
32
|
watchParticipantJoined,
|
|
33
33
|
watchParticipantLeft,
|
|
34
|
+
watchSfuErrorReports,
|
|
34
35
|
watchTrackPublished,
|
|
35
36
|
watchTrackUnpublished,
|
|
36
37
|
watchUnblockedUser,
|
|
@@ -92,6 +93,7 @@ export const registerEventHandlers = (
|
|
|
92
93
|
'call.user_muted': () => console.log('call.user_muted received'),
|
|
93
94
|
};
|
|
94
95
|
const eventHandlers = [
|
|
96
|
+
watchSfuErrorReports(dispatcher),
|
|
95
97
|
watchChangePublishQuality(dispatcher, call),
|
|
96
98
|
watchConnectionQualityChanged(dispatcher, state),
|
|
97
99
|
watchParticipantCountChanged(dispatcher, state),
|
package/src/events/internal.ts
CHANGED
|
@@ -2,6 +2,10 @@ import { Dispatcher } from '../rtc';
|
|
|
2
2
|
import { Call } from '../Call';
|
|
3
3
|
import { CallState } from '../store';
|
|
4
4
|
import { StreamVideoParticipantPatches } from '../types';
|
|
5
|
+
import { getLogger } from '../logger';
|
|
6
|
+
import { ErrorCode } from '../gen/video/sfu/models/models';
|
|
7
|
+
|
|
8
|
+
const logger = getLogger(['events']);
|
|
5
9
|
|
|
6
10
|
/**
|
|
7
11
|
* An event responder which handles the `changePublishQuality` event.
|
|
@@ -63,3 +67,19 @@ export const watchParticipantCountChanged = (
|
|
|
63
67
|
}
|
|
64
68
|
});
|
|
65
69
|
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Watches and logs the errors reported by the currently connected SFU.
|
|
73
|
+
*/
|
|
74
|
+
export const watchSfuErrorReports = (dispatcher: Dispatcher) => {
|
|
75
|
+
return dispatcher.on('error', (e) => {
|
|
76
|
+
if (e.eventPayload.oneofKind !== 'error' || !e.eventPayload.error.error)
|
|
77
|
+
return;
|
|
78
|
+
const error = e.eventPayload.error.error;
|
|
79
|
+
logger('error', 'SFU reported error', {
|
|
80
|
+
code: ErrorCode[error.code],
|
|
81
|
+
message: error.message,
|
|
82
|
+
shouldRetry: error.shouldRetry,
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
};
|
package/src/events/sessions.ts
CHANGED
|
@@ -2457,6 +2457,12 @@ export interface JoinCallRequest {
|
|
|
2457
2457
|
* @memberof JoinCallRequest
|
|
2458
2458
|
*/
|
|
2459
2459
|
members_limit?: number;
|
|
2460
|
+
/**
|
|
2461
|
+
* If the participant is migrating from another SFU, then this is the ID of the previous SFU
|
|
2462
|
+
* @type {string}
|
|
2463
|
+
* @memberof JoinCallRequest
|
|
2464
|
+
*/
|
|
2465
|
+
migrating_from?: string;
|
|
2460
2466
|
/**
|
|
2461
2467
|
*
|
|
2462
2468
|
* @type {boolean}
|