@stream-io/video-client 0.0.46 → 0.0.48

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
+ ### [0.0.48](https://github.com/GetStream/stream-video-js/compare/client0.0.47...client0.0.48) (2023-07-14)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * force iceRestart offer, delay ICE restart ([#801](https://github.com/GetStream/stream-video-js/issues/801)) ([0da298f](https://github.com/GetStream/stream-video-js/commit/0da298faff30ddc42277444aad0d40a635fafb0b)), closes [#787](https://github.com/GetStream/stream-video-js/issues/787)
11
+
12
+ ### [0.0.47](https://github.com/GetStream/stream-video-js/compare/client0.0.46...client0.0.47) (2023-07-14)
13
+
14
+
15
+ ### Features
16
+
17
+ * take the location-hint on SDK init ([#799](https://github.com/GetStream/stream-video-js/issues/799)) ([ee5b170](https://github.com/GetStream/stream-video-js/commit/ee5b170337278a7063a368790f46b270647abf71))
18
+
5
19
  ### [0.0.46](https://github.com/GetStream/stream-video-js/compare/client0.0.45...client0.0.46) (2023-07-14)
6
20
 
7
21
 
@@ -5665,7 +5665,7 @@ const logLevels = Object.freeze({
5665
5665
  warn: 3,
5666
5666
  error: 4,
5667
5667
  });
5668
- let logger$2;
5668
+ let logger$3;
5669
5669
  let level = 'info';
5670
5670
  const logToConsole = (logLevel, message, ...args) => {
5671
5671
  let logMethod;
@@ -5689,7 +5689,7 @@ const logToConsole = (logLevel, message, ...args) => {
5689
5689
  logMethod(message, ...args);
5690
5690
  };
5691
5691
  const setLogger = (l, lvl) => {
5692
- logger$2 = l;
5692
+ logger$3 = l;
5693
5693
  if (lvl) {
5694
5694
  setLogLevel(lvl);
5695
5695
  }
@@ -5698,7 +5698,7 @@ const setLogLevel = (l) => {
5698
5698
  level = l;
5699
5699
  };
5700
5700
  const getLogger = (withTags) => {
5701
- const loggerMethod = logger$2 || logToConsole;
5701
+ const loggerMethod = logger$3 || logToConsole;
5702
5702
  const tags = (withTags || []).join(':');
5703
5703
  const result = (logLevel, message, ...args) => {
5704
5704
  if (logLevels[logLevel] >= logLevels[level]) {
@@ -6318,10 +6318,10 @@ class Publisher {
6318
6318
  /**
6319
6319
  * Restarts the ICE connection and renegotiates with the SFU.
6320
6320
  */
6321
- this.restartIce = () => {
6321
+ this.restartIce = () => __awaiter(this, void 0, void 0, function* () {
6322
6322
  this.logger('debug', 'Restarting ICE connection');
6323
- this.pc.restartIce();
6324
- };
6323
+ yield this.negotiate({ iceRestart: true });
6324
+ });
6325
6325
  this.onNegotiationNeeded = () => __awaiter(this, void 0, void 0, function* () {
6326
6326
  yield this.negotiate();
6327
6327
  });
@@ -6463,10 +6463,27 @@ class Publisher {
6463
6463
  };
6464
6464
  this.onIceConnectionStateChange = () => {
6465
6465
  const state = this.pc.iceConnectionState;
6466
- this.logger('debug', `ICE Connection state changed`, state);
6467
- if (state === 'failed' || state === 'disconnected') {
6468
- this.logger('warn', `ICE Connection state changed to ${state}. Attempting to restart ICE`);
6469
- this.restartIce();
6466
+ this.logger('debug', `ICE Connection state changed to`, state);
6467
+ if (state === 'failed') {
6468
+ this.logger('warn', `Attempting to restart ICE`);
6469
+ this.restartIce().catch((e) => {
6470
+ this.logger('error', `ICE restart error`, e);
6471
+ });
6472
+ }
6473
+ else if (state === 'disconnected') {
6474
+ // when in `disconnected` state, the browser may recover automatically,
6475
+ // hence, we delay the ICE restart
6476
+ this.logger('warn', `Scheduling ICE restart in 5 seconds`);
6477
+ setTimeout(() => {
6478
+ // check if the state is still `disconnected` or `failed`
6479
+ // as the connection may have recovered (or failed) in the meantime
6480
+ if (this.pc.iceConnectionState === 'disconnected' ||
6481
+ this.pc.iceConnectionState === 'failed') {
6482
+ this.restartIce().catch((e) => {
6483
+ this.logger('error', `ICE restart error`, e);
6484
+ });
6485
+ }
6486
+ }, 5000);
6470
6487
  }
6471
6488
  };
6472
6489
  this.onIceGatheringStateChange = () => {
@@ -6491,7 +6508,7 @@ class Publisher {
6491
6508
  }
6492
6509
  }
6493
6510
 
6494
- const logger$1 = getLogger(['Subscriber']);
6511
+ const logger$2 = getLogger(['Subscriber']);
6495
6512
  /**
6496
6513
  * A wrapper around the `RTCPeerConnection` that handles the incoming
6497
6514
  * media streams from the SFU.
@@ -6567,10 +6584,10 @@ class Subscriber {
6567
6584
  // that are migrating to the new subscriber.
6568
6585
  // Once all of them are available, we can close the previous subscriber.
6569
6586
  const handleTrackMigration = (e) => {
6570
- logger$1('debug', `[Migration]: Migrated track: ${e.track.id}, ${e.track.kind}`);
6587
+ logger$2('debug', `[Migration]: Migrated track: ${e.track.id}, ${e.track.kind}`);
6571
6588
  trackIdsToMigrate.delete(e.track.id);
6572
6589
  if (trackIdsToMigrate.size === 0) {
6573
- logger$1('debug', `[Migration]: Migration complete`);
6590
+ logger$2('debug', `[Migration]: Migration complete`);
6574
6591
  pc.removeEventListener('track', handleTrackMigration);
6575
6592
  cleanupMigration();
6576
6593
  }
@@ -6598,7 +6615,7 @@ class Subscriber {
6598
6615
  * Restarts the ICE connection and renegotiates with the SFU.
6599
6616
  */
6600
6617
  this.restartIce = () => {
6601
- logger$1('debug', 'Restarting ICE connection');
6618
+ logger$2('debug', 'Restarting ICE connection');
6602
6619
  this.pc.restartIce();
6603
6620
  };
6604
6621
  this.handleOnTrack = (e) => {
@@ -6606,19 +6623,19 @@ class Subscriber {
6606
6623
  // example: `e3f6aaf8-b03d-4911-be36-83f47d37a76a:TRACK_TYPE_VIDEO`
6607
6624
  const [trackId, trackType] = primaryStream.id.split(':');
6608
6625
  const participantToUpdate = this.state.participants.find((p) => p.trackLookupPrefix === trackId);
6609
- logger$1('debug', `[onTrack]: Got remote ${trackType} track for userId: ${participantToUpdate === null || participantToUpdate === void 0 ? void 0 : participantToUpdate.userId}`, e.track.id, e.track);
6626
+ logger$2('debug', `[onTrack]: Got remote ${trackType} track for userId: ${participantToUpdate === null || participantToUpdate === void 0 ? void 0 : participantToUpdate.userId}`, e.track.id, e.track);
6610
6627
  if (!participantToUpdate) {
6611
- logger$1('error', `[onTrack]: Received track for unknown participant: ${trackId}`, e);
6628
+ logger$2('error', `[onTrack]: Received track for unknown participant: ${trackId}`, e);
6612
6629
  return;
6613
6630
  }
6614
6631
  e.track.addEventListener('mute', () => {
6615
- logger$1('info', `[onTrack]: Track muted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
6632
+ logger$2('info', `[onTrack]: Track muted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
6616
6633
  });
6617
6634
  e.track.addEventListener('unmute', () => {
6618
- logger$1('info', `[onTrack]: Track unmuted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
6635
+ logger$2('info', `[onTrack]: Track unmuted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
6619
6636
  });
6620
6637
  e.track.addEventListener('ended', () => {
6621
- logger$1('info', `[onTrack]: Track ended: ${participantToUpdate.userId} ${trackType}:${trackId}`);
6638
+ logger$2('info', `[onTrack]: Track ended: ${participantToUpdate.userId} ${trackType}:${trackId}`);
6622
6639
  });
6623
6640
  const streamKindProp = {
6624
6641
  TRACK_TYPE_AUDIO: 'audioStream',
@@ -6626,12 +6643,12 @@ class Subscriber {
6626
6643
  TRACK_TYPE_SCREEN_SHARE: 'screenShareStream',
6627
6644
  }[trackType];
6628
6645
  if (!streamKindProp) {
6629
- logger$1('error', `Unknown track type: ${trackType}`);
6646
+ logger$2('error', `Unknown track type: ${trackType}`);
6630
6647
  return;
6631
6648
  }
6632
6649
  const previousStream = participantToUpdate[streamKindProp];
6633
6650
  if (previousStream) {
6634
- logger$1('info', `[onTrack]: Cleaning up previous remote ${e.track.kind} tracks for userId: ${participantToUpdate.userId}`);
6651
+ logger$2('info', `[onTrack]: Cleaning up previous remote ${e.track.kind} tracks for userId: ${participantToUpdate.userId}`);
6635
6652
  previousStream.getTracks().forEach((t) => {
6636
6653
  t.stop();
6637
6654
  previousStream.removeTrack(t);
@@ -6644,7 +6661,7 @@ class Subscriber {
6644
6661
  this.onIceCandidate = (e) => __awaiter(this, void 0, void 0, function* () {
6645
6662
  const { candidate } = e;
6646
6663
  if (!candidate) {
6647
- logger$1('debug', 'null ice candidate');
6664
+ logger$2('debug', 'null ice candidate');
6648
6665
  return;
6649
6666
  }
6650
6667
  yield this.sfuClient.iceTrickle({
@@ -6653,7 +6670,7 @@ class Subscriber {
6653
6670
  });
6654
6671
  });
6655
6672
  this.negotiate = (subscriberOffer) => __awaiter(this, void 0, void 0, function* () {
6656
- logger$1('info', `Received subscriberOffer`, subscriberOffer);
6673
+ logger$2('info', `Received subscriberOffer`, subscriberOffer);
6657
6674
  yield this.pc.setRemoteDescription({
6658
6675
  type: 'offer',
6659
6676
  sdp: subscriberOffer.sdp,
@@ -6664,7 +6681,7 @@ class Subscriber {
6664
6681
  yield this.pc.addIceCandidate(iceCandidate);
6665
6682
  }
6666
6683
  catch (e) {
6667
- logger$1('error', `ICE candidate error`, [e, candidate]);
6684
+ logger$2('error', `ICE candidate error`, [e, candidate]);
6668
6685
  }
6669
6686
  }));
6670
6687
  // apply ice candidates
@@ -6676,15 +6693,15 @@ class Subscriber {
6676
6693
  });
6677
6694
  });
6678
6695
  this.onIceConnectionStateChange = () => {
6679
- logger$1('info', `ICE connection state changed`, this.pc.iceConnectionState);
6696
+ logger$2('info', `ICE connection state changed`, this.pc.iceConnectionState);
6680
6697
  };
6681
6698
  this.onIceGatheringStateChange = () => {
6682
- logger$1('info', `ICE gathering state changed`, this.pc.iceGatheringState);
6699
+ logger$2('info', `ICE gathering state changed`, this.pc.iceGatheringState);
6683
6700
  };
6684
6701
  this.onIceCandidateError = (e) => {
6685
6702
  const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
6686
6703
  `${e.errorCode}: ${e.errorText}`;
6687
- logger$1('error', `ICE Candidate error`, errorMessage);
6704
+ logger$2('error', `ICE Candidate error`, errorMessage);
6688
6705
  };
6689
6706
  this.sfuClient = sfuClient;
6690
6707
  this.dispatcher = dispatcher;
@@ -8013,7 +8030,7 @@ const watchCallGrantsUpdated = (state) => {
8013
8030
  };
8014
8031
  };
8015
8032
 
8016
- const logger = getLogger(['events']);
8033
+ const logger$1 = getLogger(['events']);
8017
8034
  /**
8018
8035
  * An event responder which handles the `changePublishQuality` event.
8019
8036
  */
@@ -8078,7 +8095,7 @@ const watchSfuErrorReports = (dispatcher) => {
8078
8095
  if (e.eventPayload.oneofKind !== 'error' || !e.eventPayload.error.error)
8079
8096
  return;
8080
8097
  const error = e.eventPayload.error.error;
8081
- logger('error', 'SFU reported error', {
8098
+ logger$1('error', 'SFU reported error', {
8082
8099
  code: ErrorCode[error.code],
8083
8100
  message: error.message,
8084
8101
  shouldRetry: error.shouldRetry,
@@ -8525,7 +8542,7 @@ const join = (httpClient, type, id, data) => __awaiter(void 0, void 0, void 0, f
8525
8542
  };
8526
8543
  });
8527
8544
  const doJoin = (httpClient, type, id, data) => __awaiter(void 0, void 0, void 0, function* () {
8528
- const location = yield getLocationHint();
8545
+ const location = yield httpClient.getLocationHint();
8529
8546
  const request = Object.assign(Object.assign({}, data), { location });
8530
8547
  // FIXME OL: remove this once cascading is enabled by default
8531
8548
  const cascadingModeParams = getCascadingModeParams();
@@ -8540,28 +8557,6 @@ const doJoin = (httpClient, type, id, data) => __awaiter(void 0, void 0, void 0,
8540
8557
  }
8541
8558
  return httpClient.post(`/call/${type}/${id}/join`, request);
8542
8559
  });
8543
- const getLocationHint = () => __awaiter(void 0, void 0, void 0, function* () {
8544
- const hintURL = `https://hint.stream-io-video.com/`;
8545
- const abortController = new AbortController();
8546
- const timeoutId = setTimeout(() => abortController.abort(), 1000);
8547
- const logger = getLogger(['call']);
8548
- try {
8549
- const response = yield fetch(hintURL, {
8550
- method: 'HEAD',
8551
- signal: abortController.signal,
8552
- });
8553
- const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
8554
- logger === null || logger === void 0 ? void 0 : logger('info', `Location header: ${awsPop}`);
8555
- return awsPop.substring(0, 3); // AMS1-P2 -> AMS
8556
- }
8557
- catch (e) {
8558
- logger === null || logger === void 0 ? void 0 : logger('error', `Failed to get location hint from ${hintURL}`, e);
8559
- return 'ERR';
8560
- }
8561
- finally {
8562
- clearTimeout(timeoutId);
8563
- }
8564
- });
8565
8560
  const toRtcConfiguration = (config) => {
8566
8561
  if (!config || config.length === 0)
8567
8562
  return undefined;
@@ -11330,7 +11325,30 @@ class WSConnectionFallback {
11330
11325
  }
11331
11326
  }
11332
11327
 
11333
- const version = '0.0.46';
11328
+ const version = '0.0.48';
11329
+
11330
+ const logger = getLogger(['location']);
11331
+ const HINT_URL = `https://hint.stream-io-video.com/`;
11332
+ const getLocationHint = (hintUrl = HINT_URL, timeout = 1500) => __awaiter(void 0, void 0, void 0, function* () {
11333
+ const abortController = new AbortController();
11334
+ const timeoutId = setTimeout(() => abortController.abort(), timeout);
11335
+ try {
11336
+ const response = yield fetch(HINT_URL, {
11337
+ method: 'HEAD',
11338
+ signal: abortController.signal,
11339
+ });
11340
+ const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
11341
+ logger('debug', `Location header: ${awsPop}`);
11342
+ return awsPop.substring(0, 3); // AMS1-P2 -> AMS
11343
+ }
11344
+ catch (e) {
11345
+ logger('error', `Failed to get location hint from ${HINT_URL}`, e);
11346
+ return 'ERR';
11347
+ }
11348
+ finally {
11349
+ clearTimeout(timeoutId);
11350
+ }
11351
+ });
11334
11352
 
11335
11353
  class StreamClient {
11336
11354
  /**
@@ -11360,6 +11378,14 @@ class StreamClient {
11360
11378
  .replace('http', 'ws')
11361
11379
  .replace(':3030', ':8800');
11362
11380
  };
11381
+ this.getLocationHint = (hintUrl, timeout) => __awaiter(this, void 0, void 0, function* () {
11382
+ const hint = yield this.locationHint;
11383
+ if (!hint || hint === 'ERR') {
11384
+ this.locationHint = getLocationHint(hintUrl !== null && hintUrl !== void 0 ? hintUrl : this.options.locationHintUrl, timeout !== null && timeout !== void 0 ? timeout : this.options.locationHintTimeout);
11385
+ return this.locationHint;
11386
+ }
11387
+ return hint;
11388
+ });
11363
11389
  this._getConnectionID = () => { var _a, _b; return ((_a = this.wsConnection) === null || _a === void 0 ? void 0 : _a.connectionID) || ((_b = this.wsFallback) === null || _b === void 0 ? void 0 : _b.connectionID); };
11364
11390
  this._hasConnectionID = () => Boolean(this._getConnectionID());
11365
11391
  /**
@@ -11880,6 +11906,9 @@ class StreamClient {
11880
11906
  };
11881
11907
  this.browser = inputOptions.browser || typeof window !== 'undefined';
11882
11908
  this.node = !this.browser;
11909
+ if (this.browser) {
11910
+ this.locationHint = getLocationHint(options === null || options === void 0 ? void 0 : options.locationHintUrl, options === null || options === void 0 ? void 0 : options.locationHintTimeout);
11911
+ }
11883
11912
  this.options = Object.assign({ timeout: 5000, withCredentials: false, warmUp: false }, inputOptions);
11884
11913
  if (this.node && !this.options.httpsAgent) {
11885
11914
  this.options.httpsAgent = new https.Agent({