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