@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 +14 -0
- package/dist/index.browser.es.js +82 -53
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +82 -53
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +82 -53
- package/dist/index.es.js.map +1 -1
- package/dist/src/coordinator/connection/client.d.ts +2 -0
- package/dist/src/coordinator/connection/location.d.ts +1 -0
- package/dist/src/coordinator/connection/types.d.ts +8 -0
- package/dist/src/rtc/Publisher.d.ts +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/coordinator/connection/client.ts +25 -0
- package/src/coordinator/connection/location.ts +26 -0
- package/src/coordinator/connection/types.ts +8 -0
- package/src/rtc/Publisher.ts +25 -9
- package/src/rtc/flows/join.ts +1 -23
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
|
|
package/dist/index.browser.es.js
CHANGED
|
@@ -5665,7 +5665,7 @@ const logLevels = Object.freeze({
|
|
|
5665
5665
|
warn: 3,
|
|
5666
5666
|
error: 4,
|
|
5667
5667
|
});
|
|
5668
|
-
let logger$
|
|
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$
|
|
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$
|
|
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.
|
|
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'
|
|
6468
|
-
this.logger('warn', `
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
6632
|
+
logger$2('info', `[onTrack]: Track muted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
|
|
6616
6633
|
});
|
|
6617
6634
|
e.track.addEventListener('unmute', () => {
|
|
6618
|
-
logger$
|
|
6635
|
+
logger$2('info', `[onTrack]: Track unmuted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
|
|
6619
6636
|
});
|
|
6620
6637
|
e.track.addEventListener('ended', () => {
|
|
6621
|
-
logger$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
6696
|
+
logger$2('info', `ICE connection state changed`, this.pc.iceConnectionState);
|
|
6680
6697
|
};
|
|
6681
6698
|
this.onIceGatheringStateChange = () => {
|
|
6682
|
-
logger$
|
|
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$
|
|
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.
|
|
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({
|