@stream-io/video-client 1.35.1 → 1.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/index.browser.es.js +382 -329
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +404 -333
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +382 -329
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +3 -2
- package/dist/src/StreamVideoClient.d.ts +3 -2
- package/dist/src/coordinator/connection/client.d.ts +3 -2
- package/dist/src/coordinator/connection/connection.d.ts +2 -1
- package/dist/src/coordinator/connection/types.d.ts +17 -1
- package/dist/src/devices/DeviceManager.d.ts +2 -2
- package/dist/src/logger.d.ts +9 -6
- package/dist/src/rpc/createClient.d.ts +3 -2
- package/dist/src/rtc/BasePeerConnection.d.ts +7 -4
- package/dist/src/rtc/Publisher.d.ts +3 -3
- package/dist/src/rtc/codecs.d.ts +3 -1
- package/dist/src/rtc/helpers/sdp.d.ts +8 -0
- package/dist/src/rtc/types.d.ts +4 -5
- package/dist/src/store/CallState.d.ts +1 -1
- package/dist/src/types.d.ts +6 -0
- package/package.json +3 -2
- package/src/Call.ts +49 -68
- package/src/StreamSfuClient.ts +11 -11
- package/src/StreamVideoClient.ts +19 -21
- package/src/coordinator/connection/client.ts +21 -30
- package/src/coordinator/connection/connection.ts +5 -4
- package/src/coordinator/connection/location.ts +4 -4
- package/src/coordinator/connection/types.ts +21 -2
- package/src/devices/BrowserPermission.ts +5 -5
- package/src/devices/CameraManager.ts +3 -4
- package/src/devices/DeviceManager.ts +11 -11
- package/src/devices/MicrophoneManager.ts +8 -8
- package/src/devices/devices.ts +18 -14
- package/src/events/call.ts +6 -9
- package/src/events/internal.ts +4 -4
- package/src/events/mutes.ts +3 -8
- package/src/helpers/DynascaleManager.ts +9 -9
- package/src/helpers/RNSpeechDetector.ts +5 -5
- package/src/helpers/clientUtils.ts +1 -3
- package/src/helpers/ensureExhausted.ts +2 -2
- package/src/logger.ts +9 -34
- package/src/rpc/__tests__/createClient.test.ts +5 -1
- package/src/rpc/createClient.ts +4 -3
- package/src/rpc/retryable.ts +4 -2
- package/src/rtc/BasePeerConnection.ts +26 -24
- package/src/rtc/Dispatcher.ts +4 -4
- package/src/rtc/IceTrickleBuffer.ts +5 -5
- package/src/rtc/Publisher.ts +21 -13
- package/src/rtc/Subscriber.ts +22 -17
- package/src/rtc/__tests__/Publisher.test.ts +12 -8
- package/src/rtc/codecs.ts +13 -2
- package/src/rtc/helpers/__tests__/sdp.codecs.test.ts +628 -0
- package/src/rtc/helpers/sdp.ts +82 -0
- package/src/rtc/signal.ts +7 -7
- package/src/rtc/types.ts +4 -4
- package/src/stats/CallStateStatsReporter.ts +4 -4
- package/src/stats/SfuStatsReporter.ts +6 -6
- package/src/store/CallState.ts +3 -3
- package/src/store/rxUtils.ts +4 -2
- package/src/store/stateStore.ts +6 -6
- package/src/types.ts +6 -0
package/src/rtc/signal.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SfuEvent } from '../gen/video/sfu/event/events';
|
|
2
|
-
import { getLogger } from '../logger';
|
|
3
2
|
import { DispatchableMessage, SfuEventKinds } from './Dispatcher';
|
|
4
3
|
import { Tracer } from '../stats';
|
|
4
|
+
import { videoLoggerSystem } from '../logger';
|
|
5
5
|
|
|
6
6
|
export const createWebSocketSignalChannel = (opts: {
|
|
7
7
|
endpoint: string;
|
|
@@ -10,23 +10,23 @@ export const createWebSocketSignalChannel = (opts: {
|
|
|
10
10
|
tracer: Tracer | undefined;
|
|
11
11
|
}) => {
|
|
12
12
|
const { endpoint, onMessage, tag, tracer } = opts;
|
|
13
|
-
const logger = getLogger(
|
|
14
|
-
logger('
|
|
13
|
+
const logger = videoLoggerSystem.getLogger('SfuClientWS', { tags: [tag] });
|
|
14
|
+
logger.debug('Creating signaling WS channel:', endpoint);
|
|
15
15
|
const ws = new WebSocket(endpoint);
|
|
16
16
|
ws.binaryType = 'arraybuffer'; // do we need this?
|
|
17
17
|
|
|
18
18
|
ws.addEventListener('error', (e) => {
|
|
19
|
-
logger('
|
|
19
|
+
logger.error('Signaling WS channel error', e);
|
|
20
20
|
tracer?.trace('signal.ws.error', e);
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
ws.addEventListener('close', (e) => {
|
|
24
|
-
logger('
|
|
24
|
+
logger.info('Signaling WS channel is closed', e);
|
|
25
25
|
tracer?.trace('signal.ws.close', e);
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
ws.addEventListener('open', (e) => {
|
|
29
|
-
logger('
|
|
29
|
+
logger.info('Signaling WS channel is open', e);
|
|
30
30
|
tracer?.trace('signal.ws.open', e);
|
|
31
31
|
});
|
|
32
32
|
|
|
@@ -41,7 +41,7 @@ export const createWebSocketSignalChannel = (opts: {
|
|
|
41
41
|
} catch (err) {
|
|
42
42
|
const message =
|
|
43
43
|
'Failed to decode a message. Check whether the Proto models match.';
|
|
44
|
-
logger(
|
|
44
|
+
logger.error(message, { event: e, error: err });
|
|
45
45
|
tracer?.trace('signal.ws.message.error', message);
|
|
46
46
|
}
|
|
47
47
|
});
|
package/src/rtc/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AudioBitrateProfile,
|
|
3
|
+
PeerType,
|
|
3
4
|
PublishOption,
|
|
4
5
|
WebsocketReconnectStrategy,
|
|
5
6
|
} from '../gen/video/sfu/models/models';
|
|
@@ -7,10 +8,12 @@ import { StreamSfuClient } from '../StreamSfuClient';
|
|
|
7
8
|
import { CallState } from '../store';
|
|
8
9
|
import { Dispatcher } from './Dispatcher';
|
|
9
10
|
import type { OptimalVideoLayer } from './layers';
|
|
11
|
+
import type { ClientPublishOptions } from '../types';
|
|
10
12
|
|
|
11
13
|
export type OnReconnectionNeeded = (
|
|
12
14
|
kind: WebsocketReconnectStrategy,
|
|
13
15
|
reason: string,
|
|
16
|
+
peerType: PeerType,
|
|
14
17
|
) => void;
|
|
15
18
|
|
|
16
19
|
export type BasePeerConnectionOpts = {
|
|
@@ -22,10 +25,7 @@ export type BasePeerConnectionOpts = {
|
|
|
22
25
|
tag: string;
|
|
23
26
|
enableTracing: boolean;
|
|
24
27
|
iceRestartDelay?: number;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
export type PublisherConstructorOpts = BasePeerConnectionOpts & {
|
|
28
|
-
publishOptions: PublishOption[];
|
|
28
|
+
clientPublishOptions?: ClientPublishOptions;
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
export type TrackPublishOptions = {
|
|
@@ -8,10 +8,10 @@ import type {
|
|
|
8
8
|
} from './types';
|
|
9
9
|
import { CallState } from '../store';
|
|
10
10
|
import { Publisher, Subscriber } from '../rtc';
|
|
11
|
-
import { getLogger } from '../logger';
|
|
12
11
|
import { flatten } from './utils';
|
|
13
12
|
import { TrackType } from '../gen/video/sfu/models/models';
|
|
14
13
|
import { isFirefox } from '../helpers/browsers';
|
|
14
|
+
import { videoLoggerSystem } from '../logger';
|
|
15
15
|
|
|
16
16
|
export type StatsReporterOpts = {
|
|
17
17
|
subscriber: Subscriber;
|
|
@@ -77,7 +77,7 @@ export const createStatsReporter = ({
|
|
|
77
77
|
datacenter,
|
|
78
78
|
pollingIntervalInMs = 2000,
|
|
79
79
|
}: StatsReporterOpts): StatsReporter => {
|
|
80
|
-
const logger = getLogger(
|
|
80
|
+
const logger = videoLoggerSystem.getLogger('stats');
|
|
81
81
|
const getRawStatsForTrack = async (
|
|
82
82
|
kind: PeerConnectionKind,
|
|
83
83
|
selector?: MediaStreamTrack,
|
|
@@ -148,7 +148,7 @@ export const createStatsReporter = ({
|
|
|
148
148
|
];
|
|
149
149
|
participantStats[sessionId] = await getStatsForStream(kind, tracks);
|
|
150
150
|
} catch (e) {
|
|
151
|
-
logger(
|
|
151
|
+
logger.warn(`Failed to collect ${kind} stats for ${userId}`, e);
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
}
|
|
@@ -186,7 +186,7 @@ export const createStatsReporter = ({
|
|
|
186
186
|
// (they are expensive) if no one is listening to them
|
|
187
187
|
if (state.isCallStatsReportObserved) {
|
|
188
188
|
await run().catch((e) => {
|
|
189
|
-
logger('
|
|
189
|
+
logger.debug('Failed to collect stats', e);
|
|
190
190
|
});
|
|
191
191
|
}
|
|
192
192
|
timeoutId = setTimeout(loop, pollingIntervalInMs);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { combineLatest } from 'rxjs';
|
|
2
2
|
import { StreamSfuClient } from '../StreamSfuClient';
|
|
3
3
|
import { OwnCapability, StatsOptions } from '../gen/coordinator';
|
|
4
|
-
import { getLogger } from '../logger';
|
|
5
4
|
import { Publisher, Subscriber } from '../rtc';
|
|
6
5
|
import { Tracer, TraceRecord } from './rtc';
|
|
7
6
|
import { flatten, getSdkName, getSdkVersion } from './utils';
|
|
@@ -15,6 +14,7 @@ import { CameraManager, MicrophoneManager } from '../devices';
|
|
|
15
14
|
import { createSubscription } from '../store/rxUtils';
|
|
16
15
|
import { CallState } from '../store';
|
|
17
16
|
import { Telemetry } from '../gen/video/sfu/signal_rpc/signal';
|
|
17
|
+
import { videoLoggerSystem } from '../logger';
|
|
18
18
|
|
|
19
19
|
export type SfuStatsReporterOptions = {
|
|
20
20
|
options: StatsOptions;
|
|
@@ -29,7 +29,7 @@ export type SfuStatsReporterOptions = {
|
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
export class SfuStatsReporter {
|
|
32
|
-
private readonly logger = getLogger(
|
|
32
|
+
private readonly logger = videoLoggerSystem.getLogger('SfuStatsReporter');
|
|
33
33
|
|
|
34
34
|
readonly options: StatsOptions;
|
|
35
35
|
|
|
@@ -153,7 +153,7 @@ export class SfuStatsReporter {
|
|
|
153
153
|
// intentionally not awaiting the promise here
|
|
154
154
|
// to avoid impeding with the ongoing actions.
|
|
155
155
|
this.run(telemetryData).catch((err) => {
|
|
156
|
-
this.logger('
|
|
156
|
+
this.logger.warn('Failed to send telemetry data', err);
|
|
157
157
|
});
|
|
158
158
|
};
|
|
159
159
|
|
|
@@ -217,7 +217,7 @@ export class SfuStatsReporter {
|
|
|
217
217
|
clearInterval(this.intervalId);
|
|
218
218
|
this.intervalId = setInterval(() => {
|
|
219
219
|
this.run().catch((err) => {
|
|
220
|
-
this.logger('
|
|
220
|
+
this.logger.warn('Failed to report stats', err);
|
|
221
221
|
});
|
|
222
222
|
}, this.options.reporting_interval_ms);
|
|
223
223
|
};
|
|
@@ -237,7 +237,7 @@ export class SfuStatsReporter {
|
|
|
237
237
|
|
|
238
238
|
flush = () => {
|
|
239
239
|
this.run().catch((err) => {
|
|
240
|
-
this.logger('
|
|
240
|
+
this.logger.warn('Failed to flush report stats', err);
|
|
241
241
|
});
|
|
242
242
|
};
|
|
243
243
|
|
|
@@ -245,7 +245,7 @@ export class SfuStatsReporter {
|
|
|
245
245
|
clearTimeout(this.timeoutId);
|
|
246
246
|
this.timeoutId = setTimeout(() => {
|
|
247
247
|
this.run().catch((err) => {
|
|
248
|
-
this.logger('
|
|
248
|
+
this.logger.warn('Failed to report stats', err);
|
|
249
249
|
});
|
|
250
250
|
}, timeout);
|
|
251
251
|
};
|
package/src/store/CallState.ts
CHANGED
|
@@ -55,8 +55,8 @@ import {
|
|
|
55
55
|
CallGrants,
|
|
56
56
|
} from '../gen/video/sfu/models/models';
|
|
57
57
|
import { Comparator, defaultSortPreset } from '../sorting';
|
|
58
|
-
import { getLogger } from '../logger';
|
|
59
58
|
import { hasScreenShare } from '../helpers/participantUtils';
|
|
59
|
+
import { videoLoggerSystem } from '../logger';
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
62
|
* Returns the default egress object - when no egress data is available.
|
|
@@ -312,7 +312,7 @@ export class CallState {
|
|
|
312
312
|
*/
|
|
313
313
|
closedCaptions$: Observable<CallClosedCaption[]>;
|
|
314
314
|
|
|
315
|
-
readonly logger = getLogger(
|
|
315
|
+
readonly logger = videoLoggerSystem.getLogger('CallState');
|
|
316
316
|
|
|
317
317
|
/**
|
|
318
318
|
* A list of comparators that are used to sort the participants.
|
|
@@ -997,7 +997,7 @@ export class CallState {
|
|
|
997
997
|
) => {
|
|
998
998
|
const participant = this.findParticipantBySessionId(sessionId);
|
|
999
999
|
if (!participant) {
|
|
1000
|
-
this.logger(
|
|
1000
|
+
this.logger.warn(`Participant with sessionId ${sessionId} not found`);
|
|
1001
1001
|
return;
|
|
1002
1002
|
}
|
|
1003
1003
|
|
package/src/store/rxUtils.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BehaviorSubject, combineLatest, Observable, Subject } from 'rxjs';
|
|
2
2
|
import { withoutConcurrency } from '../helpers/concurrency';
|
|
3
|
-
import {
|
|
3
|
+
import { videoLoggerSystem } from '../logger';
|
|
4
4
|
|
|
5
5
|
type FunctionPatch<T> = (currentValue: T) => T;
|
|
6
6
|
|
|
@@ -92,7 +92,9 @@ export const createSubscription = <T>(
|
|
|
92
92
|
observable: Observable<T>,
|
|
93
93
|
handler: (value: T) => void,
|
|
94
94
|
onError: (error: any) => void = (error) =>
|
|
95
|
-
|
|
95
|
+
videoLoggerSystem
|
|
96
|
+
.getLogger('RxUtils')
|
|
97
|
+
.warn('An observable emitted an error', error),
|
|
96
98
|
) => {
|
|
97
99
|
const subscription = observable.subscribe({ next: handler, error: onError });
|
|
98
100
|
return () => {
|
package/src/store/stateStore.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as RxUtils from './rxUtils';
|
|
|
4
4
|
import { Call } from '../Call';
|
|
5
5
|
import { CallingState } from './CallingState';
|
|
6
6
|
import type { OwnUserResponse } from '../gen/coordinator';
|
|
7
|
-
import {
|
|
7
|
+
import { videoLoggerSystem } from '../logger';
|
|
8
8
|
|
|
9
9
|
export class StreamVideoWriteableStateStore {
|
|
10
10
|
/**
|
|
@@ -23,15 +23,15 @@ export class StreamVideoWriteableStateStore {
|
|
|
23
23
|
this.connectedUserSubject.subscribe(async (user) => {
|
|
24
24
|
// leave all calls when the user disconnects.
|
|
25
25
|
if (!user) {
|
|
26
|
-
const logger = getLogger(
|
|
26
|
+
const logger = videoLoggerSystem.getLogger('client-state');
|
|
27
27
|
for (const call of this.calls) {
|
|
28
28
|
if (call.state.callingState === CallingState.LEFT) continue;
|
|
29
29
|
|
|
30
|
-
logger(
|
|
30
|
+
logger.info(`User disconnected, leaving call: ${call.cid}`);
|
|
31
31
|
await call
|
|
32
32
|
.leave({ message: 'client.disconnectUser() called' })
|
|
33
33
|
.catch((err) => {
|
|
34
|
-
logger(
|
|
34
|
+
logger.error(`Error leaving call: ${call.cid}`, err);
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -87,8 +87,8 @@ export class StreamVideoWriteableStateStore {
|
|
|
87
87
|
* @param call the call to remove
|
|
88
88
|
*/
|
|
89
89
|
unregisterCall = (call: Call) => {
|
|
90
|
-
const logger = getLogger(
|
|
91
|
-
logger(
|
|
90
|
+
const logger = videoLoggerSystem.getLogger('client-state');
|
|
91
|
+
logger.trace(`Unregistering call: ${call.cid}`);
|
|
92
92
|
return this.setCalls((calls) => calls.filter((c) => c !== call));
|
|
93
93
|
};
|
|
94
94
|
|
package/src/types.ts
CHANGED
|
@@ -212,6 +212,12 @@ export type ClientPublishOptions = {
|
|
|
212
212
|
* Screen share settings.
|
|
213
213
|
*/
|
|
214
214
|
screenShareSettings?: ScreenShareSettings;
|
|
215
|
+
/**
|
|
216
|
+
* Forces a specific codec to be used when publishing and subscribing a video stream.
|
|
217
|
+
* Never use it in production as it can have unforeseeable consequences.
|
|
218
|
+
* @internal
|
|
219
|
+
*/
|
|
220
|
+
dangerouslyForceCodec?: PreferredCodec;
|
|
215
221
|
};
|
|
216
222
|
|
|
217
223
|
export type ScreenShareSettings = {
|