@stream-io/video-client 1.18.5 → 1.18.7
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 +15 -0
- package/dist/index.browser.es.js +36 -60
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +36 -60
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +36 -60
- package/dist/index.es.js.map +1 -1
- package/dist/src/coordinator/connection/types.d.ts +2 -2
- package/dist/src/rtc/BasePeerConnection.d.ts +2 -2
- package/dist/src/rtc/Publisher.d.ts +0 -7
- package/dist/src/rtc/TransceiverCache.d.ts +1 -5
- package/package.json +1 -1
- package/src/Call.ts +5 -2
- package/src/coordinator/connection/types.ts +2 -2
- package/src/rtc/BasePeerConnection.ts +4 -6
- package/src/rtc/Publisher.ts +36 -56
- package/src/rtc/TransceiverCache.ts +1 -8
- package/src/rtc/__tests__/Publisher.test.ts +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
## [1.18.7](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.18.6...@stream-io/video-client-1.18.7) (2025-03-20)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* rename `toJSON` to `asJSON` ([#1729](https://github.com/GetStream/stream-video-js/issues/1729)) ([0d7d074](https://github.com/GetStream/stream-video-js/commit/0d7d074dac1032690b5f4af4d6ba5fcdd56dfaa2))
|
|
11
|
+
* update call reject reasons ([#1730](https://github.com/GetStream/stream-video-js/issues/1730)) ([100ed6b](https://github.com/GetStream/stream-video-js/commit/100ed6b9323b66e86123917abf4fc2973a677fca))
|
|
12
|
+
|
|
13
|
+
## [1.18.6](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.18.5...@stream-io/video-client-1.18.6) (2025-03-13)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* ensure negotiation runs sequentially ([#1722](https://github.com/GetStream/stream-video-js/issues/1722)) ([7e166aa](https://github.com/GetStream/stream-video-js/commit/7e166aaf606c3f751068cf60bd554e6374f701d7))
|
|
19
|
+
|
|
5
20
|
## [1.18.5](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.18.4...@stream-io/video-client-1.18.5) (2025-03-12)
|
|
6
21
|
|
|
7
22
|
|
package/dist/index.browser.es.js
CHANGED
|
@@ -5247,7 +5247,7 @@ class BasePeerConnection {
|
|
|
5247
5247
|
this.logger('debug', 'null ice candidate');
|
|
5248
5248
|
return;
|
|
5249
5249
|
}
|
|
5250
|
-
const iceCandidate = this.
|
|
5250
|
+
const iceCandidate = this.asJSON(candidate);
|
|
5251
5251
|
this.sfuClient
|
|
5252
5252
|
.iceTrickle({ peerType: this.peerType, iceCandidate })
|
|
5253
5253
|
.catch((err) => {
|
|
@@ -5259,7 +5259,7 @@ class BasePeerConnection {
|
|
|
5259
5259
|
/**
|
|
5260
5260
|
* Converts the ICE candidate to a JSON string.
|
|
5261
5261
|
*/
|
|
5262
|
-
this.
|
|
5262
|
+
this.asJSON = (candidate) => {
|
|
5263
5263
|
if (!candidate.usernameFragment) {
|
|
5264
5264
|
// react-native-webrtc doesn't include usernameFragment in the candidate
|
|
5265
5265
|
const segments = candidate.candidate.split(' ');
|
|
@@ -5347,8 +5347,6 @@ class BasePeerConnection {
|
|
|
5347
5347
|
this.pc.removeEventListener('icecandidateerror', this.onIceCandidateError);
|
|
5348
5348
|
this.pc.removeEventListener('signalingstatechange', this.onSignalingChange);
|
|
5349
5349
|
this.pc.removeEventListener('iceconnectionstatechange', this.onIceConnectionStateChange);
|
|
5350
|
-
// cancel any ongoing ICE restart process
|
|
5351
|
-
withCancellation('onIceConnectionStateChange', () => Promise.resolve());
|
|
5352
5350
|
this.pc.removeEventListener('icegatheringstatechange', this.onIceGatherChange);
|
|
5353
5351
|
this.unsubscribeIceTrickle?.();
|
|
5354
5352
|
this.subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
@@ -5378,12 +5376,6 @@ class TransceiverCache {
|
|
|
5378
5376
|
this.get = (publishOption) => {
|
|
5379
5377
|
return this.findTransceiver(publishOption)?.transceiver;
|
|
5380
5378
|
};
|
|
5381
|
-
/**
|
|
5382
|
-
* Gets the last transceiver for the given track type and publish option id.
|
|
5383
|
-
*/
|
|
5384
|
-
this.getWith = (trackType, id) => {
|
|
5385
|
-
return this.findTransceiver({ trackType, id })?.transceiver;
|
|
5386
|
-
};
|
|
5387
5379
|
/**
|
|
5388
5380
|
* Checks if the cache has the given publish option.
|
|
5389
5381
|
*/
|
|
@@ -5697,7 +5689,7 @@ class Publisher extends BasePeerConnection {
|
|
|
5697
5689
|
const trackToPublish = this.cloneTrack(track);
|
|
5698
5690
|
const transceiver = this.transceiverCache.get(publishOption);
|
|
5699
5691
|
if (!transceiver) {
|
|
5700
|
-
this.addTransceiver(trackToPublish, publishOption);
|
|
5692
|
+
await this.addTransceiver(trackToPublish, publishOption);
|
|
5701
5693
|
}
|
|
5702
5694
|
else {
|
|
5703
5695
|
const previousTrack = transceiver.sender.track;
|
|
@@ -5711,7 +5703,7 @@ class Publisher extends BasePeerConnection {
|
|
|
5711
5703
|
/**
|
|
5712
5704
|
* Adds a new transceiver carrying the given track to the peer connection.
|
|
5713
5705
|
*/
|
|
5714
|
-
this.addTransceiver = (track, publishOption) => {
|
|
5706
|
+
this.addTransceiver = async (track, publishOption) => {
|
|
5715
5707
|
const videoEncodings = computeVideoLayers(track, publishOption);
|
|
5716
5708
|
const sendEncodings = isSvcCodec(publishOption.codec?.name)
|
|
5717
5709
|
? toSvcEncodings(videoEncodings)
|
|
@@ -5723,6 +5715,7 @@ class Publisher extends BasePeerConnection {
|
|
|
5723
5715
|
const trackType = publishOption.trackType;
|
|
5724
5716
|
this.logger('debug', `Added ${TrackType[trackType]} transceiver`);
|
|
5725
5717
|
this.transceiverCache.add(publishOption, transceiver);
|
|
5718
|
+
await this.negotiate();
|
|
5726
5719
|
};
|
|
5727
5720
|
/**
|
|
5728
5721
|
* Synchronizes the current Publisher state with the provided publish options.
|
|
@@ -5742,7 +5735,7 @@ class Publisher extends BasePeerConnection {
|
|
|
5742
5735
|
// take the track from the existing transceiver for the same track type,
|
|
5743
5736
|
// clone it and publish it with the new publish options
|
|
5744
5737
|
const track = this.cloneTrack(item.transceiver.sender.track);
|
|
5745
|
-
this.addTransceiver(track, publishOption);
|
|
5738
|
+
await this.addTransceiver(track, publishOption);
|
|
5746
5739
|
}
|
|
5747
5740
|
// stop publishing with options not required anymore -> [vp9]
|
|
5748
5741
|
for (const item of this.transceiverCache.items()) {
|
|
@@ -5812,7 +5805,9 @@ class Publisher extends BasePeerConnection {
|
|
|
5812
5805
|
const enabledLayers = layers.filter((l) => l.active);
|
|
5813
5806
|
const tag = 'Update publish quality:';
|
|
5814
5807
|
this.logger('info', `${tag} requested layers by SFU:`, enabledLayers);
|
|
5815
|
-
const
|
|
5808
|
+
const transceiverId = this.transceiverCache.find((t) => t.publishOption.id === publishOptionId &&
|
|
5809
|
+
t.publishOption.trackType === trackType);
|
|
5810
|
+
const sender = transceiverId?.transceiver.sender;
|
|
5816
5811
|
if (!sender) {
|
|
5817
5812
|
return this.logger('warn', `${tag} no video sender found.`);
|
|
5818
5813
|
}
|
|
@@ -5820,8 +5815,8 @@ class Publisher extends BasePeerConnection {
|
|
|
5820
5815
|
if (params.encodings.length === 0) {
|
|
5821
5816
|
return this.logger('warn', `${tag} there are no encodings set.`);
|
|
5822
5817
|
}
|
|
5823
|
-
const
|
|
5824
|
-
const usesSvcCodec = codecInUse && isSvcCodec(codecInUse
|
|
5818
|
+
const codecInUse = transceiverId?.publishOption.codec?.name;
|
|
5819
|
+
const usesSvcCodec = codecInUse && isSvcCodec(codecInUse);
|
|
5825
5820
|
let changed = false;
|
|
5826
5821
|
for (const encoder of params.encodings) {
|
|
5827
5822
|
const layer = usesSvcCodec
|
|
@@ -5879,40 +5874,32 @@ class Publisher extends BasePeerConnection {
|
|
|
5879
5874
|
}
|
|
5880
5875
|
await this.negotiate({ iceRestart: true });
|
|
5881
5876
|
};
|
|
5882
|
-
this.onNegotiationNeeded = () => {
|
|
5883
|
-
withCancellation('publisher.negotiate', (signal) => this.negotiate().catch((err) => {
|
|
5884
|
-
if (signal.aborted)
|
|
5885
|
-
return;
|
|
5886
|
-
this.logger('error', `Negotiation failed.`, err);
|
|
5887
|
-
this.onUnrecoverableError?.();
|
|
5888
|
-
}));
|
|
5889
|
-
};
|
|
5890
5877
|
/**
|
|
5891
5878
|
* Initiates a new offer/answer exchange with the currently connected SFU.
|
|
5892
5879
|
*
|
|
5893
5880
|
* @param options the optional offer options to use.
|
|
5894
5881
|
*/
|
|
5895
5882
|
this.negotiate = async (options) => {
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5883
|
+
return withoutConcurrency('publisher.negotiate', async () => {
|
|
5884
|
+
const offer = await this.pc.createOffer(options);
|
|
5885
|
+
const tracks = this.getAnnouncedTracks(offer.sdp);
|
|
5886
|
+
if (!tracks.length)
|
|
5887
|
+
throw new Error(`Can't negotiate without any tracks`);
|
|
5888
|
+
try {
|
|
5889
|
+
this.isIceRestarting = options?.iceRestart ?? false;
|
|
5890
|
+
await this.pc.setLocalDescription(offer);
|
|
5891
|
+
const { sdp = '' } = offer;
|
|
5892
|
+
const { response } = await this.sfuClient.setPublisher({ sdp, tracks });
|
|
5893
|
+
if (response.error)
|
|
5894
|
+
throw new Error(response.error.message);
|
|
5895
|
+
const { sdp: answerSdp } = response;
|
|
5896
|
+
await this.pc.setRemoteDescription({ type: 'answer', sdp: answerSdp });
|
|
5897
|
+
}
|
|
5898
|
+
finally {
|
|
5899
|
+
this.isIceRestarting = false;
|
|
5900
|
+
}
|
|
5901
|
+
this.addTrickledIceCandidates();
|
|
5902
|
+
});
|
|
5916
5903
|
};
|
|
5917
5904
|
/**
|
|
5918
5905
|
* Returns a list of tracks that are currently being published.
|
|
@@ -5996,7 +5983,6 @@ class Publisher extends BasePeerConnection {
|
|
|
5996
5983
|
this.clonedTracks.delete(track);
|
|
5997
5984
|
};
|
|
5998
5985
|
this.publishOptions = publishOptions;
|
|
5999
|
-
this.pc.addEventListener('negotiationneeded', this.onNegotiationNeeded);
|
|
6000
5986
|
this.on('iceRestart', (iceRestart) => {
|
|
6001
5987
|
if (iceRestart.peerType !== PeerType.PUBLISHER_UNSPECIFIED)
|
|
6002
5988
|
return;
|
|
@@ -6015,17 +6001,6 @@ class Publisher extends BasePeerConnection {
|
|
|
6015
6001
|
return this.syncPublishOptions();
|
|
6016
6002
|
});
|
|
6017
6003
|
}
|
|
6018
|
-
/**
|
|
6019
|
-
* Detaches the event handlers from the `RTCPeerConnection`.
|
|
6020
|
-
* This is useful when we want to replace the `RTCPeerConnection`
|
|
6021
|
-
* instance with a new one (in case of migration).
|
|
6022
|
-
*/
|
|
6023
|
-
detachEventHandlers() {
|
|
6024
|
-
super.detachEventHandlers();
|
|
6025
|
-
this.pc.removeEventListener('negotiationneeded', this.onNegotiationNeeded);
|
|
6026
|
-
// abort any ongoing negotiation
|
|
6027
|
-
withCancellation('publisher.negotiate', () => Promise.resolve());
|
|
6028
|
-
}
|
|
6029
6004
|
/**
|
|
6030
6005
|
* Disposes this Publisher instance.
|
|
6031
6006
|
*/
|
|
@@ -7457,7 +7432,7 @@ const aggregate = (stats) => {
|
|
|
7457
7432
|
return report;
|
|
7458
7433
|
};
|
|
7459
7434
|
|
|
7460
|
-
const version = "1.18.
|
|
7435
|
+
const version = "1.18.7";
|
|
7461
7436
|
const [major, minor, patch] = version.split('.');
|
|
7462
7437
|
let sdkInfo = {
|
|
7463
7438
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -10428,7 +10403,7 @@ class Call {
|
|
|
10428
10403
|
}
|
|
10429
10404
|
if (callingState === CallingState.RINGING && reject !== false) {
|
|
10430
10405
|
if (reject) {
|
|
10431
|
-
await this.reject(
|
|
10406
|
+
await this.reject('decline');
|
|
10432
10407
|
}
|
|
10433
10408
|
else {
|
|
10434
10409
|
// if reject was undefined, we still have to cancel the call automatically
|
|
@@ -10458,6 +10433,7 @@ class Call {
|
|
|
10458
10433
|
this.initialized = false;
|
|
10459
10434
|
this.hasJoinedOnce = false;
|
|
10460
10435
|
this.ringingSubject.next(false);
|
|
10436
|
+
this.cancelAutoDrop();
|
|
10461
10437
|
this.clientStore.unregisterCall(this);
|
|
10462
10438
|
this.camera.dispose();
|
|
10463
10439
|
this.microphone.dispose();
|
|
@@ -10596,7 +10572,7 @@ class Call {
|
|
|
10596
10572
|
*
|
|
10597
10573
|
* @param reason the reason for rejecting the call.
|
|
10598
10574
|
*/
|
|
10599
|
-
this.reject = async (reason) => {
|
|
10575
|
+
this.reject = async (reason = 'decline') => {
|
|
10600
10576
|
return this.streamClient.post(`${this.streamClientBasePath}/reject`, { reason: reason });
|
|
10601
10577
|
};
|
|
10602
10578
|
/**
|
|
@@ -13096,7 +13072,7 @@ class StreamClient {
|
|
|
13096
13072
|
this.getUserAgent = () => {
|
|
13097
13073
|
if (!this.cachedUserAgent) {
|
|
13098
13074
|
const { clientAppIdentifier = {} } = this.options;
|
|
13099
|
-
const { sdkName = 'js', sdkVersion = "1.18.
|
|
13075
|
+
const { sdkName = 'js', sdkVersion = "1.18.7", ...extras } = clientAppIdentifier;
|
|
13100
13076
|
this.cachedUserAgent = [
|
|
13101
13077
|
`stream-video-${sdkName}-v${sdkVersion}`,
|
|
13102
13078
|
...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
|