livekit-client 2.13.0 → 2.13.2
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/livekit-client.e2ee.worker.js +1 -1
- package/dist/livekit-client.e2ee.worker.js.map +1 -1
- package/dist/livekit-client.e2ee.worker.mjs +1 -0
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +383 -117
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +1 -1
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +6 -2
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/defaults.d.ts.map +1 -1
- package/dist/src/room/errors.d.ts +2 -1
- package/dist/src/room/errors.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +5 -1
- package/dist/src/room/events.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +9 -0
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/Participant.d.ts +1 -1
- package/dist/src/room/participant/Participant.d.ts.map +1 -1
- package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrack.d.ts +10 -0
- package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +1 -0
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/room/track/options.d.ts +8 -0
- package/dist/src/room/track/options.d.ts.map +1 -1
- package/dist/src/room/track/record.d.ts +6 -0
- package/dist/src/room/track/record.d.ts.map +1 -0
- package/dist/src/room/utils.d.ts +3 -0
- package/dist/src/room/utils.d.ts.map +1 -1
- package/dist/ts4.2/src/index.d.ts +1 -0
- package/dist/ts4.2/src/room/RTCEngine.d.ts +1 -1
- package/dist/ts4.2/src/room/Room.d.ts +5 -1
- package/dist/ts4.2/src/room/errors.d.ts +2 -1
- package/dist/ts4.2/src/room/events.d.ts +5 -1
- package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +9 -0
- package/dist/ts4.2/src/room/participant/Participant.d.ts +1 -1
- package/dist/ts4.2/src/room/track/LocalTrack.d.ts +10 -0
- package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +1 -1
- package/dist/ts4.2/src/room/track/Track.d.ts +1 -0
- package/dist/ts4.2/src/room/track/options.d.ts +8 -0
- package/dist/ts4.2/src/room/track/record.d.ts +6 -0
- package/dist/ts4.2/src/room/utils.d.ts +3 -0
- package/package.json +13 -12
- package/src/e2ee/worker/tsconfig.json +9 -1
- package/src/index.ts +2 -0
- package/src/room/RTCEngine.ts +7 -7
- package/src/room/Room.ts +23 -8
- package/src/room/defaults.ts +1 -0
- package/src/room/errors.ts +1 -0
- package/src/room/events.ts +5 -0
- package/src/room/participant/LocalParticipant.ts +215 -34
- package/src/room/participant/Participant.ts +1 -1
- package/src/room/participant/publishUtils.ts +4 -0
- package/src/room/track/LocalTrack.ts +47 -2
- package/src/room/track/LocalVideoTrack.ts +14 -5
- package/src/room/track/Track.ts +1 -0
- package/src/room/track/options.ts +9 -0
- package/src/room/track/record.ts +51 -0
- package/src/room/utils.ts +14 -1
@@ -7182,7 +7182,7 @@ let deprecationWarnings_ = true;
|
|
7182
7182
|
*/
|
7183
7183
|
function extractVersion(uastring, expr, pos) {
|
7184
7184
|
const match = uastring.match(expr);
|
7185
|
-
return match && match.length >= pos &&
|
7185
|
+
return match && match.length >= pos && parseFloat(match[pos], 10);
|
7186
7186
|
}
|
7187
7187
|
|
7188
7188
|
// Wraps the peerconnection event eventNameToWrap in a function
|
@@ -7327,19 +7327,21 @@ function detectBrowser(window) {
|
|
7327
7327
|
if (navigator.mozGetUserMedia) {
|
7328
7328
|
// Firefox.
|
7329
7329
|
result.browser = 'firefox';
|
7330
|
-
result.version = extractVersion(navigator.userAgent, /Firefox\/(\d+)\./, 1);
|
7330
|
+
result.version = parseInt(extractVersion(navigator.userAgent, /Firefox\/(\d+)\./, 1));
|
7331
7331
|
} else if (navigator.webkitGetUserMedia || window.isSecureContext === false && window.webkitRTCPeerConnection) {
|
7332
7332
|
// Chrome, Chromium, Webview, Opera.
|
7333
7333
|
// Version matches Chrome/WebRTC version.
|
7334
7334
|
// Chrome 74 removed webkitGetUserMedia on http as well so we need the
|
7335
7335
|
// more complicated fallback to webkitRTCPeerConnection.
|
7336
7336
|
result.browser = 'chrome';
|
7337
|
-
result.version = extractVersion(navigator.userAgent, /Chrom(e|ium)\/(\d+)\./, 2);
|
7337
|
+
result.version = parseInt(extractVersion(navigator.userAgent, /Chrom(e|ium)\/(\d+)\./, 2));
|
7338
7338
|
} else if (window.RTCPeerConnection && navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) {
|
7339
7339
|
// Safari.
|
7340
7340
|
result.browser = 'safari';
|
7341
|
-
result.version = extractVersion(navigator.userAgent, /AppleWebKit\/(\d+)\./, 1);
|
7341
|
+
result.version = parseInt(extractVersion(navigator.userAgent, /AppleWebKit\/(\d+)\./, 1));
|
7342
7342
|
result.supportsUnifiedPlan = window.RTCRtpTransceiver && 'currentDirection' in window.RTCRtpTransceiver.prototype;
|
7343
|
+
// Only for internal usage.
|
7344
|
+
result._safariVersion = extractVersion(navigator.userAgent, /Version\/(\d+(\.?\d+))/, 1);
|
7343
7345
|
} else {
|
7344
7346
|
// Default fallthrough: not supported.
|
7345
7347
|
result.browser = 'Not a supported browser.';
|
@@ -9940,7 +9942,7 @@ function removeExtmapAllowMixed(window, browserDetails) {
|
|
9940
9942
|
if (browserDetails.browser === 'chrome' && browserDetails.version >= 71) {
|
9941
9943
|
return;
|
9942
9944
|
}
|
9943
|
-
if (browserDetails.browser === 'safari' && browserDetails.
|
9945
|
+
if (browserDetails.browser === 'safari' && browserDetails._safariVersion >= 13.1) {
|
9944
9946
|
return;
|
9945
9947
|
}
|
9946
9948
|
const nativeSRD = window.RTCPeerConnection.prototype.setRemoteDescription;
|
@@ -10477,6 +10479,7 @@ var ConnectionErrorReason;
|
|
10477
10479
|
ConnectionErrorReason[ConnectionErrorReason["InternalError"] = 2] = "InternalError";
|
10478
10480
|
ConnectionErrorReason[ConnectionErrorReason["Cancelled"] = 3] = "Cancelled";
|
10479
10481
|
ConnectionErrorReason[ConnectionErrorReason["LeaveRequest"] = 4] = "LeaveRequest";
|
10482
|
+
ConnectionErrorReason[ConnectionErrorReason["Timeout"] = 5] = "Timeout";
|
10480
10483
|
})(ConnectionErrorReason || (ConnectionErrorReason = {}));
|
10481
10484
|
class ConnectionError extends LivekitError {
|
10482
10485
|
constructor(message, reason, status, context) {
|
@@ -11178,6 +11181,10 @@ var TrackEvent;
|
|
11178
11181
|
* @experimental
|
11179
11182
|
*/
|
11180
11183
|
TrackEvent["TimeSyncUpdate"] = "timeSyncUpdate";
|
11184
|
+
/**
|
11185
|
+
* @internal
|
11186
|
+
*/
|
11187
|
+
TrackEvent["PreConnectBufferFlushed"] = "preConnectBufferFlushed";
|
11181
11188
|
})(TrackEvent || (TrackEvent = {}));
|
11182
11189
|
|
11183
11190
|
function cloneDeep(value) {
|
@@ -11259,7 +11266,7 @@ function getOSVersion(ua) {
|
|
11259
11266
|
return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
|
11260
11267
|
}
|
11261
11268
|
|
11262
|
-
var version$1 = "2.13.
|
11269
|
+
var version$1 = "2.13.2";
|
11263
11270
|
|
11264
11271
|
const version = version$1;
|
11265
11272
|
const protocolVersion = 16;
|
@@ -11869,10 +11876,21 @@ function isSafari() {
|
|
11869
11876
|
var _a;
|
11870
11877
|
return ((_a = getBrowser()) === null || _a === void 0 ? void 0 : _a.name) === 'Safari';
|
11871
11878
|
}
|
11879
|
+
function isSafariBased() {
|
11880
|
+
const b = getBrowser();
|
11881
|
+
return (b === null || b === void 0 ? void 0 : b.name) === 'Safari' || (b === null || b === void 0 ? void 0 : b.os) === 'iOS';
|
11882
|
+
}
|
11872
11883
|
function isSafari17() {
|
11873
11884
|
const b = getBrowser();
|
11874
11885
|
return (b === null || b === void 0 ? void 0 : b.name) === 'Safari' && b.version.startsWith('17.');
|
11875
11886
|
}
|
11887
|
+
function isSafariSvcApi(browser) {
|
11888
|
+
if (!browser) {
|
11889
|
+
browser = getBrowser();
|
11890
|
+
}
|
11891
|
+
// Safari 18.4 requires legacy svc api and scaleResolutionDown to be set
|
11892
|
+
return (browser === null || browser === void 0 ? void 0 : browser.name) === 'Safari' && compareVersions(browser.version, '18.3') > 0;
|
11893
|
+
}
|
11876
11894
|
function isMobile() {
|
11877
11895
|
var _a, _b;
|
11878
11896
|
if (!isWeb()) return false;
|
@@ -15066,7 +15084,8 @@ const publishDefaults = {
|
|
15066
15084
|
screenShareEncoding: ScreenSharePresets.h1080fps15.encoding,
|
15067
15085
|
stopMicTrackOnMute: false,
|
15068
15086
|
videoCodec: defaultVideoCodec,
|
15069
|
-
backupCodec: true
|
15087
|
+
backupCodec: true,
|
15088
|
+
preConnectBuffer: false
|
15070
15089
|
};
|
15071
15090
|
const audioDefaults = {
|
15072
15091
|
deviceId: {
|
@@ -15514,7 +15533,49 @@ function computeBitrate(currentStats, prevStats) {
|
|
15514
15533
|
return (bytesNow - bytesPrev) * 8 * 1000 / (currentStats.timestamp - prevStats.timestamp);
|
15515
15534
|
}
|
15516
15535
|
|
15517
|
-
|
15536
|
+
class LocalTrackRecorder extends MediaRecorder {
|
15537
|
+
constructor(track, options) {
|
15538
|
+
super(new MediaStream([track.mediaStreamTrack]), options);
|
15539
|
+
let dataListener;
|
15540
|
+
let streamController;
|
15541
|
+
const isClosed = () => streamController === undefined;
|
15542
|
+
const onStop = () => {
|
15543
|
+
this.removeEventListener('dataavailable', dataListener);
|
15544
|
+
this.removeEventListener('stop', onStop);
|
15545
|
+
this.removeEventListener('error', onError);
|
15546
|
+
streamController === null || streamController === void 0 ? void 0 : streamController.close();
|
15547
|
+
streamController = undefined;
|
15548
|
+
};
|
15549
|
+
const onError = event => {
|
15550
|
+
streamController === null || streamController === void 0 ? void 0 : streamController.error(event);
|
15551
|
+
this.removeEventListener('dataavailable', dataListener);
|
15552
|
+
this.removeEventListener('stop', onStop);
|
15553
|
+
this.removeEventListener('error', onError);
|
15554
|
+
streamController = undefined;
|
15555
|
+
};
|
15556
|
+
this.byteStream = new ReadableStream({
|
15557
|
+
start: controller => {
|
15558
|
+
streamController = controller;
|
15559
|
+
dataListener = event => __awaiter(this, void 0, void 0, function* () {
|
15560
|
+
const arrayBuffer = yield event.data.arrayBuffer();
|
15561
|
+
if (isClosed()) {
|
15562
|
+
return;
|
15563
|
+
}
|
15564
|
+
controller.enqueue(new Uint8Array(arrayBuffer));
|
15565
|
+
});
|
15566
|
+
this.addEventListener('dataavailable', dataListener);
|
15567
|
+
},
|
15568
|
+
cancel: () => {
|
15569
|
+
onStop();
|
15570
|
+
}
|
15571
|
+
});
|
15572
|
+
this.addEventListener('stop', onStop);
|
15573
|
+
this.addEventListener('error', onError);
|
15574
|
+
}
|
15575
|
+
}
|
15576
|
+
|
15577
|
+
const DEFAULT_DIMENSIONS_TIMEOUT = 1000;
|
15578
|
+
const PRE_CONNECT_BUFFER_TIMEOUT = 10000;
|
15518
15579
|
class LocalTrack extends Track {
|
15519
15580
|
/** @internal */
|
15520
15581
|
get sender() {
|
@@ -15527,6 +15588,9 @@ class LocalTrack extends Track {
|
|
15527
15588
|
get constraints() {
|
15528
15589
|
return this._constraints;
|
15529
15590
|
}
|
15591
|
+
get hasPreConnectBuffer() {
|
15592
|
+
return !!this.localTrackRecorder;
|
15593
|
+
}
|
15530
15594
|
/**
|
15531
15595
|
*
|
15532
15596
|
* @param mediaTrack
|
@@ -15682,7 +15746,7 @@ class LocalTrack extends Track {
|
|
15682
15746
|
waitForDimensions() {
|
15683
15747
|
return __awaiter(this, arguments, void 0, function () {
|
15684
15748
|
var _this = this;
|
15685
|
-
let timeout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] :
|
15749
|
+
let timeout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_DIMENSIONS_TIMEOUT;
|
15686
15750
|
return function* () {
|
15687
15751
|
var _a;
|
15688
15752
|
if (_this.kind === Track.Kind.Audio) {
|
@@ -16037,6 +16101,36 @@ class LocalTrack extends Track {
|
|
16037
16101
|
}();
|
16038
16102
|
});
|
16039
16103
|
}
|
16104
|
+
/** @internal */
|
16105
|
+
startPreConnectBuffer() {
|
16106
|
+
let timeslice = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 100;
|
16107
|
+
if (!this.localTrackRecorder) {
|
16108
|
+
this.localTrackRecorder = new LocalTrackRecorder(this, {
|
16109
|
+
mimeType: 'audio/webm;codecs=opus'
|
16110
|
+
});
|
16111
|
+
} else {
|
16112
|
+
this.log.warn('preconnect buffer already started');
|
16113
|
+
return;
|
16114
|
+
}
|
16115
|
+
this.localTrackRecorder.start(timeslice);
|
16116
|
+
this.autoStopPreConnectBuffer = setTimeout(() => {
|
16117
|
+
this.log.warn('preconnect buffer timed out, stopping recording automatically', this.logContext);
|
16118
|
+
this.stopPreConnectBuffer();
|
16119
|
+
}, PRE_CONNECT_BUFFER_TIMEOUT);
|
16120
|
+
}
|
16121
|
+
/** @internal */
|
16122
|
+
stopPreConnectBuffer() {
|
16123
|
+
clearTimeout(this.autoStopPreConnectBuffer);
|
16124
|
+
if (this.localTrackRecorder) {
|
16125
|
+
this.localTrackRecorder.stop();
|
16126
|
+
this.localTrackRecorder = undefined;
|
16127
|
+
}
|
16128
|
+
}
|
16129
|
+
/** @internal */
|
16130
|
+
getPreConnectBuffer() {
|
16131
|
+
var _a;
|
16132
|
+
return (_a = this.localTrackRecorder) === null || _a === void 0 ? void 0 : _a.byteStream;
|
16133
|
+
}
|
16040
16134
|
}
|
16041
16135
|
|
16042
16136
|
class LocalAudioTrack extends LocalTrack {
|
@@ -16349,12 +16443,15 @@ function computeVideoEncodings(isScreenShare, width, height, options) {
|
|
16349
16443
|
// TODO: when we upstream libwebrtc, this will need additional verification
|
16350
16444
|
isReactNative() || (browser === null || browser === void 0 ? void 0 : browser.name) === 'Chrome' && compareVersions(browser === null || browser === void 0 ? void 0 : browser.version, '113') < 0) {
|
16351
16445
|
const bitratesRatio = sm.suffix == 'h' ? 2 : 3;
|
16446
|
+
// safari 18.4 uses a different svc API that requires scaleResolutionDownBy to be set.
|
16447
|
+
const requireScale = isSafariSvcApi(browser);
|
16352
16448
|
for (let i = 0; i < sm.spatial; i += 1) {
|
16353
16449
|
// in legacy SVC, scaleResolutionDownBy cannot be set
|
16354
16450
|
encodings.push({
|
16355
16451
|
rid: videoRids[2 - i],
|
16356
16452
|
maxBitrate: videoEncoding.maxBitrate / Math.pow(bitratesRatio, i),
|
16357
|
-
maxFramerate: original.encoding.maxFramerate
|
16453
|
+
maxFramerate: original.encoding.maxFramerate,
|
16454
|
+
scaleResolutionDownBy: requireScale ? Math.pow(2, i) : undefined
|
16358
16455
|
});
|
16359
16456
|
}
|
16360
16457
|
// legacy SVC, scalabilityMode is set only on the first encoding
|
@@ -16861,7 +16958,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
16861
16958
|
}));
|
16862
16959
|
}
|
16863
16960
|
this.log.debug("setting publishing quality. max quality ".concat(maxQuality), this.logContext);
|
16864
|
-
this.setPublishingLayers(qualities);
|
16961
|
+
this.setPublishingLayers(isSVCCodec(this.codec), qualities);
|
16865
16962
|
}
|
16866
16963
|
restartTrack(options) {
|
16867
16964
|
return __awaiter(this, void 0, void 0, function* () {
|
@@ -16996,7 +17093,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
16996
17093
|
}));
|
16997
17094
|
// only enable simulcast codec for preference codec setted
|
16998
17095
|
if (!this.codec && codecs.length > 0) {
|
16999
|
-
yield this.setPublishingLayers(codecs[0].qualities);
|
17096
|
+
yield this.setPublishingLayers(isSVCCodec(codecs[0].codec), codecs[0].qualities);
|
17000
17097
|
return [];
|
17001
17098
|
}
|
17002
17099
|
this.subscribedCodecs = codecs;
|
@@ -17007,7 +17104,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
17007
17104
|
_a = false;
|
17008
17105
|
const codec = _d;
|
17009
17106
|
if (!this.codec || this.codec === codec.codec) {
|
17010
|
-
yield this.setPublishingLayers(codec.qualities);
|
17107
|
+
yield this.setPublishingLayers(isSVCCodec(codec.codec), codec.qualities);
|
17011
17108
|
} else {
|
17012
17109
|
const simulcastCodecInfo = this.simulcastCodecs.get(codec.codec);
|
17013
17110
|
this.log.debug("try setPublishingCodec for ".concat(codec.codec), Object.assign(Object.assign({}, this.logContext), {
|
@@ -17022,7 +17119,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
17022
17119
|
}
|
17023
17120
|
} else if (simulcastCodecInfo.encodings) {
|
17024
17121
|
this.log.debug("try setPublishingLayersForSender ".concat(codec.codec), this.logContext);
|
17025
|
-
yield setPublishingLayersForSender(simulcastCodecInfo.sender, simulcastCodecInfo.encodings, codec.qualities, this.senderLock, this.log, this.logContext);
|
17122
|
+
yield setPublishingLayersForSender(simulcastCodecInfo.sender, simulcastCodecInfo.encodings, codec.qualities, this.senderLock, isSVCCodec(codec.codec), this.log, this.logContext);
|
17026
17123
|
}
|
17027
17124
|
}
|
17028
17125
|
}
|
@@ -17044,7 +17141,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
17044
17141
|
* @internal
|
17045
17142
|
* Sets layers that should be publishing
|
17046
17143
|
*/
|
17047
|
-
setPublishingLayers(qualities) {
|
17144
|
+
setPublishingLayers(isSvc, qualities) {
|
17048
17145
|
return __awaiter(this, void 0, void 0, function* () {
|
17049
17146
|
this.log.debug('setting publishing layers', Object.assign(Object.assign({}, this.logContext), {
|
17050
17147
|
qualities
|
@@ -17052,7 +17149,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
17052
17149
|
if (!this.sender || !this.encodings) {
|
17053
17150
|
return;
|
17054
17151
|
}
|
17055
|
-
yield setPublishingLayersForSender(this.sender, this.encodings, qualities, this.senderLock, this.log, this.logContext);
|
17152
|
+
yield setPublishingLayersForSender(this.sender, this.encodings, qualities, this.senderLock, isSvc, this.log, this.logContext);
|
17056
17153
|
});
|
17057
17154
|
}
|
17058
17155
|
handleAppVisibilityChanged() {
|
@@ -17070,7 +17167,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
17070
17167
|
});
|
17071
17168
|
}
|
17072
17169
|
}
|
17073
|
-
function setPublishingLayersForSender(sender, senderEncodings, qualities, senderLock, log, logContext) {
|
17170
|
+
function setPublishingLayersForSender(sender, senderEncodings, qualities, senderLock, isSVC, log, logContext) {
|
17074
17171
|
return __awaiter(this, void 0, void 0, function* () {
|
17075
17172
|
const unlock = yield senderLock.lock();
|
17076
17173
|
log.debug('setPublishingLayersForSender', Object.assign(Object.assign({}, logContext), {
|
@@ -17132,6 +17229,12 @@ function setPublishingLayersForSender(sender, senderEncodings, qualities, sender
|
|
17132
17229
|
}
|
17133
17230
|
}
|
17134
17231
|
} else {
|
17232
|
+
if (isSVC) {
|
17233
|
+
const hasEnabledEncoding = qualities.some(q => q.enabled);
|
17234
|
+
if (hasEnabledEncoding) {
|
17235
|
+
qualities.forEach(q => q.enabled = true);
|
17236
|
+
}
|
17237
|
+
}
|
17135
17238
|
// simulcast dynacast encodings
|
17136
17239
|
encodings.forEach((encoding, idx) => {
|
17137
17240
|
var _a;
|
@@ -17445,12 +17548,12 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17445
17548
|
}
|
17446
17549
|
/** @internal */
|
17447
17550
|
get logContext() {
|
17448
|
-
var _a, _b, _c, _d, _e, _f
|
17551
|
+
var _a, _b, _c, _d, _e, _f;
|
17449
17552
|
return {
|
17450
17553
|
room: (_b = (_a = this.latestJoinResponse) === null || _a === void 0 ? void 0 : _a.room) === null || _b === void 0 ? void 0 : _b.name,
|
17451
17554
|
roomID: (_d = (_c = this.latestJoinResponse) === null || _c === void 0 ? void 0 : _c.room) === null || _d === void 0 ? void 0 : _d.sid,
|
17452
17555
|
participant: (_f = (_e = this.latestJoinResponse) === null || _e === void 0 ? void 0 : _e.participant) === null || _f === void 0 ? void 0 : _f.identity,
|
17453
|
-
pID:
|
17556
|
+
pID: this.participantSid
|
17454
17557
|
};
|
17455
17558
|
}
|
17456
17559
|
join(url, token, opts, abortSignal) {
|
@@ -17474,10 +17577,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17474
17577
|
this.negotiate();
|
17475
17578
|
}
|
17476
17579
|
this.clientConfiguration = joinResponse.clientConfiguration;
|
17477
|
-
|
17478
|
-
setTimeout(() => {
|
17479
|
-
this.emit(EngineEvent.SignalConnected);
|
17480
|
-
}, 10);
|
17580
|
+
this.emit(EngineEvent.SignalConnected, joinResponse);
|
17481
17581
|
return joinResponse;
|
17482
17582
|
} catch (e) {
|
17483
17583
|
if (e instanceof ConnectionError) {
|
@@ -17551,7 +17651,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17551
17651
|
return new Promise((resolve, reject) => {
|
17552
17652
|
const publicationTimeout = setTimeout(() => {
|
17553
17653
|
delete this.pendingTrackResolvers[req.cid];
|
17554
|
-
reject(new ConnectionError('publication of local track timed out, no response from server', ConnectionErrorReason.
|
17654
|
+
reject(new ConnectionError('publication of local track timed out, no response from server', ConnectionErrorReason.Timeout));
|
17555
17655
|
}, 10000);
|
17556
17656
|
this.pendingTrackResolvers[req.cid] = {
|
17557
17657
|
resolve: info => {
|
@@ -17727,6 +17827,9 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17727
17827
|
this.client.onRoomMoved = res => {
|
17728
17828
|
var _a;
|
17729
17829
|
this.participantSid = (_a = res.participant) === null || _a === void 0 ? void 0 : _a.sid;
|
17830
|
+
if (this.latestJoinResponse) {
|
17831
|
+
this.latestJoinResponse.room = res.room;
|
17832
|
+
}
|
17730
17833
|
this.emit(EngineEvent.RoomMoved, res);
|
17731
17834
|
};
|
17732
17835
|
this.client.onClose = () => {
|
@@ -20027,12 +20130,29 @@ class LocalParticipant extends Participant {
|
|
20027
20130
|
this.updateTrackSubscriptionPermissions();
|
20028
20131
|
};
|
20029
20132
|
this.handleDisconnected = () => {
|
20030
|
-
var _a, _b;
|
20133
|
+
var _a, _b, _c, _d, _e, _f;
|
20031
20134
|
if (this.reconnectFuture) {
|
20032
20135
|
this.reconnectFuture.promise.catch(e => this.log.warn(e.message, this.logContext));
|
20033
20136
|
(_b = (_a = this.reconnectFuture) === null || _a === void 0 ? void 0 : _a.reject) === null || _b === void 0 ? void 0 : _b.call(_a, 'Got disconnected during reconnection attempt');
|
20034
20137
|
this.reconnectFuture = undefined;
|
20035
20138
|
}
|
20139
|
+
if (this.signalConnectedFuture) {
|
20140
|
+
(_d = (_c = this.signalConnectedFuture).reject) === null || _d === void 0 ? void 0 : _d.call(_c, 'Got disconnected without signal connected');
|
20141
|
+
this.signalConnectedFuture = undefined;
|
20142
|
+
}
|
20143
|
+
(_f = (_e = this.activeAgentFuture) === null || _e === void 0 ? void 0 : _e.reject) === null || _f === void 0 ? void 0 : _f.call(_e, 'Got disconnected without active agent present');
|
20144
|
+
this.activeAgentFuture = undefined;
|
20145
|
+
this.firstActiveAgent = undefined;
|
20146
|
+
};
|
20147
|
+
this.handleSignalConnected = joinResponse => {
|
20148
|
+
var _a, _b;
|
20149
|
+
if (joinResponse.participant) {
|
20150
|
+
this.updateInfo(joinResponse.participant);
|
20151
|
+
}
|
20152
|
+
if (!this.signalConnectedFuture) {
|
20153
|
+
this.signalConnectedFuture = new Future();
|
20154
|
+
}
|
20155
|
+
(_b = (_a = this.signalConnectedFuture).resolve) === null || _b === void 0 ? void 0 : _b.call(_a);
|
20036
20156
|
};
|
20037
20157
|
this.handleSignalRequestResponse = response => {
|
20038
20158
|
const {
|
@@ -20108,7 +20228,7 @@ class LocalParticipant extends Participant {
|
|
20108
20228
|
};
|
20109
20229
|
this.handleSubscribedQualityUpdate = update => __awaiter(this, void 0, void 0, function* () {
|
20110
20230
|
var _a, e_1, _b, _c;
|
20111
|
-
var _d
|
20231
|
+
var _d;
|
20112
20232
|
if (!((_d = this.roomOptions) === null || _d === void 0 ? void 0 : _d.dynacast)) {
|
20113
20233
|
return;
|
20114
20234
|
}
|
@@ -20119,34 +20239,30 @@ class LocalParticipant extends Participant {
|
|
20119
20239
|
}));
|
20120
20240
|
return;
|
20121
20241
|
}
|
20122
|
-
if (
|
20123
|
-
|
20124
|
-
|
20242
|
+
if (!pub.videoTrack) {
|
20243
|
+
return;
|
20244
|
+
}
|
20245
|
+
const newCodecs = yield pub.videoTrack.setPublishingCodecs(update.subscribedCodecs);
|
20246
|
+
try {
|
20247
|
+
for (var _e = true, newCodecs_1 = __asyncValues(newCodecs), newCodecs_1_1; newCodecs_1_1 = yield newCodecs_1.next(), _a = newCodecs_1_1.done, !_a; _e = true) {
|
20248
|
+
_c = newCodecs_1_1.value;
|
20249
|
+
_e = false;
|
20250
|
+
const codec = _c;
|
20251
|
+
if (isBackupCodec(codec)) {
|
20252
|
+
this.log.debug("publish ".concat(codec, " for ").concat(pub.videoTrack.sid), Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(pub)));
|
20253
|
+
yield this.publishAdditionalCodecForTrack(pub.videoTrack, codec, pub.options);
|
20254
|
+
}
|
20125
20255
|
}
|
20126
|
-
|
20256
|
+
} catch (e_1_1) {
|
20257
|
+
e_1 = {
|
20258
|
+
error: e_1_1
|
20259
|
+
};
|
20260
|
+
} finally {
|
20127
20261
|
try {
|
20128
|
-
|
20129
|
-
_c = newCodecs_1_1.value;
|
20130
|
-
_f = false;
|
20131
|
-
const codec = _c;
|
20132
|
-
if (isBackupCodec(codec)) {
|
20133
|
-
this.log.debug("publish ".concat(codec, " for ").concat(pub.videoTrack.sid), Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(pub)));
|
20134
|
-
yield this.publishAdditionalCodecForTrack(pub.videoTrack, codec, pub.options);
|
20135
|
-
}
|
20136
|
-
}
|
20137
|
-
} catch (e_1_1) {
|
20138
|
-
e_1 = {
|
20139
|
-
error: e_1_1
|
20140
|
-
};
|
20262
|
+
if (!_e && !_a && (_b = newCodecs_1.return)) yield _b.call(newCodecs_1);
|
20141
20263
|
} finally {
|
20142
|
-
|
20143
|
-
if (!_f && !_a && (_b = newCodecs_1.return)) yield _b.call(newCodecs_1);
|
20144
|
-
} finally {
|
20145
|
-
if (e_1) throw e_1.error;
|
20146
|
-
}
|
20264
|
+
if (e_1) throw e_1.error;
|
20147
20265
|
}
|
20148
|
-
} else if (update.subscribedQualities.length > 0) {
|
20149
|
-
yield (_e = pub.videoTrack) === null || _e === void 0 ? void 0 : _e.setPublishingLayers(update.subscribedQualities);
|
20150
20266
|
}
|
20151
20267
|
});
|
20152
20268
|
this.handleLocalTrackUnpublished = unpublished => {
|
@@ -20255,7 +20371,7 @@ class LocalParticipant extends Participant {
|
|
20255
20371
|
pub.unmute();
|
20256
20372
|
}
|
20257
20373
|
});
|
20258
|
-
this.engine.on(EngineEvent.Connected, this.handleReconnected).on(EngineEvent.SignalRestarted, this.handleReconnected).on(EngineEvent.SignalResumed, this.handleReconnected).on(EngineEvent.Restarting, this.handleReconnecting).on(EngineEvent.Resuming, this.handleReconnecting).on(EngineEvent.LocalTrackUnpublished, this.handleLocalTrackUnpublished).on(EngineEvent.SubscribedQualityUpdate, this.handleSubscribedQualityUpdate).on(EngineEvent.Disconnected, this.handleDisconnected).on(EngineEvent.SignalRequestResponse, this.handleSignalRequestResponse).on(EngineEvent.DataPacketReceived, this.handleDataPacket);
|
20374
|
+
this.engine.on(EngineEvent.Connected, this.handleReconnected).on(EngineEvent.SignalConnected, this.handleSignalConnected).on(EngineEvent.SignalRestarted, this.handleReconnected).on(EngineEvent.SignalResumed, this.handleReconnected).on(EngineEvent.Restarting, this.handleReconnecting).on(EngineEvent.Resuming, this.handleReconnecting).on(EngineEvent.LocalTrackUnpublished, this.handleLocalTrackUnpublished).on(EngineEvent.SubscribedQualityUpdate, this.handleSubscribedQualityUpdate).on(EngineEvent.Disconnected, this.handleDisconnected).on(EngineEvent.SignalRequestResponse, this.handleSignalRequestResponse).on(EngineEvent.DataPacketReceived, this.handleDataPacket);
|
20259
20375
|
}
|
20260
20376
|
/**
|
20261
20377
|
* Sets and updates the metadata of the local participant.
|
@@ -20433,11 +20549,17 @@ class LocalParticipant extends Participant {
|
|
20433
20549
|
tr.stop();
|
20434
20550
|
});
|
20435
20551
|
if (e instanceof Error) {
|
20436
|
-
this.emit(ParticipantEvent.MediaDevicesError, e);
|
20552
|
+
this.emit(ParticipantEvent.MediaDevicesError, e, sourceToKind(source));
|
20437
20553
|
}
|
20438
20554
|
this.pendingPublishing.delete(source);
|
20439
20555
|
throw e;
|
20440
20556
|
}
|
20557
|
+
for (const localTrack of localTracks) {
|
20558
|
+
if (source === Track.Source.Microphone && isAudioTrack(localTrack) && (publishOptions === null || publishOptions === void 0 ? void 0 : publishOptions.preConnectBuffer)) {
|
20559
|
+
this.log.info('starting preconnect buffer for microphone', Object.assign({}, this.logContext));
|
20560
|
+
localTrack.startPreConnectBuffer();
|
20561
|
+
}
|
20562
|
+
}
|
20441
20563
|
try {
|
20442
20564
|
const publishPromises = [];
|
20443
20565
|
for (const localTrack of localTracks) {
|
@@ -20712,23 +20834,13 @@ class LocalParticipant extends Participant {
|
|
20712
20834
|
this.log.debug('deferring track publication until signal is connected', Object.assign(Object.assign({}, this.logContext), {
|
20713
20835
|
track: getLogContextFromTrack(track)
|
20714
20836
|
}));
|
20715
|
-
const
|
20716
|
-
try {
|
20717
|
-
const publication = yield this.publish(track, opts, isStereo);
|
20718
|
-
resolve(publication);
|
20719
|
-
} catch (e) {
|
20720
|
-
reject(e);
|
20721
|
-
}
|
20722
|
-
});
|
20723
|
-
setTimeout(() => {
|
20724
|
-
this.engine.off(EngineEvent.SignalConnected, onSignalConnected);
|
20837
|
+
const timeout = setTimeout(() => {
|
20725
20838
|
reject(new PublishTrackError('publishing rejected as engine not connected within timeout', 408));
|
20726
20839
|
}, 15000);
|
20727
|
-
this.
|
20728
|
-
|
20729
|
-
|
20730
|
-
|
20731
|
-
});
|
20840
|
+
yield this.waitUntilEngineConnected();
|
20841
|
+
clearTimeout(timeout);
|
20842
|
+
const publication = yield this.publish(track, opts, isStereo);
|
20843
|
+
resolve(publication);
|
20732
20844
|
} else {
|
20733
20845
|
try {
|
20734
20846
|
const publication = yield this.publish(track, opts, isStereo);
|
@@ -20753,6 +20865,12 @@ class LocalParticipant extends Participant {
|
|
20753
20865
|
}();
|
20754
20866
|
});
|
20755
20867
|
}
|
20868
|
+
waitUntilEngineConnected() {
|
20869
|
+
if (!this.signalConnectedFuture) {
|
20870
|
+
this.signalConnectedFuture = new Future();
|
20871
|
+
}
|
20872
|
+
return this.signalConnectedFuture.promise;
|
20873
|
+
}
|
20756
20874
|
hasPermissionsToPublish(track) {
|
20757
20875
|
if (!this.permissions) {
|
20758
20876
|
this.log.warn('no permissions present for publishing track', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
|
@@ -20810,6 +20928,27 @@ class LocalParticipant extends Participant {
|
|
20810
20928
|
track.on(TrackEvent.UpstreamPaused, this.onTrackUpstreamPaused);
|
20811
20929
|
track.on(TrackEvent.UpstreamResumed, this.onTrackUpstreamResumed);
|
20812
20930
|
track.on(TrackEvent.AudioTrackFeatureUpdate, this.onTrackFeatureUpdate);
|
20931
|
+
const audioFeatures = [];
|
20932
|
+
const disableDtx = !((_a = opts.dtx) !== null && _a !== void 0 ? _a : true);
|
20933
|
+
const settings = track.getSourceTrackSettings();
|
20934
|
+
if (settings.autoGainControl) {
|
20935
|
+
audioFeatures.push(AudioTrackFeature.TF_AUTO_GAIN_CONTROL);
|
20936
|
+
}
|
20937
|
+
if (settings.echoCancellation) {
|
20938
|
+
audioFeatures.push(AudioTrackFeature.TF_ECHO_CANCELLATION);
|
20939
|
+
}
|
20940
|
+
if (settings.noiseSuppression) {
|
20941
|
+
audioFeatures.push(AudioTrackFeature.TF_NOISE_SUPPRESSION);
|
20942
|
+
}
|
20943
|
+
if (settings.channelCount && settings.channelCount > 1) {
|
20944
|
+
audioFeatures.push(AudioTrackFeature.TF_STEREO);
|
20945
|
+
}
|
20946
|
+
if (disableDtx) {
|
20947
|
+
audioFeatures.push(AudioTrackFeature.TF_NO_DTX);
|
20948
|
+
}
|
20949
|
+
if (isLocalAudioTrack(track) && track.hasPreConnectBuffer) {
|
20950
|
+
audioFeatures.push(AudioTrackFeature.TF_PRECONNECT_BUFFER);
|
20951
|
+
}
|
20813
20952
|
// create track publication from track
|
20814
20953
|
const req = new AddTrackRequest({
|
20815
20954
|
// get local track id for use during publishing
|
@@ -20818,12 +20957,13 @@ class LocalParticipant extends Participant {
|
|
20818
20957
|
type: Track.kindToProto(track.kind),
|
20819
20958
|
muted: track.isMuted,
|
20820
20959
|
source: Track.sourceToProto(track.source),
|
20821
|
-
disableDtx
|
20960
|
+
disableDtx,
|
20822
20961
|
encryption: this.encryptionType,
|
20823
20962
|
stereo: isStereo,
|
20824
20963
|
disableRed: this.isE2EEEnabled || !((_b = opts.red) !== null && _b !== void 0 ? _b : true),
|
20825
20964
|
stream: opts === null || opts === void 0 ? void 0 : opts.stream,
|
20826
|
-
backupCodecPolicy: opts === null || opts === void 0 ? void 0 : opts.backupCodecPolicy
|
20965
|
+
backupCodecPolicy: opts === null || opts === void 0 ? void 0 : opts.backupCodecPolicy,
|
20966
|
+
audioFeatures
|
20827
20967
|
});
|
20828
20968
|
// compute encodings and layers for video
|
20829
20969
|
let encodings;
|
@@ -20949,11 +21089,28 @@ class LocalParticipant extends Participant {
|
|
20949
21089
|
yield this.engine.negotiate();
|
20950
21090
|
});
|
20951
21091
|
let ti;
|
21092
|
+
const addTrackPromise = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
21093
|
+
var _a;
|
21094
|
+
try {
|
21095
|
+
ti = yield this.engine.addTrack(req);
|
21096
|
+
resolve(ti);
|
21097
|
+
} catch (err) {
|
21098
|
+
if (track.sender && ((_a = this.engine.pcManager) === null || _a === void 0 ? void 0 : _a.publisher)) {
|
21099
|
+
this.engine.pcManager.publisher.removeTrack(track.sender);
|
21100
|
+
yield this.engine.negotiate().catch(negotiateErr => {
|
21101
|
+
this.log.error('failed to negotiate after removing track due to failed add track request', Object.assign(Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)), {
|
21102
|
+
error: negotiateErr
|
21103
|
+
}));
|
21104
|
+
});
|
21105
|
+
}
|
21106
|
+
reject(err);
|
21107
|
+
}
|
21108
|
+
}));
|
20952
21109
|
if (this.enabledPublishVideoCodecs.length > 0) {
|
20953
|
-
const rets = yield Promise.all([
|
21110
|
+
const rets = yield Promise.all([addTrackPromise, negotiate()]);
|
20954
21111
|
ti = rets[0];
|
20955
21112
|
} else {
|
20956
|
-
ti = yield
|
21113
|
+
ti = yield addTrackPromise;
|
20957
21114
|
// server might not support the codec the client has requested, in that case, fallback
|
20958
21115
|
// to a supported codec
|
20959
21116
|
let primaryCodecMime;
|
@@ -20994,6 +21151,75 @@ class LocalParticipant extends Participant {
|
|
20994
21151
|
this.addTrackPublication(publication);
|
20995
21152
|
// send event for publication
|
20996
21153
|
this.emit(ParticipantEvent.LocalTrackPublished, publication);
|
21154
|
+
if (isLocalAudioTrack(track) && ti.audioFeatures.includes(AudioTrackFeature.TF_PRECONNECT_BUFFER)) {
|
21155
|
+
const stream = track.getPreConnectBuffer();
|
21156
|
+
// TODO: we're registering the listener after negotiation, so there might be a race
|
21157
|
+
this.on(ParticipantEvent.LocalTrackSubscribed, pub => {
|
21158
|
+
if (pub.trackSid === ti.sid) {
|
21159
|
+
if (!track.hasPreConnectBuffer) {
|
21160
|
+
this.log.warn('subscribe event came to late, buffer already closed', this.logContext);
|
21161
|
+
return;
|
21162
|
+
}
|
21163
|
+
this.log.debug('finished recording preconnect buffer', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
|
21164
|
+
track.stopPreConnectBuffer();
|
21165
|
+
}
|
21166
|
+
});
|
21167
|
+
if (stream) {
|
21168
|
+
const bufferStreamPromise = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
21169
|
+
var _a, e_2, _b, _c;
|
21170
|
+
var _d, _e;
|
21171
|
+
try {
|
21172
|
+
this.log.debug('waiting for agent', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
|
21173
|
+
const agentActiveTimeout = setTimeout(() => {
|
21174
|
+
reject(new Error('agent not active within 10 seconds'));
|
21175
|
+
}, 10000);
|
21176
|
+
const agent = yield this.waitUntilActiveAgentPresent();
|
21177
|
+
clearTimeout(agentActiveTimeout);
|
21178
|
+
this.log.debug('sending preconnect buffer', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
|
21179
|
+
const writer = yield this.streamBytes({
|
21180
|
+
name: 'preconnect-buffer',
|
21181
|
+
mimeType: 'audio/opus',
|
21182
|
+
topic: 'lk.agent.pre-connect-audio-buffer',
|
21183
|
+
destinationIdentities: [agent.identity],
|
21184
|
+
attributes: {
|
21185
|
+
trackId: publication.trackSid,
|
21186
|
+
sampleRate: String((_d = settings.sampleRate) !== null && _d !== void 0 ? _d : '48000'),
|
21187
|
+
channels: String((_e = settings.channelCount) !== null && _e !== void 0 ? _e : '1')
|
21188
|
+
}
|
21189
|
+
});
|
21190
|
+
try {
|
21191
|
+
for (var _f = true, stream_1 = __asyncValues(stream), stream_1_1; stream_1_1 = yield stream_1.next(), _a = stream_1_1.done, !_a; _f = true) {
|
21192
|
+
_c = stream_1_1.value;
|
21193
|
+
_f = false;
|
21194
|
+
const chunk = _c;
|
21195
|
+
yield writer.write(chunk);
|
21196
|
+
}
|
21197
|
+
} catch (e_2_1) {
|
21198
|
+
e_2 = {
|
21199
|
+
error: e_2_1
|
21200
|
+
};
|
21201
|
+
} finally {
|
21202
|
+
try {
|
21203
|
+
if (!_f && !_a && (_b = stream_1.return)) yield _b.call(stream_1);
|
21204
|
+
} finally {
|
21205
|
+
if (e_2) throw e_2.error;
|
21206
|
+
}
|
21207
|
+
}
|
21208
|
+
yield writer.close();
|
21209
|
+
resolve();
|
21210
|
+
} catch (e) {
|
21211
|
+
reject(e);
|
21212
|
+
}
|
21213
|
+
}));
|
21214
|
+
bufferStreamPromise.then(() => {
|
21215
|
+
this.log.debug('preconnect buffer sent successfully', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
|
21216
|
+
}).catch(e => {
|
21217
|
+
this.log.error('error sending preconnect buffer', Object.assign(Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)), {
|
21218
|
+
error: e
|
21219
|
+
}));
|
21220
|
+
});
|
21221
|
+
}
|
21222
|
+
}
|
20997
21223
|
return publication;
|
20998
21224
|
});
|
20999
21225
|
}
|
@@ -21742,6 +21968,29 @@ class LocalParticipant extends Participant {
|
|
21742
21968
|
});
|
21743
21969
|
return true;
|
21744
21970
|
}
|
21971
|
+
/** @internal */
|
21972
|
+
setActiveAgent(agent) {
|
21973
|
+
var _a, _b, _c, _d;
|
21974
|
+
this.firstActiveAgent = agent;
|
21975
|
+
if (agent && !this.firstActiveAgent) {
|
21976
|
+
this.firstActiveAgent = agent;
|
21977
|
+
}
|
21978
|
+
if (agent) {
|
21979
|
+
(_b = (_a = this.activeAgentFuture) === null || _a === void 0 ? void 0 : _a.resolve) === null || _b === void 0 ? void 0 : _b.call(_a, agent);
|
21980
|
+
} else {
|
21981
|
+
(_d = (_c = this.activeAgentFuture) === null || _c === void 0 ? void 0 : _c.reject) === null || _d === void 0 ? void 0 : _d.call(_c, 'Agent disconnected');
|
21982
|
+
}
|
21983
|
+
this.activeAgentFuture = undefined;
|
21984
|
+
}
|
21985
|
+
waitUntilActiveAgentPresent() {
|
21986
|
+
if (this.firstActiveAgent) {
|
21987
|
+
return Promise.resolve(this.firstActiveAgent);
|
21988
|
+
}
|
21989
|
+
if (!this.activeAgentFuture) {
|
21990
|
+
this.activeAgentFuture = new Future();
|
21991
|
+
}
|
21992
|
+
return this.activeAgentFuture.promise;
|
21993
|
+
}
|
21745
21994
|
getPublicationForTrack(track) {
|
21746
21995
|
let publication;
|
21747
21996
|
this.trackPublications.forEach(pub => {
|
@@ -22935,49 +23184,10 @@ class Room extends eventsExports.EventEmitter {
|
|
22935
23184
|
}
|
22936
23185
|
};
|
22937
23186
|
this.handleDeviceChange = () => __awaiter(this, void 0, void 0, function* () {
|
22938
|
-
var _a
|
22939
|
-
|
22940
|
-
|
22941
|
-
|
22942
|
-
const browser = getBrowser();
|
22943
|
-
if ((browser === null || browser === void 0 ? void 0 : browser.name) === 'Chrome' && browser.os !== 'iOS') {
|
22944
|
-
for (let availableDevice of availableDevices) {
|
22945
|
-
const previousDevice = previousDevices.find(info => info.deviceId === availableDevice.deviceId);
|
22946
|
-
if (previousDevice && previousDevice.label !== '' && previousDevice.kind === availableDevice.kind && previousDevice.label !== availableDevice.label) {
|
22947
|
-
// label has changed on device the same deviceId, indicating that the default device has changed on the OS level
|
22948
|
-
if (this.getActiveDevice(availableDevice.kind) === 'default') {
|
22949
|
-
// emit an active device change event only if the selected output device is actually on `default`
|
22950
|
-
this.emit(RoomEvent.ActiveDeviceChanged, availableDevice.kind, availableDevice.deviceId);
|
22951
|
-
}
|
22952
|
-
}
|
22953
|
-
}
|
22954
|
-
}
|
22955
|
-
const kinds = ['audiooutput', 'audioinput', 'videoinput'];
|
22956
|
-
for (let kind of kinds) {
|
22957
|
-
const targetSource = kindToSource(kind);
|
22958
|
-
const targetPublication = this.localParticipant.getTrackPublication(targetSource);
|
22959
|
-
if (targetPublication && ((_a = targetPublication.track) === null || _a === void 0 ? void 0 : _a.isUserProvided)) {
|
22960
|
-
// if the track is user provided, we don't want to switch devices on behalf of the user
|
22961
|
-
continue;
|
22962
|
-
}
|
22963
|
-
const devicesOfKind = availableDevices.filter(d => d.kind === kind);
|
22964
|
-
const activeDevice = this.getActiveDevice(kind);
|
22965
|
-
if (activeDevice === ((_b = previousDevices.filter(info => info.kind === kind)[0]) === null || _b === void 0 ? void 0 : _b.deviceId)) {
|
22966
|
-
// in Safari the first device is always the default, so we assume a user on the default device would like to switch to the default once it changes
|
22967
|
-
// FF doesn't emit an event when the default device changes, so we perform the same best effort and switch to the new device once connected and if it's the first in the array
|
22968
|
-
if (devicesOfKind.length > 0 && ((_c = devicesOfKind[0]) === null || _c === void 0 ? void 0 : _c.deviceId) !== activeDevice) {
|
22969
|
-
yield this.switchActiveDevice(kind, devicesOfKind[0].deviceId);
|
22970
|
-
continue;
|
22971
|
-
}
|
22972
|
-
}
|
22973
|
-
if (kind === 'audioinput' && !isSafari() || kind === 'videoinput') {
|
22974
|
-
// airpods on Safari need special handling for audioinput as the track doesn't end as soon as you take them out
|
22975
|
-
continue;
|
22976
|
-
}
|
22977
|
-
// switch to first available device if previously active device is not available any more
|
22978
|
-
if (devicesOfKind.length > 0 && !devicesOfKind.find(deviceInfo => deviceInfo.deviceId === this.getActiveDevice(kind))) {
|
22979
|
-
yield this.switchActiveDevice(kind, devicesOfKind[0].deviceId);
|
22980
|
-
}
|
23187
|
+
var _a;
|
23188
|
+
if (((_a = getBrowser()) === null || _a === void 0 ? void 0 : _a.os) !== 'iOS') {
|
23189
|
+
// default devices are non deterministic on iOS, so we don't attempt to select them here
|
23190
|
+
yield this.selectDefaultDevices();
|
22981
23191
|
}
|
22982
23192
|
this.emit(RoomEvent.MediaDevicesChanged);
|
22983
23193
|
});
|
@@ -23059,8 +23269,8 @@ class Room extends eventsExports.EventEmitter {
|
|
23059
23269
|
this.onLocalConnectionQualityChanged = quality => {
|
23060
23270
|
this.emit(RoomEvent.ConnectionQualityChanged, quality, this.localParticipant);
|
23061
23271
|
};
|
23062
|
-
this.onMediaDevicesError = e => {
|
23063
|
-
this.emit(RoomEvent.MediaDevicesError, e);
|
23272
|
+
this.onMediaDevicesError = (e, kind) => {
|
23273
|
+
this.emit(RoomEvent.MediaDevicesError, e, kind);
|
23064
23274
|
};
|
23065
23275
|
this.onLocalParticipantPermissionsChanged = prevPermissions => {
|
23066
23276
|
this.emit(RoomEvent.ParticipantPermissionsChanged, prevPermissions, this.localParticipant);
|
@@ -23882,6 +24092,59 @@ class Room extends eventsExports.EventEmitter {
|
|
23882
24092
|
}
|
23883
24093
|
}
|
23884
24094
|
}
|
24095
|
+
/**
|
24096
|
+
* attempt to select the default devices if the previously selected devices are no longer available after a device change event
|
24097
|
+
*/
|
24098
|
+
selectDefaultDevices() {
|
24099
|
+
return __awaiter(this, void 0, void 0, function* () {
|
24100
|
+
var _a, _b, _c;
|
24101
|
+
const previousDevices = DeviceManager.getInstance().previousDevices;
|
24102
|
+
// check for available devices, but don't request permissions in order to avoid prompts for kinds that haven't been used before
|
24103
|
+
const availableDevices = yield DeviceManager.getInstance().getDevices(undefined, false);
|
24104
|
+
const browser = getBrowser();
|
24105
|
+
if ((browser === null || browser === void 0 ? void 0 : browser.name) === 'Chrome' && browser.os !== 'iOS') {
|
24106
|
+
for (let availableDevice of availableDevices) {
|
24107
|
+
const previousDevice = previousDevices.find(info => info.deviceId === availableDevice.deviceId);
|
24108
|
+
if (previousDevice && previousDevice.label !== '' && previousDevice.kind === availableDevice.kind && previousDevice.label !== availableDevice.label) {
|
24109
|
+
// label has changed on device the same deviceId, indicating that the default device has changed on the OS level
|
24110
|
+
if (this.getActiveDevice(availableDevice.kind) === 'default') {
|
24111
|
+
// emit an active device change event only if the selected output device is actually on `default`
|
24112
|
+
this.emit(RoomEvent.ActiveDeviceChanged, availableDevice.kind, availableDevice.deviceId);
|
24113
|
+
}
|
24114
|
+
}
|
24115
|
+
}
|
24116
|
+
}
|
24117
|
+
const kinds = ['audiooutput', 'audioinput', 'videoinput'];
|
24118
|
+
for (let kind of kinds) {
|
24119
|
+
const targetSource = kindToSource(kind);
|
24120
|
+
const targetPublication = this.localParticipant.getTrackPublication(targetSource);
|
24121
|
+
if (targetPublication && ((_a = targetPublication.track) === null || _a === void 0 ? void 0 : _a.isUserProvided)) {
|
24122
|
+
// if the track is user provided, we don't want to switch devices on behalf of the user
|
24123
|
+
continue;
|
24124
|
+
}
|
24125
|
+
const devicesOfKind = availableDevices.filter(d => d.kind === kind);
|
24126
|
+
const activeDevice = this.getActiveDevice(kind);
|
24127
|
+
if (activeDevice === ((_b = previousDevices.filter(info => info.kind === kind)[0]) === null || _b === void 0 ? void 0 : _b.deviceId)) {
|
24128
|
+
// in Safari the first device is always the default, so we assume a user on the default device would like to switch to the default once it changes
|
24129
|
+
// FF doesn't emit an event when the default device changes, so we perform the same best effort and switch to the new device once connected and if it's the first in the array
|
24130
|
+
if (devicesOfKind.length > 0 && ((_c = devicesOfKind[0]) === null || _c === void 0 ? void 0 : _c.deviceId) !== activeDevice) {
|
24131
|
+
yield this.switchActiveDevice(kind, devicesOfKind[0].deviceId);
|
24132
|
+
continue;
|
24133
|
+
}
|
24134
|
+
}
|
24135
|
+
if (kind === 'audioinput' && !isSafariBased() || kind === 'videoinput') {
|
24136
|
+
// airpods on Safari need special handling for audioinput as the track doesn't end as soon as you take them out
|
24137
|
+
continue;
|
24138
|
+
}
|
24139
|
+
// switch to first available device if previously active device is not available any more
|
24140
|
+
if (devicesOfKind.length > 0 && !devicesOfKind.find(deviceInfo => deviceInfo.deviceId === this.getActiveDevice(kind)) && (
|
24141
|
+
// avoid switching audio output on safari without explicit user action as it leads to slowed down audio playback
|
24142
|
+
kind !== 'audiooutput' || !isSafariBased())) {
|
24143
|
+
yield this.switchActiveDevice(kind, devicesOfKind[0].deviceId);
|
24144
|
+
}
|
24145
|
+
}
|
24146
|
+
});
|
24147
|
+
}
|
23885
24148
|
acquireAudioContext() {
|
23886
24149
|
return __awaiter(this, void 0, void 0, function* () {
|
23887
24150
|
var _a, _b;
|
@@ -23995,6 +24258,9 @@ class Room extends eventsExports.EventEmitter {
|
|
23995
24258
|
this.emitWhenConnected(RoomEvent.TrackSubscriptionPermissionChanged, pub, status, participant);
|
23996
24259
|
}).on(ParticipantEvent.Active, () => {
|
23997
24260
|
this.emitWhenConnected(RoomEvent.ParticipantActive, participant);
|
24261
|
+
if (participant.kind === ParticipantInfo_Kind.AGENT) {
|
24262
|
+
this.localParticipant.setActiveAgent(participant);
|
24263
|
+
}
|
23998
24264
|
});
|
23999
24265
|
// update info at the end after callbacks have been set up
|
24000
24266
|
if (info) {
|
@@ -25050,5 +25316,5 @@ function isFacingModeValue(item) {
|
|
25050
25316
|
return item === undefined || allowedValues.includes(item);
|
25051
25317
|
}
|
25052
25318
|
|
25053
|
-
export { AudioPresets, BackupCodecPolicy, BaseKeyProvider, CheckStatus, Checker, ConnectionCheck, ConnectionError, ConnectionErrorReason, ConnectionQuality, ConnectionState, CriticalTimers, CryptorError, CryptorErrorReason, CryptorEvent, DataPacket_Kind, DefaultReconnectPolicy, DeviceUnsupportedError, DisconnectReason, EncryptionEvent, EngineEvent, ExternalE2EEKeyProvider, KeyHandlerEvent, KeyProviderEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, LoggerNames, MediaDeviceFailure, _ as Mutex, NegotiationError, Participant, ParticipantEvent, ParticipantInfo_Kind as ParticipantKind, PublishDataError, PublishTrackError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, RpcError, ScreenSharePresets, SignalRequestError, SubscriptionError, Track, TrackEvent, TrackInvalidError, TrackPublication, TrackType, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, compareVersions, createAudioAnalyser, createE2EEKey, createKeyMaterialFromBuffer, createKeyMaterialFromString, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, deriveKeys, detachTrack, facingModeFromDeviceLabel, facingModeFromLocalTrack, getBrowser, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, getLogger, importKey, isAudioTrack, isBackupCodec, isBrowserSupported, isE2EESupported, isInsertableStreamSupported, isLocalParticipant, isLocalTrack, isRemoteParticipant, isRemoteTrack, isScriptTransformSupported, isVideoFrame, isVideoTrack, needsRbspUnescaping, parseRbsp, protocolVersion, ratchet, setLogExtension, setLogLevel, supportsAV1, supportsAdaptiveStream, supportsDynacast, supportsVP9, version, videoCodecs, writeRbsp };
|
25319
|
+
export { AudioPresets, BackupCodecPolicy, BaseKeyProvider, CheckStatus, Checker, ConnectionCheck, ConnectionError, ConnectionErrorReason, ConnectionQuality, ConnectionState, CriticalTimers, CryptorError, CryptorErrorReason, CryptorEvent, DataPacket_Kind, DefaultReconnectPolicy, DeviceUnsupportedError, DisconnectReason, EncryptionEvent, EngineEvent, ExternalE2EEKeyProvider, KeyHandlerEvent, KeyProviderEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalTrackRecorder, LocalVideoTrack, LogLevel, LoggerNames, MediaDeviceFailure, _ as Mutex, NegotiationError, Participant, ParticipantEvent, ParticipantInfo_Kind as ParticipantKind, PublishDataError, PublishTrackError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, RpcError, ScreenSharePresets, SignalRequestError, SubscriptionError, Track, TrackEvent, TrackInvalidError, TrackPublication, TrackType, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, compareVersions, createAudioAnalyser, createE2EEKey, createKeyMaterialFromBuffer, createKeyMaterialFromString, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, deriveKeys, detachTrack, facingModeFromDeviceLabel, facingModeFromLocalTrack, getBrowser, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, getLogger, importKey, isAudioTrack, isBackupCodec, isBrowserSupported, isE2EESupported, isInsertableStreamSupported, isLocalParticipant, isLocalTrack, isRemoteParticipant, isRemoteTrack, isScriptTransformSupported, isVideoFrame, isVideoTrack, needsRbspUnescaping, parseRbsp, protocolVersion, ratchet, setLogExtension, setLogLevel, supportsAV1, supportsAdaptiveStream, supportsDynacast, supportsVP9, version, videoCodecs, writeRbsp };
|
25054
25320
|
//# sourceMappingURL=livekit-client.esm.mjs.map
|