@stream-io/video-client 1.16.3 → 1.16.5

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,20 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ## [1.16.5](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.16.4...@stream-io/video-client-1.16.5) (2025-02-10)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * ensure all tracks are stopped when disposing a Publisher ([#1677](https://github.com/GetStream/stream-video-js/issues/1677)) ([172d345](https://github.com/GetStream/stream-video-js/commit/172d345ceada2bf82df1aec604a2325947896c5c)), closes [#1676](https://github.com/GetStream/stream-video-js/issues/1676)
11
+
12
+ ## [1.16.4](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.16.3...@stream-io/video-client-1.16.4) (2025-02-07)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * ensure tracks are stopped when disposing a Publisher ([#1676](https://github.com/GetStream/stream-video-js/issues/1676)) ([948f672](https://github.com/GetStream/stream-video-js/commit/948f672243e1f2a0e9499184ee31db4bc88f9952))
18
+
5
19
  ## [1.16.3](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.16.2...@stream-io/video-client-1.16.3) (2025-02-06)
6
20
 
7
21
 
@@ -5203,15 +5203,6 @@ class BasePeerConnection {
5203
5203
  this.isIceRestarting = false;
5204
5204
  this.isDisposed = false;
5205
5205
  this.subscriptions = [];
5206
- /**
5207
- * Disposes the `RTCPeerConnection` instance.
5208
- */
5209
- this.dispose = () => {
5210
- this.onUnrecoverableError = undefined;
5211
- this.isDisposed = true;
5212
- this.detachEventHandlers();
5213
- this.pc.close();
5214
- };
5215
5206
  /**
5216
5207
  * Handles events synchronously.
5217
5208
  * Consecutive events are queued and executed one after the other.
@@ -5348,6 +5339,15 @@ class BasePeerConnection {
5348
5339
  this.pc.addEventListener('icegatheringstatechange', this.onIceGatherChange);
5349
5340
  this.pc.addEventListener('signalingstatechange', this.onSignalingChange);
5350
5341
  }
5342
+ /**
5343
+ * Disposes the `RTCPeerConnection` instance.
5344
+ */
5345
+ dispose() {
5346
+ this.onUnrecoverableError = undefined;
5347
+ this.isDisposed = true;
5348
+ this.detachEventHandlers();
5349
+ this.pc.close();
5350
+ }
5351
5351
  /**
5352
5352
  * Detaches the event handlers from the `RTCPeerConnection`.
5353
5353
  */
@@ -5684,6 +5684,7 @@ class Publisher extends BasePeerConnection {
5684
5684
  constructor({ publishOptions, ...baseOptions }) {
5685
5685
  super(PeerType.PUBLISHER_UNSPECIFIED, baseOptions);
5686
5686
  this.transceiverCache = new TransceiverCache();
5687
+ this.clonedTracks = new Set();
5687
5688
  /**
5688
5689
  * Starts publishing the given track of the given media stream.
5689
5690
  *
@@ -5702,13 +5703,15 @@ class Publisher extends BasePeerConnection {
5702
5703
  continue;
5703
5704
  // create a clone of the track as otherwise the same trackId will
5704
5705
  // appear in the SDP in multiple transceivers
5705
- const trackToPublish = track.clone();
5706
+ const trackToPublish = this.cloneTrack(track);
5706
5707
  const transceiver = this.transceiverCache.get(publishOption);
5707
5708
  if (!transceiver) {
5708
5709
  this.addTransceiver(trackToPublish, publishOption);
5709
5710
  }
5710
5711
  else {
5712
+ const previousTrack = transceiver.sender.track;
5711
5713
  await transceiver.sender.replaceTrack(trackToPublish);
5714
+ this.stopTrack(previousTrack);
5712
5715
  }
5713
5716
  }
5714
5717
  };
@@ -5745,7 +5748,7 @@ class Publisher extends BasePeerConnection {
5745
5748
  continue;
5746
5749
  // take the track from the existing transceiver for the same track type,
5747
5750
  // clone it and publish it with the new publish options
5748
- const track = item.transceiver.sender.track.clone();
5751
+ const track = this.cloneTrack(item.transceiver.sender.track);
5749
5752
  this.addTransceiver(track, publishOption);
5750
5753
  }
5751
5754
  // stop publishing with options not required anymore -> [vp9]
@@ -5756,7 +5759,7 @@ class Publisher extends BasePeerConnection {
5756
5759
  if (hasPublishOption)
5757
5760
  continue;
5758
5761
  // it is safe to stop the track here, it is a clone
5759
- transceiver.sender.track?.stop();
5762
+ this.stopTrack(transceiver.sender.track);
5760
5763
  await transceiver.sender.replaceTrack(null);
5761
5764
  }
5762
5765
  };
@@ -5797,7 +5800,18 @@ class Publisher extends BasePeerConnection {
5797
5800
  const { publishOption, transceiver } = item;
5798
5801
  if (!trackTypes.includes(publishOption.trackType))
5799
5802
  continue;
5800
- transceiver.sender.track?.stop();
5803
+ this.stopTrack(transceiver.sender.track);
5804
+ }
5805
+ };
5806
+ /**
5807
+ * Stops all the cloned tracks that are being published to the SFU.
5808
+ */
5809
+ this.stopAllTracks = () => {
5810
+ for (const { transceiver } of this.transceiverCache.items()) {
5811
+ this.stopTrack(transceiver.sender.track);
5812
+ }
5813
+ for (const track of this.clonedTracks) {
5814
+ this.stopTrack(track);
5801
5815
  }
5802
5816
  };
5803
5817
  this.changePublishQuality = async (videoSender) => {
@@ -5977,6 +5991,17 @@ class Publisher extends BasePeerConnection {
5977
5991
  publishOptionId: publishOption.id,
5978
5992
  };
5979
5993
  };
5994
+ this.cloneTrack = (track) => {
5995
+ const clone = track.clone();
5996
+ this.clonedTracks.add(clone);
5997
+ return clone;
5998
+ };
5999
+ this.stopTrack = (track) => {
6000
+ if (!track)
6001
+ return;
6002
+ track.stop();
6003
+ this.clonedTracks.delete(track);
6004
+ };
5980
6005
  this.publishOptions = publishOptions;
5981
6006
  this.pc.addEventListener('negotiationneeded', this.onNegotiationNeeded);
5982
6007
  this.on('iceRestart', (iceRestart) => {
@@ -6008,6 +6033,14 @@ class Publisher extends BasePeerConnection {
6008
6033
  // abort any ongoing negotiation
6009
6034
  withCancellation('publisher.negotiate', () => Promise.resolve());
6010
6035
  }
6036
+ /**
6037
+ * Disposes this Publisher instance.
6038
+ */
6039
+ dispose() {
6040
+ super.dispose();
6041
+ this.stopAllTracks();
6042
+ this.clonedTracks.clear();
6043
+ }
6011
6044
  }
6012
6045
 
6013
6046
  /**
@@ -7431,7 +7464,7 @@ const aggregate = (stats) => {
7431
7464
  return report;
7432
7465
  };
7433
7466
 
7434
- const version = "1.16.3";
7467
+ const version = "1.16.5";
7435
7468
  const [major, minor, patch] = version.split('.');
7436
7469
  let sdkInfo = {
7437
7470
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -13039,7 +13072,7 @@ class StreamClient {
13039
13072
  return await this.wsConnection.connect(this.defaultWSTimeout);
13040
13073
  };
13041
13074
  this.getUserAgent = () => {
13042
- const version = "1.16.3";
13075
+ const version = "1.16.5";
13043
13076
  return (this.userAgent ||
13044
13077
  `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
13045
13078
  };