@stream-io/video-client 0.3.13 → 0.3.14

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,13 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ### [0.3.14](https://github.com/GetStream/stream-video-js/compare/client0.3.13...client0.3.14) (2023-09-05)
6
+
7
+
8
+ ### Features
9
+
10
+ * new device api remote mutes ([#988](https://github.com/GetStream/stream-video-js/issues/988)) ([5bbcefb](https://github.com/GetStream/stream-video-js/commit/5bbcefbf0d8be59025fef8111253a8a0baaf6001))
11
+
5
12
  ### [0.3.13](https://github.com/GetStream/stream-video-js/compare/client0.3.12...client0.3.13) (2023-08-31)
6
13
 
7
14
 
@@ -6490,6 +6490,9 @@ class Publisher {
6490
6490
  // by an external factor as permission revokes, device disconnected, etc.
6491
6491
  // keep in mind that `track.stop()` doesn't trigger this event.
6492
6492
  track.addEventListener('ended', handleTrackEnded);
6493
+ if (!track.enabled) {
6494
+ track.enabled = true;
6495
+ }
6493
6496
  transceiver = this.pc.addTransceiver(track, {
6494
6497
  direction: 'sendonly',
6495
6498
  streams: trackType === TrackType.VIDEO || trackType === TrackType.SCREEN_SHARE
@@ -6527,16 +6530,25 @@ class Publisher {
6527
6530
  * @param stopTrack specifies whether track should be stopped or just disabled
6528
6531
  */
6529
6532
  this.unpublishStream = (trackType, stopTrack) => __awaiter(this, void 0, void 0, function* () {
6533
+ var _b;
6530
6534
  const transceiver = this.pc
6531
6535
  .getTransceivers()
6532
6536
  .find((t) => t === this.transceiverRegistry[trackType] && t.sender.track);
6533
6537
  if (transceiver &&
6534
6538
  transceiver.sender.track &&
6535
- transceiver.sender.track.readyState === 'live') {
6539
+ (stopTrack
6540
+ ? transceiver.sender.track.readyState === 'live'
6541
+ : transceiver.sender.track.enabled)) {
6536
6542
  stopTrack
6537
6543
  ? transceiver.sender.track.stop()
6538
6544
  : (transceiver.sender.track.enabled = false);
6539
- return this.notifyTrackMuteStateChanged(undefined, transceiver.sender.track, trackType, true);
6545
+ // We don't need to notify SFU if unpublishing in response to remote soft mute
6546
+ if (!((_b = this.state.localParticipant) === null || _b === void 0 ? void 0 : _b.publishedTracks.includes(trackType))) {
6547
+ return;
6548
+ }
6549
+ else {
6550
+ return this.notifyTrackMuteStateChanged(undefined, transceiver.sender.track, trackType, true);
6551
+ }
6540
6552
  }
6541
6553
  });
6542
6554
  /**
@@ -6545,6 +6557,21 @@ class Publisher {
6545
6557
  * @param trackType the track type to check.
6546
6558
  */
6547
6559
  this.isPublishing = (trackType) => {
6560
+ const transceiverForTrackType = this.transceiverRegistry[trackType];
6561
+ if (transceiverForTrackType && transceiverForTrackType.sender) {
6562
+ const sender = transceiverForTrackType.sender;
6563
+ return (!!sender.track &&
6564
+ sender.track.readyState === 'live' &&
6565
+ sender.track.enabled);
6566
+ }
6567
+ return false;
6568
+ };
6569
+ /**
6570
+ * Returns true if the given track type is currently live
6571
+ *
6572
+ * @param trackType the track type to check.
6573
+ */
6574
+ this.isLive = (trackType) => {
6548
6575
  const transceiverForTrackType = this.transceiverRegistry[trackType];
6549
6576
  if (transceiverForTrackType && transceiverForTrackType.sender) {
6550
6577
  const sender = transceiverForTrackType.sender;
@@ -6585,9 +6612,9 @@ class Publisher {
6585
6612
  });
6586
6613
  };
6587
6614
  this.updateVideoPublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
6588
- var _b;
6615
+ var _c;
6589
6616
  logger$3('info', 'Update publish quality, requested rids by SFU:', enabledRids);
6590
- const videoSender = (_b = this.transceiverRegistry[TrackType.VIDEO]) === null || _b === void 0 ? void 0 : _b.sender;
6617
+ const videoSender = (_c = this.transceiverRegistry[TrackType.VIDEO]) === null || _c === void 0 ? void 0 : _c.sender;
6591
6618
  if (!videoSender) {
6592
6619
  logger$3('warn', 'Update publish quality, no video sender found.');
6593
6620
  return;
@@ -6685,8 +6712,8 @@ class Publisher {
6685
6712
  * @param options the optional offer options to use.
6686
6713
  */
6687
6714
  this.negotiate = (options) => __awaiter(this, void 0, void 0, function* () {
6688
- var _c;
6689
- this.isIceRestarting = (_c = options === null || options === void 0 ? void 0 : options.iceRestart) !== null && _c !== void 0 ? _c : false;
6715
+ var _d;
6716
+ this.isIceRestarting = (_d = options === null || options === void 0 ? void 0 : options.iceRestart) !== null && _d !== void 0 ? _d : false;
6690
6717
  const offer = yield this.pc.createOffer(options);
6691
6718
  offer.sdp = this.mungeCodecs(offer.sdp);
6692
6719
  const trackInfos = this.getCurrentTrackInfos(offer.sdp);
@@ -7474,6 +7501,9 @@ const retryable = (rpc, logger) => __awaiter(void 0, void 0, void 0, function* (
7474
7501
  retryAttempt++;
7475
7502
  } while (((_a = rpcCallResult.response.error) === null || _a === void 0 ? void 0 : _a.shouldRetry) &&
7476
7503
  retryAttempt < MAX_RETRIES);
7504
+ if (rpcCallResult.response.error) {
7505
+ throw rpcCallResult.response.error;
7506
+ }
7477
7507
  return rpcCallResult;
7478
7508
  });
7479
7509
 
@@ -9797,6 +9827,190 @@ class CameraManagerState extends InputMediaDeviceManagerState {
9797
9827
  }
9798
9828
  }
9799
9829
 
9830
+ class InputMediaDeviceManager {
9831
+ constructor(call, state, trackType) {
9832
+ this.call = call;
9833
+ this.state = state;
9834
+ this.trackType = trackType;
9835
+ this.logger = getLogger([`${TrackType[trackType].toLowerCase()} manager`]);
9836
+ }
9837
+ /**
9838
+ * Lists the available audio/video devices
9839
+ *
9840
+ * Note: It prompts the user for a permission to use devices (if not already granted)
9841
+ *
9842
+ * @returns an Observable that will be updated if a device is connected or disconnected
9843
+ */
9844
+ listDevices() {
9845
+ return this.getDevices();
9846
+ }
9847
+ /**
9848
+ * Starts camera/microphone
9849
+ */
9850
+ enable() {
9851
+ return __awaiter(this, void 0, void 0, function* () {
9852
+ if (this.state.status === 'enabled') {
9853
+ return;
9854
+ }
9855
+ this.enablePromise = this.unmuteStream();
9856
+ try {
9857
+ yield this.enablePromise;
9858
+ this.state.setStatus('enabled');
9859
+ }
9860
+ catch (error) {
9861
+ this.enablePromise = undefined;
9862
+ throw error;
9863
+ }
9864
+ });
9865
+ }
9866
+ /**
9867
+ * Stops camera/microphone
9868
+ *
9869
+ * @returns
9870
+ */
9871
+ disable() {
9872
+ return __awaiter(this, void 0, void 0, function* () {
9873
+ this.state.prevStatus = this.state.status;
9874
+ if (this.state.status === 'disabled') {
9875
+ return;
9876
+ }
9877
+ this.disablePromise = this.muteStream(this.state.disableMode === 'stop-tracks');
9878
+ try {
9879
+ yield this.disablePromise;
9880
+ this.state.setStatus('disabled');
9881
+ this.disablePromise = undefined;
9882
+ }
9883
+ catch (error) {
9884
+ this.disablePromise = undefined;
9885
+ throw error;
9886
+ }
9887
+ });
9888
+ }
9889
+ /**
9890
+ * If status was previously enabled, it will reenable the device.
9891
+ */
9892
+ resume() {
9893
+ return __awaiter(this, void 0, void 0, function* () {
9894
+ if (this.state.prevStatus === 'enabled' &&
9895
+ this.state.status === 'disabled') {
9896
+ this.enable();
9897
+ }
9898
+ });
9899
+ }
9900
+ /**
9901
+ * If current device statis is disabled, it will enable the device, else it will disable it.
9902
+ *
9903
+ * @returns
9904
+ */
9905
+ toggle() {
9906
+ return __awaiter(this, void 0, void 0, function* () {
9907
+ if (this.state.status === 'enabled') {
9908
+ return this.disable();
9909
+ }
9910
+ else {
9911
+ return this.enable();
9912
+ }
9913
+ });
9914
+ }
9915
+ /**
9916
+ * Select device
9917
+ *
9918
+ * Note: this method is not supported in React Native
9919
+ *
9920
+ * @param deviceId
9921
+ */
9922
+ select(deviceId) {
9923
+ return __awaiter(this, void 0, void 0, function* () {
9924
+ if (isReactNative()) {
9925
+ throw new Error('This method is not supported in React Native');
9926
+ }
9927
+ if (deviceId === this.state.selectedDevice) {
9928
+ return;
9929
+ }
9930
+ this.state.setDevice(deviceId);
9931
+ yield this.applySettingsToStream();
9932
+ });
9933
+ }
9934
+ applySettingsToStream() {
9935
+ return __awaiter(this, void 0, void 0, function* () {
9936
+ if (this.state.status === 'enabled') {
9937
+ yield this.muteStream();
9938
+ yield this.unmuteStream();
9939
+ }
9940
+ });
9941
+ }
9942
+ muteStream(stopTracks = true) {
9943
+ var _a;
9944
+ return __awaiter(this, void 0, void 0, function* () {
9945
+ if (!this.state.mediaStream) {
9946
+ return;
9947
+ }
9948
+ this.logger('debug', `${stopTracks ? 'Stopping' : 'Disabling'} stream`);
9949
+ if (this.call.state.callingState === CallingState.JOINED) {
9950
+ yield this.stopPublishStream(stopTracks);
9951
+ }
9952
+ this.muteLocalStream(stopTracks);
9953
+ if (((_a = this.getTrack()) === null || _a === void 0 ? void 0 : _a.readyState) === 'ended') {
9954
+ // @ts-expect-error release() is present in react-native-webrtc and must be called to dispose the stream
9955
+ if (typeof this.state.mediaStream.release === 'function') {
9956
+ // @ts-expect-error
9957
+ this.state.mediaStream.release();
9958
+ }
9959
+ this.state.setMediaStream(undefined);
9960
+ }
9961
+ });
9962
+ }
9963
+ muteTrack() {
9964
+ const track = this.getTrack();
9965
+ if (!track || !track.enabled) {
9966
+ return;
9967
+ }
9968
+ track.enabled = false;
9969
+ }
9970
+ unmuteTrack() {
9971
+ const track = this.getTrack();
9972
+ if (!track || track.enabled) {
9973
+ return;
9974
+ }
9975
+ track.enabled = true;
9976
+ }
9977
+ stopTrack() {
9978
+ const track = this.getTrack();
9979
+ if (!track || track.readyState === 'ended') {
9980
+ return;
9981
+ }
9982
+ track.stop();
9983
+ }
9984
+ muteLocalStream(stopTracks) {
9985
+ if (!this.state.mediaStream) {
9986
+ return;
9987
+ }
9988
+ stopTracks ? this.stopTrack() : this.muteTrack();
9989
+ }
9990
+ unmuteStream() {
9991
+ var _a;
9992
+ return __awaiter(this, void 0, void 0, function* () {
9993
+ this.logger('debug', 'Starting stream');
9994
+ let stream;
9995
+ if (this.state.mediaStream && ((_a = this.getTrack()) === null || _a === void 0 ? void 0 : _a.readyState) === 'live') {
9996
+ stream = this.state.mediaStream;
9997
+ this.unmuteTrack();
9998
+ }
9999
+ else {
10000
+ if (this.state.mediaStream) {
10001
+ this.stopTrack();
10002
+ }
10003
+ const constraints = { deviceId: this.state.selectedDevice };
10004
+ stream = yield this.getStream(constraints);
10005
+ }
10006
+ if (this.call.state.callingState === CallingState.JOINED) {
10007
+ yield this.publishStream(stream);
10008
+ }
10009
+ this.state.setMediaStream(stream);
10010
+ });
10011
+ }
10012
+ }
10013
+
9800
10014
  const getDevices = (constraints) => {
9801
10015
  return new Observable((subscriber) => {
9802
10016
  navigator.mediaDevices
@@ -10045,156 +10259,9 @@ const disposeOfMediaStream = (stream) => {
10045
10259
  }
10046
10260
  };
10047
10261
 
10048
- class InputMediaDeviceManager {
10049
- constructor(call, state) {
10050
- this.call = call;
10051
- this.state = state;
10052
- }
10053
- /**
10054
- * Lists the available audio/video devices
10055
- *
10056
- * Note: It prompts the user for a permission to use devices (if not already granted)
10057
- *
10058
- * @returns an Observable that will be updated if a device is connected or disconnected
10059
- */
10060
- listDevices() {
10061
- return this.getDevices();
10062
- }
10063
- /**
10064
- * Starts camera/microphone
10065
- */
10066
- enable() {
10067
- return __awaiter(this, void 0, void 0, function* () {
10068
- if (this.state.status === 'enabled') {
10069
- return;
10070
- }
10071
- this.enablePromise = this.unmuteStream();
10072
- try {
10073
- yield this.enablePromise;
10074
- this.state.setStatus('enabled');
10075
- }
10076
- catch (error) {
10077
- this.enablePromise = undefined;
10078
- throw error;
10079
- }
10080
- });
10081
- }
10082
- /**
10083
- * Stops camera/microphone
10084
- *
10085
- * @returns
10086
- */
10087
- disable() {
10088
- return __awaiter(this, void 0, void 0, function* () {
10089
- this.state.prevStatus = this.state.status;
10090
- if (this.state.status === 'disabled') {
10091
- return;
10092
- }
10093
- this.disablePromise = this.muteStream(this.state.disableMode === 'stop-tracks');
10094
- try {
10095
- yield this.disablePromise;
10096
- this.state.setStatus('disabled');
10097
- this.disablePromise = undefined;
10098
- }
10099
- catch (error) {
10100
- this.disablePromise = undefined;
10101
- throw error;
10102
- }
10103
- });
10104
- }
10105
- /**
10106
- * If status was previously enabled, it will reenable the device.
10107
- */
10108
- resume() {
10109
- return __awaiter(this, void 0, void 0, function* () {
10110
- if (this.state.prevStatus === 'enabled' &&
10111
- this.state.status === 'disabled') {
10112
- this.enable();
10113
- }
10114
- });
10115
- }
10116
- /**
10117
- * If current device statis is disabled, it will enable the device, else it will disable it.
10118
- *
10119
- * @returns
10120
- */
10121
- toggle() {
10122
- return __awaiter(this, void 0, void 0, function* () {
10123
- if (this.state.status === 'enabled') {
10124
- return this.disable();
10125
- }
10126
- else {
10127
- return this.enable();
10128
- }
10129
- });
10130
- }
10131
- /**
10132
- * Select device
10133
- *
10134
- * Note: this method is not supported in React Native
10135
- *
10136
- * @param deviceId
10137
- */
10138
- select(deviceId) {
10139
- return __awaiter(this, void 0, void 0, function* () {
10140
- if (isReactNative()) {
10141
- throw new Error('This method is not supported in React Native');
10142
- }
10143
- if (deviceId === this.state.selectedDevice) {
10144
- return;
10145
- }
10146
- this.state.setDevice(deviceId);
10147
- yield this.applySettingsToStream();
10148
- });
10149
- }
10150
- applySettingsToStream() {
10151
- return __awaiter(this, void 0, void 0, function* () {
10152
- if (this.state.status === 'enabled') {
10153
- yield this.muteStream();
10154
- yield this.unmuteStream();
10155
- }
10156
- });
10157
- }
10158
- muteStream(stopTracks = true) {
10159
- return __awaiter(this, void 0, void 0, function* () {
10160
- if (!this.state.mediaStream) {
10161
- return;
10162
- }
10163
- if (this.call.state.callingState === CallingState.JOINED) {
10164
- yield this.stopPublishStream(stopTracks);
10165
- }
10166
- else if (this.state.mediaStream) {
10167
- stopTracks
10168
- ? disposeOfMediaStream(this.state.mediaStream)
10169
- : this.muteTracks();
10170
- }
10171
- if (stopTracks) {
10172
- this.state.setMediaStream(undefined);
10173
- }
10174
- });
10175
- }
10176
- unmuteStream() {
10177
- return __awaiter(this, void 0, void 0, function* () {
10178
- let stream;
10179
- if (this.state.mediaStream) {
10180
- stream = this.state.mediaStream;
10181
- this.unmuteTracks();
10182
- }
10183
- else {
10184
- const constraints = { deviceId: this.state.selectedDevice };
10185
- stream = yield this.getStream(constraints);
10186
- }
10187
- if (this.call.state.callingState === CallingState.JOINED) {
10188
- yield this.publishStream(stream);
10189
- }
10190
- this.state.setMediaStream(stream);
10191
- });
10192
- }
10193
- }
10194
-
10195
10262
  class CameraManager extends InputMediaDeviceManager {
10196
10263
  constructor(call) {
10197
- super(call, new CameraManagerState());
10264
+ super(call, new CameraManagerState(), TrackType.VIDEO);
10198
10265
  this.targetResolution = {
10199
10266
  width: 1280,
10200
10267
  height: 720,
@@ -10246,6 +10313,7 @@ class CameraManager extends InputMediaDeviceManager {
10246
10313
  if (width !== this.targetResolution.width ||
10247
10314
  height !== this.targetResolution.height)
10248
10315
  yield this.applySettingsToStream();
10316
+ this.logger('debug', `${width}x${height} target resolution applied to media stream`);
10249
10317
  }
10250
10318
  });
10251
10319
  }
@@ -10269,13 +10337,9 @@ class CameraManager extends InputMediaDeviceManager {
10269
10337
  stopPublishStream(stopTracks) {
10270
10338
  return this.call.stopPublish(TrackType.VIDEO, stopTracks);
10271
10339
  }
10272
- muteTracks() {
10273
- var _a;
10274
- (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks().forEach((t) => (t.enabled = false));
10275
- }
10276
- unmuteTracks() {
10340
+ getTrack() {
10277
10341
  var _a;
10278
- (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks().forEach((t) => (t.enabled = true));
10342
+ return (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks()[0];
10279
10343
  }
10280
10344
  }
10281
10345
 
@@ -10291,7 +10355,7 @@ class MicrophoneManagerState extends InputMediaDeviceManagerState {
10291
10355
 
10292
10356
  class MicrophoneManager extends InputMediaDeviceManager {
10293
10357
  constructor(call) {
10294
- super(call, new MicrophoneManagerState());
10358
+ super(call, new MicrophoneManagerState(), TrackType.AUDIO);
10295
10359
  }
10296
10360
  getDevices() {
10297
10361
  return getAudioDevices();
@@ -10305,13 +10369,9 @@ class MicrophoneManager extends InputMediaDeviceManager {
10305
10369
  stopPublishStream(stopTracks) {
10306
10370
  return this.call.stopPublish(TrackType.AUDIO, stopTracks);
10307
10371
  }
10308
- muteTracks() {
10309
- var _a;
10310
- (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks().forEach((t) => (t.enabled = false));
10311
- }
10312
- unmuteTracks() {
10372
+ getTrack() {
10313
10373
  var _a;
10314
- (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks().forEach((t) => (t.enabled = true));
10374
+ return (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks()[0];
10315
10375
  }
10316
10376
  }
10317
10377
 
@@ -10997,7 +11057,7 @@ class Call {
10997
11057
  */
10998
11058
  this.stopPublish = (trackType, stopTrack = true) => __awaiter(this, void 0, void 0, function* () {
10999
11059
  var _j;
11000
- this.logger('info', `stopPublish ${TrackType[trackType]}`);
11060
+ this.logger('info', `stopPublish ${TrackType[trackType]}, stop tracks: ${stopTrack}`);
11001
11061
  yield ((_j = this.publisher) === null || _j === void 0 ? void 0 : _j.unpublishStream(trackType, stopTrack));
11002
11062
  });
11003
11063
  /**
@@ -11575,6 +11635,27 @@ class Call {
11575
11635
  this.leaveCallHooks.add(createSubscription(this.trackSubscriptionsSubject.pipe(debounce((v) => timer(v.type)), map$2((v) => v.data)), (subscriptions) => { var _a; return (_a = this.sfuClient) === null || _a === void 0 ? void 0 : _a.updateSubscriptions(subscriptions); }));
11576
11636
  this.camera = new CameraManager(this);
11577
11637
  this.microphone = new MicrophoneManager(this);
11638
+ this.state.localParticipant$.subscribe((p) => __awaiter(this, void 0, void 0, function* () {
11639
+ var _l, _m;
11640
+ // Mute via device manager
11641
+ // If integrator doesn't use device manager, we mute using stopPublish
11642
+ if (!(p === null || p === void 0 ? void 0 : p.publishedTracks.includes(TrackType.VIDEO)) &&
11643
+ ((_l = this.publisher) === null || _l === void 0 ? void 0 : _l.isPublishing(TrackType.VIDEO))) {
11644
+ this.logger('info', `Local participant's video track is muted remotely`);
11645
+ yield this.camera.disable();
11646
+ if (this.publisher.isPublishing(TrackType.VIDEO)) {
11647
+ this.stopPublish(TrackType.VIDEO);
11648
+ }
11649
+ }
11650
+ if (!(p === null || p === void 0 ? void 0 : p.publishedTracks.includes(TrackType.AUDIO)) &&
11651
+ ((_m = this.publisher) === null || _m === void 0 ? void 0 : _m.isPublishing(TrackType.AUDIO))) {
11652
+ this.logger('info', `Local participant's audio track is muted remotely`);
11653
+ yield this.microphone.disable();
11654
+ if (this.publisher.isPublishing(TrackType.AUDIO)) {
11655
+ this.stopPublish(TrackType.AUDIO);
11656
+ }
11657
+ }
11658
+ }));
11578
11659
  this.speaker = new SpeakerManager();
11579
11660
  }
11580
11661
  registerEffects() {
@@ -11600,9 +11681,27 @@ class Call {
11600
11681
  };
11601
11682
  for (const [permission, trackType] of Object.entries(permissionToTrackType)) {
11602
11683
  const hasPermission = this.permissionsContext.hasPermission(permission);
11603
- if (!hasPermission && this.publisher.isPublishing(trackType)) {
11604
- this.stopPublish(trackType).catch((err) => {
11684
+ if (!hasPermission &&
11685
+ (this.publisher.isPublishing(trackType) ||
11686
+ this.publisher.isLive(trackType))) {
11687
+ // Stop tracks, then notify device manager
11688
+ this.stopPublish(trackType)
11689
+ .catch((err) => {
11605
11690
  this.logger('error', `Error stopping publish ${trackType}`, err);
11691
+ })
11692
+ .then(() => {
11693
+ if (trackType === TrackType.VIDEO &&
11694
+ this.camera.state.status === 'enabled') {
11695
+ this.camera
11696
+ .disable()
11697
+ .catch((err) => this.logger('error', `Error disabling camera after pemission revoked`, err));
11698
+ }
11699
+ if (trackType === TrackType.AUDIO &&
11700
+ this.microphone.state.status === 'enabled') {
11701
+ this.microphone
11702
+ .disable()
11703
+ .catch((err) => this.logger('error', `Error disabling microphone after pemission revoked`, err));
11704
+ }
11606
11705
  });
11607
11706
  }
11608
11707
  }
@@ -12865,11 +12964,11 @@ class WSConnectionFallback {
12865
12964
  }
12866
12965
  }
12867
12966
 
12868
- const version = '0.3.13';
12967
+ const version = '0.3.14';
12869
12968
 
12870
12969
  const logger = getLogger(['location']);
12871
12970
  const HINT_URL = `https://hint.stream-io-video.com/`;
12872
- const getLocationHint = (hintUrl = HINT_URL, timeout = 1500) => __awaiter(void 0, void 0, void 0, function* () {
12971
+ const getLocationHint = (hintUrl = HINT_URL, timeout = 2000) => __awaiter(void 0, void 0, void 0, function* () {
12873
12972
  const abortController = new AbortController();
12874
12973
  const timeoutId = setTimeout(() => abortController.abort(), timeout);
12875
12974
  try {
@@ -12882,7 +12981,7 @@ const getLocationHint = (hintUrl = HINT_URL, timeout = 1500) => __awaiter(void 0
12882
12981
  return awsPop.substring(0, 3); // AMS1-P2 -> AMS
12883
12982
  }
12884
12983
  catch (e) {
12885
- logger('error', `Failed to get location hint from ${HINT_URL}`, e);
12984
+ logger('warn', `Failed to get location hint from ${HINT_URL}`, e);
12886
12985
  return 'ERR';
12887
12986
  }
12888
12987
  finally {