@stream-io/video-client 0.3.36 → 0.4.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ### [0.4.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-0.4.0...@stream-io/video-client-0.4.1) (2023-10-30)
6
+
7
+
8
+ ### Features
9
+
10
+ * Apply device config settings when call state becomes available ([#1167](https://github.com/GetStream/stream-video-js/issues/1167)) ([38e8ba4](https://github.com/GetStream/stream-video-js/commit/38e8ba459b60d9705af96ad7b9a2a7fa1827ad1e))
11
+
12
+ ## [0.4.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-0.3.36...@stream-io/video-client-0.4.0) (2023-10-27)
13
+
14
+
15
+ ### ⚠ BREAKING CHANGES
16
+
17
+ * **react-sdk:** Universal Device Management API (#1127)
18
+
19
+ ### Features
20
+
21
+ * **react-sdk:** Universal Device Management API ([#1127](https://github.com/GetStream/stream-video-js/issues/1127)) ([aeb3561](https://github.com/GetStream/stream-video-js/commit/aeb35612745f45254b536281c5f81d1bcac2bab5))
22
+
5
23
  ### [0.3.36](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-0.3.35...@stream-io/video-client-0.3.36) (2023-10-25)
6
24
 
7
25
 
@@ -5736,9 +5736,6 @@ var DebounceType;
5736
5736
  DebounceType[DebounceType["MEDIUM"] = 600] = "MEDIUM";
5737
5737
  DebounceType[DebounceType["SLOW"] = 1200] = "SLOW";
5738
5738
  })(DebounceType || (DebounceType = {}));
5739
- const isStreamVideoLocalParticipant = (p) => {
5740
- return !!p.isLocalParticipant;
5741
- };
5742
5739
 
5743
5740
  /**
5744
5741
  * @generated from protobuf service stream.video.sfu.signal.SignalServer
@@ -6222,21 +6219,6 @@ const trackTypeToParticipantStreamKey = (trackType) => {
6222
6219
  throw new Error(`Unknown track type: ${exhaustiveTrackTypeCheck}`);
6223
6220
  }
6224
6221
  };
6225
- const trackTypeToDeviceIdKey = (trackType) => {
6226
- switch (trackType) {
6227
- case TrackType.AUDIO:
6228
- return 'audioDeviceId';
6229
- case TrackType.VIDEO:
6230
- return 'videoDeviceId';
6231
- case TrackType.SCREEN_SHARE:
6232
- case TrackType.SCREEN_SHARE_AUDIO:
6233
- case TrackType.UNSPECIFIED:
6234
- return undefined;
6235
- default:
6236
- const exhaustiveTrackTypeCheck = trackType;
6237
- throw new Error(`Unknown track type: ${exhaustiveTrackTypeCheck}`);
6238
- }
6239
- };
6240
6222
  const muteTypeToTrackType = (muteType) => {
6241
6223
  switch (muteType) {
6242
6224
  case 'audio':
@@ -6628,14 +6610,11 @@ class Publisher {
6628
6610
  }));
6629
6611
  }
6630
6612
  else {
6631
- const deviceId = track.getSettings().deviceId;
6632
- const audioOrVideoDeviceKey = trackTypeToDeviceIdKey(trackType);
6633
6613
  this.state.updateParticipant(this.sfuClient.sessionId, (p) => {
6634
6614
  return {
6635
6615
  publishedTracks: p.publishedTracks.includes(trackType)
6636
6616
  ? p.publishedTracks
6637
6617
  : [...p.publishedTracks, trackType],
6638
- ...(audioOrVideoDeviceKey && { [audioOrVideoDeviceKey]: deviceId }),
6639
6618
  [audioOrVideoOrScreenShareStream]: mediaStream,
6640
6619
  };
6641
6620
  });
@@ -8477,7 +8456,7 @@ class CallState {
8477
8456
  // maintain stable-sort by mutating the participants stored
8478
8457
  // in the original subject
8479
8458
  map$1((ps) => ps.sort(this.sortParticipantsBy)), shareReplay({ bufferSize: 1, refCount: true }));
8480
- this.localParticipant$ = this.participants$.pipe(map$1((participants) => participants.find(isStreamVideoLocalParticipant)), shareReplay({ bufferSize: 1, refCount: true }));
8459
+ this.localParticipant$ = this.participants$.pipe(map$1((participants) => participants.find((p) => p.isLocalParticipant)), shareReplay({ bufferSize: 1, refCount: true }));
8481
8460
  this.remoteParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => !p.isLocalParticipant)), shareReplay({ bufferSize: 1, refCount: true }));
8482
8461
  this.pinnedParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => !!p.pin)), shareReplay({ bufferSize: 1, refCount: true }));
8483
8462
  this.dominantSpeaker$ = this.participants$.pipe(map$1((participants) => participants.find((p) => p.isDominantSpeaker)), shareReplay({ bufferSize: 1, refCount: true }));
@@ -9212,14 +9191,7 @@ const reconcileParticipantLocalState = (target, source) => {
9212
9191
  if (!source)
9213
9192
  return target;
9214
9193
  // copy everything from source to target
9215
- Object.assign(target, source);
9216
- if (isStreamVideoLocalParticipant(source) &&
9217
- isStreamVideoLocalParticipant(target)) {
9218
- target.audioDeviceId = source.audioDeviceId;
9219
- target.videoDeviceId = source.videoDeviceId;
9220
- target.audioOutputDeviceId = source.audioOutputDeviceId;
9221
- }
9222
- return target;
9194
+ return Object.assign(target, source);
9223
9195
  };
9224
9196
 
9225
9197
  /**
@@ -9822,24 +9794,20 @@ class DynascaleManager {
9822
9794
  }
9823
9795
  });
9824
9796
  });
9825
- const sinkIdSubscription = combineLatest([
9826
- this.call.state.localParticipant$,
9827
- this.call.speaker.state.selectedDevice$,
9828
- ]).subscribe(([p, selectedDevice]) => {
9829
- const deviceId = getSdkInfo()?.type === SdkType.REACT
9830
- ? p?.audioOutputDeviceId
9831
- : selectedDevice;
9832
- if ('setSinkId' in audioElement && typeof deviceId === 'string') {
9833
- // @ts-expect-error setSinkId is not yet in the lib
9834
- audioElement.setSinkId(deviceId);
9835
- }
9836
- });
9797
+ const sinkIdSubscription = !('setSinkId' in audioElement)
9798
+ ? null
9799
+ : this.call.speaker.state.selectedDevice$.subscribe((deviceId) => {
9800
+ if (deviceId) {
9801
+ // @ts-expect-error setSinkId is not yet in the lib
9802
+ audioElement.setSinkId(deviceId);
9803
+ }
9804
+ });
9837
9805
  const volumeSubscription = this.call.speaker.state.volume$.subscribe((volume) => {
9838
9806
  audioElement.volume = volume;
9839
9807
  });
9840
9808
  audioElement.autoplay = true;
9841
9809
  return () => {
9842
- sinkIdSubscription.unsubscribe();
9810
+ sinkIdSubscription?.unsubscribe();
9843
9811
  volumeSubscription.unsubscribe();
9844
9812
  updateMediaStreamSubscription.unsubscribe();
9845
9813
  };
@@ -9888,11 +9856,12 @@ class PermissionsContext {
9888
9856
  * within the call.
9889
9857
  *
9890
9858
  * @param permission the permission to check for.
9859
+ * @param settings the call settings to check against (optional).
9891
9860
  */
9892
- this.canRequest = (permission) => {
9893
- if (!this.settings)
9861
+ this.canRequest = (permission, settings = this.settings) => {
9862
+ if (!settings)
9894
9863
  return false;
9895
- const { audio, video, screensharing } = this.settings;
9864
+ const { audio, video, screensharing } = settings;
9896
9865
  switch (permission) {
9897
9866
  case OwnCapability.SEND_AUDIO:
9898
9867
  return audio.access_request_enabled;
@@ -10300,6 +10269,7 @@ class InputMediaDeviceManager {
10300
10269
  try {
10301
10270
  await this.enablePromise;
10302
10271
  this.state.setStatus('enabled');
10272
+ this.enablePromise = undefined;
10303
10273
  }
10304
10274
  catch (error) {
10305
10275
  this.enablePromise = undefined;
@@ -11145,6 +11115,7 @@ class Call {
11145
11115
  this.watching = true;
11146
11116
  this.clientStore.registerCall(this);
11147
11117
  }
11118
+ this.applyDeviceConfig();
11148
11119
  return response;
11149
11120
  };
11150
11121
  /**
@@ -11164,6 +11135,7 @@ class Call {
11164
11135
  this.watching = true;
11165
11136
  this.clientStore.registerCall(this);
11166
11137
  }
11138
+ this.applyDeviceConfig();
11167
11139
  return response;
11168
11140
  };
11169
11141
  /**
@@ -11495,15 +11467,12 @@ class Call {
11495
11467
  this.state.setServerSidePins(pins);
11496
11468
  this.reconnectAttempts = 0; // reset the reconnect attempts counter
11497
11469
  this.state.setCallingState(CallingState.JOINED);
11498
- // React uses a different device management for now
11499
- if (getSdkInfo()?.type !== SdkType.REACT) {
11500
- try {
11501
- await this.initCamera();
11502
- await this.initMic();
11503
- }
11504
- catch (error) {
11505
- this.logger('warn', 'Camera and/or mic init failed during join call');
11506
- }
11470
+ try {
11471
+ await this.initCamera({ setStatus: true });
11472
+ await this.initMic({ setStatus: true });
11473
+ }
11474
+ catch (error) {
11475
+ this.logger('warn', 'Camera and/or mic init failed during join call');
11507
11476
  }
11508
11477
  // 3. once we have the "joinResponse", and possibly reconciled the local state
11509
11478
  // we schedule a fast subscription update for all remote participants
@@ -11730,56 +11699,6 @@ class Call {
11730
11699
  this.stopReportingStatsFor = (sessionId) => {
11731
11700
  return this.statsReporter?.stopReportingStatsFor(sessionId);
11732
11701
  };
11733
- /**
11734
- * Sets the used audio output device (`audioOutputDeviceId` of the [`localParticipant$`](./StreamVideoClient.md/#readonlystatestore).
11735
- *
11736
- * This method only stores the selection, if you're using custom UI components, you'll have to implement the audio switching, for more information see: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/sinkId.
11737
- *
11738
- *
11739
- * @param deviceId the selected device, `undefined` means the user wants to use the system's default audio output
11740
- *
11741
- * @deprecated use `call.speaker` instead
11742
- */
11743
- this.setAudioOutputDevice = (deviceId) => {
11744
- if (!this.sfuClient)
11745
- return;
11746
- this.state.updateParticipant(this.sfuClient.sessionId, {
11747
- audioOutputDeviceId: deviceId,
11748
- });
11749
- };
11750
- /**
11751
- * Sets the `audioDeviceId` property of the [`localParticipant$`](./StreamVideoClient.md/#readonlystatestore)).
11752
- *
11753
- * This method only stores the selection, if you want to start publishing a media stream call the [`publishAudioStream` method](#publishaudiostream) that will set `audioDeviceId` as well.
11754
- *
11755
- *
11756
- * @param deviceId the selected device, pass `undefined` to clear the device selection
11757
- *
11758
- * @deprecated use call.microphone.select
11759
- */
11760
- this.setAudioDevice = (deviceId) => {
11761
- if (!this.sfuClient)
11762
- return;
11763
- this.state.updateParticipant(this.sfuClient.sessionId, {
11764
- audioDeviceId: deviceId,
11765
- });
11766
- };
11767
- /**
11768
- * Sets the `videoDeviceId` property of the [`localParticipant$`](./StreamVideoClient.md/#readonlystatestore).
11769
- *
11770
- * This method only stores the selection, if you want to start publishing a media stream call the [`publishVideoStream` method](#publishvideostream) that will set `videoDeviceId` as well.
11771
- *
11772
- * @param deviceId the selected device, pass `undefined` to clear the device selection
11773
- *
11774
- * @deprecated use call.camera.select
11775
- */
11776
- this.setVideoDevice = (deviceId) => {
11777
- if (!this.sfuClient)
11778
- return;
11779
- this.state.updateParticipant(this.sfuClient.sessionId, {
11780
- videoDeviceId: deviceId,
11781
- });
11782
- };
11783
11702
  /**
11784
11703
  * Resets the last sent reaction for the user holding the given `sessionId`. This is a local action, it won't reset the reaction on the backend.
11785
11704
  *
@@ -12126,6 +12045,10 @@ class Call {
12126
12045
  this.sendCustomEvent = async (payload) => {
12127
12046
  return this.streamClient.post(`${this.streamClientBasePath}/event`, { custom: payload });
12128
12047
  };
12048
+ this.applyDeviceConfig = () => {
12049
+ this.initCamera({ setStatus: false });
12050
+ this.initMic({ setStatus: false });
12051
+ };
12129
12052
  /**
12130
12053
  * Will begin tracking the given element for visibility changes within the
12131
12054
  * configured viewport element (`call.setViewport`).
@@ -12371,7 +12294,7 @@ class Call {
12371
12294
  get isCreatedByMe() {
12372
12295
  return this.state.createdBy?.id === this.currentUserId;
12373
12296
  }
12374
- async initCamera() {
12297
+ async initCamera(options) {
12375
12298
  // Wait for any in progress camera operation
12376
12299
  if (this.camera.enablePromise) {
12377
12300
  await this.camera.enablePromise;
@@ -12397,19 +12320,21 @@ class Call {
12397
12320
  if (targetResolution) {
12398
12321
  await this.camera.selectTargetResolution(targetResolution);
12399
12322
  }
12400
- // Publish already that was set before we joined
12401
- if (this.camera.state.status === 'enabled' &&
12402
- this.camera.state.mediaStream &&
12403
- !this.publisher?.isPublishing(TrackType.VIDEO)) {
12404
- await this.publishVideoStream(this.camera.state.mediaStream);
12405
- }
12406
- // Start camera if backend config speicifies, and there is no local setting
12407
- if (this.camera.state.status === undefined &&
12408
- this.state.settings?.video.camera_default_on) {
12409
- await this.camera.enable();
12323
+ if (options.setStatus) {
12324
+ // Publish already that was set before we joined
12325
+ if (this.camera.state.status === 'enabled' &&
12326
+ this.camera.state.mediaStream &&
12327
+ !this.publisher?.isPublishing(TrackType.VIDEO)) {
12328
+ await this.publishVideoStream(this.camera.state.mediaStream);
12329
+ }
12330
+ // Start camera if backend config speicifies, and there is no local setting
12331
+ if (this.camera.state.status === undefined &&
12332
+ this.state.settings?.video.camera_default_on) {
12333
+ await this.camera.enable();
12334
+ }
12410
12335
  }
12411
12336
  }
12412
- async initMic() {
12337
+ async initMic(options) {
12413
12338
  // Wait for any in progress mic operation
12414
12339
  if (this.microphone.enablePromise) {
12415
12340
  await this.microphone.enablePromise;
@@ -12421,16 +12346,18 @@ class Call {
12421
12346
  !this.permissionsContext.hasPermission('send-audio')) {
12422
12347
  return;
12423
12348
  }
12424
- // Publish media stream that was set before we joined
12425
- if (this.microphone.state.status === 'enabled' &&
12426
- this.microphone.state.mediaStream &&
12427
- !this.publisher?.isPublishing(TrackType.AUDIO)) {
12428
- await this.publishAudioStream(this.microphone.state.mediaStream);
12429
- }
12430
- // Start mic if backend config specifies, and there is no local setting
12431
- if (this.microphone.state.status === undefined &&
12432
- this.state.settings?.audio.mic_default_on) {
12433
- await this.microphone.enable();
12349
+ if (options.setStatus) {
12350
+ // Publish media stream that was set before we joined
12351
+ if (this.microphone.state.status === 'enabled' &&
12352
+ this.microphone.state.mediaStream &&
12353
+ !this.publisher?.isPublishing(TrackType.AUDIO)) {
12354
+ await this.publishAudioStream(this.microphone.state.mediaStream);
12355
+ }
12356
+ // Start mic if backend config specifies, and there is no local setting
12357
+ if (this.microphone.state.status === undefined &&
12358
+ this.state.settings?.audio.mic_default_on) {
12359
+ await this.microphone.enable();
12360
+ }
12434
12361
  }
12435
12362
  }
12436
12363
  }
@@ -14015,7 +13942,7 @@ class StreamClient {
14015
13942
  });
14016
13943
  };
14017
13944
  this.getUserAgent = () => {
14018
- const version = "0.3.36" ;
13945
+ const version = "0.4.1" ;
14019
13946
  return (this.userAgent ||
14020
13947
  `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
14021
13948
  };
@@ -14263,6 +14190,7 @@ class StreamVideoClient {
14263
14190
  clientStore: this.writeableStateStore,
14264
14191
  });
14265
14192
  call.state.updateFromCallResponse(c.call);
14193
+ call.applyDeviceConfig();
14266
14194
  if (data.watch) {
14267
14195
  this.writeableStateStore.registerCall(call);
14268
14196
  }
@@ -14549,5 +14477,5 @@ class StreamVideoServerClient extends StreamVideoClient {
14549
14477
  }
14550
14478
  }
14551
14479
 
14552
- export { AudioSettingsDefaultDeviceEnum, AudioSettingsRequestDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, CreateDeviceRequestPushProviderEnum, DebounceType, DynascaleManager, ErrorFromResponse, InputMediaDeviceManager, InputMediaDeviceManagerState, LayoutSettingsNameEnum, LayoutSettingsRequestNameEnum, MicrophoneManager, MicrophoneManagerState, OwnCapability, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoServerClient, StreamVideoWriteableStateStore, TranscriptionSettingsModeEnum, TranscriptionSettingsRequestModeEnum, VideoSettingsCameraFacingEnum, VideoSettingsRequestCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, disposeOfMediaStream, dominantSpeaker, getAudioDevices, getAudioOutputDevices, getAudioStream, getClientDetails, getDeviceInfo, getLogger, getOSInfo, getScreenShareStream, getSdkInfo, getVideoDevices, getVideoStream, isStreamVideoLocalParticipant, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, paginatedLayoutSortPreset, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setSdkInfo, speakerLayoutSortPreset, speaking, watchForAddedDefaultAudioDevice, watchForAddedDefaultAudioOutputDevice, watchForAddedDefaultVideoDevice, watchForDisconnectedAudioDevice, watchForDisconnectedAudioOutputDevice, watchForDisconnectedVideoDevice };
14480
+ export { AudioSettingsDefaultDeviceEnum, AudioSettingsRequestDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, CreateDeviceRequestPushProviderEnum, DebounceType, DynascaleManager, ErrorFromResponse, InputMediaDeviceManager, InputMediaDeviceManagerState, LayoutSettingsNameEnum, LayoutSettingsRequestNameEnum, MicrophoneManager, MicrophoneManagerState, OwnCapability, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoServerClient, StreamVideoWriteableStateStore, TranscriptionSettingsModeEnum, TranscriptionSettingsRequestModeEnum, VideoSettingsCameraFacingEnum, VideoSettingsRequestCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, disposeOfMediaStream, dominantSpeaker, getAudioDevices, getAudioOutputDevices, getAudioStream, getClientDetails, getDeviceInfo, getLogger, getOSInfo, getScreenShareStream, getSdkInfo, getVideoDevices, getVideoStream, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, paginatedLayoutSortPreset, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setSdkInfo, speakerLayoutSortPreset, speaking, watchForAddedDefaultAudioDevice, watchForAddedDefaultAudioOutputDevice, watchForAddedDefaultVideoDevice, watchForDisconnectedAudioDevice, watchForDisconnectedAudioOutputDevice, watchForDisconnectedVideoDevice };
14553
14481
  //# sourceMappingURL=index.browser.es.js.map