@stream-io/video-client 1.22.1 → 1.23.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 CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ## [1.23.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.22.2...@stream-io/video-client-1.23.0) (2025-05-20)
6
+
7
+ ### Features
8
+
9
+ - **react-native:** Noise Cancellation ([#1793](https://github.com/GetStream/stream-video-js/issues/1793)) ([d7843e1](https://github.com/GetStream/stream-video-js/commit/d7843e1a23e6f6a35d1c159438d09bdfd17450a5))
10
+ - **web:** improved noise cancellation ([#1794](https://github.com/GetStream/stream-video-js/issues/1794)) ([d59f19b](https://github.com/GetStream/stream-video-js/commit/d59f19b1ba1ff83fe5f024d783b868f4e98d3380))
11
+
12
+ ### Bug Fixes
13
+
14
+ - do not mutate filters array during pipeline setup ([#1798](https://github.com/GetStream/stream-video-js/issues/1798)) ([e9832e5](https://github.com/GetStream/stream-video-js/commit/e9832e5ef41b3f6cddfe2d0cb2cf840e9b28bb86))
15
+
16
+ ## [1.22.2](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.22.1...@stream-io/video-client-1.22.2) (2025-05-15)
17
+
18
+ - adjust ErrorFromResponse class ([#1791](https://github.com/GetStream/stream-video-js/issues/1791)) ([c0abcba](https://github.com/GetStream/stream-video-js/commit/c0abcbacfddeb87d8378c4418f80e6770981cdc8)), closes [GetStream/chat#1540](https://github.com/GetStream/chat/issues/1540)
19
+
20
+ ### Bug Fixes
21
+
22
+ - enable chore releases ([#1792](https://github.com/GetStream/stream-video-js/issues/1792)) ([6046654](https://github.com/GetStream/stream-video-js/commit/6046654fe19505a1c115a4fb838759d010540614))
23
+
5
24
  ## [1.22.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.22.0...@stream-io/video-client-1.22.1) (2025-05-14)
6
25
 
7
26
  ### Bug Fixes
@@ -298,6 +298,34 @@ const VideoSettingsResponseCameraFacingEnum = {
298
298
  };
299
299
 
300
300
  class ErrorFromResponse extends Error {
301
+ constructor({ message, code, status, response, unrecoverable, }) {
302
+ super(message);
303
+ this.name = 'ErrorFromResponse';
304
+ this.code = code;
305
+ this.response = response;
306
+ this.status = status;
307
+ this.unrecoverable = unrecoverable;
308
+ }
309
+ // Vitest helper (serialized errors are too large to read)
310
+ // https://github.com/vitest-dev/vitest/blob/v3.1.3/packages/utils/src/error.ts#L60-L62
311
+ toJSON() {
312
+ const extra = [
313
+ ['status', this.status],
314
+ ['code', this.code],
315
+ ['unrecoverable', this.unrecoverable],
316
+ ];
317
+ const joinable = [];
318
+ for (const [key, value] of extra) {
319
+ if (typeof value !== 'undefined' && value !== null) {
320
+ joinable.push(`${key}: ${value}`);
321
+ }
322
+ }
323
+ return {
324
+ message: `(${joinable.join(', ')}) - ${this.message}`,
325
+ stack: this.stack,
326
+ name: this.name,
327
+ };
328
+ }
301
329
  }
302
330
 
303
331
  // @generated by protobuf-ts 2.9.6 with parameter long_type_string,client_generic,server_none,eslint_disable,optimize_code_size
@@ -5652,7 +5680,7 @@ const aggregate = (stats) => {
5652
5680
  return report;
5653
5681
  };
5654
5682
 
5655
- const version = "1.22.1";
5683
+ const version = "1.23.0";
5656
5684
  const [major, minor, patch] = version.split('.');
5657
5685
  let sdkInfo = {
5658
5686
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -9433,13 +9461,16 @@ class InputMediaDeviceManager {
9433
9461
  start: filter,
9434
9462
  stop: undefined,
9435
9463
  };
9464
+ this.call.tracer.trace(`registerFilter.${TrackType[this.trackType]}`, null);
9436
9465
  const registered = withoutConcurrency(this.filterRegistrationConcurrencyTag, async () => {
9466
+ await settled(this.statusChangeConcurrencyTag);
9437
9467
  this.filters.push(entry);
9438
9468
  await this.applySettingsToStream();
9439
9469
  });
9440
9470
  return {
9441
9471
  registered,
9442
9472
  unregister: () => withoutConcurrency(this.filterRegistrationConcurrencyTag, async () => {
9473
+ await settled(this.statusChangeConcurrencyTag);
9443
9474
  entry.stop?.();
9444
9475
  this.filters = this.filters.filter((f) => f !== entry);
9445
9476
  await this.applySettingsToStream();
@@ -10310,7 +10341,17 @@ class MicrophoneManager extends InputMediaDeviceManager {
10310
10341
  NoiseCancellationSettingsModeEnum.AUTO_ON;
10311
10342
  if (autoOn && callingState === CallingState.JOINED) {
10312
10343
  this.noiseCancellationRegistration
10313
- .then(() => this.noiseCancellation?.enable())
10344
+ .then(() => {
10345
+ if (this.noiseCancellation?.canAutoEnable) {
10346
+ return this.noiseCancellation.canAutoEnable();
10347
+ }
10348
+ return true;
10349
+ })
10350
+ .then((canAutoEnable) => {
10351
+ if (canAutoEnable) {
10352
+ this.noiseCancellation?.enable();
10353
+ }
10354
+ })
10314
10355
  .catch((err) => {
10315
10356
  this.logger('warn', `Failed to enable noise cancellation`, err);
10316
10357
  return this.call.notifyNoiseCancellationStopped();
@@ -10328,13 +10369,9 @@ class MicrophoneManager extends InputMediaDeviceManager {
10328
10369
  /**
10329
10370
  * Enables noise cancellation for the microphone.
10330
10371
  *
10331
- * Note: not supported in React Native.
10332
10372
  * @param noiseCancellation - a noise cancellation instance to use.
10333
10373
  */
10334
10374
  async enableNoiseCancellation(noiseCancellation) {
10335
- if (isReactNative()) {
10336
- throw new Error('Noise cancellation is not supported in React Native');
10337
- }
10338
10375
  const { ownCapabilities, settings } = this.call.state;
10339
10376
  const hasNoiseCancellationCapability = ownCapabilities.includes(OwnCapability.ENABLE_NOISE_CANCELLATION);
10340
10377
  if (!hasNoiseCancellationCapability) {
@@ -10350,6 +10387,7 @@ class MicrophoneManager extends InputMediaDeviceManager {
10350
10387
  this.noiseCancellation = noiseCancellation;
10351
10388
  // listen for change events and notify the SFU
10352
10389
  this.noiseCancellationChangeUnsubscribe = this.noiseCancellation.on('change', (enabled) => {
10390
+ this.call.tracer.trace('noiseCancellation.enabled', enabled);
10353
10391
  if (enabled) {
10354
10392
  this.call.notifyNoiseCancellationStarting().catch((err) => {
10355
10393
  this.logger('warn', `notifyNoiseCancellationStart failed`, err);
@@ -10361,16 +10399,37 @@ class MicrophoneManager extends InputMediaDeviceManager {
10361
10399
  });
10362
10400
  }
10363
10401
  });
10364
- const registrationResult = this.registerFilter(noiseCancellation.toFilter());
10365
- this.noiseCancellationRegistration = registrationResult.registered;
10366
- this.unregisterNoiseCancellation = registrationResult.unregister;
10367
- await this.noiseCancellationRegistration;
10402
+ if (isReactNative()) {
10403
+ // no filter registration in React Native, its done in the native code on app init
10404
+ this.noiseCancellationRegistration = Promise.resolve();
10405
+ }
10406
+ else {
10407
+ // Krisp recommends disabling the browser's built-in noise cancellation
10408
+ // and echo cancellation when using Krisp, so we do that here.
10409
+ // https://sdk-docs.krisp.ai/docs/getting-started-js
10410
+ this.setDefaultConstraints({
10411
+ ...this.state.defaultConstraints,
10412
+ echoCancellation: false,
10413
+ noiseSuppression: false,
10414
+ autoGainControl: false,
10415
+ });
10416
+ const registrationResult = this.registerFilter(noiseCancellation.toFilter());
10417
+ this.noiseCancellationRegistration = registrationResult.registered;
10418
+ this.unregisterNoiseCancellation = registrationResult.unregister;
10419
+ await this.noiseCancellationRegistration;
10420
+ }
10368
10421
  // handles an edge case where a noise cancellation is enabled after
10369
10422
  // the participant as joined the call -> we immediately enable NC
10370
10423
  if (noiseCancellationSettings.mode ===
10371
10424
  NoiseCancellationSettingsModeEnum.AUTO_ON &&
10372
10425
  this.call.state.callingState === CallingState.JOINED) {
10373
- noiseCancellation.enable();
10426
+ let canAutoEnable = true;
10427
+ if (noiseCancellation.canAutoEnable) {
10428
+ canAutoEnable = await noiseCancellation.canAutoEnable();
10429
+ }
10430
+ if (canAutoEnable) {
10431
+ noiseCancellation.enable();
10432
+ }
10374
10433
  }
10375
10434
  }
10376
10435
  catch (e) {
@@ -10382,13 +10441,8 @@ class MicrophoneManager extends InputMediaDeviceManager {
10382
10441
  }
10383
10442
  /**
10384
10443
  * Disables noise cancellation for the microphone.
10385
- *
10386
- * Note: not supported in React Native.
10387
10444
  */
10388
10445
  async disableNoiseCancellation() {
10389
- if (isReactNative()) {
10390
- throw new Error('Noise cancellation is not supported in React Native');
10391
- }
10392
10446
  await (this.unregisterNoiseCancellation?.() ?? Promise.resolve())
10393
10447
  .then(() => this.noiseCancellation?.disable())
10394
10448
  .then(() => this.noiseCancellationChangeUnsubscribe?.())
@@ -13695,13 +13749,13 @@ class StreamClient {
13695
13749
  };
13696
13750
  this.errorFromResponse = (response) => {
13697
13751
  const { data, status } = response;
13698
- const err = new ErrorFromResponse();
13699
- err.message = `Stream error code ${data.code}: ${data.message}`;
13700
- err.code = data.code;
13701
- err.unrecoverable = data.unrecoverable;
13702
- err.response = response;
13703
- err.status = status;
13704
- return err;
13752
+ return new ErrorFromResponse({
13753
+ message: `Stream error code ${data.code}: ${data.message}`,
13754
+ code: data.code ?? null,
13755
+ unrecoverable: data.unrecoverable ?? null,
13756
+ response: response,
13757
+ status: status,
13758
+ });
13705
13759
  };
13706
13760
  this.handleResponse = (response) => {
13707
13761
  const data = response.data;
@@ -13742,7 +13796,7 @@ class StreamClient {
13742
13796
  this.getUserAgent = () => {
13743
13797
  if (!this.cachedUserAgent) {
13744
13798
  const { clientAppIdentifier = {} } = this.options;
13745
- const { sdkName = 'js', sdkVersion = "1.22.1", ...extras } = clientAppIdentifier;
13799
+ const { sdkName = 'js', sdkVersion = "1.23.0", ...extras } = clientAppIdentifier;
13746
13800
  this.cachedUserAgent = [
13747
13801
  `stream-video-${sdkName}-v${sdkVersion}`,
13748
13802
  ...Object.entries(extras).map(([key, value]) => `${key}=${value}`),