@stream-io/video-client 1.33.0 → 1.33.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.
@@ -47,9 +47,12 @@ export declare const pinned: Comparator<StreamVideoParticipant>;
47
47
  * A comparator creator which will set up a comparator which prioritizes
48
48
  * participants who are from a specific source (e.g., WebRTC, RTMP, WHIP...).
49
49
  *
50
- * @param source the source to prioritize.
50
+ * The priority of a source is determined by the order of the sources passed in.
51
+ * e.g. [SRT, RTMP, WHIP] will prioritize SRT sources first, then RTMP, then WHIP.
52
+ *
53
+ * @param sources the sources to prioritize.
51
54
  */
52
- export declare const withParticipantSource: (source: ParticipantSource) => Comparator<StreamVideoParticipant>;
55
+ export declare const withParticipantSource: (...sources: ParticipantSource[]) => Comparator<StreamVideoParticipant>;
53
56
  /**
54
57
  * A comparator creator which will set up a comparator which prioritizes
55
58
  * participants who have a specific reaction.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/video-client",
3
- "version": "1.33.0",
3
+ "version": "1.33.1",
4
4
  "main": "dist/index.cjs.js",
5
5
  "module": "dist/index.es.js",
6
6
  "browser": "dist/index.browser.es.js",
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, it } from 'vitest';
2
+ import { ParticipantSource } from '../../gen/video/sfu/models/models';
2
3
  import {
3
4
  combineComparators,
4
5
  Comparator,
@@ -8,6 +9,7 @@ import {
8
9
  publishingAudio,
9
10
  publishingVideo,
10
11
  screenSharing,
12
+ withParticipantSource,
11
13
  } from '../index';
12
14
  import * as TestData from './participant-data';
13
15
 
@@ -43,4 +45,108 @@ describe('Sorting', () => {
43
45
  const disableComparator = conditional<number>(() => false);
44
46
  expect([...input].sort(disableComparator(byValue))).toEqual([2, 3, 1]);
45
47
  });
48
+
49
+ it('withParticipantSource', () => {
50
+ expect(
51
+ withParticipantSource(ParticipantSource.SRT)(
52
+ // @ts-expect-error incomplete data
53
+ { source: ParticipantSource.WEBRTC_UNSPECIFIED }, // -1
54
+ { source: ParticipantSource.SRT }, // 0
55
+ ),
56
+ ).toEqual(1);
57
+ expect(
58
+ withParticipantSource(ParticipantSource.RTMP)(
59
+ // @ts-expect-error incomplete data
60
+ { source: ParticipantSource.WEBRTC_UNSPECIFIED },
61
+ { source: ParticipantSource.SIP },
62
+ ),
63
+ ).toEqual(0);
64
+ expect(
65
+ withParticipantSource(ParticipantSource.RTMP)(
66
+ // @ts-expect-error incomplete data
67
+ { source: ParticipantSource.RTMP },
68
+ { source: ParticipantSource.SIP },
69
+ ),
70
+ ).toEqual(-1);
71
+ expect(
72
+ withParticipantSource(ParticipantSource.RTMP)(
73
+ // @ts-expect-error incomplete data
74
+ { source: ParticipantSource.SIP },
75
+ { source: ParticipantSource.RTMP },
76
+ ),
77
+ ).toEqual(1);
78
+ expect(
79
+ withParticipantSource(ParticipantSource.RTMP)(
80
+ // @ts-expect-error incomplete data
81
+ { source: ParticipantSource.WEBRTC_UNSPECIFIED },
82
+ { source: ParticipantSource.RTMP },
83
+ ),
84
+ ).toEqual(1);
85
+
86
+ expect(
87
+ withParticipantSource(ParticipantSource.SRT, ParticipantSource.RTMP)(
88
+ // @ts-expect-error incomplete data
89
+ { source: ParticipantSource.RTMP },
90
+ { source: ParticipantSource.SRT },
91
+ ),
92
+ ).toEqual(1);
93
+
94
+ expect(
95
+ withParticipantSource(ParticipantSource.RTMP, ParticipantSource.SRT)(
96
+ // @ts-expect-error incomplete data
97
+ { source: ParticipantSource.RTMP },
98
+ { source: ParticipantSource.SRT },
99
+ ),
100
+ ).toEqual(-1);
101
+ expect(
102
+ withParticipantSource(ParticipantSource.RTMP, ParticipantSource.SRT)(
103
+ // @ts-expect-error incomplete data
104
+ { source: ParticipantSource.WHIP },
105
+ { source: ParticipantSource.SRT },
106
+ ),
107
+ ).toEqual(1);
108
+
109
+ expect(
110
+ withParticipantSource(
111
+ ParticipantSource.WHIP,
112
+ ParticipantSource.RTMP,
113
+ ParticipantSource.SRT,
114
+ )(
115
+ // @ts-expect-error incomplete data
116
+ { source: ParticipantSource.WHIP },
117
+ { source: ParticipantSource.SRT },
118
+ ),
119
+ ).toEqual(-1);
120
+ });
121
+
122
+ it('withParticipantSources with multiple participants', () => {
123
+ const participants = [
124
+ { source: ParticipantSource.WEBRTC_UNSPECIFIED },
125
+ { source: ParticipantSource.SRT },
126
+ { source: ParticipantSource.RTMP },
127
+ { source: ParticipantSource.SIP },
128
+ { source: ParticipantSource.RTSP },
129
+ { source: ParticipantSource.WHIP },
130
+ ];
131
+
132
+ const sorted = [...participants].sort(
133
+ withParticipantSource(
134
+ ParticipantSource.RTMP,
135
+ ParticipantSource.SRT,
136
+ ParticipantSource.WHIP,
137
+ ParticipantSource.RTSP,
138
+ ParticipantSource.SIP,
139
+ ParticipantSource.WEBRTC_UNSPECIFIED,
140
+ ),
141
+ );
142
+
143
+ expect(sorted).toEqual([
144
+ { source: ParticipantSource.RTMP },
145
+ { source: ParticipantSource.SRT },
146
+ { source: ParticipantSource.WHIP },
147
+ { source: ParticipantSource.RTSP },
148
+ { source: ParticipantSource.SIP },
149
+ { source: ParticipantSource.WEBRTC_UNSPECIFIED },
150
+ ]);
151
+ });
46
152
  });
@@ -38,8 +38,10 @@ export const speaking: Comparator<StreamVideoParticipant> = (a, b) => {
38
38
  * @param b the second participant.
39
39
  */
40
40
  export const screenSharing: Comparator<StreamVideoParticipant> = (a, b) => {
41
- if (hasScreenShare(a) && !hasScreenShare(b)) return -1;
42
- if (!hasScreenShare(a) && hasScreenShare(b)) return 1;
41
+ const hasA = hasScreenShare(a);
42
+ const hasB = hasScreenShare(b);
43
+ if (hasA && !hasB) return -1;
44
+ if (!hasA && hasB) return 1;
43
45
  return 0;
44
46
  };
45
47
 
@@ -50,8 +52,10 @@ export const screenSharing: Comparator<StreamVideoParticipant> = (a, b) => {
50
52
  * @param b the second participant.
51
53
  */
52
54
  export const publishingVideo: Comparator<StreamVideoParticipant> = (a, b) => {
53
- if (hasVideo(a) && !hasVideo(b)) return -1;
54
- if (!hasVideo(a) && hasVideo(b)) return 1;
55
+ const hasA = hasVideo(a);
56
+ const hasB = hasVideo(b);
57
+ if (hasA && !hasB) return -1;
58
+ if (!hasA && hasB) return 1;
55
59
  return 0;
56
60
  };
57
61
 
@@ -62,8 +66,10 @@ export const publishingVideo: Comparator<StreamVideoParticipant> = (a, b) => {
62
66
  * @param b the second participant.
63
67
  */
64
68
  export const publishingAudio: Comparator<StreamVideoParticipant> = (a, b) => {
65
- if (hasAudio(a) && !hasAudio(b)) return -1;
66
- if (!hasAudio(a) && hasAudio(b)) return 1;
69
+ const hasA = hasAudio(a);
70
+ const hasB = hasAudio(b);
71
+ if (hasA && !hasB) return -1;
72
+ if (!hasA && hasB) return 1;
67
73
  return 0;
68
74
  };
69
75
 
@@ -91,15 +97,23 @@ export const pinned: Comparator<StreamVideoParticipant> = (a, b) => {
91
97
  * A comparator creator which will set up a comparator which prioritizes
92
98
  * participants who are from a specific source (e.g., WebRTC, RTMP, WHIP...).
93
99
  *
94
- * @param source the source to prioritize.
100
+ * The priority of a source is determined by the order of the sources passed in.
101
+ * e.g. [SRT, RTMP, WHIP] will prioritize SRT sources first, then RTMP, then WHIP.
102
+ *
103
+ * @param sources the sources to prioritize.
95
104
  */
96
- export const withParticipantSource =
97
- (source: ParticipantSource): Comparator<StreamVideoParticipant> =>
98
- (a, b) => {
99
- if (a.source === source && b.source !== source) return -1;
100
- if (a.source !== source && b.source === source) return 1;
105
+ export const withParticipantSource = (
106
+ ...sources: ParticipantSource[]
107
+ ): Comparator<StreamVideoParticipant> => {
108
+ const priority = (i: number) => (i === -1 ? Number.MAX_SAFE_INTEGER : i);
109
+ return (a, b) => {
110
+ const priorityA = priority(sources.indexOf(a.source));
111
+ const priorityB = priority(sources.indexOf(b.source));
112
+ if (priorityA < priorityB) return -1;
113
+ if (priorityA > priorityB) return 1;
101
114
  return 0;
102
115
  };
116
+ };
103
117
 
104
118
  /**
105
119
  * A comparator creator which will set up a comparator which prioritizes
@@ -126,8 +140,10 @@ export const reactionType = (
126
140
  export const role =
127
141
  (...roles: string[]): Comparator<StreamVideoParticipant> =>
128
142
  (a, b) => {
129
- if (hasAnyRole(a, roles) && !hasAnyRole(b, roles)) return -1;
130
- if (!hasAnyRole(a, roles) && hasAnyRole(b, roles)) return 1;
143
+ const hasA = hasAnyRole(a, roles);
144
+ const hasB = hasAnyRole(b, roles);
145
+ if (hasA && !hasB) return -1;
146
+ if (!hasA && hasB) return 1;
131
147
  return 0;
132
148
  };
133
149
 
@@ -1,6 +1,6 @@
1
- import { ParticipantSource } from '../gen/video/sfu/models/models';
2
1
  import { StreamVideoParticipant, VisibilityState } from '../types';
3
2
  import { combineComparators, conditional } from './comparator';
3
+ import { ParticipantSource } from '../gen/video/sfu/models/models';
4
4
  import {
5
5
  dominantSpeaker,
6
6
  pinned,
@@ -35,6 +35,16 @@ const ifInvisibleOrUnknownBy = conditional(
35
35
  b.viewportVisibilityState?.videoTrack === VisibilityState.UNKNOWN,
36
36
  );
37
37
 
38
+ /**
39
+ * A comparator that prioritizes participants with video ingress sources.
40
+ */
41
+ const withVideoIngressSource = withParticipantSource(
42
+ ParticipantSource.RTMP,
43
+ ParticipantSource.SRT,
44
+ ParticipantSource.WHIP,
45
+ ParticipantSource.RTSP,
46
+ );
47
+
38
48
  /**
39
49
  * The default sorting preset.
40
50
  */
@@ -63,6 +73,7 @@ export const speakerLayoutSortPreset = combineComparators(
63
73
  combineComparators(
64
74
  speaking,
65
75
  reactionType('raised-hand'),
76
+ withVideoIngressSource,
66
77
  publishingVideo,
67
78
  publishingAudio,
68
79
  ),
@@ -80,6 +91,7 @@ export const paginatedLayoutSortPreset = combineComparators(
80
91
  dominantSpeaker,
81
92
  speaking,
82
93
  reactionType('raised-hand'),
94
+ withVideoIngressSource,
83
95
  publishingVideo,
84
96
  publishingAudio,
85
97
  ),
@@ -95,7 +107,7 @@ export const livestreamOrAudioRoomSortPreset = combineComparators(
95
107
  dominantSpeaker,
96
108
  speaking,
97
109
  reactionType('raised-hand'),
98
- withParticipantSource(ParticipantSource.RTMP),
110
+ withVideoIngressSource,
99
111
  publishingVideo,
100
112
  publishingAudio,
101
113
  ),