@stream-io/video-client 1.33.0 → 1.34.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 +19 -0
- package/dist/index.browser.es.js +50 -24
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +50 -24
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +50 -24
- package/dist/index.es.js.map +1 -1
- package/dist/src/sorting/participants.d.ts +5 -2
- package/package.json +20 -21
- package/src/Call.ts +1 -0
- package/src/devices/SpeakerManager.ts +9 -6
- package/src/devices/__tests__/SpeakerManager.test.ts +8 -5
- package/src/rtc/__tests__/layers.test.ts +99 -74
- package/src/sorting/__tests__/sorting.test.ts +106 -0
- package/src/sorting/participants.ts +30 -14
- package/src/sorting/presets.ts +14 -2
- package/src/store/__tests__/CallState.test.ts +7 -12
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.34.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.33.1...@stream-io/video-client-1.34.0) (2025-10-14)
|
|
6
|
+
|
|
7
|
+
- use fromPartial instead of suppressing ts-errors ([#1949](https://github.com/GetStream/stream-video-js/issues/1949)) ([95e5654](https://github.com/GetStream/stream-video-js/commit/95e5654e2bac5dc7c5126079795fca9951652290))
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
- **deps:** React 19.1, React Native 0.81, NextJS 15.5, Expo 54 ([#1940](https://github.com/GetStream/stream-video-js/issues/1940)) ([30f8ce2](https://github.com/GetStream/stream-video-js/commit/30f8ce2b335189e1f77160236839bc6c6a02f634))
|
|
12
|
+
- move audio route manager inside SDK ([#1840](https://github.com/GetStream/stream-video-js/issues/1840)) ([847dd30](https://github.com/GetStream/stream-video-js/commit/847dd30d6240a0780fe3d58d681554bc392f6f51)), closes [#1829](https://github.com/GetStream/stream-video-js/issues/1829)
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
- flush rtc stats when reconnecting ([#1946](https://github.com/GetStream/stream-video-js/issues/1946)) ([fb1f6fc](https://github.com/GetStream/stream-video-js/commit/fb1f6fcb2837154a4fe746a6efe4f9a4830bca20))
|
|
17
|
+
|
|
18
|
+
## [1.33.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.33.0...@stream-io/video-client-1.33.1) (2025-10-02)
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
- ensure ingress participants are prioritized ([#1943](https://github.com/GetStream/stream-video-js/issues/1943)) ([a51a119](https://github.com/GetStream/stream-video-js/commit/a51a119cfb9f13736395b4afb3d3947ef994a6d9))
|
|
23
|
+
|
|
5
24
|
## [1.33.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.32.0...@stream-io/video-client-1.33.0) (2025-09-30)
|
|
6
25
|
|
|
7
26
|
### Features
|
package/dist/index.browser.es.js
CHANGED
|
@@ -4580,9 +4580,11 @@ const speaking = (a, b) => {
|
|
|
4580
4580
|
* @param b the second participant.
|
|
4581
4581
|
*/
|
|
4582
4582
|
const screenSharing = (a, b) => {
|
|
4583
|
-
|
|
4583
|
+
const hasA = hasScreenShare(a);
|
|
4584
|
+
const hasB = hasScreenShare(b);
|
|
4585
|
+
if (hasA && !hasB)
|
|
4584
4586
|
return -1;
|
|
4585
|
-
if (!
|
|
4587
|
+
if (!hasA && hasB)
|
|
4586
4588
|
return 1;
|
|
4587
4589
|
return 0;
|
|
4588
4590
|
};
|
|
@@ -4593,9 +4595,11 @@ const screenSharing = (a, b) => {
|
|
|
4593
4595
|
* @param b the second participant.
|
|
4594
4596
|
*/
|
|
4595
4597
|
const publishingVideo = (a, b) => {
|
|
4596
|
-
|
|
4598
|
+
const hasA = hasVideo(a);
|
|
4599
|
+
const hasB = hasVideo(b);
|
|
4600
|
+
if (hasA && !hasB)
|
|
4597
4601
|
return -1;
|
|
4598
|
-
if (!
|
|
4602
|
+
if (!hasA && hasB)
|
|
4599
4603
|
return 1;
|
|
4600
4604
|
return 0;
|
|
4601
4605
|
};
|
|
@@ -4606,9 +4610,11 @@ const publishingVideo = (a, b) => {
|
|
|
4606
4610
|
* @param b the second participant.
|
|
4607
4611
|
*/
|
|
4608
4612
|
const publishingAudio = (a, b) => {
|
|
4609
|
-
|
|
4613
|
+
const hasA = hasAudio(a);
|
|
4614
|
+
const hasB = hasAudio(b);
|
|
4615
|
+
if (hasA && !hasB)
|
|
4610
4616
|
return -1;
|
|
4611
|
-
if (!
|
|
4617
|
+
if (!hasA && hasB)
|
|
4612
4618
|
return 1;
|
|
4613
4619
|
return 0;
|
|
4614
4620
|
};
|
|
@@ -4639,14 +4645,22 @@ const pinned = (a, b) => {
|
|
|
4639
4645
|
* A comparator creator which will set up a comparator which prioritizes
|
|
4640
4646
|
* participants who are from a specific source (e.g., WebRTC, RTMP, WHIP...).
|
|
4641
4647
|
*
|
|
4642
|
-
*
|
|
4648
|
+
* The priority of a source is determined by the order of the sources passed in.
|
|
4649
|
+
* e.g. [SRT, RTMP, WHIP] will prioritize SRT sources first, then RTMP, then WHIP.
|
|
4650
|
+
*
|
|
4651
|
+
* @param sources the sources to prioritize.
|
|
4643
4652
|
*/
|
|
4644
|
-
const withParticipantSource = (
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4653
|
+
const withParticipantSource = (...sources) => {
|
|
4654
|
+
const priority = (i) => (i === -1 ? Number.MAX_SAFE_INTEGER : i);
|
|
4655
|
+
return (a, b) => {
|
|
4656
|
+
const priorityA = priority(sources.indexOf(a.source));
|
|
4657
|
+
const priorityB = priority(sources.indexOf(b.source));
|
|
4658
|
+
if (priorityA < priorityB)
|
|
4659
|
+
return -1;
|
|
4660
|
+
if (priorityA > priorityB)
|
|
4661
|
+
return 1;
|
|
4662
|
+
return 0;
|
|
4663
|
+
};
|
|
4650
4664
|
};
|
|
4651
4665
|
/**
|
|
4652
4666
|
* A comparator creator which will set up a comparator which prioritizes
|
|
@@ -4670,9 +4684,11 @@ const reactionType = (type) => {
|
|
|
4670
4684
|
* @param roles the roles to prioritize.
|
|
4671
4685
|
*/
|
|
4672
4686
|
const role = (...roles) => (a, b) => {
|
|
4673
|
-
|
|
4687
|
+
const hasA = hasAnyRole(a, roles);
|
|
4688
|
+
const hasB = hasAnyRole(b, roles);
|
|
4689
|
+
if (hasA && !hasB)
|
|
4674
4690
|
return -1;
|
|
4675
|
-
if (!
|
|
4691
|
+
if (!hasA && hasB)
|
|
4676
4692
|
return 1;
|
|
4677
4693
|
return 0;
|
|
4678
4694
|
};
|
|
@@ -4705,6 +4721,10 @@ const ifInvisibleOrUnknownBy = conditional((a, b) => a.viewportVisibilityState?.
|
|
|
4705
4721
|
a.viewportVisibilityState?.videoTrack === VisibilityState.UNKNOWN ||
|
|
4706
4722
|
b.viewportVisibilityState?.videoTrack === VisibilityState.INVISIBLE ||
|
|
4707
4723
|
b.viewportVisibilityState?.videoTrack === VisibilityState.UNKNOWN);
|
|
4724
|
+
/**
|
|
4725
|
+
* A comparator that prioritizes participants with video ingress sources.
|
|
4726
|
+
*/
|
|
4727
|
+
const withVideoIngressSource = withParticipantSource(ParticipantSource.RTMP, ParticipantSource.SRT, ParticipantSource.WHIP, ParticipantSource.RTSP);
|
|
4708
4728
|
/**
|
|
4709
4729
|
* The default sorting preset.
|
|
4710
4730
|
*/
|
|
@@ -4712,16 +4732,16 @@ const defaultSortPreset = combineComparators(screenSharing, pinned, ifInvisibleB
|
|
|
4712
4732
|
/**
|
|
4713
4733
|
* The sorting preset for speaker layout.
|
|
4714
4734
|
*/
|
|
4715
|
-
const speakerLayoutSortPreset = combineComparators(screenSharing, pinned, dominantSpeaker, ifInvisibleBy(combineComparators(speaking, reactionType('raised-hand'), publishingVideo, publishingAudio)));
|
|
4735
|
+
const speakerLayoutSortPreset = combineComparators(screenSharing, pinned, dominantSpeaker, ifInvisibleBy(combineComparators(speaking, reactionType('raised-hand'), withVideoIngressSource, publishingVideo, publishingAudio)));
|
|
4716
4736
|
/**
|
|
4717
4737
|
* The sorting preset for layouts that don't render all participants but
|
|
4718
4738
|
* instead, render them in pages.
|
|
4719
4739
|
*/
|
|
4720
|
-
const paginatedLayoutSortPreset = combineComparators(pinned, ifInvisibleOrUnknownBy(combineComparators(dominantSpeaker, speaking, reactionType('raised-hand'), publishingVideo, publishingAudio)));
|
|
4740
|
+
const paginatedLayoutSortPreset = combineComparators(pinned, ifInvisibleOrUnknownBy(combineComparators(dominantSpeaker, speaking, reactionType('raised-hand'), withVideoIngressSource, publishingVideo, publishingAudio)));
|
|
4721
4741
|
/**
|
|
4722
4742
|
* The sorting preset for livestreams and audio rooms.
|
|
4723
4743
|
*/
|
|
4724
|
-
const livestreamOrAudioRoomSortPreset = combineComparators(ifInvisibleBy(combineComparators(dominantSpeaker, speaking, reactionType('raised-hand'),
|
|
4744
|
+
const livestreamOrAudioRoomSortPreset = combineComparators(ifInvisibleBy(combineComparators(dominantSpeaker, speaking, reactionType('raised-hand'), withVideoIngressSource, publishingVideo, publishingAudio)), role('admin', 'host', 'speaker'));
|
|
4725
4745
|
|
|
4726
4746
|
/**
|
|
4727
4747
|
* Returns the default egress object - when no egress data is available.
|
|
@@ -5833,7 +5853,7 @@ const getSdkVersion = (sdk) => {
|
|
|
5833
5853
|
return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
|
|
5834
5854
|
};
|
|
5835
5855
|
|
|
5836
|
-
const version = "1.
|
|
5856
|
+
const version = "1.34.0";
|
|
5837
5857
|
const [major, minor, patch] = version.split('.');
|
|
5838
5858
|
let sdkInfo = {
|
|
5839
5859
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -11623,13 +11643,18 @@ class SpeakerManager {
|
|
|
11623
11643
|
* @param volume a number between 0 and 1. Set it to `undefined` to use the default volume.
|
|
11624
11644
|
*/
|
|
11625
11645
|
setParticipantVolume(sessionId, volume) {
|
|
11626
|
-
if (isReactNative()) {
|
|
11627
|
-
throw new Error('This feature is not supported in React Native. Please visit https://getstream.io/video/docs/reactnative/core/camera-and-microphone/#speaker-management for more details');
|
|
11628
|
-
}
|
|
11629
11646
|
if (volume && (volume < 0 || volume > 1)) {
|
|
11630
11647
|
throw new Error('Volume must be between 0 and 1, or undefined');
|
|
11631
11648
|
}
|
|
11632
|
-
this.call.state.updateParticipant(sessionId,
|
|
11649
|
+
this.call.state.updateParticipant(sessionId, (p) => {
|
|
11650
|
+
if (isReactNative() && p.audioStream) {
|
|
11651
|
+
for (const track of p.audioStream.getAudioTracks()) {
|
|
11652
|
+
// @ts-expect-error track._setVolume is present in react-native-webrtc
|
|
11653
|
+
track?._setVolume(volume);
|
|
11654
|
+
}
|
|
11655
|
+
}
|
|
11656
|
+
return { audioVolume: volume };
|
|
11657
|
+
});
|
|
11633
11658
|
}
|
|
11634
11659
|
}
|
|
11635
11660
|
|
|
@@ -12443,6 +12468,7 @@ class Call {
|
|
|
12443
12468
|
});
|
|
12444
12469
|
}
|
|
12445
12470
|
this.tracer.setEnabled(enableTracing);
|
|
12471
|
+
this.sfuStatsReporter?.flush();
|
|
12446
12472
|
this.sfuStatsReporter?.stop();
|
|
12447
12473
|
if (statsOptions?.reporting_interval_ms > 0) {
|
|
12448
12474
|
this.sfuStatsReporter = new SfuStatsReporter(sfuClient, {
|
|
@@ -14778,7 +14804,7 @@ class StreamClient {
|
|
|
14778
14804
|
this.getUserAgent = () => {
|
|
14779
14805
|
if (!this.cachedUserAgent) {
|
|
14780
14806
|
const { clientAppIdentifier = {} } = this.options;
|
|
14781
|
-
const { sdkName = 'js', sdkVersion = "1.
|
|
14807
|
+
const { sdkName = 'js', sdkVersion = "1.34.0", ...extras } = clientAppIdentifier;
|
|
14782
14808
|
this.cachedUserAgent = [
|
|
14783
14809
|
`stream-video-${sdkName}-v${sdkVersion}`,
|
|
14784
14810
|
...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
|