@stream-io/video-client 1.16.1 → 1.16.3

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.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
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * relaxed validation for submitting feedback ([#1673](https://github.com/GetStream/stream-video-js/issues/1673)) ([98685b9](https://github.com/GetStream/stream-video-js/commit/98685b9fcf3c3b0309a7072d51cde4657e028528))
11
+
12
+ ## [1.16.2](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.16.1...@stream-io/video-client-1.16.2) (2025-02-05)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * race condition with unrecoverable error handling ([#1672](https://github.com/GetStream/stream-video-js/issues/1672)) ([be8095c](https://github.com/GetStream/stream-video-js/commit/be8095ce946cf98a0dfc1f3ea3391376cc7d2896)), closes [#1649](https://github.com/GetStream/stream-video-js/issues/1649) [#1618](https://github.com/GetStream/stream-video-js/issues/1618)
18
+
5
19
  ## [1.16.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.16.0...@stream-io/video-client-1.16.1) (2025-02-05)
6
20
 
7
21
 
@@ -31,6 +31,22 @@ const CreateDeviceRequestPushProviderEnum = {
31
31
  HUAWEI: 'huawei',
32
32
  XIAOMI: 'xiaomi',
33
33
  };
34
+ /**
35
+ * @export
36
+ */
37
+ const FrameRecordingSettingsRequestModeEnum = {
38
+ AVAILABLE: 'available',
39
+ DISABLED: 'disabled',
40
+ AUTO_ON: 'auto-on',
41
+ };
42
+ /**
43
+ * @export
44
+ */
45
+ const FrameRecordingSettingsResponseModeEnum = {
46
+ AVAILABLE: 'available',
47
+ DISABLED: 'disabled',
48
+ AUTO_ON: 'auto-on',
49
+ };
34
50
  /**
35
51
  * @export
36
52
  */
@@ -72,10 +88,12 @@ const OwnCapability = {
72
88
  SEND_VIDEO: 'send-video',
73
89
  START_BROADCAST_CALL: 'start-broadcast-call',
74
90
  START_CLOSED_CAPTIONS_CALL: 'start-closed-captions-call',
91
+ START_FRAME_RECORD_CALL: 'start-frame-record-call',
75
92
  START_RECORD_CALL: 'start-record-call',
76
93
  START_TRANSCRIPTION_CALL: 'start-transcription-call',
77
94
  STOP_BROADCAST_CALL: 'stop-broadcast-call',
78
95
  STOP_CLOSED_CAPTIONS_CALL: 'stop-closed-captions-call',
96
+ STOP_FRAME_RECORD_CALL: 'stop-frame-record-call',
79
97
  STOP_RECORD_CALL: 'stop-record-call',
80
98
  STOP_TRANSCRIPTION_CALL: 'stop-transcription-call',
81
99
  UPDATE_CALL: 'update-call',
@@ -5183,11 +5201,14 @@ class BasePeerConnection {
5183
5201
  */
5184
5202
  constructor(peerType, { sfuClient, connectionConfig, state, dispatcher, onUnrecoverableError, logTag, }) {
5185
5203
  this.isIceRestarting = false;
5204
+ this.isDisposed = false;
5186
5205
  this.subscriptions = [];
5187
5206
  /**
5188
5207
  * Disposes the `RTCPeerConnection` instance.
5189
5208
  */
5190
5209
  this.dispose = () => {
5210
+ this.onUnrecoverableError = undefined;
5211
+ this.isDisposed = true;
5191
5212
  this.detachEventHandlers();
5192
5213
  this.pc.close();
5193
5214
  };
@@ -5198,6 +5219,8 @@ class BasePeerConnection {
5198
5219
  this.on = (event, fn) => {
5199
5220
  this.subscriptions.push(this.dispatcher.on(event, (e) => {
5200
5221
  withoutConcurrency(`pc.${event}`, async () => fn(e)).catch((err) => {
5222
+ if (this.isDisposed)
5223
+ return;
5201
5224
  this.logger('warn', `Error handling ${event}`, err);
5202
5225
  });
5203
5226
  }));
@@ -5213,6 +5236,8 @@ class BasePeerConnection {
5213
5236
  this.unsubscribeIceTrickle?.();
5214
5237
  this.unsubscribeIceTrickle = createSafeAsyncSubscription(observable, async (candidate) => {
5215
5238
  return this.pc.addIceCandidate(candidate).catch((e) => {
5239
+ if (this.isDisposed)
5240
+ return;
5216
5241
  this.logger('warn', `ICE candidate error`, e, candidate);
5217
5242
  });
5218
5243
  });
@@ -5245,7 +5270,11 @@ class BasePeerConnection {
5245
5270
  const iceCandidate = this.toJSON(candidate);
5246
5271
  this.sfuClient
5247
5272
  .iceTrickle({ peerType: this.peerType, iceCandidate })
5248
- .catch((err) => this.logger('warn', `ICETrickle failed`, err));
5273
+ .catch((err) => {
5274
+ if (this.isDisposed)
5275
+ return;
5276
+ this.logger('warn', `ICETrickle failed`, err);
5277
+ });
5249
5278
  };
5250
5279
  /**
5251
5280
  * Converts the ICE candidate to a JSON string.
@@ -5274,6 +5303,8 @@ class BasePeerConnection {
5274
5303
  if (state === 'failed' || state === 'disconnected') {
5275
5304
  this.logger('debug', `Attempting to restart ICE`);
5276
5305
  this.restartIce().catch((e) => {
5306
+ if (this.isDisposed)
5307
+ return;
5277
5308
  this.logger('error', `ICE restart failed`, e);
5278
5309
  this.onUnrecoverableError?.();
5279
5310
  });
@@ -5325,6 +5356,8 @@ class BasePeerConnection {
5325
5356
  this.pc.removeEventListener('icecandidateerror', this.onIceCandidateError);
5326
5357
  this.pc.removeEventListener('signalingstatechange', this.onSignalingChange);
5327
5358
  this.pc.removeEventListener('iceconnectionstatechange', this.onIceConnectionStateChange);
5359
+ // cancel any ongoing ICE restart process
5360
+ withCancellation('onIceConnectionStateChange', () => Promise.resolve());
5328
5361
  this.pc.removeEventListener('icegatheringstatechange', this.onIceGatherChange);
5329
5362
  this.unsubscribeIceTrickle?.();
5330
5363
  this.subscriptions.forEach((unsubscribe) => unsubscribe());
@@ -5840,10 +5873,12 @@ class Publisher extends BasePeerConnection {
5840
5873
  await this.negotiate({ iceRestart: true });
5841
5874
  };
5842
5875
  this.onNegotiationNeeded = () => {
5843
- withoutConcurrency('publisher.negotiate', () => this.negotiate()).catch((err) => {
5876
+ withCancellation('publisher.negotiate', (signal) => this.negotiate().catch((err) => {
5877
+ if (signal.aborted)
5878
+ return;
5844
5879
  this.logger('error', `Negotiation failed.`, err);
5845
5880
  this.onUnrecoverableError?.();
5846
- });
5881
+ }));
5847
5882
  };
5848
5883
  /**
5849
5884
  * Initiates a new offer/answer exchange with the currently connected SFU.
@@ -5970,6 +6005,8 @@ class Publisher extends BasePeerConnection {
5970
6005
  detachEventHandlers() {
5971
6006
  super.detachEventHandlers();
5972
6007
  this.pc.removeEventListener('negotiationneeded', this.onNegotiationNeeded);
6008
+ // abort any ongoing negotiation
6009
+ withCancellation('publisher.negotiate', () => Promise.resolve());
5973
6010
  }
5974
6011
  }
5975
6012
 
@@ -7394,7 +7431,7 @@ const aggregate = (stats) => {
7394
7431
  return report;
7395
7432
  };
7396
7433
 
7397
- const version = "1.16.1";
7434
+ const version = "1.16.3";
7398
7435
  const [major, minor, patch] = version.split('.');
7399
7436
  let sdkInfo = {
7400
7437
  type: SdkType.PLAIN_JAVASCRIPT,
@@ -11521,6 +11558,19 @@ class Call {
11521
11558
  this.stopRTMPBroadcast = async (name) => {
11522
11559
  return this.streamClient.post(`${this.streamClientBasePath}/rtmp_broadcasts/${name}/stop`);
11523
11560
  };
11561
+ /**
11562
+ * Starts frame by frame recording.
11563
+ * Sends call.frame_recording_started events
11564
+ */
11565
+ this.startFrameRecording = async (data) => {
11566
+ return this.streamClient.post(`${this.streamClientBasePath}/start_frame_recording`, data);
11567
+ };
11568
+ /**
11569
+ * Stops frame recording.
11570
+ */
11571
+ this.stopFrameRecording = async () => {
11572
+ return this.streamClient.post(`${this.streamClientBasePath}/stop_frame_recording`);
11573
+ };
11524
11574
  /**
11525
11575
  * Updates the call settings or custom data.
11526
11576
  *
@@ -11678,25 +11728,13 @@ class Call {
11678
11728
  * @param rating Rating between 1 and 5 denoting the experience of the user in the call
11679
11729
  * @param reason The reason/description for the rating
11680
11730
  * @param custom Custom data
11681
- * @returns
11682
11731
  */
11683
11732
  this.submitFeedback = async (rating, { reason, custom, } = {}) => {
11684
- if (rating < 1 || rating > 5) {
11685
- throw new Error('Rating must be between 1 and 5');
11686
- }
11687
- const callSessionId = this.state.session?.id;
11688
- if (!callSessionId) {
11689
- throw new Error('Feedback can be submitted only in the context of a call session');
11690
- }
11691
11733
  const { sdkName, sdkVersion, ...platform } = getSdkSignature(getClientDetails());
11692
- // user sessionId is not available once the call has been left
11693
- // until we relax the backend validation, we'll send N/A
11694
- const userSessionId = this.sfuClient?.sessionId ?? 'N/A';
11695
- const endpoint = `${this.streamClientBasePath}/feedback/${callSessionId}`;
11696
- return this.streamClient.post(endpoint, {
11734
+ return this.streamClient.post(`${this.streamClientBasePath}/feedback`, {
11697
11735
  rating,
11698
11736
  reason,
11699
- user_session_id: userSessionId,
11737
+ user_session_id: this.sfuClient?.sessionId,
11700
11738
  sdk: sdkName,
11701
11739
  sdk_version: sdkVersion,
11702
11740
  custom: {
@@ -13001,7 +13039,7 @@ class StreamClient {
13001
13039
  return await this.wsConnection.connect(this.defaultWSTimeout);
13002
13040
  };
13003
13041
  this.getUserAgent = () => {
13004
- const version = "1.16.1";
13042
+ const version = "1.16.3";
13005
13043
  return (this.userAgent ||
13006
13044
  `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
13007
13045
  };
@@ -13510,5 +13548,5 @@ class StreamVideoClient {
13510
13548
  }
13511
13549
  StreamVideoClient._instanceMap = new Map();
13512
13550
 
13513
- export { AudioSettingsRequestDefaultDeviceEnum, AudioSettingsResponseDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, CreateDeviceRequestPushProviderEnum, DebounceType, DynascaleManager, ErrorFromResponse, InputMediaDeviceManager, InputMediaDeviceManagerState, LayoutSettingsRequestNameEnum, MicrophoneManager, MicrophoneManagerState, NoiseCancellationSettingsModeEnum, OwnCapability, RTMPBroadcastRequestQualityEnum, RTMPSettingsRequestQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, 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, getDeviceInfo, getDeviceState, getLogLevel, getLogger, getOSInfo, getScreenShareStream, getSdkInfo, getVideoBrowserPermission, getVideoDevices, getVideoStream, getWebRTCInfo, hasAudio, hasScreenShare, hasScreenShareAudio, hasVideo, isPinned, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, paginatedLayoutSortPreset, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setPowerState, setSdkInfo, setThermalState, setWebRTCInfo, speakerLayoutSortPreset, speaking };
13551
+ export { AudioSettingsRequestDefaultDeviceEnum, AudioSettingsResponseDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, CreateDeviceRequestPushProviderEnum, DebounceType, DynascaleManager, ErrorFromResponse, FrameRecordingSettingsRequestModeEnum, FrameRecordingSettingsResponseModeEnum, InputMediaDeviceManager, InputMediaDeviceManagerState, LayoutSettingsRequestNameEnum, MicrophoneManager, MicrophoneManagerState, NoiseCancellationSettingsModeEnum, OwnCapability, RTMPBroadcastRequestQualityEnum, RTMPSettingsRequestQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, 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, getDeviceInfo, getDeviceState, getLogLevel, getLogger, getOSInfo, getScreenShareStream, getSdkInfo, getVideoBrowserPermission, getVideoDevices, getVideoStream, getWebRTCInfo, hasAudio, hasScreenShare, hasScreenShareAudio, hasVideo, isPinned, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, paginatedLayoutSortPreset, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setPowerState, setSdkInfo, setThermalState, setWebRTCInfo, speakerLayoutSortPreset, speaking };
13514
13552
  //# sourceMappingURL=index.browser.es.js.map