@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.
Files changed (63) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/index.browser.es.js +382 -329
  3. package/dist/index.browser.es.js.map +1 -1
  4. package/dist/index.cjs.js +404 -333
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.es.js +382 -329
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/src/Call.d.ts +3 -2
  9. package/dist/src/StreamVideoClient.d.ts +3 -2
  10. package/dist/src/coordinator/connection/client.d.ts +3 -2
  11. package/dist/src/coordinator/connection/connection.d.ts +2 -1
  12. package/dist/src/coordinator/connection/types.d.ts +17 -1
  13. package/dist/src/devices/DeviceManager.d.ts +2 -2
  14. package/dist/src/logger.d.ts +9 -6
  15. package/dist/src/rpc/createClient.d.ts +3 -2
  16. package/dist/src/rtc/BasePeerConnection.d.ts +7 -4
  17. package/dist/src/rtc/Publisher.d.ts +3 -3
  18. package/dist/src/rtc/codecs.d.ts +3 -1
  19. package/dist/src/rtc/helpers/sdp.d.ts +8 -0
  20. package/dist/src/rtc/types.d.ts +4 -5
  21. package/dist/src/store/CallState.d.ts +1 -1
  22. package/dist/src/types.d.ts +6 -0
  23. package/package.json +3 -2
  24. package/src/Call.ts +49 -68
  25. package/src/StreamSfuClient.ts +11 -11
  26. package/src/StreamVideoClient.ts +19 -21
  27. package/src/coordinator/connection/client.ts +21 -30
  28. package/src/coordinator/connection/connection.ts +5 -4
  29. package/src/coordinator/connection/location.ts +4 -4
  30. package/src/coordinator/connection/types.ts +21 -2
  31. package/src/devices/BrowserPermission.ts +5 -5
  32. package/src/devices/CameraManager.ts +3 -4
  33. package/src/devices/DeviceManager.ts +11 -11
  34. package/src/devices/MicrophoneManager.ts +8 -8
  35. package/src/devices/devices.ts +18 -14
  36. package/src/events/call.ts +6 -9
  37. package/src/events/internal.ts +4 -4
  38. package/src/events/mutes.ts +3 -8
  39. package/src/helpers/DynascaleManager.ts +9 -9
  40. package/src/helpers/RNSpeechDetector.ts +5 -5
  41. package/src/helpers/clientUtils.ts +1 -3
  42. package/src/helpers/ensureExhausted.ts +2 -2
  43. package/src/logger.ts +9 -34
  44. package/src/rpc/__tests__/createClient.test.ts +5 -1
  45. package/src/rpc/createClient.ts +4 -3
  46. package/src/rpc/retryable.ts +4 -2
  47. package/src/rtc/BasePeerConnection.ts +26 -24
  48. package/src/rtc/Dispatcher.ts +4 -4
  49. package/src/rtc/IceTrickleBuffer.ts +5 -5
  50. package/src/rtc/Publisher.ts +21 -13
  51. package/src/rtc/Subscriber.ts +22 -17
  52. package/src/rtc/__tests__/Publisher.test.ts +12 -8
  53. package/src/rtc/codecs.ts +13 -2
  54. package/src/rtc/helpers/__tests__/sdp.codecs.test.ts +628 -0
  55. package/src/rtc/helpers/sdp.ts +82 -0
  56. package/src/rtc/signal.ts +7 -7
  57. package/src/rtc/types.ts +4 -4
  58. package/src/stats/CallStateStatsReporter.ts +4 -4
  59. package/src/stats/SfuStatsReporter.ts +6 -6
  60. package/src/store/CallState.ts +3 -3
  61. package/src/store/rxUtils.ts +4 -2
  62. package/src/store/stateStore.ts +6 -6
  63. 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(['SfuClientWS', tag]);
14
- logger('debug', 'Creating signaling WS channel:', endpoint);
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('error', 'Signaling WS channel error', e);
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('info', 'Signaling WS channel is closed', e);
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('info', 'Signaling WS channel is open', e);
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('error', message, { event: e, error: err });
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(['stats']);
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('warn', `Failed to collect ${kind} stats for ${userId}`, e);
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('debug', 'Failed to collect stats', e);
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(['SfuStatsReporter']);
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('warn', 'Failed to send telemetry data', err);
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('warn', 'Failed to report stats', err);
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('warn', 'Failed to flush report stats', err);
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('warn', 'Failed to report stats', err);
248
+ this.logger.warn('Failed to report stats', err);
249
249
  });
250
250
  }, timeout);
251
251
  };
@@ -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(['CallState']);
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('warn', `Participant with sessionId ${sessionId} not found`);
1000
+ this.logger.warn(`Participant with sessionId ${sessionId} not found`);
1001
1001
  return;
1002
1002
  }
1003
1003
 
@@ -1,6 +1,6 @@
1
1
  import { BehaviorSubject, combineLatest, Observable, Subject } from 'rxjs';
2
2
  import { withoutConcurrency } from '../helpers/concurrency';
3
- import { getLogger } from '../logger';
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
- getLogger(['RxUtils'])('warn', 'An observable emitted an error', error),
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 () => {
@@ -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 { getLogger } from '../logger';
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(['client-state']);
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('info', `User disconnected, leaving call: ${call.cid}`);
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('error', `Error leaving call: ${call.cid}`, err);
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(['client-state']);
91
- logger('trace', `Unregistering call: ${call.cid}`);
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 = {