@stream-io/video-client 1.28.1 → 1.30.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.30.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.29.0...@stream-io/video-client-1.30.0) (2025-09-11)
6
+
7
+ - Skip tests for StreamVideoClient coordinator API ([aabe1d0](https://github.com/GetStream/stream-video-js/commit/aabe1d0ad3e3a95698b422991729e46289ab0277))
8
+
9
+ ### Features
10
+
11
+ - Participant Source ([#1896](https://github.com/GetStream/stream-video-js/issues/1896)) ([b1cf710](https://github.com/GetStream/stream-video-js/commit/b1cf710ac3bfda573c0379dac1e6a107d2dbabf6))
12
+
13
+ ## [1.29.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.28.1...@stream-io/video-client-1.29.0) (2025-09-09)
14
+
15
+ ### Features
16
+
17
+ - opt-out from optimistic updates ([#1904](https://github.com/GetStream/stream-video-js/issues/1904)) ([45dba34](https://github.com/GetStream/stream-video-js/commit/45dba34d38dc64f456e37b593e38e420426529f5))
18
+
19
+ ### Bug Fixes
20
+
21
+ - capabilities and call grants ([#1899](https://github.com/GetStream/stream-video-js/issues/1899)) ([5725dfa](https://github.com/GetStream/stream-video-js/commit/5725dfa29b1e5fdb6fe4e26825ce7b268664d2fa))
22
+ - graceful Axios request config overrides ([#1913](https://github.com/GetStream/stream-video-js/issues/1913)) ([a124099](https://github.com/GetStream/stream-video-js/commit/a124099f984a592750d66ac440ef6c27ae7a02d9))
23
+
5
24
  ## [1.28.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.28.0...@stream-io/video-client-1.28.1) (2025-08-22)
6
25
 
7
26
  ### Bug Fixes
@@ -4,7 +4,7 @@ import { ServiceType, stackIntercept, RpcError } from '@protobuf-ts/runtime-rpc'
4
4
  import axios from 'axios';
5
5
  export { AxiosError } from 'axios';
6
6
  import { TwirpFetchTransport, TwirpErrorCode } from '@protobuf-ts/twirp-transport';
7
- import { ReplaySubject, combineLatest, BehaviorSubject, shareReplay, map, distinctUntilChanged, takeWhile, distinctUntilKeyChanged, fromEventPattern, startWith, concatMap, merge, from, fromEvent, tap, debounceTime, pairwise, of } from 'rxjs';
7
+ import { ReplaySubject, combineLatest, BehaviorSubject, shareReplay, map, distinctUntilChanged, startWith, takeWhile, distinctUntilKeyChanged, fromEventPattern, concatMap, merge, from, fromEvent, tap, debounceTime, pairwise, of } from 'rxjs';
8
8
  import { UAParser } from 'ua-parser-js';
9
9
  import { parse, write } from 'sdp-transform';
10
10
 
@@ -925,6 +925,38 @@ var TrackType;
925
925
  */
926
926
  TrackType[TrackType["SCREEN_SHARE_AUDIO"] = 4] = "SCREEN_SHARE_AUDIO";
927
927
  })(TrackType || (TrackType = {}));
928
+ /**
929
+ * must be aligned with kit
930
+ *
931
+ * @generated from protobuf enum stream.video.sfu.models.ParticipantSource
932
+ */
933
+ var ParticipantSource;
934
+ (function (ParticipantSource) {
935
+ /**
936
+ * @generated from protobuf enum value: PARTICIPANT_SOURCE_WEBRTC_UNSPECIFIED = 0;
937
+ */
938
+ ParticipantSource[ParticipantSource["WEBRTC_UNSPECIFIED"] = 0] = "WEBRTC_UNSPECIFIED";
939
+ /**
940
+ * @generated from protobuf enum value: PARTICIPANT_SOURCE_RTMP = 1;
941
+ */
942
+ ParticipantSource[ParticipantSource["RTMP"] = 1] = "RTMP";
943
+ /**
944
+ * @generated from protobuf enum value: PARTICIPANT_SOURCE_WHIP = 2;
945
+ */
946
+ ParticipantSource[ParticipantSource["WHIP"] = 2] = "WHIP";
947
+ /**
948
+ * @generated from protobuf enum value: PARTICIPANT_SOURCE_SIP = 3;
949
+ */
950
+ ParticipantSource[ParticipantSource["SIP"] = 3] = "SIP";
951
+ /**
952
+ * @generated from protobuf enum value: PARTICIPANT_SOURCE_RTSP = 4;
953
+ */
954
+ ParticipantSource[ParticipantSource["RTSP"] = 4] = "RTSP";
955
+ /**
956
+ * @generated from protobuf enum value: PARTICIPANT_SOURCE_SRT = 5;
957
+ */
958
+ ParticipantSource[ParticipantSource["SRT"] = 5] = "SRT";
959
+ })(ParticipantSource || (ParticipantSource = {}));
928
960
  /**
929
961
  * @generated from protobuf enum stream.video.sfu.models.ErrorCode
930
962
  */
@@ -1386,6 +1418,16 @@ class Participant$Type extends MessageType {
1386
1418
  repeat: 2 /*RepeatType.UNPACKED*/,
1387
1419
  T: 9 /*ScalarType.STRING*/,
1388
1420
  },
1421
+ {
1422
+ no: 14,
1423
+ name: 'source',
1424
+ kind: 'enum',
1425
+ T: () => [
1426
+ 'stream.video.sfu.models.ParticipantSource',
1427
+ ParticipantSource,
1428
+ 'PARTICIPANT_SOURCE_',
1429
+ ],
1430
+ },
1389
1431
  ]);
1390
1432
  }
1391
1433
  }
@@ -1959,6 +2001,7 @@ var models = /*#__PURE__*/Object.freeze({
1959
2001
  OS: OS,
1960
2002
  Participant: Participant,
1961
2003
  ParticipantCount: ParticipantCount,
2004
+ get ParticipantSource () { return ParticipantSource; },
1962
2005
  get PeerType () { return PeerType; },
1963
2006
  PerformanceStats: PerformanceStats,
1964
2007
  Pin: Pin,
@@ -2961,6 +3004,16 @@ class JoinRequest$Type extends MessageType {
2961
3004
  'CLIENT_CAPABILITY_',
2962
3005
  ],
2963
3006
  },
3007
+ {
3008
+ no: 12,
3009
+ name: 'source',
3010
+ kind: 'enum',
3011
+ T: () => [
3012
+ 'stream.video.sfu.models.ParticipantSource',
3013
+ ParticipantSource,
3014
+ 'PARTICIPANT_SOURCE_',
3015
+ ],
3016
+ },
2964
3017
  ]);
2965
3018
  }
2966
3019
  }
@@ -4525,6 +4578,19 @@ const pinned = (a, b) => {
4525
4578
  return 1;
4526
4579
  return 0;
4527
4580
  };
4581
+ /**
4582
+ * A comparator creator which will set up a comparator which prioritizes
4583
+ * participants who are from a specific source (e.g., WebRTC, RTMP, WHIP...).
4584
+ *
4585
+ * @param source the source to prioritize.
4586
+ */
4587
+ const withParticipantSource = (source) => (a, b) => {
4588
+ if (a.source === source && b.source !== source)
4589
+ return -1;
4590
+ if (a.source !== source && b.source === source)
4591
+ return 1;
4592
+ return 0;
4593
+ };
4528
4594
  /**
4529
4595
  * A comparator creator which will set up a comparator which prioritizes
4530
4596
  * participants who have a specific reaction.
@@ -4598,7 +4664,7 @@ const paginatedLayoutSortPreset = combineComparators(pinned, ifInvisibleOrUnknow
4598
4664
  /**
4599
4665
  * The sorting preset for livestreams and audio rooms.
4600
4666
  */
4601
- const livestreamOrAudioRoomSortPreset = combineComparators(ifInvisibleBy(combineComparators(dominantSpeaker, speaking, reactionType('raised-hand'), publishingVideo, publishingAudio)), role('admin', 'host', 'speaker'));
4667
+ const livestreamOrAudioRoomSortPreset = combineComparators(ifInvisibleBy(combineComparators(dominantSpeaker, speaking, reactionType('raised-hand'), withParticipantSource(ParticipantSource.RTMP), publishingVideo, publishingAudio)), role('admin', 'host', 'speaker'));
4602
4668
 
4603
4669
  /**
4604
4670
  * Returns the default egress object - when no egress data is available.
@@ -4649,6 +4715,7 @@ class CallState {
4649
4715
  // This happens when the participantJoined event hasn't been received yet.
4650
4716
  // We keep these tracks around until we can associate them with a participant.
4651
4717
  this.orphanedTracks = [];
4718
+ this.callGrantsSubject = new ReplaySubject(1);
4652
4719
  this.logger = getLogger(['CallState']);
4653
4720
  /**
4654
4721
  * A list of comparators that are used to sort the participants.
@@ -4776,6 +4843,15 @@ class CallState {
4776
4843
  this.setOwnCapabilities = (capabilities) => {
4777
4844
  return this.setCurrentValue(this.ownCapabilitiesSubject, capabilities);
4778
4845
  };
4846
+ /**
4847
+ * Sets the call grants (used for own capabilities).
4848
+ *
4849
+ * @internal
4850
+ * @param grants the grants to set.
4851
+ */
4852
+ this.setCallGrants = (grants) => {
4853
+ return this.setCurrentValue(this.callGrantsSubject, grants);
4854
+ };
4779
4855
  /**
4780
4856
  * Sets the backstage state.
4781
4857
  * @param backstage the backstage state.
@@ -5207,7 +5283,7 @@ class CallState {
5207
5283
  };
5208
5284
  this.updateOwnCapabilities = (event) => {
5209
5285
  if (event.user.id === this.localParticipant?.userId) {
5210
- this.setCurrentValue(this.ownCapabilitiesSubject, event.own_capabilities);
5286
+ this.setOwnCapabilities(event.own_capabilities);
5211
5287
  }
5212
5288
  };
5213
5289
  this.updateFromClosedCaptions = (event) => {
@@ -5276,25 +5352,53 @@ class CallState {
5276
5352
  const isShallowEqual = (a, b) => {
5277
5353
  if (a.length !== b.length)
5278
5354
  return false;
5279
- for (const item of a)
5355
+ for (const item of a) {
5280
5356
  if (!b.includes(item))
5281
5357
  return false;
5282
- for (const item of b)
5358
+ }
5359
+ for (const item of b) {
5283
5360
  if (!a.includes(item))
5284
5361
  return false;
5362
+ }
5285
5363
  return true;
5286
5364
  };
5287
5365
  /**
5288
5366
  * Creates an Observable from the given subject by piping to the
5289
5367
  * `distinctUntilChanged()` operator.
5290
5368
  */
5291
- const duc = (subject, comparator) => subject.asObservable().pipe(distinctUntilChanged(comparator));
5369
+ const duc = (subject, comparator) => subject.pipe(distinctUntilChanged(comparator));
5292
5370
  // primitive values should only emit once the value they hold changes
5293
5371
  this.anonymousParticipantCount$ = duc(this.anonymousParticipantCountSubject);
5294
5372
  this.blockedUserIds$ = duc(this.blockedUserIdsSubject, isShallowEqual);
5295
5373
  this.backstage$ = duc(this.backstageSubject);
5296
5374
  this.callingState$ = duc(this.callingStateSubject);
5297
- this.ownCapabilities$ = duc(this.ownCapabilitiesSubject, isShallowEqual);
5375
+ this.ownCapabilities$ = combineLatest([
5376
+ this.ownCapabilitiesSubject,
5377
+ this.callGrantsSubject.pipe(startWith(undefined)),
5378
+ ]).pipe(map(([capabilities, grants]) => {
5379
+ if (!grants)
5380
+ return capabilities;
5381
+ const { canPublishAudio, canPublishVideo, canScreenshare } = grants;
5382
+ const update = {
5383
+ [OwnCapability.SEND_AUDIO]: canPublishAudio,
5384
+ [OwnCapability.SEND_VIDEO]: canPublishVideo,
5385
+ [OwnCapability.SCREENSHARE]: canScreenshare,
5386
+ };
5387
+ const nextCapabilities = [...capabilities];
5388
+ for (const _capability in update) {
5389
+ const capability = _capability;
5390
+ const allowed = update[capability];
5391
+ // grants take precedence over capabilities, reconstruct the capabilities
5392
+ if (allowed && !nextCapabilities.includes(capability)) {
5393
+ nextCapabilities.push(capability);
5394
+ }
5395
+ else if (!allowed && nextCapabilities.includes(capability)) {
5396
+ const index = nextCapabilities.indexOf(capability);
5397
+ nextCapabilities.splice(index, 1);
5398
+ }
5399
+ }
5400
+ return nextCapabilities;
5401
+ }), distinctUntilChanged(isShallowEqual), shareReplay({ bufferSize: 1, refCount: true }));
5298
5402
  this.participantCount$ = duc(this.participantCountSubject);
5299
5403
  this.recording$ = duc(this.recordingSubject);
5300
5404
  this.transcribing$ = duc(this.transcribingSubject);
@@ -5653,7 +5757,7 @@ const getSdkVersion = (sdk) => {
5653
5757
  return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
5654
5758
  };
5655
5759
 
5656
- const version = "1.28.1";
5760
+ const version = "1.30.0";
5657
5761
  const [major, minor, patch] = version.split('.');
5658
5762
  let sdkInfo = {
5659
5763
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -8387,21 +8491,9 @@ const watchSfuCallEnded = (call) => {
8387
8491
  const watchCallGrantsUpdated = (state) => {
8388
8492
  return function onCallGrantsUpdated(event) {
8389
8493
  const { currentGrants } = event;
8390
- if (currentGrants) {
8391
- const { canPublishAudio, canPublishVideo, canScreenshare } = currentGrants;
8392
- const update = {
8393
- [OwnCapability.SEND_AUDIO]: canPublishAudio,
8394
- [OwnCapability.SEND_VIDEO]: canPublishVideo,
8395
- [OwnCapability.SCREENSHARE]: canScreenshare,
8396
- };
8397
- const nextCapabilities = state.ownCapabilities.filter((capability) => update[capability] !== false);
8398
- Object.entries(update).forEach(([capability, value]) => {
8399
- if (value && !nextCapabilities.includes(capability)) {
8400
- nextCapabilities.push(capability);
8401
- }
8402
- });
8403
- state.setOwnCapabilities(nextCapabilities);
8404
- }
8494
+ if (!currentGrants)
8495
+ return;
8496
+ state.setCallGrants(currentGrants);
8405
8497
  };
8406
8498
  };
8407
8499
 
@@ -9996,11 +10088,10 @@ class InputMediaDeviceManager {
9996
10088
  }
9997
10089
  });
9998
10090
  }
9999
- /**
10000
- * Stops or pauses the stream based on state.disableMode
10001
- * @param {boolean} [forceStop=false] when true, stops the tracks regardless of the state.disableMode
10002
- */
10003
- async disable(forceStop = false) {
10091
+ async disable(forceStopOrOptions) {
10092
+ const forceStop = typeof forceStopOrOptions === 'boolean'
10093
+ ? forceStopOrOptions
10094
+ : (forceStopOrOptions?.forceStop ?? false);
10004
10095
  this.state.prevStatus = this.state.optimisticStatus;
10005
10096
  if (!forceStop && this.state.optimisticStatus === 'disabled') {
10006
10097
  return;
@@ -12020,6 +12111,7 @@ class Call {
12020
12111
  preferredPublishOptions,
12021
12112
  preferredSubscribeOptions,
12022
12113
  capabilities: Array.from(this.clientCapabilities),
12114
+ source: ParticipantSource.WEBRTC_UNSPECIFIED,
12023
12115
  });
12024
12116
  this.currentPublishOptions = publishOptions;
12025
12117
  this.fastReconnectDeadlineSeconds = fastReconnectDeadlineSeconds;
@@ -14569,7 +14661,7 @@ class StreamClient {
14569
14661
  this.getUserAgent = () => {
14570
14662
  if (!this.cachedUserAgent) {
14571
14663
  const { clientAppIdentifier = {} } = this.options;
14572
- const { sdkName = 'js', sdkVersion = "1.28.1", ...extras } = clientAppIdentifier;
14664
+ const { sdkName = 'js', sdkVersion = "1.30.0", ...extras } = clientAppIdentifier;
14573
14665
  this.cachedUserAgent = [
14574
14666
  `stream-video-${sdkName}-v${sdkVersion}`,
14575
14667
  ...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
@@ -14591,12 +14683,14 @@ class StreamClient {
14591
14683
  'x-client-request-id': generateUUIDv4(),
14592
14684
  };
14593
14685
  }
14686
+ const { params: axiosConfigParams, headers: axiosConfigHeaders, ...axiosRequestConfig } = this.options.axiosRequestConfig || {};
14594
14687
  return {
14595
14688
  params: {
14596
14689
  user_id: this.userID,
14597
14690
  connection_id: this._getConnectionID(),
14598
14691
  api_key: this.key,
14599
14692
  ...options.params,
14693
+ ...axiosConfigParams,
14600
14694
  },
14601
14695
  headers: {
14602
14696
  ...authorization,
@@ -14605,9 +14699,10 @@ class StreamClient {
14605
14699
  : this.getAuthType(),
14606
14700
  'X-Stream-Client': this.getUserAgent(),
14607
14701
  ...options.headers,
14702
+ ...axiosConfigHeaders,
14608
14703
  },
14609
14704
  ...options.config,
14610
- ...this.options.axiosRequestConfig,
14705
+ ...axiosRequestConfig,
14611
14706
  };
14612
14707
  };
14613
14708
  this._getToken = () => {
@@ -15134,5 +15229,5 @@ class StreamVideoClient {
15134
15229
  }
15135
15230
  StreamVideoClient._instances = new Map();
15136
15231
 
15137
- export { AudioSettingsRequestDefaultDeviceEnum, AudioSettingsResponseDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, CreateDeviceRequestPushProviderEnum, DebounceType, DynascaleManager, ErrorFromResponse, FrameRecordingSettingsRequestModeEnum, FrameRecordingSettingsRequestQualityEnum, FrameRecordingSettingsResponseModeEnum, IngressAudioEncodingOptionsRequestChannelsEnum, IngressVideoLayerRequestCodecEnum, InputMediaDeviceManager, InputMediaDeviceManagerState, LayoutSettingsRequestNameEnum, MicrophoneManager, MicrophoneManagerState, NoiseCancellationSettingsModeEnum, OwnCapability, RNSpeechDetector, RTMPBroadcastRequestQualityEnum, RTMPSettingsRequestQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, StartClosedCaptionsRequestLanguageEnum, StartTranscriptionRequestLanguageEnum, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsRequestClosedCaptionModeEnum, TranscriptionSettingsRequestLanguageEnum, TranscriptionSettingsRequestModeEnum, TranscriptionSettingsResponseClosedCaptionModeEnum, TranscriptionSettingsResponseLanguageEnum, TranscriptionSettingsResponseModeEnum, VideoSettingsRequestCameraFacingEnum, VideoSettingsResponseCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, deviceIds$, disposeOfMediaStream, dominantSpeaker, getAudioBrowserPermission, getAudioDevices, getAudioOutputDevices, getAudioStream, getClientDetails, getDeviceState, getLogLevel, getLogger, getScreenShareStream, getSdkInfo, getVideoBrowserPermission, getVideoDevices, getVideoStream, getWebRTCInfo, hasAudio, hasPausedTrack, hasScreenShare, hasScreenShareAudio, hasVideo, isPinned, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, paginatedLayoutSortPreset, pinned, publishingAudio, publishingVideo, reactionType, resolveDeviceId, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setPowerState, setSdkInfo, setThermalState, setWebRTCInfo, speakerLayoutSortPreset, speaking };
15232
+ export { AudioSettingsRequestDefaultDeviceEnum, AudioSettingsResponseDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, CreateDeviceRequestPushProviderEnum, DebounceType, DynascaleManager, ErrorFromResponse, FrameRecordingSettingsRequestModeEnum, FrameRecordingSettingsRequestQualityEnum, FrameRecordingSettingsResponseModeEnum, IngressAudioEncodingOptionsRequestChannelsEnum, IngressVideoLayerRequestCodecEnum, InputMediaDeviceManager, InputMediaDeviceManagerState, LayoutSettingsRequestNameEnum, MicrophoneManager, MicrophoneManagerState, NoiseCancellationSettingsModeEnum, OwnCapability, RNSpeechDetector, RTMPBroadcastRequestQualityEnum, RTMPSettingsRequestQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, StartClosedCaptionsRequestLanguageEnum, StartTranscriptionRequestLanguageEnum, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsRequestClosedCaptionModeEnum, TranscriptionSettingsRequestLanguageEnum, TranscriptionSettingsRequestModeEnum, TranscriptionSettingsResponseClosedCaptionModeEnum, TranscriptionSettingsResponseLanguageEnum, TranscriptionSettingsResponseModeEnum, VideoSettingsRequestCameraFacingEnum, VideoSettingsResponseCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, deviceIds$, disposeOfMediaStream, dominantSpeaker, getAudioBrowserPermission, getAudioDevices, getAudioOutputDevices, getAudioStream, getClientDetails, getDeviceState, getLogLevel, getLogger, getScreenShareStream, getSdkInfo, getVideoBrowserPermission, getVideoDevices, getVideoStream, getWebRTCInfo, hasAudio, hasPausedTrack, hasScreenShare, hasScreenShareAudio, hasVideo, isPinned, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, paginatedLayoutSortPreset, pinned, publishingAudio, publishingVideo, reactionType, resolveDeviceId, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setPowerState, setSdkInfo, setThermalState, setWebRTCInfo, speakerLayoutSortPreset, speaking, withParticipantSource };
15138
15233
  //# sourceMappingURL=index.browser.es.js.map