livekit-client 2.22.2 → 2.22.4
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/README.md +35 -0
- 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 +488 -438
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +954 -301
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.fm.worker.js +1 -1
- package/dist/livekit-client.fm.worker.js.map +1 -1
- package/dist/livekit-client.fm.worker.mjs +10 -2
- package/dist/livekit-client.fm.worker.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/api/SignalClient.d.ts +4 -2
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/api/WebSocketStream.d.ts.map +1 -1
- package/dist/src/api/utils.d.ts +1 -0
- package/dist/src/api/utils.d.ts.map +1 -1
- package/dist/src/e2ee/E2eeManager.d.ts +26 -0
- package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
- package/dist/src/e2ee/types.d.ts +15 -1
- package/dist/src/e2ee/types.d.ts.map +1 -1
- package/dist/src/e2ee/worker/DataCryptor.d.ts.map +1 -1
- package/dist/src/e2ee/worker/ErrorRateLimiter.d.ts +21 -0
- package/dist/src/e2ee/worker/ErrorRateLimiter.d.ts.map +1 -0
- package/dist/src/e2ee/worker/FrameCryptor.d.ts +1 -18
- package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
- package/dist/src/logger.d.ts +4 -0
- package/dist/src/logger.d.ts.map +1 -1
- package/dist/src/options.d.ts +14 -0
- package/dist/src/options.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts +78 -7
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/PCTransportManager.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +9 -0
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +1 -1
- 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 +18 -0
- package/dist/src/room/errors.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +3 -2
- package/dist/src/room/events.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/publishUtils.d.ts +16 -0
- package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
- package/dist/src/room/rpc/client/RpcClientManager.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts +9 -0
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/options.d.ts +1 -1
- package/dist/src/room/track/utils.d.ts +13 -0
- package/dist/src/room/track/utils.d.ts.map +1 -1
- package/dist/src/room/utils.d.ts +66 -0
- package/dist/src/room/utils.d.ts.map +1 -1
- package/dist/src/test/compressionStreamStubs.d.ts +12 -0
- package/dist/src/test/compressionStreamStubs.d.ts.map +1 -0
- package/dist/ts4.2/api/SignalClient.d.ts +187 -185
- package/dist/ts4.2/api/SignalClientStateMachine.d.ts +85 -85
- package/dist/ts4.2/api/WebSocketStream.d.ts +33 -33
- package/dist/ts4.2/api/utils.d.ts +9 -8
- package/dist/ts4.2/connectionHelper/ConnectionCheck.d.ts +30 -30
- package/dist/ts4.2/connectionHelper/checks/Checker.d.ts +62 -62
- package/dist/ts4.2/connectionHelper/checks/cloudRegion.d.ts +18 -18
- package/dist/ts4.2/connectionHelper/checks/connectionProtocol.d.ts +20 -20
- package/dist/ts4.2/connectionHelper/checks/publishAudio.d.ts +6 -6
- package/dist/ts4.2/connectionHelper/checks/publishVideo.d.ts +7 -7
- package/dist/ts4.2/connectionHelper/checks/reconnect.d.ts +6 -6
- package/dist/ts4.2/connectionHelper/checks/turn.d.ts +6 -6
- package/dist/ts4.2/connectionHelper/checks/webrtc.d.ts +6 -6
- package/dist/ts4.2/connectionHelper/checks/websocket.d.ts +6 -6
- package/dist/ts4.2/e2ee/E2eeManager.d.ts +111 -85
- package/dist/ts4.2/e2ee/KeyProvider.d.ts +54 -54
- package/dist/ts4.2/e2ee/constants.d.ts +21 -21
- package/dist/ts4.2/e2ee/errors.d.ts +12 -12
- package/dist/ts4.2/e2ee/events.d.ts +39 -39
- package/dist/ts4.2/e2ee/index.d.ts +6 -6
- package/dist/ts4.2/e2ee/types.d.ts +231 -217
- package/dist/ts4.2/e2ee/utils.d.ts +32 -32
- package/dist/ts4.2/e2ee/worker/DataCryptor.d.ts +16 -16
- package/dist/ts4.2/e2ee/worker/ErrorRateLimiter.d.ts +21 -0
- package/dist/ts4.2/e2ee/worker/FrameCryptor.d.ts +209 -226
- package/dist/ts4.2/e2ee/worker/ParticipantKeyHandler.d.ts +81 -84
- package/dist/ts4.2/e2ee/worker/e2ee.worker.d.ts +2 -2
- package/dist/ts4.2/e2ee/worker/naluUtils.d.ts +28 -28
- package/dist/ts4.2/e2ee/worker/sifPayload.d.ts +23 -23
- package/dist/ts4.2/frameMetadata/FrameMetadataManager.d.ts +53 -53
- package/dist/ts4.2/frameMetadata/frameMetadata.d.ts +33 -33
- package/dist/ts4.2/frameMetadata/types.d.ts +62 -62
- package/dist/ts4.2/frameMetadata/utils.d.ts +9 -9
- package/dist/ts4.2/frameMetadata/worker/frameMetadata.worker.d.ts +2 -2
- package/dist/ts4.2/index.d.ts +76 -76
- package/dist/ts4.2/logger.d.ts +66 -62
- package/dist/ts4.2/options.d.ts +163 -149
- package/dist/ts4.2/room/BackOffStrategy.d.ts +27 -27
- package/dist/ts4.2/room/DefaultReconnectPolicy.d.ts +8 -8
- package/dist/ts4.2/room/DeviceManager.d.ts +12 -12
- package/dist/ts4.2/room/PCTransport.d.ts +246 -175
- package/dist/ts4.2/room/PCTransportManager.d.ts +77 -77
- package/dist/ts4.2/room/RTCEngine.d.ts +269 -261
- package/dist/ts4.2/room/ReconnectPolicy.d.ts +24 -24
- package/dist/ts4.2/room/RegionUrlProvider.d.ts +36 -36
- package/dist/ts4.2/room/Room.d.ts +354 -365
- package/dist/ts4.2/room/attribute-typings.d.ts +35 -35
- package/dist/ts4.2/room/data-channel/DataChannelManager.d.ts +62 -62
- package/dist/ts4.2/room/data-channel/FlowControlledDataChannel.d.ts +94 -95
- package/dist/ts4.2/room/data-channel/LossyDataChannel.d.ts +41 -41
- package/dist/ts4.2/room/data-channel/ReliableDataChannel.d.ts +57 -57
- package/dist/ts4.2/room/data-channel/types.d.ts +12 -12
- package/dist/ts4.2/room/data-stream/compression.d.ts +49 -49
- package/dist/ts4.2/room/data-stream/constants.d.ts +18 -18
- package/dist/ts4.2/room/data-stream/incoming/IncomingDataStreamManager.d.ts +29 -29
- package/dist/ts4.2/room/data-stream/incoming/StreamReader.d.ts +80 -80
- package/dist/ts4.2/room/data-stream/outgoing/OutgoingDataStreamManager.d.ts +73 -73
- package/dist/ts4.2/room/data-stream/outgoing/StreamWriter.d.ts +16 -16
- package/dist/ts4.2/room/data-stream/outgoing/header-utils.d.ts +18 -18
- package/dist/ts4.2/room/data-track/LocalDataTrack.d.ts +79 -80
- package/dist/ts4.2/room/data-track/RemoteDataTrack.d.ts +50 -50
- package/dist/ts4.2/room/data-track/depacketizer.d.ts +59 -59
- package/dist/ts4.2/room/data-track/frame.d.ts +22 -22
- package/dist/ts4.2/room/data-track/handle.d.ts +27 -27
- package/dist/ts4.2/room/data-track/incoming/IncomingDataTrackManager.d.ts +124 -124
- package/dist/ts4.2/room/data-track/incoming/errors.d.ts +24 -24
- package/dist/ts4.2/room/data-track/incoming/pipeline.d.ts +41 -41
- package/dist/ts4.2/room/data-track/incoming/types.d.ts +20 -20
- package/dist/ts4.2/room/data-track/outgoing/OutgoingDataTrackManager.d.ts +126 -126
- package/dist/ts4.2/room/data-track/outgoing/errors.d.ts +74 -74
- package/dist/ts4.2/room/data-track/outgoing/pipeline.d.ts +23 -23
- package/dist/ts4.2/room/data-track/outgoing/types.d.ts +48 -48
- package/dist/ts4.2/room/data-track/packet/constants.d.ts +20 -20
- package/dist/ts4.2/room/data-track/packet/errors.d.ts +40 -40
- package/dist/ts4.2/room/data-track/packet/extensions.d.ts +69 -69
- package/dist/ts4.2/room/data-track/packet/index.d.ts +98 -98
- package/dist/ts4.2/room/data-track/packet/serializable.d.ts +13 -13
- package/dist/ts4.2/room/data-track/packetizer.d.ts +43 -43
- package/dist/ts4.2/room/data-track/track-interfaces.d.ts +23 -23
- package/dist/ts4.2/room/data-track/types.d.ts +22 -22
- package/dist/ts4.2/room/data-track/utils.d.ts +60 -60
- package/dist/ts4.2/room/debounce.d.ts +11 -11
- package/dist/ts4.2/room/defaults.d.ts +9 -9
- package/dist/ts4.2/room/errors.d.ts +180 -162
- package/dist/ts4.2/room/events.d.ts +638 -637
- package/dist/ts4.2/room/participant/LocalParticipant.d.ts +287 -287
- package/dist/ts4.2/room/participant/Participant.d.ts +142 -144
- package/dist/ts4.2/room/participant/ParticipantTrackPermission.d.ts +26 -26
- package/dist/ts4.2/room/participant/RemoteParticipant.d.ts +85 -86
- package/dist/ts4.2/room/participant/publishUtils.d.ts +53 -37
- package/dist/ts4.2/room/rpc/client/RpcClientManager.d.ts +43 -43
- package/dist/ts4.2/room/rpc/client/events.d.ts +8 -8
- package/dist/ts4.2/room/rpc/index.d.ts +7 -7
- package/dist/ts4.2/room/rpc/server/RpcServerManager.d.ts +44 -44
- package/dist/ts4.2/room/rpc/server/events.d.ts +8 -8
- package/dist/ts4.2/room/rpc/utils.d.ts +131 -131
- package/dist/ts4.2/room/stats.d.ts +71 -71
- package/dist/ts4.2/room/statsSummary.d.ts +13 -13
- package/dist/ts4.2/room/timers.d.ts +12 -12
- package/dist/ts4.2/room/token-source/TokenSource.d.ts +82 -82
- package/dist/ts4.2/room/token-source/types.d.ts +70 -70
- package/dist/ts4.2/room/token-source/utils.d.ts +8 -8
- package/dist/ts4.2/room/track/FrameMetadataExtractor.d.ts +19 -19
- package/dist/ts4.2/room/track/LocalAudioTrack.d.ts +39 -42
- package/dist/ts4.2/room/track/LocalTrack.d.ts +125 -125
- package/dist/ts4.2/room/track/LocalTrackPublication.d.ts +42 -42
- package/dist/ts4.2/room/track/LocalVideoTrack.d.ts +102 -93
- package/dist/ts4.2/room/track/RemoteAudioTrack.d.ts +55 -55
- package/dist/ts4.2/room/track/RemoteTrack.d.ts +38 -38
- package/dist/ts4.2/room/track/RemoteTrackPublication.d.ts +72 -75
- package/dist/ts4.2/room/track/RemoteVideoTrack.d.ts +73 -76
- package/dist/ts4.2/room/track/Track.d.ts +156 -166
- package/dist/ts4.2/room/track/TrackPublication.d.ts +75 -81
- package/dist/ts4.2/room/track/create.d.ts +25 -25
- package/dist/ts4.2/room/track/facingMode.d.ts +41 -41
- package/dist/ts4.2/room/track/options.d.ts +403 -403
- package/dist/ts4.2/room/track/processor/types.d.ts +31 -31
- package/dist/ts4.2/room/track/record.d.ts +13 -13
- package/dist/ts4.2/room/track/types.d.ts +28 -28
- package/dist/ts4.2/room/track/utils.d.ts +60 -47
- package/dist/ts4.2/room/types.d.ts +127 -127
- package/dist/ts4.2/room/utils.d.ts +246 -180
- package/dist/ts4.2/test/MockMediaStreamTrack.d.ts +26 -26
- package/dist/ts4.2/test/compressionStreamStubs.d.ts +12 -0
- package/dist/ts4.2/test/mocks.d.ts +12 -12
- package/dist/ts4.2/test/promiseState.d.ts +12 -12
- package/dist/ts4.2/test/signalToken.d.ts +26 -26
- package/dist/ts4.2/type-polyfills/non-shared-typed-arrays.d.ts +2 -2
- package/dist/ts4.2/utils/AsyncQueue.d.ts +23 -23
- package/dist/ts4.2/utils/TypedPromise.d.ts +17 -17
- package/dist/ts4.2/utils/abort-signal-polyfill.d.ts +13 -13
- package/dist/ts4.2/utils/browserParser.d.ts +13 -13
- package/dist/ts4.2/utils/camelToSnakeCase.d.ts +8 -8
- package/dist/ts4.2/utils/cloneDeep.d.ts +2 -2
- package/dist/ts4.2/utils/dataPacketBuffer.d.ts +34 -34
- package/dist/ts4.2/utils/deferrable-map.d.ts +32 -32
- package/dist/ts4.2/utils/machineInspector.d.ts +54 -54
- package/dist/ts4.2/utils/serializer.d.ts +48 -48
- package/dist/ts4.2/utils/subscribeToEvents.d.ts +15 -15
- package/dist/ts4.2/utils/ttlmap.d.ts +20 -20
- package/dist/ts4.2/version.d.ts +15 -15
- package/package.json +5 -4
- package/src/api/SignalClient.e2e.test.ts +1 -3
- package/src/api/SignalClient.test.ts +160 -10
- package/src/api/SignalClient.ts +75 -54
- package/src/api/WebSocketStream.ts +3 -8
- package/src/api/utils.ts +10 -0
- package/src/e2ee/E2eeManager.test.ts +196 -0
- package/src/e2ee/E2eeManager.ts +114 -19
- package/src/e2ee/types.ts +19 -1
- package/src/e2ee/worker/DataCryptor.ts +2 -1
- package/src/e2ee/worker/ErrorRateLimiter.test.ts +53 -0
- package/src/e2ee/worker/ErrorRateLimiter.ts +52 -0
- package/src/e2ee/worker/FrameCryptor.ts +20 -70
- package/src/e2ee/worker/e2ee.worker.ts +34 -11
- package/src/logger.ts +22 -0
- package/src/options.ts +16 -0
- package/src/room/PCTransport.test.ts +183 -7
- package/src/room/PCTransport.ts +197 -36
- package/src/room/PCTransportManager.ts +3 -1
- package/src/room/RTCEngine.test.ts +84 -0
- package/src/room/RTCEngine.ts +52 -12
- package/src/room/Room.test.ts +32 -6
- package/src/room/Room.ts +27 -7
- package/src/room/data-stream/incoming/IncomingDataStreamManager.test.ts +16 -20
- package/src/room/data-stream/incoming/IncomingDataStreamManager.ts +5 -5
- package/src/room/data-stream/outgoing/OutgoingDataStreamManager.test.ts +60 -39
- package/src/room/data-stream/outgoing/OutgoingDataStreamManager.ts +4 -4
- package/src/room/defaults.ts +1 -0
- package/src/room/errors.test.ts +36 -0
- package/src/room/errors.ts +27 -0
- package/src/room/events.ts +2 -1
- package/src/room/participant/LocalParticipant.ts +30 -14
- package/src/room/participant/publishUtils.test.ts +133 -0
- package/src/room/participant/publishUtils.ts +54 -38
- package/src/room/rpc/client/RpcClientManager.test.ts +51 -0
- package/src/room/rpc/client/RpcClientManager.ts +32 -15
- package/src/room/track/LocalTrack.ts +18 -7
- package/src/room/track/LocalVideoTrack.ts +25 -8
- package/src/room/track/RemoteAudioTrack.ts +3 -3
- package/src/room/track/RemoteVideoTrack.test.ts +210 -0
- package/src/room/track/RemoteVideoTrack.ts +29 -3
- package/src/room/track/options.ts +1 -1
- package/src/room/track/utils.test.ts +201 -2
- package/src/room/track/utils.ts +88 -0
- package/src/room/utils.test.ts +211 -0
- package/src/room/utils.ts +129 -0
- package/src/test/compressionStreamStubs.ts +53 -0
|
@@ -930,7 +930,10 @@ function isScalarZeroValue(type, value) {
|
|
|
930
930
|
return value == 0;
|
|
931
931
|
// Loose comparison matches 0n, 0 and "0"
|
|
932
932
|
}
|
|
933
|
-
}function
|
|
933
|
+
}function _OverloadYield(e, d) {
|
|
934
|
+
this.v = e, this.k = d;
|
|
935
|
+
}
|
|
936
|
+
function _arrayLikeToArray(r, a) {
|
|
934
937
|
(null == a || a > r.length) && (a = r.length);
|
|
935
938
|
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
|
|
936
939
|
return n;
|
|
@@ -1046,7 +1049,61 @@ function _unsupportedIterableToArray(r, a) {
|
|
|
1046
1049
|
var t = {}.toString.call(r).slice(8, -1);
|
|
1047
1050
|
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
|
|
1048
1051
|
}
|
|
1049
|
-
}
|
|
1052
|
+
}
|
|
1053
|
+
function _wrapAsyncGenerator(e) {
|
|
1054
|
+
return function () {
|
|
1055
|
+
return new AsyncGenerator(e.apply(this, arguments));
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
function AsyncGenerator(e) {
|
|
1059
|
+
var t, n;
|
|
1060
|
+
function resume(t, n) {
|
|
1061
|
+
try {
|
|
1062
|
+
var r = e[t](n),
|
|
1063
|
+
o = r.value,
|
|
1064
|
+
u = o instanceof _OverloadYield;
|
|
1065
|
+
Promise.resolve(u ? o.v : o).then(function (n) {
|
|
1066
|
+
if (u) {
|
|
1067
|
+
var i = "return" === t && o.k ? t : "next";
|
|
1068
|
+
if (!o.k || n.done) return resume(i, n);
|
|
1069
|
+
n = e[i](n).value;
|
|
1070
|
+
}
|
|
1071
|
+
settle(!!r.done, n);
|
|
1072
|
+
}, function (e) {
|
|
1073
|
+
resume("throw", e);
|
|
1074
|
+
});
|
|
1075
|
+
} catch (e) {
|
|
1076
|
+
settle(2, e);
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
function settle(e, r) {
|
|
1080
|
+
2 === e ? t.reject(r) : t.resolve({
|
|
1081
|
+
value: r,
|
|
1082
|
+
done: e
|
|
1083
|
+
}), (t = t.next) ? resume(t.key, t.arg) : n = null;
|
|
1084
|
+
}
|
|
1085
|
+
this._invoke = function (e, r) {
|
|
1086
|
+
return new Promise(function (o, u) {
|
|
1087
|
+
var i = {
|
|
1088
|
+
key: e,
|
|
1089
|
+
arg: r,
|
|
1090
|
+
resolve: o,
|
|
1091
|
+
reject: u,
|
|
1092
|
+
next: null
|
|
1093
|
+
};
|
|
1094
|
+
n ? n = n.next = i : (t = n = i, resume(e, r));
|
|
1095
|
+
});
|
|
1096
|
+
}, "function" != typeof e.return && (this.return = void 0);
|
|
1097
|
+
}
|
|
1098
|
+
AsyncGenerator.prototype["function" == typeof Symbol && Symbol.asyncIterator || "@@asyncIterator"] = function () {
|
|
1099
|
+
return this;
|
|
1100
|
+
}, AsyncGenerator.prototype.next = function (e) {
|
|
1101
|
+
return this._invoke("next", e);
|
|
1102
|
+
}, AsyncGenerator.prototype.throw = function (e) {
|
|
1103
|
+
return this._invoke("throw", e);
|
|
1104
|
+
}, AsyncGenerator.prototype.return = function (e) {
|
|
1105
|
+
return this._invoke("return", e);
|
|
1106
|
+
};/* eslint-disable prefer-const,no-case-declarations,@typescript-eslint/restrict-plus-operands */
|
|
1050
1107
|
/**
|
|
1051
1108
|
* Protobuf binary format wire types.
|
|
1052
1109
|
*
|
|
@@ -5416,6 +5473,9 @@ const ClientInfo_SDK = /* @__PURE__ */proto3.makeEnum("livekit.ClientInfo.SDK",
|
|
|
5416
5473
|
}, {
|
|
5417
5474
|
no: 14,
|
|
5418
5475
|
name: "ESP32"
|
|
5476
|
+
}, {
|
|
5477
|
+
no: 15,
|
|
5478
|
+
name: "DOTNET"
|
|
5419
5479
|
}]);
|
|
5420
5480
|
const ClientInfo_Capability = /* @__PURE__ */proto3.makeEnum("livekit.ClientInfo.Capability", [{
|
|
5421
5481
|
no: 0,
|
|
@@ -5784,6 +5844,9 @@ const EncodingOptionsPreset = /* @__PURE__ */proto3.makeEnum("livekit.EncodingOp
|
|
|
5784
5844
|
}, {
|
|
5785
5845
|
no: 7,
|
|
5786
5846
|
name: "PORTRAIT_H264_1080P_60"
|
|
5847
|
+
}, {
|
|
5848
|
+
no: 8,
|
|
5849
|
+
name: "PASSTHROUGH"
|
|
5787
5850
|
}]);
|
|
5788
5851
|
const EncodedFileType = /* @__PURE__ */proto3.makeEnum("livekit.EncodedFileType", [{
|
|
5789
5852
|
no: 0,
|
|
@@ -7768,6 +7831,11 @@ const SyncState = /* @__PURE__ */proto3.makeMessageType("livekit.SyncState", ()
|
|
|
7768
7831
|
kind: "message",
|
|
7769
7832
|
T: PublishDataTrackResponse,
|
|
7770
7833
|
repeated: true
|
|
7834
|
+
}, {
|
|
7835
|
+
no: 9,
|
|
7836
|
+
name: "data_subscription",
|
|
7837
|
+
kind: "message",
|
|
7838
|
+
T: UpdateDataSubscription
|
|
7771
7839
|
}]);
|
|
7772
7840
|
const DataChannelReceiveState = /* @__PURE__ */proto3.makeMessageType("livekit.DataChannelReceiveState", () => [{
|
|
7773
7841
|
no: 1,
|
|
@@ -8625,7 +8693,21 @@ function setLogExtension(extension, logger) {
|
|
|
8625
8693
|
logR.setLevel(logR.getLevel());
|
|
8626
8694
|
});
|
|
8627
8695
|
}
|
|
8628
|
-
const workerLogger = loglevelExports.getLogger(LoggerNames.E2EE);
|
|
8696
|
+
const workerLogger = loglevelExports.getLogger(LoggerNames.E2EE);
|
|
8697
|
+
const workerLogLevelListeners = new Set();
|
|
8698
|
+
const originalWorkerSetLevel = workerLogger.setLevel.bind(workerLogger);
|
|
8699
|
+
workerLogger.setLevel = (level, persist) => {
|
|
8700
|
+
originalWorkerSetLevel(level, persist);
|
|
8701
|
+
const numeric = workerLogger.getLevel();
|
|
8702
|
+
workerLogLevelListeners.forEach(cb => cb(numeric));
|
|
8703
|
+
};
|
|
8704
|
+
/** @internal Subscribe to workerLogger level changes (so E2EE workers can be kept in sync). */
|
|
8705
|
+
function onWorkerLogLevelChanged(cb) {
|
|
8706
|
+
workerLogLevelListeners.add(cb);
|
|
8707
|
+
return () => {
|
|
8708
|
+
workerLogLevelListeners.delete(cb);
|
|
8709
|
+
};
|
|
8710
|
+
}const maxRetryDelay = 7000;
|
|
8629
8711
|
const DEFAULT_RETRY_DELAYS_IN_MS = [0, 300, 2 * 2 * 300, 3 * 3 * 300, 4 * 4 * 300, maxRetryDelay, maxRetryDelay, maxRetryDelay, maxRetryDelay, maxRetryDelay];
|
|
8630
8712
|
class DefaultReconnectPolicy {
|
|
8631
8713
|
constructor(retryDelays) {
|
|
@@ -12208,7 +12290,7 @@ function getMatch(exp, ua) {
|
|
|
12208
12290
|
}
|
|
12209
12291
|
function getOSVersion(ua) {
|
|
12210
12292
|
return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
|
|
12211
|
-
}var version$1 = "2.22.
|
|
12293
|
+
}var version$1 = "2.22.4";const version = version$1;
|
|
12212
12294
|
const protocolVersion = 17;
|
|
12213
12295
|
/** Initial client protocol. */
|
|
12214
12296
|
const CLIENT_PROTOCOL_DEFAULT = 0;
|
|
@@ -12289,6 +12371,32 @@ class ConnectionError extends LivekitReasonedError {
|
|
|
12289
12371
|
return new ConnectionError(message, ConnectionErrorReason.ServiceNotFound, undefined, serviceName);
|
|
12290
12372
|
}
|
|
12291
12373
|
}
|
|
12374
|
+
/**
|
|
12375
|
+
* Whether a failed connection attempt may be retried against a different LiveKit Cloud region.
|
|
12376
|
+
*
|
|
12377
|
+
* LiveKit Cloud signals project-level region pinning by returning 403 on the RTC paths when the
|
|
12378
|
+
* project is not allowed in the region the client geo-routed to. `/settings/regions` is
|
|
12379
|
+
* deliberately left reachable so the client can discover its allowed regions and connect there, so
|
|
12380
|
+
* a 403 must not be treated as terminal.
|
|
12381
|
+
*
|
|
12382
|
+
* A 401 stays terminal: no other region will accept a token this one rejected. So does the 404
|
|
12383
|
+
* "requested room does not exist" case, which is also reported as `NotAllowed`.
|
|
12384
|
+
*
|
|
12385
|
+
* We key on the status rather than the server's error message because that message is an
|
|
12386
|
+
* unversioned human-readable string; matching it would let a copy edit break already-shipped
|
|
12387
|
+
* clients. If a 403 really was a permissions failure rather than region pinning, every region
|
|
12388
|
+
* attempt fails the same way and the original error still surfaces — at the cost of one extra
|
|
12389
|
+
* region lookup.
|
|
12390
|
+
*/
|
|
12391
|
+
function canFailOverToAnotherRegion(error) {
|
|
12392
|
+
if (error.reason === ConnectionErrorReason.Cancelled) {
|
|
12393
|
+
return false;
|
|
12394
|
+
}
|
|
12395
|
+
if (error.reason === ConnectionErrorReason.NotAllowed) {
|
|
12396
|
+
return error.status === 403;
|
|
12397
|
+
}
|
|
12398
|
+
return true;
|
|
12399
|
+
}
|
|
12292
12400
|
class DeviceUnsupportedError extends LivekitError {
|
|
12293
12401
|
constructor(message) {
|
|
12294
12402
|
super(21, message !== null && message !== void 0 ? message : 'device is unsupported');
|
|
@@ -12622,7 +12730,7 @@ var RoomEvent;
|
|
|
12622
12730
|
* Data packets provides the ability to use LiveKit to send/receive arbitrary payloads.
|
|
12623
12731
|
* All participants in the room will receive the messages sent to the room.
|
|
12624
12732
|
*
|
|
12625
|
-
* args: (payload: NonSharedUint8Array, participant: [[Participant]], kind: [[DataPacket_Kind]], topic?: string)
|
|
12733
|
+
* args: (payload: NonSharedUint8Array, participant: [[Participant]] | undefined, kind: [[DataPacket_Kind]], topic?: string, encryptionType?: Encryption_Type, participantIdentity?: string)
|
|
12626
12734
|
*/
|
|
12627
12735
|
RoomEvent["DataReceived"] = "dataReceived";
|
|
12628
12736
|
/**
|
|
@@ -12980,6 +13088,7 @@ var EngineEvent;
|
|
|
12980
13088
|
EngineEvent["Joined"] = "joined";
|
|
12981
13089
|
EngineEvent["TokenRefreshed"] = "tokenRefreshed";
|
|
12982
13090
|
EngineEvent["ServerRegionsReported"] = "serverRegionsReported";
|
|
13091
|
+
EngineEvent["RequestSubscribedCodecRefresh"] = "requestSubscribedCodecRefresh";
|
|
12983
13092
|
})(EngineEvent || (EngineEvent = {}));
|
|
12984
13093
|
var TrackEvent;
|
|
12985
13094
|
(function (TrackEvent) {
|
|
@@ -13674,6 +13783,85 @@ function areDimensionsSmaller(a, b) {
|
|
|
13674
13783
|
function layerDimensionsFor(trackInfo, quality) {
|
|
13675
13784
|
var _a;
|
|
13676
13785
|
return (_a = trackInfo.layers) === null || _a === void 0 ? void 0 : _a.find(l => l.quality === quality);
|
|
13786
|
+
}
|
|
13787
|
+
/**
|
|
13788
|
+
* Waits until `track` has actually produced a video frame.
|
|
13789
|
+
*
|
|
13790
|
+
* iOS keeps reporting the camera's sensor frame from `getSettings()` until the camera has
|
|
13791
|
+
* delivered its first picture, so a portrait capture initially reads as landscape. The arrival
|
|
13792
|
+
* of that first frame is the only reliable signal that the reported settings describe reality.
|
|
13793
|
+
*
|
|
13794
|
+
* Best effort, never throws. Resolves `true` when a frame was observed, `false` when no frame
|
|
13795
|
+
* can be observed (the track is already ended, muted or disabled) or `timeoutMs` elapsed first.
|
|
13796
|
+
*
|
|
13797
|
+
* @internal
|
|
13798
|
+
*/
|
|
13799
|
+
function waitForFirstVideoFrame(track_1, timeoutMs_1) {
|
|
13800
|
+
return __awaiter(this, arguments, void 0, function (track, timeoutMs) {
|
|
13801
|
+
let candidateElements = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
|
|
13802
|
+
return function* () {
|
|
13803
|
+
var _a;
|
|
13804
|
+
if (typeof document === 'undefined') {
|
|
13805
|
+
return false;
|
|
13806
|
+
}
|
|
13807
|
+
if (track.readyState === 'ended' || track.muted || !track.enabled) {
|
|
13808
|
+
// no frame is ever going to arrive, don't hold the caller up for the full timeout
|
|
13809
|
+
return false;
|
|
13810
|
+
}
|
|
13811
|
+
// requestVideoFrameCallback (Safari 15.4 and up) is a platform capability, so the answer is the
|
|
13812
|
+
// same for every element
|
|
13813
|
+
const supportsFrameCallback = typeof HTMLVideoElement.prototype.requestVideoFrameCallback === 'function';
|
|
13814
|
+
// prefer an element that is already rendering this track (a local preview, typically) over
|
|
13815
|
+
// spinning up a second decode just to observe a frame
|
|
13816
|
+
const existingElement = candidateElements.find(el => el instanceof HTMLVideoElement && el.srcObject instanceof MediaStream && el.srcObject.getVideoTracks().includes(track) && (
|
|
13817
|
+
// without requestVideoFrameCallback we depend on `loadeddata`, which is one-shot: an element
|
|
13818
|
+
// that already decoded a frame (readyState >= HAVE_CURRENT_DATA) never fires it again.
|
|
13819
|
+
// Leave those alone and set up our own element, which starts out empty.
|
|
13820
|
+
supportsFrameCallback || el.readyState < 2));
|
|
13821
|
+
const element = existingElement !== null && existingElement !== void 0 ? existingElement : document.createElement('video');
|
|
13822
|
+
if (!existingElement) {
|
|
13823
|
+
element.playsInline = true;
|
|
13824
|
+
element.muted = true;
|
|
13825
|
+
element.srcObject = new MediaStream([track]);
|
|
13826
|
+
// the element is deliberately never added to the DOM, it only exists to pull frames.
|
|
13827
|
+
// WebKit delivers frames to a paused element too, so a rejected play() (Safari's low power
|
|
13828
|
+
// mode, for instance) is not a reason to stop waiting
|
|
13829
|
+
element.play().catch(error => {
|
|
13830
|
+
livekitLogger.debug('could not play element while waiting for the first video frame', {
|
|
13831
|
+
error
|
|
13832
|
+
});
|
|
13833
|
+
});
|
|
13834
|
+
}
|
|
13835
|
+
let timer;
|
|
13836
|
+
let frameHandle;
|
|
13837
|
+
let onLoadedData;
|
|
13838
|
+
try {
|
|
13839
|
+
return yield new Promise(resolve => {
|
|
13840
|
+
timer = setTimeout(() => resolve(false), timeoutMs);
|
|
13841
|
+
if (supportsFrameCallback) {
|
|
13842
|
+
frameHandle = element.requestVideoFrameCallback(() => resolve(true));
|
|
13843
|
+
} else {
|
|
13844
|
+
// Safari below 15.4 has no requestVideoFrameCallback. `loadeddata` fires once the first
|
|
13845
|
+
// frame has been decoded, which is the same signal a few milliseconds earlier.
|
|
13846
|
+
onLoadedData = () => resolve(true);
|
|
13847
|
+
element.addEventListener('loadeddata', onLoadedData);
|
|
13848
|
+
}
|
|
13849
|
+
});
|
|
13850
|
+
} finally {
|
|
13851
|
+
clearTimeout(timer);
|
|
13852
|
+
if (frameHandle !== undefined) {
|
|
13853
|
+
(_a = element.cancelVideoFrameCallback) === null || _a === void 0 ? void 0 : _a.call(element, frameHandle);
|
|
13854
|
+
}
|
|
13855
|
+
if (onLoadedData) {
|
|
13856
|
+
element.removeEventListener('loadeddata', onLoadedData);
|
|
13857
|
+
}
|
|
13858
|
+
if (!existingElement) {
|
|
13859
|
+
element.pause();
|
|
13860
|
+
element.srcObject = null;
|
|
13861
|
+
}
|
|
13862
|
+
}
|
|
13863
|
+
}();
|
|
13864
|
+
});
|
|
13677
13865
|
}const BACKGROUND_REACTION_DELAY = 5000;
|
|
13678
13866
|
// keep old audio elements when detached, we would re-use them since on iOS
|
|
13679
13867
|
// Safari tracks which audio elements have been "blessed" by the user.
|
|
@@ -14216,6 +14404,56 @@ function negotiateDependencyDescriptor(transceiver) {
|
|
|
14216
14404
|
return false;
|
|
14217
14405
|
}
|
|
14218
14406
|
}
|
|
14407
|
+
/**
|
|
14408
|
+
* VP9 and AV1 are published as SVC (a single RTP stream carrying every spatial layer)
|
|
14409
|
+
* by default. They can instead be published as real, rid based simulcast — one
|
|
14410
|
+
* independent stream per rid, each carrying a single spatial layer — when the caller
|
|
14411
|
+
* opts in with `simulcast: true` and a single spatial layer scalability mode (`L1Tx`).
|
|
14412
|
+
*
|
|
14413
|
+
* The SFU has to be told about this: without an explicit
|
|
14414
|
+
* `SimulcastCodec.videoLayerMode` it assumes `MULTIPLE_SPATIAL_LAYERS_PER_STREAM` for
|
|
14415
|
+
* any SVC capable codec.
|
|
14416
|
+
*/
|
|
14417
|
+
function isSVCSimulcast(codec, options) {
|
|
14418
|
+
var _a;
|
|
14419
|
+
return isSVCCodec(codec) && !!(options === null || options === void 0 ? void 0 : options.simulcast) && !!((_a = options.scalabilityMode) === null || _a === void 0 ? void 0 : _a.startsWith('L1T'));
|
|
14420
|
+
}
|
|
14421
|
+
/**
|
|
14422
|
+
* Whether the browser reads multiple encodings on an SVC capable codec as *legacy SVC*
|
|
14423
|
+
* rather than as real simulcast.
|
|
14424
|
+
*
|
|
14425
|
+
* Before Chrome M113, supplying more than one encoding for VP9/AV1 selected SVC mode;
|
|
14426
|
+
* only from M113 does libwebrtc treat such encodings as simulcast, and only when each
|
|
14427
|
+
* one carries its own scalabilityMode. Safari (and anything WebKit based, i. e. every
|
|
14428
|
+
* browser on iOS) still uses the old interpretation, as does React Native's libwebrtc.
|
|
14429
|
+
* Announced at https://groups.google.com/g/discuss-webrtc/c/-QQ3pxrl-fw
|
|
14430
|
+
*
|
|
14431
|
+
* Where this is true the rids would not exist on the wire, so VP9/AV1 must be published
|
|
14432
|
+
* as SVC no matter what the caller asked for.
|
|
14433
|
+
*/
|
|
14434
|
+
function usesLegacySVCEncodings() {
|
|
14435
|
+
const browser = getBrowser();
|
|
14436
|
+
return isSafariBased() ||
|
|
14437
|
+
// Even tho RN runs M114, it does not produce SVC layers when a single encoding
|
|
14438
|
+
// is provided. So we'll use the legacy SVC specification for now.
|
|
14439
|
+
// TODO: when we upstream libwebrtc, this will need additional verification
|
|
14440
|
+
isReactNative() || (browser === null || browser === void 0 ? void 0 : browser.name) === 'Chrome' && compareVersions(browser.version, '113') < 0;
|
|
14441
|
+
}
|
|
14442
|
+
/**
|
|
14443
|
+
* Last server version that doesn't support vp9/av1 simulcast.
|
|
14444
|
+
*/
|
|
14445
|
+
const svcSimulcastMinServerVersion = '1.13.6';
|
|
14446
|
+
/**
|
|
14447
|
+
* Whether the connected server honours `SimulcastCodec.videoLayerMode`, i. e. whether
|
|
14448
|
+
* VP9/AV1 can be published as rid based simulcast. An unknown version is treated as
|
|
14449
|
+
* unsupported so the publish falls back to SVC.
|
|
14450
|
+
*/
|
|
14451
|
+
function isSVCSimulcastSupportedByServer(serverVersion) {
|
|
14452
|
+
if (!serverVersion) {
|
|
14453
|
+
return false;
|
|
14454
|
+
}
|
|
14455
|
+
return compareVersions(serverVersion, svcSimulcastMinServerVersion) > 0;
|
|
14456
|
+
}
|
|
14219
14457
|
function supportsSetSinkId(elm) {
|
|
14220
14458
|
if (!document || isSafariBased()) {
|
|
14221
14459
|
return false;
|
|
@@ -14263,6 +14501,32 @@ function isSafariBased() {
|
|
|
14263
14501
|
const b = getBrowser();
|
|
14264
14502
|
return (b === null || b === void 0 ? void 0 : b.name) === 'Safari' || (b === null || b === void 0 ? void 0 : b.os) === 'iOS';
|
|
14265
14503
|
}
|
|
14504
|
+
/**
|
|
14505
|
+
* iPadOS has sent the desktop Macintosh user agent by default since iPadOS 13, so `getBrowser()`
|
|
14506
|
+
* reports `os: 'macOS'` there and every `os === 'iOS'` check misses it. macOS Safari implements no
|
|
14507
|
+
* touch events at all (`TouchEvent` undefined, `maxTouchPoints` 0) regardless of any touchscreen
|
|
14508
|
+
* attached, so touch capability separates the two. Measured on an iPad 6 / iPadOS 17
|
|
14509
|
+
* (`maxTouchPoints` 5) against macOS Safari 26.4 (`maxTouchPoints` 0).
|
|
14510
|
+
*
|
|
14511
|
+
* Deliberately a separate helper rather than a fix in `browserParser`: iPadOS spoofs the Mac
|
|
14512
|
+
* version too, so reporting `os: 'iOS'` there would leave `osVersion` at `10.15.7` and silently
|
|
14513
|
+
* break {@link isSafari17Based} and {@link isSafariSvcApi}, which compare it.
|
|
14514
|
+
*/
|
|
14515
|
+
function isIPadOS() {
|
|
14516
|
+
if (!isWeb()) {
|
|
14517
|
+
return false;
|
|
14518
|
+
}
|
|
14519
|
+
const b = getBrowser();
|
|
14520
|
+
return (b === null || b === void 0 ? void 0 : b.name) === 'Safari' && (b === null || b === void 0 ? void 0 : b.os) === 'macOS' && navigator.maxTouchPoints > 1;
|
|
14521
|
+
}
|
|
14522
|
+
/**
|
|
14523
|
+
* iPhone, iPad and iOS-hosted browsers — everything running the Apple camera capture pipeline,
|
|
14524
|
+
* including iPads that present themselves as a Mac.
|
|
14525
|
+
*/
|
|
14526
|
+
function isAppleMobile() {
|
|
14527
|
+
var _a;
|
|
14528
|
+
return ((_a = getBrowser()) === null || _a === void 0 ? void 0 : _a.os) === 'iOS' || isIPadOS();
|
|
14529
|
+
}
|
|
14266
14530
|
function isSafari17Based() {
|
|
14267
14531
|
const b = getBrowser();
|
|
14268
14532
|
return (b === null || b === void 0 ? void 0 : b.name) === 'Safari' && b.version.startsWith('17.') || (b === null || b === void 0 ? void 0 : b.os) === 'iOS' && !!(b === null || b === void 0 ? void 0 : b.osVersion) && compareVersions(b.osVersion, '17') >= 0;
|
|
@@ -14754,6 +15018,35 @@ function extractMaxAgeFromRequestHeaders(headers) {
|
|
|
14754
15018
|
function isCompressionStreamSupported() {
|
|
14755
15019
|
return typeof CompressionStream !== 'undefined';
|
|
14756
15020
|
}
|
|
15021
|
+
let deflateRawCompressionSupported = null;
|
|
15022
|
+
/**
|
|
15023
|
+
* Whether this runtime can compress AND decompress the `deflate-raw` format, which is a stricter
|
|
15024
|
+
* requirement than {@link isCompressionStreamSupported}: Chromium 80-102 included
|
|
15025
|
+
* `CompressionStream` supporting only `gzip` / `deflate`, and `deflate-raw` was added in Chromium
|
|
15026
|
+
* 103 (Firefox 113, Safari 16.4).
|
|
15027
|
+
*/
|
|
15028
|
+
function isDeflateRawCompressionSupported() {
|
|
15029
|
+
if (typeof deflateRawCompressionSupported !== 'boolean') {
|
|
15030
|
+
deflateRawCompressionSupported = probeDeflateRawCompressionSupport();
|
|
15031
|
+
}
|
|
15032
|
+
return deflateRawCompressionSupported;
|
|
15033
|
+
}
|
|
15034
|
+
function probeDeflateRawCompressionSupport() {
|
|
15035
|
+
if (typeof CompressionStream === 'undefined' || typeof DecompressionStream === 'undefined') {
|
|
15036
|
+
return false;
|
|
15037
|
+
}
|
|
15038
|
+
try {
|
|
15039
|
+
// There is no api to query format support, and constructing with an unsupported format throws
|
|
15040
|
+
// synchronously, so constructing one of each is the probe. Both are checked because the
|
|
15041
|
+
// deflate-raw capability advertised to peers is as much about decompressing what they send us
|
|
15042
|
+
// as it is about compressing what we send them.
|
|
15043
|
+
new CompressionStream('deflate-raw');
|
|
15044
|
+
new DecompressionStream('deflate-raw');
|
|
15045
|
+
return true;
|
|
15046
|
+
} catch (_a) {
|
|
15047
|
+
return false;
|
|
15048
|
+
}
|
|
15049
|
+
}
|
|
14757
15050
|
function isPublisherOfferWithJoinSupported() {
|
|
14758
15051
|
// we have connectivity issue about publisher offer with join on firefox #1919
|
|
14759
15052
|
return isCompressionStreamSupported() && !isFireFox();
|
|
@@ -14824,6 +15117,15 @@ function getAbortReasonAsString(signal) {
|
|
|
14824
15117
|
default:
|
|
14825
15118
|
return 'toString' in reason ? reason.toString() : defaultMessage;
|
|
14826
15119
|
}
|
|
15120
|
+
}
|
|
15121
|
+
function getErrorDescription(error, errorCategory) {
|
|
15122
|
+
if (error instanceof Error) {
|
|
15123
|
+
if (error.name && error.message) {
|
|
15124
|
+
return "".concat(error.name, ": ").concat(error.message);
|
|
15125
|
+
}
|
|
15126
|
+
return error.name;
|
|
15127
|
+
}
|
|
15128
|
+
return "Encountered unknown ".concat(errorCategory, " error: ").concat(String(error));
|
|
14827
15129
|
}const ENCRYPTION_ALGORITHM = 'AES-GCM';
|
|
14828
15130
|
// How many consecutive frames can fail decrypting before a particular key gets marked as invalid
|
|
14829
15131
|
const DECRYPTION_FAILURE_TOLERANCE = 10;
|
|
@@ -15747,11 +16049,38 @@ class HTMLElementInfo {
|
|
|
15747
16049
|
}
|
|
15748
16050
|
}
|
|
15749
16051
|
function isElementInPiP(el) {
|
|
15750
|
-
var _a
|
|
16052
|
+
var _a;
|
|
15751
16053
|
// Simple video PiP
|
|
15752
16054
|
if (document.pictureInPictureElement === el) return true;
|
|
15753
|
-
// Document PiP
|
|
15754
|
-
|
|
16055
|
+
// Document PiP: the element has to actually live in the PiP window, otherwise an
|
|
16056
|
+
// opener-document element whose coordinates happen to fall inside the PiP window's
|
|
16057
|
+
// bounds is reported as being in PiP.
|
|
16058
|
+
const pipWindow = (_a = window.documentPictureInPicture) === null || _a === void 0 ? void 0 : _a.window;
|
|
16059
|
+
if (pipWindow) {
|
|
16060
|
+
return isDocumentInPiPWindow(el.ownerDocument, pipWindow) && isElementInViewport(el, pipWindow);
|
|
16061
|
+
}
|
|
16062
|
+
return false;
|
|
16063
|
+
}
|
|
16064
|
+
// Whether the document is the Document PiP window's own document, or the document of a frame
|
|
16065
|
+
// nested inside it. The spec allows frames in a PiP window, so an element in one is in PiP:
|
|
16066
|
+
// https://wicg.github.io/document-picture-in-picture/#iframes
|
|
16067
|
+
function isDocumentInPiPWindow(doc, pipWindow) {
|
|
16068
|
+
var _a, _b, _c;
|
|
16069
|
+
// A cross-origin frame anywhere between the element and the PiP window hides frameElement
|
|
16070
|
+
// from the walk below, but top stays readable across origins and identifies the top-level
|
|
16071
|
+
// window the element belongs to. For an opener element that is the opener, not the PiP window.
|
|
16072
|
+
if (((_a = doc.defaultView) === null || _a === void 0 ? void 0 : _a.top) === pipWindow) return true;
|
|
16073
|
+
let current = doc;
|
|
16074
|
+
while (current) {
|
|
16075
|
+
if (current === pipWindow.document) return true;
|
|
16076
|
+
try {
|
|
16077
|
+
// Reading frameElement across a cross-origin boundary throws, which means we cannot
|
|
16078
|
+
// establish the ancestry and must not claim the element is in PiP.
|
|
16079
|
+
current = (_c = (_b = current.defaultView) === null || _b === void 0 ? void 0 : _b.frameElement) === null || _c === void 0 ? void 0 : _c.ownerDocument;
|
|
16080
|
+
} catch (_d) {
|
|
16081
|
+
return false;
|
|
16082
|
+
}
|
|
16083
|
+
}
|
|
15755
16084
|
return false;
|
|
15756
16085
|
}
|
|
15757
16086
|
// does not account for occlusion by other elements or opacity property
|
|
@@ -15775,10 +16104,18 @@ function isElementInViewport(el, win) {
|
|
|
15775
16104
|
* @experimental
|
|
15776
16105
|
*/
|
|
15777
16106
|
class E2EEManager extends eventsExports.EventEmitter {
|
|
16107
|
+
get logContext() {
|
|
16108
|
+
var _a, _b;
|
|
16109
|
+
return {
|
|
16110
|
+
room: (_a = this.room) === null || _a === void 0 ? void 0 : _a.name,
|
|
16111
|
+
participant: (_b = this.room) === null || _b === void 0 ? void 0 : _b.localParticipant.identity
|
|
16112
|
+
};
|
|
16113
|
+
}
|
|
15778
16114
|
constructor(options, dcEncryptionEnabled) {
|
|
15779
16115
|
super();
|
|
15780
16116
|
this.decryptDataRequests = new Map();
|
|
15781
16117
|
this.encryptDataRequests = new Map();
|
|
16118
|
+
this.log = getLogger(LoggerNames.E2EE, () => this.logContext);
|
|
15782
16119
|
this.onWorkerMessage = ev => {
|
|
15783
16120
|
var _a, _b;
|
|
15784
16121
|
const _ev$data = ev.data,
|
|
@@ -15786,22 +16123,22 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
15786
16123
|
data = _ev$data.data;
|
|
15787
16124
|
switch (kind) {
|
|
15788
16125
|
case 'error':
|
|
15789
|
-
|
|
15790
|
-
//
|
|
15791
|
-
//
|
|
16126
|
+
// If error has uuid, it's from an async operation (encrypt/decrypt).
|
|
16127
|
+
// Reject the corresponding future and let the caller decide how to log/handle;
|
|
16128
|
+
// logging here would duplicate whatever the caller does.
|
|
15792
16129
|
if (data.uuid) {
|
|
15793
16130
|
const decryptFuture = this.decryptDataRequests.get(data.uuid);
|
|
15794
16131
|
if (decryptFuture === null || decryptFuture === void 0 ? void 0 : decryptFuture.reject) {
|
|
15795
16132
|
decryptFuture.reject(data.error);
|
|
15796
|
-
break;
|
|
16133
|
+
break;
|
|
15797
16134
|
}
|
|
15798
16135
|
const encryptFuture = this.encryptDataRequests.get(data.uuid);
|
|
15799
16136
|
if (encryptFuture === null || encryptFuture === void 0 ? void 0 : encryptFuture.reject) {
|
|
15800
16137
|
encryptFuture.reject(data.error);
|
|
15801
|
-
break;
|
|
16138
|
+
break;
|
|
15802
16139
|
}
|
|
15803
16140
|
}
|
|
15804
|
-
|
|
16141
|
+
this.log.error(data.error.message);
|
|
15805
16142
|
this.emit(EncryptionEvent.EncryptionError, data.error, data.participantIdentity);
|
|
15806
16143
|
break;
|
|
15807
16144
|
case 'initAck':
|
|
@@ -15846,10 +16183,13 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
15846
16183
|
case 'packetTrailerMetadata':
|
|
15847
16184
|
this.handleFrameMetadata(data.trackId, data.rtpTimestamp, data.ssrc, data.metadata);
|
|
15848
16185
|
break;
|
|
16186
|
+
case 'log':
|
|
16187
|
+
workerLogger[data.level](data.msg, data.context);
|
|
16188
|
+
break;
|
|
15849
16189
|
}
|
|
15850
16190
|
};
|
|
15851
16191
|
this.onWorkerError = ev => {
|
|
15852
|
-
|
|
16192
|
+
this.log.error('e2ee worker encountered an error:', {
|
|
15853
16193
|
error: ev.error
|
|
15854
16194
|
});
|
|
15855
16195
|
this.emit(EncryptionEvent.EncryptionError, ev.error, undefined);
|
|
@@ -15872,7 +16212,7 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
15872
16212
|
if (!isE2EESupported()) {
|
|
15873
16213
|
throw new DeviceUnsupportedError('tried to setup end-to-end encryption on an unsupported browser');
|
|
15874
16214
|
}
|
|
15875
|
-
|
|
16215
|
+
this.log.info('setting up e2ee');
|
|
15876
16216
|
if (room !== this.room) {
|
|
15877
16217
|
this.room = room;
|
|
15878
16218
|
this.setupEventListeners(room, this.keyProvider);
|
|
@@ -15885,20 +16225,94 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
15885
16225
|
}
|
|
15886
16226
|
};
|
|
15887
16227
|
if (this.worker) {
|
|
15888
|
-
|
|
16228
|
+
this.log.info("initializing worker", {
|
|
15889
16229
|
worker: this.worker
|
|
15890
16230
|
});
|
|
15891
16231
|
this.worker.onmessage = this.onWorkerMessage;
|
|
15892
16232
|
this.worker.onerror = this.onWorkerError;
|
|
15893
16233
|
this.worker.postMessage(msg);
|
|
16234
|
+
this.subscribeToLogLevelChanges();
|
|
15894
16235
|
}
|
|
15895
16236
|
}
|
|
15896
16237
|
}
|
|
16238
|
+
/**
|
|
16239
|
+
* Subscribe the current worker to main-thread `workerLogger` level changes,
|
|
16240
|
+
* without strongly retaining `this` or `this.worker` from the module-global
|
|
16241
|
+
* listener Set on the logger. See {@link disposeRegistry}.
|
|
16242
|
+
*/
|
|
16243
|
+
subscribeToLogLevelChanges() {
|
|
16244
|
+
var _a;
|
|
16245
|
+
// Guard against duplicate registration on re-setup.
|
|
16246
|
+
(_a = this.unsubscribeLogLevel) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
16247
|
+
let unsub;
|
|
16248
|
+
if (E2EEManager.disposeRegistry) {
|
|
16249
|
+
// Modern engines: hold the worker weakly so the module-global listener Set
|
|
16250
|
+
// on the logger can't retain this manager, and clean up the entry on GC.
|
|
16251
|
+
const workerRef = new WeakRef(this.worker);
|
|
16252
|
+
unsub = onWorkerLogLevelChanged(level => {
|
|
16253
|
+
const worker = workerRef.deref();
|
|
16254
|
+
if (!worker) {
|
|
16255
|
+
unsub === null || unsub === void 0 ? void 0 : unsub();
|
|
16256
|
+
return;
|
|
16257
|
+
}
|
|
16258
|
+
worker.postMessage({
|
|
16259
|
+
kind: 'setLogLevel',
|
|
16260
|
+
data: {
|
|
16261
|
+
level
|
|
16262
|
+
}
|
|
16263
|
+
});
|
|
16264
|
+
});
|
|
16265
|
+
E2EEManager.disposeRegistry.register(this, unsub, this);
|
|
16266
|
+
} else {
|
|
16267
|
+
// Safari <14.1 and similar: no WeakRef. Fall back to a strong reference;
|
|
16268
|
+
// the leak lives until the consumer calls `dispose()`.
|
|
16269
|
+
const worker = this.worker;
|
|
16270
|
+
unsub = onWorkerLogLevelChanged(level => {
|
|
16271
|
+
worker.postMessage({
|
|
16272
|
+
kind: 'setLogLevel',
|
|
16273
|
+
data: {
|
|
16274
|
+
level
|
|
16275
|
+
}
|
|
16276
|
+
});
|
|
16277
|
+
});
|
|
16278
|
+
}
|
|
16279
|
+
this.unsubscribeLogLevel = unsub;
|
|
16280
|
+
}
|
|
16281
|
+
/**
|
|
16282
|
+
* @internal
|
|
16283
|
+
* Release the log-level subscription, reject any pending encrypt/decrypt
|
|
16284
|
+
* futures, and detach the worker message handlers. The worker itself is
|
|
16285
|
+
* caller-owned and is not terminated. Idempotent.
|
|
16286
|
+
*/
|
|
16287
|
+
dispose() {
|
|
16288
|
+
var _a, _b, _c;
|
|
16289
|
+
(_a = this.unsubscribeLogLevel) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
16290
|
+
this.unsubscribeLogLevel = undefined;
|
|
16291
|
+
if (E2EEManager.disposeRegistry) {
|
|
16292
|
+
E2EEManager.disposeRegistry.unregister(this);
|
|
16293
|
+
}
|
|
16294
|
+
// Reject pending futures BEFORE detaching worker handlers, so any late
|
|
16295
|
+
// response can't resolve one after we've cut the pipe. Each future's
|
|
16296
|
+
// `onFinally` deletes its own map entry, so both maps drain themselves.
|
|
16297
|
+
// Snapshot before iterating in case a rejection handler mutates the map.
|
|
16298
|
+
const disposalError = new CryptorError('E2EEManager disposed', CryptorErrorReason.InternalError);
|
|
16299
|
+
for (const future of [...this.encryptDataRequests.values()]) {
|
|
16300
|
+
(_b = future.reject) === null || _b === void 0 ? void 0 : _b.call(future, disposalError);
|
|
16301
|
+
}
|
|
16302
|
+
for (const future of [...this.decryptDataRequests.values()]) {
|
|
16303
|
+
(_c = future.reject) === null || _c === void 0 ? void 0 : _c.call(future, disposalError);
|
|
16304
|
+
}
|
|
16305
|
+
if (this.worker) {
|
|
16306
|
+
this.worker.onmessage = null;
|
|
16307
|
+
this.worker.onerror = null;
|
|
16308
|
+
}
|
|
16309
|
+
this.removeAllListeners();
|
|
16310
|
+
}
|
|
15897
16311
|
/**
|
|
15898
16312
|
* @internal
|
|
15899
16313
|
*/
|
|
15900
16314
|
setParticipantCryptorEnabled(enabled, participantIdentity) {
|
|
15901
|
-
|
|
16315
|
+
this.log.debug("set e2ee to ".concat(enabled, " for participant ").concat(participantIdentity));
|
|
15902
16316
|
this.postEnable(enabled, participantIdentity);
|
|
15903
16317
|
}
|
|
15904
16318
|
/**
|
|
@@ -15906,7 +16320,7 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
15906
16320
|
*/
|
|
15907
16321
|
setSifTrailer(trailer) {
|
|
15908
16322
|
if (!trailer || trailer.length === 0) {
|
|
15909
|
-
|
|
16323
|
+
this.log.warn("ignoring server sent trailer as it's empty");
|
|
15910
16324
|
} else {
|
|
15911
16325
|
this.postSifTrailer(trailer);
|
|
15912
16326
|
}
|
|
@@ -16113,8 +16527,7 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
16113
16527
|
*/
|
|
16114
16528
|
setParticipantCryptorEnabledForPublication(pub, participantIdentity) {
|
|
16115
16529
|
if (!pub.trackInfo) {
|
|
16116
|
-
|
|
16117
|
-
participant: participantIdentity,
|
|
16530
|
+
this.log.warn('skipping e2ee enabled update for publication without trackInfo', {
|
|
16118
16531
|
trackSid: pub.trackSid
|
|
16119
16532
|
});
|
|
16120
16533
|
return;
|
|
@@ -16134,7 +16547,7 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
16134
16547
|
setupE2EESender(track, sender) {
|
|
16135
16548
|
var _a, _b, _c;
|
|
16136
16549
|
if (!isLocalTrack(track) || !sender) {
|
|
16137
|
-
if (!sender)
|
|
16550
|
+
if (!sender) this.log.warn('early return because sender is not ready');
|
|
16138
16551
|
return;
|
|
16139
16552
|
}
|
|
16140
16553
|
this.handleSender(sender, track.mediaStreamID, undefined, isVideoTrack(track) ? (_b = (_a = track.publishOptions) === null || _a === void 0 ? void 0 : _a.frameMetadata) !== null && _b !== void 0 ? _b : (_c = track.publishOptions) === null || _c === void 0 ? void 0 : _c.packetTrailer : undefined);
|
|
@@ -16227,7 +16640,7 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
16227
16640
|
throw TypeError('local identity needs to be known in order to set up encrypted sender');
|
|
16228
16641
|
}
|
|
16229
16642
|
if (isScriptTransformSupportedForWorker()) {
|
|
16230
|
-
|
|
16643
|
+
this.log.info('initialize script transform');
|
|
16231
16644
|
const options = {
|
|
16232
16645
|
kind: 'encode',
|
|
16233
16646
|
participantIdentity: this.room.localParticipant.identity,
|
|
@@ -16239,7 +16652,7 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
16239
16652
|
// @ts-ignore
|
|
16240
16653
|
sender.transform = new RTCRtpScriptTransform(this.worker, options);
|
|
16241
16654
|
} else {
|
|
16242
|
-
|
|
16655
|
+
this.log.info('initialize encoded streams');
|
|
16243
16656
|
// @ts-ignore
|
|
16244
16657
|
const senderStreams = sender.createEncodedStreams();
|
|
16245
16658
|
const msg = {
|
|
@@ -16259,7 +16672,15 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
|
16259
16672
|
// @ts-ignore
|
|
16260
16673
|
sender[E2EE_FLAG] = true;
|
|
16261
16674
|
}
|
|
16262
|
-
}
|
|
16675
|
+
}
|
|
16676
|
+
/**
|
|
16677
|
+
* Runs a cleanup callback once this manager is garbage collected. Lets the
|
|
16678
|
+
* log-level listener (held in a module-global Set on the main-thread logger)
|
|
16679
|
+
* fall out of scope even when the consumer forgets to call `dispose()`.
|
|
16680
|
+
*/
|
|
16681
|
+
E2EEManager.disposeRegistry = typeof FinalizationRegistry !== 'undefined' && typeof WeakRef !== 'undefined' && new FinalizationRegistry(cleanup => {
|
|
16682
|
+
cleanup();
|
|
16683
|
+
});const MAX_ENTRIES = 300;
|
|
16263
16684
|
/**
|
|
16264
16685
|
* Caches frame metadata extracted from received video frames,
|
|
16265
16686
|
* keyed by RTP timestamp so it can be looked up when the frame is displayed.
|
|
@@ -18070,9 +18491,9 @@ class WebSocketStream {
|
|
|
18070
18491
|
let data = _ref2.data;
|
|
18071
18492
|
return controller.enqueue(data);
|
|
18072
18493
|
};
|
|
18073
|
-
ws.onerror = e => controller.error(ConnectionError.websocket(
|
|
18494
|
+
ws.onerror = e => controller.error(ConnectionError.websocket(getErrorDescription(e, 'websocket')));
|
|
18074
18495
|
ws.onclose = ev => {
|
|
18075
|
-
if (ev.wasClean) {
|
|
18496
|
+
if (ev.wasClean || ev.code === 1000) {
|
|
18076
18497
|
controller.close();
|
|
18077
18498
|
} else {
|
|
18078
18499
|
controller.error(ConnectionError.websocket("WS closed unexpectedly with code ".concat(ev.code)));
|
|
@@ -18354,7 +18775,7 @@ class SignalClient {
|
|
|
18354
18775
|
const rtcUrl = createRtcUrl(url, params, useV0Path).toString();
|
|
18355
18776
|
const validateUrl = createValidateUrl(rtcUrl).toString();
|
|
18356
18777
|
return new Promise((resolve, reject) => __awaiter(_this2, void 0, void 0, function* () {
|
|
18357
|
-
var _a, _b;
|
|
18778
|
+
var _a, _b, _c, _d, _e;
|
|
18358
18779
|
try {
|
|
18359
18780
|
let alreadyAborted = false;
|
|
18360
18781
|
const abortHandler = eventOrError => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -18461,38 +18882,56 @@ class SignalClient {
|
|
|
18461
18882
|
const signalReader = connection.readable.getReader();
|
|
18462
18883
|
this.streamWriter = connection.writable.getWriter();
|
|
18463
18884
|
// wsTimeout only guarded the upgrade; guard the first-message read with
|
|
18464
|
-
// its own
|
|
18465
|
-
|
|
18466
|
-
|
|
18885
|
+
// its own deadline so a silent server can't hang join() forever.
|
|
18886
|
+
// During reconnect, drop any stray messages that arrive before the
|
|
18887
|
+
// ReconnectResponse so we do not declare the channel reconnected on the
|
|
18888
|
+
// wrong signal.
|
|
18889
|
+
let firstSignalResponse;
|
|
18467
18890
|
try {
|
|
18468
|
-
|
|
18469
|
-
|
|
18470
|
-
|
|
18471
|
-
|
|
18472
|
-
|
|
18891
|
+
const deadline = Date.now() + JOIN_RESPONSE_TIMEOUT;
|
|
18892
|
+
// eslint-disable-next-line no-constant-condition
|
|
18893
|
+
while (true) {
|
|
18894
|
+
const remaining = deadline - Date.now();
|
|
18895
|
+
if (remaining <= 0) {
|
|
18896
|
+
throw ConnectionError.timeout('signal connection timed out while waiting for the first message');
|
|
18897
|
+
}
|
|
18898
|
+
let readTimeout;
|
|
18899
|
+
const readResult = yield Promise.race([signalReader.read(), new Promise((_, rejectRead) => {
|
|
18900
|
+
readTimeout = setTimeout(() => {
|
|
18901
|
+
rejectRead(ConnectionError.timeout('signal connection timed out while waiting for the first message'));
|
|
18902
|
+
}, remaining);
|
|
18903
|
+
})]);
|
|
18904
|
+
clearTimeout(readTimeout);
|
|
18905
|
+
if (!readResult.value) {
|
|
18906
|
+
throw ConnectionError.internal('no message received as first message');
|
|
18907
|
+
}
|
|
18908
|
+
const parsed = parseSignalResponse(readResult.value);
|
|
18909
|
+
if (this.lifecycleState === 'reconnecting' && ((_a = parsed.message) === null || _a === void 0 ? void 0 : _a.case) !== 'reconnect' && ((_b = parsed.message) === null || _b === void 0 ? void 0 : _b.case) !== 'leave') {
|
|
18910
|
+
this.log.warn('dropping signal message while awaiting reconnect response', {
|
|
18911
|
+
messageCase: (_c = parsed.message) === null || _c === void 0 ? void 0 : _c.case
|
|
18912
|
+
});
|
|
18913
|
+
continue;
|
|
18914
|
+
}
|
|
18915
|
+
firstSignalResponse = parsed;
|
|
18916
|
+
break;
|
|
18917
|
+
}
|
|
18473
18918
|
} catch (e) {
|
|
18474
|
-
// No first message in time: release the reader and tear down the ws
|
|
18919
|
+
// No usable first message in time: release the reader and tear down the ws
|
|
18475
18920
|
// so we surface the timeout instead of leaking an open connection.
|
|
18476
18921
|
signalReader.releaseLock();
|
|
18477
18922
|
reject(e);
|
|
18478
18923
|
this.close();
|
|
18479
18924
|
return;
|
|
18480
|
-
} finally {
|
|
18481
|
-
clearTimeout(firstMessageTimeout);
|
|
18482
18925
|
}
|
|
18483
18926
|
signalReader.releaseLock();
|
|
18484
|
-
if (!firstMessage.value) {
|
|
18485
|
-
throw ConnectionError.internal('no message received as first message');
|
|
18486
|
-
}
|
|
18487
|
-
const firstSignalResponse = parseSignalResponse(firstMessage.value);
|
|
18488
18927
|
// Validate the first message
|
|
18489
|
-
const validation = this.validateFirstMessage(firstSignalResponse, (
|
|
18928
|
+
const validation = this.validateFirstMessage(firstSignalResponse, (_d = opts.reconnect) !== null && _d !== void 0 ? _d : false);
|
|
18490
18929
|
if (!validation.isValid) {
|
|
18491
18930
|
reject(validation.error);
|
|
18492
18931
|
return;
|
|
18493
18932
|
}
|
|
18494
18933
|
// Handle join response
|
|
18495
|
-
if (((
|
|
18934
|
+
if (((_e = firstSignalResponse.message) === null || _e === void 0 ? void 0 : _e.case) === 'join') {
|
|
18496
18935
|
// Set up ping configuration
|
|
18497
18936
|
this.pingTimeoutDuration = firstSignalResponse.message.value.pingTimeout;
|
|
18498
18937
|
this.pingIntervalDuration = firstSignalResponse.message.value.pingInterval;
|
|
@@ -18506,9 +18945,7 @@ class SignalClient {
|
|
|
18506
18945
|
this.onJoined(firstSignalResponse.message.value);
|
|
18507
18946
|
}
|
|
18508
18947
|
}
|
|
18509
|
-
|
|
18510
|
-
const firstMessageToProcess = validation.shouldProcessFirstMessage ? firstSignalResponse : undefined;
|
|
18511
|
-
this.handleSignalConnected(connection, wsTimeout, attemptId, firstMessageToProcess);
|
|
18948
|
+
this.handleSignalConnected(connection, wsTimeout, attemptId);
|
|
18512
18949
|
resolve(validation.response);
|
|
18513
18950
|
} catch (e) {
|
|
18514
18951
|
reject(e);
|
|
@@ -18522,11 +18959,8 @@ class SignalClient {
|
|
|
18522
18959
|
}();
|
|
18523
18960
|
});
|
|
18524
18961
|
}
|
|
18525
|
-
startReadingLoop(signalReader
|
|
18962
|
+
startReadingLoop(signalReader) {
|
|
18526
18963
|
return __awaiter(this, void 0, void 0, function* () {
|
|
18527
|
-
if (firstMessage) {
|
|
18528
|
-
this.handleSignalResponse(firstMessage);
|
|
18529
|
-
}
|
|
18530
18964
|
const attemptId = this.attemptId;
|
|
18531
18965
|
while (true) {
|
|
18532
18966
|
if (this.signalLatency) {
|
|
@@ -18962,6 +19396,7 @@ class SignalClient {
|
|
|
18962
19396
|
return __awaiter(this, arguments, void 0, function (reason) {
|
|
18963
19397
|
var _this6 = this;
|
|
18964
19398
|
let attemptId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.attemptId;
|
|
19399
|
+
let simulateReconnectDelay = arguments.length > 2 ? arguments[2] : undefined;
|
|
18965
19400
|
return function* () {
|
|
18966
19401
|
const onCloseCallback = _this6.onClose;
|
|
18967
19402
|
if (!_this6.sendLifecycleInput({
|
|
@@ -18983,6 +19418,10 @@ class SignalClient {
|
|
|
18983
19418
|
_this6.log.info("websocket connection closed: ".concat(reason), {
|
|
18984
19419
|
reason
|
|
18985
19420
|
});
|
|
19421
|
+
if (simulateReconnectDelay) {
|
|
19422
|
+
_this6.log.info("waiting for ".concat(simulateReconnectDelay, "ms until reconnecting signal"));
|
|
19423
|
+
yield sleep(simulateReconnectDelay);
|
|
19424
|
+
}
|
|
18986
19425
|
if (onCloseCallback) {
|
|
18987
19426
|
onCloseCallback(reason);
|
|
18988
19427
|
}
|
|
@@ -19043,7 +19482,7 @@ class SignalClient {
|
|
|
19043
19482
|
* @param firstMessage Optional first message to process
|
|
19044
19483
|
* @internal
|
|
19045
19484
|
*/
|
|
19046
|
-
handleSignalConnected(connection, timeoutHandle, attemptId
|
|
19485
|
+
handleSignalConnected(connection, timeoutHandle, attemptId) {
|
|
19047
19486
|
clearTimeout(timeoutHandle);
|
|
19048
19487
|
const established = this.sendLifecycleInput(this.lifecycleState === 'reconnecting' ? {
|
|
19049
19488
|
type: 'reconnectComplete',
|
|
@@ -19065,7 +19504,7 @@ class SignalClient {
|
|
|
19065
19504
|
}
|
|
19066
19505
|
this.log.info('signal connected');
|
|
19067
19506
|
this.startPingInterval();
|
|
19068
|
-
this.startReadingLoop(connection.readable.getReader()
|
|
19507
|
+
this.startReadingLoop(connection.readable.getReader());
|
|
19069
19508
|
}
|
|
19070
19509
|
/**
|
|
19071
19510
|
* Validates the first message received from the signal server
|
|
@@ -19075,28 +19514,18 @@ class SignalClient {
|
|
|
19075
19514
|
* @internal
|
|
19076
19515
|
*/
|
|
19077
19516
|
validateFirstMessage(firstSignalResponse, isReconnect) {
|
|
19078
|
-
var _a, _b, _c, _d
|
|
19517
|
+
var _a, _b, _c, _d;
|
|
19079
19518
|
if (((_a = firstSignalResponse.message) === null || _a === void 0 ? void 0 : _a.case) === 'join') {
|
|
19080
19519
|
return {
|
|
19081
19520
|
isValid: true,
|
|
19082
19521
|
response: firstSignalResponse.message.value
|
|
19083
19522
|
};
|
|
19084
|
-
} else if (this.lifecycleState === 'reconnecting' && ((_b = firstSignalResponse.message) === null || _b === void 0 ? void 0 : _b.case)
|
|
19085
|
-
|
|
19086
|
-
|
|
19087
|
-
|
|
19088
|
-
|
|
19089
|
-
|
|
19090
|
-
} else {
|
|
19091
|
-
// in reconnecting, any message received means signal reconnected and we still need to process it
|
|
19092
|
-
this.log.debug('declaring signal reconnected without reconnect response received');
|
|
19093
|
-
return {
|
|
19094
|
-
isValid: true,
|
|
19095
|
-
response: undefined,
|
|
19096
|
-
shouldProcessFirstMessage: true
|
|
19097
|
-
};
|
|
19098
|
-
}
|
|
19099
|
-
} else if (this.isEstablishingConnection && ((_d = firstSignalResponse.message) === null || _d === void 0 ? void 0 : _d.case) === 'leave') {
|
|
19523
|
+
} else if (this.lifecycleState === 'reconnecting' && ((_b = firstSignalResponse.message) === null || _b === void 0 ? void 0 : _b.case) === 'reconnect') {
|
|
19524
|
+
return {
|
|
19525
|
+
isValid: true,
|
|
19526
|
+
response: firstSignalResponse.message.value
|
|
19527
|
+
};
|
|
19528
|
+
} else if (this.isEstablishingConnection && ((_c = firstSignalResponse.message) === null || _c === void 0 ? void 0 : _c.case) === 'leave') {
|
|
19100
19529
|
return {
|
|
19101
19530
|
isValid: false,
|
|
19102
19531
|
error: ConnectionError.leaveRequest('Received leave request while trying to (re)connect', firstSignalResponse.message.value.reason)
|
|
@@ -19105,7 +19534,7 @@ class SignalClient {
|
|
|
19105
19534
|
// non-reconnect case, should receive join response first
|
|
19106
19535
|
return {
|
|
19107
19536
|
isValid: false,
|
|
19108
|
-
error: ConnectionError.internal("did not receive join response, got ".concat((
|
|
19537
|
+
error: ConnectionError.internal("did not receive join response, got ".concat((_d = firstSignalResponse.message) === null || _d === void 0 ? void 0 : _d.case, " instead"))
|
|
19109
19538
|
};
|
|
19110
19539
|
}
|
|
19111
19540
|
return {
|
|
@@ -19210,6 +19639,12 @@ function createConnectionParams(token, info, opts) {
|
|
|
19210
19639
|
if (opts.adaptiveStream) {
|
|
19211
19640
|
params.set('adaptive_stream', '1');
|
|
19212
19641
|
}
|
|
19642
|
+
if (opts.disableIceLite) {
|
|
19643
|
+
params.set('disable_ice_lite', '1');
|
|
19644
|
+
}
|
|
19645
|
+
if (typeof opts.subscriberAllowPause !== 'undefined') {
|
|
19646
|
+
params.set('subscriber_allow_pause', opts.subscriberAllowPause ? '1' : '0');
|
|
19647
|
+
}
|
|
19213
19648
|
if (opts.reconnectReason) {
|
|
19214
19649
|
params.set('reconnect_reason', opts.reconnectReason.toString());
|
|
19215
19650
|
}
|
|
@@ -19228,7 +19663,9 @@ function createJoinRequestConnectionParams(token, info, opts, publisherOffer) {
|
|
|
19228
19663
|
clientInfo: info,
|
|
19229
19664
|
connectionSettings: new ConnectionSettings({
|
|
19230
19665
|
autoSubscribe: !!opts.autoSubscribe,
|
|
19231
|
-
adaptiveStream: !!opts.adaptiveStream
|
|
19666
|
+
adaptiveStream: !!opts.adaptiveStream,
|
|
19667
|
+
disableIceLite: !!opts.disableIceLite,
|
|
19668
|
+
subscriberAllowPause: opts.subscriberAllowPause
|
|
19232
19669
|
}),
|
|
19233
19670
|
reconnect: !!opts.reconnect,
|
|
19234
19671
|
participantSid: opts.sid ? opts.sid : undefined,
|
|
@@ -20069,40 +20506,112 @@ function requireLib() {
|
|
|
20069
20506
|
const startBitrateMultiplier = 0.9;
|
|
20070
20507
|
/** Maximum x-google-start-bitrate in kbps. 1 Mbps prevents BWE from starting too aggressively. */
|
|
20071
20508
|
const maxStartBitrateKbps = 1000;
|
|
20509
|
+
/**
|
|
20510
|
+
* Minimum target bitrate in kbps for the start bitrate hint. Below this, seeding above the
|
|
20511
|
+
* real capacity costs more than the ramp it saves, so libwebrtc's default is left in place.
|
|
20512
|
+
*/
|
|
20513
|
+
const minTargetBitrateKbps = 300;
|
|
20072
20514
|
const debounceInterval = 20;
|
|
20073
20515
|
/**
|
|
20074
|
-
*
|
|
20075
|
-
* This SDP munging is used for a bitrate setting that cannot be applied through
|
|
20076
|
-
* `RTCRtpEncodingParameters`.
|
|
20516
|
+
* Codec payload for `codec` in this media section, when the section carries `cid`.
|
|
20077
20517
|
*
|
|
20078
|
-
* Returns `undefined` when the section does not belong to the track, `0` when
|
|
20079
|
-
*
|
|
20080
|
-
* requested codec is present (whether the bitrate was added or already set).
|
|
20518
|
+
* Returns `undefined` when the section does not belong to the track, `0` when it does but
|
|
20519
|
+
* does not offer the requested codec, and the codec payload otherwise.
|
|
20081
20520
|
*
|
|
20082
20521
|
* @internal
|
|
20083
20522
|
*/
|
|
20084
|
-
function
|
|
20085
|
-
let isScreenShare = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
20523
|
+
function findTrackCodecPayload(media, cid, codec) {
|
|
20086
20524
|
var _a, _b, _c;
|
|
20087
20525
|
if (!((_a = media.msid) === null || _a === void 0 ? void 0 : _a.includes(cid))) {
|
|
20088
20526
|
return undefined;
|
|
20089
20527
|
}
|
|
20090
|
-
|
|
20091
|
-
|
|
20092
|
-
|
|
20528
|
+
return (_c = (_b = media.rtp.find(rtp => rtp.codec.toUpperCase() === codec.toUpperCase())) === null || _b === void 0 ? void 0 : _b.payload) !== null && _c !== void 0 ? _c : 0;
|
|
20529
|
+
}
|
|
20530
|
+
/**
|
|
20531
|
+
* Start bitrate hinted for a single track, or `undefined` when its target is too low to
|
|
20532
|
+
* be worth seeding.
|
|
20533
|
+
*
|
|
20534
|
+
* 90% of the target leaves ~10% headroom for the estimator to settle. The same multiplier
|
|
20535
|
+
* is used for every codec because the target already reflects the codec's efficiency.
|
|
20536
|
+
* Camera is capped at 1 Mbps so the estimator does not open too aggressively on a
|
|
20537
|
+
* high-bitrate track; screen share is exempt, because its content needs the bitrate
|
|
20538
|
+
* immediately to stay legible.
|
|
20539
|
+
*
|
|
20540
|
+
* TODO: adjust dynamically from network conditions (e.g. a previous BWE estimate) rather
|
|
20541
|
+
* than a fixed cap.
|
|
20542
|
+
*
|
|
20543
|
+
* @internal
|
|
20544
|
+
*/
|
|
20545
|
+
function computeTrackStartBitrate(trackbr) {
|
|
20546
|
+
if (trackbr.maxbr < minTargetBitrateKbps) {
|
|
20547
|
+
return undefined;
|
|
20093
20548
|
}
|
|
20094
|
-
|
|
20095
|
-
|
|
20096
|
-
|
|
20097
|
-
|
|
20098
|
-
|
|
20099
|
-
|
|
20549
|
+
const calculated = Math.round(trackbr.maxbr * startBitrateMultiplier);
|
|
20550
|
+
return trackbr.isScreenShare ? calculated : Math.min(calculated, maxStartBitrateKbps);
|
|
20551
|
+
}
|
|
20552
|
+
/**
|
|
20553
|
+
* The single start bitrate for this peer connection: the largest hint among the video
|
|
20554
|
+
* m-sections of `media` that map to a published track.
|
|
20555
|
+
*
|
|
20556
|
+
* libwebrtc reads `x-google-start-bitrate` per m-section but applies it to the shared
|
|
20557
|
+
* `Call` (`WebRtcVideoSendChannel::ApplyChangedParams` -> `SetSdpBitrateParameters`), where
|
|
20558
|
+
* `RtpBitrateConfigurator` holds one config for the whole connection. Differing per-section
|
|
20559
|
+
* values are therefore last-writer-wins, decided by m-section order, so every video section
|
|
20560
|
+
* gets the same number instead.
|
|
20561
|
+
*
|
|
20562
|
+
* Only sections that can send local media are considered. `trackBitrates` is append-only and an
|
|
20563
|
+
* unpublished section keeps its `a=msid`, so matching on msid alone would still pair a stale
|
|
20564
|
+
* entry with its old section — letting an uncapped screen-share target seed a connection that
|
|
20565
|
+
* now carries only a camera, or consuming the one-shot hint on a section that sends nothing.
|
|
20566
|
+
*
|
|
20567
|
+
* The direction is the discriminator, as an exclusion rather than a match: `recvonly` and
|
|
20568
|
+
* `inactive` are the only directions that cannot carry local media, and they are exactly the
|
|
20569
|
+
* two a dead section lands on — unpublish sets `inactive` (explicitly in
|
|
20570
|
+
* `LocalParticipant.unpublishTrack`, and via `removeTrack`'s sendonly -> inactive transition for
|
|
20571
|
+
* the simulcast senders), `removeTrack` on a `sendrecv` transceiver leaves `recvonly`, and the
|
|
20572
|
+
* pre-populated placeholders are `recvonly`. Everything else sends: `sendonly` from the
|
|
20573
|
+
* `addTransceiver` path, `sendrecv` from the legacy `addTrack` fallback (which reuses a
|
|
20574
|
+
* transceiver rather than creating a sendonly one), and a section with no direction attribute,
|
|
20575
|
+
* which SDP defaults to `sendrecv`.
|
|
20576
|
+
*
|
|
20577
|
+
* @internal
|
|
20578
|
+
*/
|
|
20579
|
+
function computeConnectionStartBitrate(media, trackBitrates) {
|
|
20580
|
+
let connectionStartBitrate;
|
|
20581
|
+
for (const m of media) {
|
|
20582
|
+
if (m.type !== 'video' || m.direction === 'recvonly' || m.direction === 'inactive') {
|
|
20583
|
+
continue;
|
|
20584
|
+
}
|
|
20585
|
+
for (const trackbr of trackBitrates) {
|
|
20586
|
+
if (!trackbr.cid) {
|
|
20587
|
+
continue;
|
|
20588
|
+
}
|
|
20589
|
+
const codecPayload = findTrackCodecPayload(m, trackbr.cid, trackbr.codec);
|
|
20590
|
+
if (codecPayload === undefined) {
|
|
20591
|
+
continue;
|
|
20592
|
+
}
|
|
20593
|
+
const startBitrate = codecPayload > 0 ? computeTrackStartBitrate(trackbr) : undefined;
|
|
20594
|
+
if (startBitrate !== undefined && (connectionStartBitrate === undefined || startBitrate > connectionStartBitrate)) {
|
|
20595
|
+
connectionStartBitrate = startBitrate;
|
|
20596
|
+
}
|
|
20597
|
+
break;
|
|
20598
|
+
}
|
|
20599
|
+
}
|
|
20600
|
+
return connectionStartBitrate;
|
|
20601
|
+
}
|
|
20602
|
+
/**
|
|
20603
|
+
* Declares `x-google-start-bitrate` on `codecPayload`'s fmtp. This SDP munging is used for
|
|
20604
|
+
* a bitrate setting that cannot be applied through `RTCRtpEncodingParameters`.
|
|
20605
|
+
*
|
|
20606
|
+
* Returns whether the section now carries the hint.
|
|
20607
|
+
*
|
|
20608
|
+
* @internal
|
|
20609
|
+
*/
|
|
20610
|
+
function applyVideoStartBitrate(media, codecPayload, startBitrate) {
|
|
20100
20611
|
const fmtp = media.fmtp.find(entry => entry.payload === codecPayload);
|
|
20101
20612
|
if (fmtp) {
|
|
20102
|
-
//
|
|
20103
|
-
//
|
|
20104
|
-
// This forces every track sharing that payload to use the initial track's
|
|
20105
|
-
// start bitrate.
|
|
20613
|
+
// A payload type is shared across the bundle, so a value written for one section is
|
|
20614
|
+
// already the connection-level one; leave it rather than rewrite it.
|
|
20106
20615
|
if (!fmtp.config.includes('x-google-start-bitrate')) {
|
|
20107
20616
|
fmtp.config += ";x-google-start-bitrate=".concat(startBitrate);
|
|
20108
20617
|
}
|
|
@@ -20113,7 +20622,7 @@ function applyVideoStartBitrate(media, cid, codec, maxbr) {
|
|
|
20113
20622
|
config: "x-google-start-bitrate=".concat(startBitrate)
|
|
20114
20623
|
});
|
|
20115
20624
|
}
|
|
20116
|
-
return
|
|
20625
|
+
return true;
|
|
20117
20626
|
}
|
|
20118
20627
|
const PCEvents = {
|
|
20119
20628
|
NegotiationStarted: 'negotiationStarted',
|
|
@@ -20141,11 +20650,20 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20141
20650
|
this.iceLog = livekitLogger;
|
|
20142
20651
|
this.ddExtID = 0;
|
|
20143
20652
|
this.latestOfferId = 0;
|
|
20653
|
+
this.answeredOfferId = 0;
|
|
20144
20654
|
this.latestAcknowledgedOfferId = 0;
|
|
20145
20655
|
this.pendingCandidates = [];
|
|
20146
20656
|
this.restartingIce = false;
|
|
20147
20657
|
this.renegotiate = false;
|
|
20148
20658
|
this.trackBitrates = [];
|
|
20659
|
+
/**
|
|
20660
|
+
* Whether an offer carrying the connection-level `x-google-start-bitrate` has been
|
|
20661
|
+
* accepted locally. The hint is written once per peer connection: libwebrtc retains
|
|
20662
|
+
* `start_bitrate_bps` in `RtpBitrateConfigurator` and re-applies it on network route
|
|
20663
|
+
* changes, so a later rewrite is at best a no-op and at worst restarts a converged
|
|
20664
|
+
* bandwidth estimator. A new peer connection (full reconnect) seeds a new estimator.
|
|
20665
|
+
*/
|
|
20666
|
+
this.hasAppliedVideoStartBitrate = false;
|
|
20149
20667
|
this.remoteStereoMids = [];
|
|
20150
20668
|
this.remoteNackMids = [];
|
|
20151
20669
|
// debounced negotiate interface
|
|
@@ -20254,7 +20772,7 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20254
20772
|
}
|
|
20255
20773
|
setRemoteDescription(sd, offerId) {
|
|
20256
20774
|
return __awaiter(this, void 0, void 0, function* () {
|
|
20257
|
-
var _a
|
|
20775
|
+
var _a;
|
|
20258
20776
|
if (sd.type === 'answer' && this.latestOfferId > 0 && offerId > 0 && offerId !== this.latestOfferId) {
|
|
20259
20777
|
this.log.warn('ignoring answer for old offer', {
|
|
20260
20778
|
offerId,
|
|
@@ -20262,6 +20780,29 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20262
20780
|
});
|
|
20263
20781
|
return false;
|
|
20264
20782
|
}
|
|
20783
|
+
if (sd.type === 'answer') {
|
|
20784
|
+
if (isDuplicateAnswer(offerId, this.answerInFlight, this.answeredOfferId, (_a = this._pc) === null || _a === void 0 ? void 0 : _a.signalingState, this.pendingInitialOffer !== undefined)) {
|
|
20785
|
+
// a repeat of an answer already applied or being applied (e.g.
|
|
20786
|
+
// duplicated by a proxy): there is no local offer left to answer
|
|
20787
|
+
this.log.warn('ignoring duplicate answer', {
|
|
20788
|
+
offerId
|
|
20789
|
+
});
|
|
20790
|
+
return false;
|
|
20791
|
+
}
|
|
20792
|
+
// claimed before any await, so a copy arriving mid-apply is caught too;
|
|
20793
|
+
// released however the apply ends, so a genuine retry is still possible
|
|
20794
|
+
this.answerInFlight = offerId;
|
|
20795
|
+
}
|
|
20796
|
+
try {
|
|
20797
|
+
return yield this.applyRemoteDescription(sd, offerId);
|
|
20798
|
+
} finally {
|
|
20799
|
+
if (sd.type === 'answer') this.answerInFlight = undefined;
|
|
20800
|
+
}
|
|
20801
|
+
});
|
|
20802
|
+
}
|
|
20803
|
+
applyRemoteDescription(sd, offerId) {
|
|
20804
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20805
|
+
var _a, _b;
|
|
20265
20806
|
let mungedSDP = undefined;
|
|
20266
20807
|
if (sd.type === 'offer') {
|
|
20267
20808
|
let _extractStereoAndNack = extractStereoAndNackAudioFromOffer(sd),
|
|
@@ -20335,6 +20876,8 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20335
20876
|
mungedSDP = libExports.write(sdpParsed);
|
|
20336
20877
|
}
|
|
20337
20878
|
yield this.setMungedSDP(sd, mungedSDP, true);
|
|
20879
|
+
// only a successfully applied answer makes later copies duplicates
|
|
20880
|
+
if (sd.type === 'answer' && offerId > 0) this.answeredOfferId = offerId;
|
|
20338
20881
|
if (this.pendingCandidates.length > 0) {
|
|
20339
20882
|
this.iceLog.debug('flushing queued ICE candidates', {
|
|
20340
20883
|
count: this.pendingCandidates.length
|
|
@@ -20442,6 +20985,12 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20442
20985
|
sdp: offer.sdp
|
|
20443
20986
|
});
|
|
20444
20987
|
const sdpParsed = libExports.parse((_a = offer.sdp) !== null && _a !== void 0 ? _a : '');
|
|
20988
|
+
// One value for every video m-section, written only on the first offer that carries
|
|
20989
|
+
// local video: the hint is connection-level in libwebrtc, so differing per-section
|
|
20990
|
+
// values would be last-writer-wins on m-section order. Offers before any video is
|
|
20991
|
+
// published (data channel or audio only) find no target and leave the latch unset.
|
|
20992
|
+
const connectionStartBitrate = this.hasAppliedVideoStartBitrate ? undefined : computeConnectionStartBitrate(sdpParsed.media, this.trackBitrates);
|
|
20993
|
+
let appliedVideoStartBitrate = false;
|
|
20445
20994
|
sdpParsed.media.forEach(media => {
|
|
20446
20995
|
ensureIPAddrMatchVersion(media);
|
|
20447
20996
|
if (media.type === 'audio') {
|
|
@@ -20451,12 +21000,17 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20451
21000
|
if (!trackbr.cid) {
|
|
20452
21001
|
return false;
|
|
20453
21002
|
}
|
|
20454
|
-
const codecPayload =
|
|
21003
|
+
const codecPayload = findTrackCodecPayload(media, trackbr.cid, trackbr.codec);
|
|
20455
21004
|
if (codecPayload === undefined) {
|
|
20456
21005
|
return false;
|
|
20457
21006
|
}
|
|
20458
|
-
if (codecPayload > 0
|
|
20459
|
-
|
|
21007
|
+
if (codecPayload > 0) {
|
|
21008
|
+
if (connectionStartBitrate !== undefined) {
|
|
21009
|
+
appliedVideoStartBitrate = applyVideoStartBitrate(media, codecPayload, connectionStartBitrate) || appliedVideoStartBitrate;
|
|
21010
|
+
}
|
|
21011
|
+
if (isSVCCodec(trackbr.codec) && !isSafari()) {
|
|
21012
|
+
this.ddExtID = ensureVideoDDExtension(media, sdpParsed, this.ddExtID);
|
|
21013
|
+
}
|
|
20460
21014
|
}
|
|
20461
21015
|
return true;
|
|
20462
21016
|
});
|
|
@@ -20478,7 +21032,13 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20478
21032
|
});
|
|
20479
21033
|
return;
|
|
20480
21034
|
}
|
|
20481
|
-
|
|
21035
|
+
const mungedSdp = libExports.write(sdpParsed);
|
|
21036
|
+
yield this.setMungedSDP(offer, mungedSdp);
|
|
21037
|
+
// setMungedSDP falls back to the unmunged SDP on rejection. Only consume the
|
|
21038
|
+
// one-shot hint once the SDP carrying it has been accepted locally.
|
|
21039
|
+
if (appliedVideoStartBitrate && offer.sdp === mungedSdp) {
|
|
21040
|
+
this.hasAppliedVideoStartBitrate = true;
|
|
21041
|
+
}
|
|
20482
21042
|
this.onOffer(offer, this.latestOfferId);
|
|
20483
21043
|
} finally {
|
|
20484
21044
|
unlock();
|
|
@@ -20874,6 +21434,19 @@ function conformBundledCodecFmtp(media, isPlaceholder) {
|
|
|
20874
21434
|
}
|
|
20875
21435
|
}
|
|
20876
21436
|
/** @internal */
|
|
21437
|
+
/**
|
|
21438
|
+
* Whether an incoming answer repeats one already applied or being applied.
|
|
21439
|
+
* Any answer for the offer whose answer is in flight is a duplicate, numbered
|
|
21440
|
+
* or not. With an offerId (current servers) an answer is also a duplicate if
|
|
21441
|
+
* that offer's answer was already applied. Without one, fall back to the
|
|
21442
|
+
* signaling state: in `stable` no local offer is pending, unless the initial
|
|
21443
|
+
* offer is still deferred (it is set locally only once its answer arrives).
|
|
21444
|
+
*/
|
|
21445
|
+
function isDuplicateAnswer(offerId, answerInFlight, answeredOfferId, signalingState, hasPendingInitialOffer) {
|
|
21446
|
+
if (answerInFlight === offerId) return true;
|
|
21447
|
+
if (offerId > 0) return offerId === answeredOfferId;
|
|
21448
|
+
return signalingState === 'stable' && !hasPendingInitialOffer;
|
|
21449
|
+
}
|
|
20877
21450
|
function extractStereoAndNackAudioFromOffer(offer) {
|
|
20878
21451
|
var _a;
|
|
20879
21452
|
const stereoMids = [];
|
|
@@ -20965,6 +21538,7 @@ const roomOptionDefaults = {
|
|
|
20965
21538
|
};
|
|
20966
21539
|
const roomConnectOptionDefaults = {
|
|
20967
21540
|
autoSubscribe: true,
|
|
21541
|
+
disableIceLite: false,
|
|
20968
21542
|
maxRetries: 1,
|
|
20969
21543
|
peerConnectionTimeout: 15000,
|
|
20970
21544
|
websocketTimeout: 15000
|
|
@@ -21178,7 +21752,9 @@ class PCTransportManager {
|
|
|
21178
21752
|
try {
|
|
21179
21753
|
if (this.isPublisherConnectionRequired && this.publisher.getConnectionState() !== 'connected' && this.publisher.getConnectionState() !== 'connecting') {
|
|
21180
21754
|
this.log.debug('negotiation required, start negotiating');
|
|
21181
|
-
this.publisher.negotiate()
|
|
21755
|
+
this.publisher.negotiate().catch(err => {
|
|
21756
|
+
this.log.error(err);
|
|
21757
|
+
});
|
|
21182
21758
|
}
|
|
21183
21759
|
yield Promise.all((_a = this.requiredTransports) === null || _a === void 0 ? void 0 : _a.map(transport => this.ensureTransportConnected(transport, abortController, timeout)));
|
|
21184
21760
|
} finally {
|
|
@@ -22216,21 +22792,29 @@ class LocalTrack extends Track {
|
|
|
22216
22792
|
var _this = this;
|
|
22217
22793
|
let timeout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_DIMENSIONS_TIMEOUT;
|
|
22218
22794
|
return function* () {
|
|
22219
|
-
var _a;
|
|
22220
22795
|
if (_this.kind === Track.Kind.Audio) {
|
|
22221
22796
|
throw new Error('cannot get dimensions for audio tracks');
|
|
22222
22797
|
}
|
|
22223
|
-
if (((_a = getBrowser()) === null || _a === void 0 ? void 0 : _a.os) === 'iOS') {
|
|
22224
|
-
// browsers report wrong initial resolution on iOS.
|
|
22225
|
-
// when slightly delaying the call to .getSettings(), the correct resolution is being reported
|
|
22226
|
-
yield sleep(10);
|
|
22227
|
-
}
|
|
22228
22798
|
const started = Date.now();
|
|
22229
|
-
|
|
22799
|
+
if (isAppleMobile()) {
|
|
22800
|
+
// iOS and iPadOS keep reporting the camera's sensor frame from getSettings() until the
|
|
22801
|
+
// camera has delivered its first picture, so a portrait capture initially reads as
|
|
22802
|
+
// landscape. Wait for that first frame instead of guessing at a delay.
|
|
22803
|
+
// Gated to the Apple capture pipeline rather than run everywhere: elsewhere getSettings() is
|
|
22804
|
+
// already right and the first frame can be hundreds of milliseconds out (measured ~500ms on
|
|
22805
|
+
// macOS Safari), which would be pure added publish latency.
|
|
22806
|
+
// https://github.com/livekit/client-sdk-js/issues/2099
|
|
22807
|
+
// https://github.com/livekit/client-sdk-js/issues/2107
|
|
22808
|
+
yield waitForFirstVideoFrame(_this._mediaStreamTrack, timeout, _this.attachedElements);
|
|
22809
|
+
}
|
|
22810
|
+
while (true) {
|
|
22230
22811
|
const dims = _this.dimensions;
|
|
22231
22812
|
if (dims) {
|
|
22232
22813
|
return dims;
|
|
22233
22814
|
}
|
|
22815
|
+
if (Date.now() - started >= timeout) {
|
|
22816
|
+
break;
|
|
22817
|
+
}
|
|
22234
22818
|
yield sleep(50);
|
|
22235
22819
|
}
|
|
22236
22820
|
throw new TrackInvalidError('unable to get track dimensions after timeout');
|
|
@@ -22933,24 +23517,6 @@ const computeDefaultScreenShareSimulcastPresets = fromPreset => {
|
|
|
22933
23517
|
return new VideoPreset(Math.floor(fromPreset.width / t.scaleResolutionDownBy), Math.floor(fromPreset.height / t.scaleResolutionDownBy), Math.max(150000, Math.floor(fromPreset.encoding.maxBitrate / (Math.pow(t.scaleResolutionDownBy, 2) * (((_a = fromPreset.encoding.maxFramerate) !== null && _a !== void 0 ? _a : 30) / ((_b = t.fps) !== null && _b !== void 0 ? _b : 30))))), t.fps, fromPreset.encoding.priority);
|
|
22934
23518
|
});
|
|
22935
23519
|
};
|
|
22936
|
-
// /**
|
|
22937
|
-
// *
|
|
22938
|
-
// * @internal
|
|
22939
|
-
// * @experimental
|
|
22940
|
-
// */
|
|
22941
|
-
// const computeDefaultMultiCodecSimulcastEncodings = (width: number, height: number) => {
|
|
22942
|
-
// // use vp8 as a default
|
|
22943
|
-
// const vp8 = determineAppropriateEncoding(false, width, height);
|
|
22944
|
-
// const vp9 = { ...vp8, maxBitrate: vp8.maxBitrate * 0.9 };
|
|
22945
|
-
// const h264 = { ...vp8, maxBitrate: vp8.maxBitrate * 1.1 };
|
|
22946
|
-
// const av1 = { ...vp8, maxBitrate: vp8.maxBitrate * 0.7 };
|
|
22947
|
-
// return {
|
|
22948
|
-
// vp8,
|
|
22949
|
-
// vp9,
|
|
22950
|
-
// h264,
|
|
22951
|
-
// av1,
|
|
22952
|
-
// };
|
|
22953
|
-
// };
|
|
22954
23520
|
const videoRids = ['q', 'h', 'f'];
|
|
22955
23521
|
/* @internal */
|
|
22956
23522
|
function computeVideoEncodings(isScreenShare, width, height, options) {
|
|
@@ -22962,6 +23528,8 @@ function computeVideoEncodings(isScreenShare, width, height, options) {
|
|
|
22962
23528
|
const useSimulcast = options === null || options === void 0 ? void 0 : options.simulcast;
|
|
22963
23529
|
const scalabilityMode = options === null || options === void 0 ? void 0 : options.scalabilityMode;
|
|
22964
23530
|
const videoCodec = options === null || options === void 0 ? void 0 : options.videoCodec;
|
|
23531
|
+
// VP9/AV1 published as rid based simulcast rather than SVC, see isSVCSimulcast
|
|
23532
|
+
const useSVCSimulcast = isSVCSimulcast(videoCodec, options);
|
|
22965
23533
|
if (!videoEncoding && !useSimulcast && !scalabilityMode || !width || !height) {
|
|
22966
23534
|
// when we aren't simulcasting or svc, will need to return a single encoding without
|
|
22967
23535
|
// capping bandwidth. we always require a encoding for dynacast
|
|
@@ -22974,23 +23542,16 @@ function computeVideoEncodings(isScreenShare, width, height, options) {
|
|
|
22974
23542
|
}
|
|
22975
23543
|
const sourceFramerate = videoEncoding.maxFramerate;
|
|
22976
23544
|
const original = new VideoPreset(width, height, videoEncoding.maxBitrate, videoEncoding.maxFramerate, videoEncoding.priority);
|
|
22977
|
-
if (scalabilityMode && isSVCCodec(videoCodec)) {
|
|
23545
|
+
if (scalabilityMode && isSVCCodec(videoCodec) && !useSVCSimulcast) {
|
|
22978
23546
|
const sm = new ScalabilityMode(scalabilityMode);
|
|
22979
23547
|
const encodings = [];
|
|
22980
23548
|
if (sm.spatial > 3) {
|
|
22981
23549
|
throw new Error("unsupported scalabilityMode: ".concat(scalabilityMode));
|
|
22982
23550
|
}
|
|
22983
|
-
//
|
|
22984
|
-
//
|
|
22985
|
-
// This is a bit confusing but is due to how libwebrtc interpreted the encodings field
|
|
22986
|
-
// before M113.
|
|
22987
|
-
// Announced here: https://groups.google.com/g/discuss-webrtc/c/-QQ3pxrl-fw?pli=1
|
|
23551
|
+
// Browsers that read multiple encodings on an SVC codec as SVC rather than as
|
|
23552
|
+
// simulcast, see usesLegacySVCEncodings
|
|
22988
23553
|
const browser = getBrowser();
|
|
22989
|
-
if (
|
|
22990
|
-
// Even tho RN runs M114, it does not produce SVC layers when a single encoding
|
|
22991
|
-
// is provided. So we'll use the legacy SVC specification for now.
|
|
22992
|
-
// TODO: when we upstream libwebrtc, this will need additional verification
|
|
22993
|
-
isReactNative() || (browser === null || browser === void 0 ? void 0 : browser.name) === 'Chrome' && compareVersions(browser === null || browser === void 0 ? void 0 : browser.version, '113') < 0) {
|
|
23554
|
+
if (usesLegacySVCEncodings()) {
|
|
22994
23555
|
const bitratesRatio = sm.suffix == 'h' ? 2 : 3;
|
|
22995
23556
|
// safari 18.4 uses a different svc API that requires scaleResolutionDownBy to be set.
|
|
22996
23557
|
const requireScale = isSafariSvcApi(browser);
|
|
@@ -23026,6 +23587,18 @@ function computeVideoEncodings(isScreenShare, width, height, options) {
|
|
|
23026
23587
|
if (!useSimulcast) {
|
|
23027
23588
|
return [videoEncoding];
|
|
23028
23589
|
}
|
|
23590
|
+
// Chrome M113+ only treats multiple encodings on an SVC capable codec as real
|
|
23591
|
+
// simulcast when every encoding carries an explicit scalabilityMode next to its
|
|
23592
|
+
// scaleResolutionDownBy. Without it the encodings are interpreted as legacy SVC.
|
|
23593
|
+
const applySVCSimulcastMode = encodings => {
|
|
23594
|
+
if (useSVCSimulcast) {
|
|
23595
|
+
encodings.forEach(encoding => {
|
|
23596
|
+
/* @ts-ignore */
|
|
23597
|
+
encoding.scalabilityMode = scalabilityMode;
|
|
23598
|
+
});
|
|
23599
|
+
}
|
|
23600
|
+
return encodings;
|
|
23601
|
+
};
|
|
23029
23602
|
let presets;
|
|
23030
23603
|
if (isScreenShare) {
|
|
23031
23604
|
presets = (_a = sortPresets(options === null || options === void 0 ? void 0 : options.screenShareSimulcastLayers)) !== null && _a !== void 0 ? _a : defaultSimulcastLayers(isScreenShare, original);
|
|
@@ -23051,13 +23624,38 @@ function computeVideoEncodings(isScreenShare, width, height, options) {
|
|
|
23051
23624
|
// based on other conditions.
|
|
23052
23625
|
const size = Math.max(width, height);
|
|
23053
23626
|
if (size >= 960 && midPreset) {
|
|
23054
|
-
return encodingsFromPresets(width, height, [lowPreset, midPreset, original], sourceFramerate);
|
|
23627
|
+
return applySVCSimulcastMode(encodingsFromPresets(width, height, [lowPreset, midPreset, original], sourceFramerate));
|
|
23055
23628
|
}
|
|
23056
23629
|
if (size >= 480) {
|
|
23057
|
-
return encodingsFromPresets(width, height, [lowPreset, original], sourceFramerate);
|
|
23630
|
+
return applySVCSimulcastMode(encodingsFromPresets(width, height, [lowPreset, original], sourceFramerate));
|
|
23058
23631
|
}
|
|
23059
23632
|
}
|
|
23060
|
-
return encodingsFromPresets(width, height, [original]);
|
|
23633
|
+
return applySVCSimulcastMode(encodingsFromPresets(width, height, [original]));
|
|
23634
|
+
}
|
|
23635
|
+
/**
|
|
23636
|
+
* Bitrate to hint to the bandwidth estimator through `x-google-start-bitrate`, so that
|
|
23637
|
+
* a publish does not spend its first seconds ramping up from a very low rate.
|
|
23638
|
+
*
|
|
23639
|
+
* It has to be the total the encoder will put on the wire, which means picking the
|
|
23640
|
+
* encoding that carries the inclusive bitrate:
|
|
23641
|
+
* - SVC publishes a single stream with the layers built in. `encodings[0]` holds the
|
|
23642
|
+
* full bitrate — the legacy SVC shape orders its encodings `f`..`q`, so that holds
|
|
23643
|
+
* for both SVC shapes.
|
|
23644
|
+
* - Simulcast publishes independent streams ordered `q`..`f`, so the total is the sum.
|
|
23645
|
+
* This includes VP9/AV1 published as rid based simulcast, where `encodings[0]` is
|
|
23646
|
+
* the *smallest* layer even though the codec is SVC capable.
|
|
23647
|
+
*
|
|
23648
|
+
* @internal
|
|
23649
|
+
*/
|
|
23650
|
+
function computeStartTargetBitrate(codec, options, encodings) {
|
|
23651
|
+
var _a, _b;
|
|
23652
|
+
if (isSVCCodec(codec) && !isSVCSimulcast(codec, options)) {
|
|
23653
|
+
return (_b = (_a = encodings[0]) === null || _a === void 0 ? void 0 : _a.maxBitrate) !== null && _b !== void 0 ? _b : 0;
|
|
23654
|
+
}
|
|
23655
|
+
return encodings.reduce((sum, enc) => {
|
|
23656
|
+
var _a;
|
|
23657
|
+
return sum + ((_a = enc.maxBitrate) !== null && _a !== void 0 ? _a : 0);
|
|
23658
|
+
}, 0);
|
|
23061
23659
|
}
|
|
23062
23660
|
function computeTrackBackupEncodings(track, videoCodec, opts) {
|
|
23063
23661
|
var _a, _b, _c, _d;
|
|
@@ -23511,6 +24109,15 @@ class LocalVideoTrack extends LocalTrack {
|
|
|
23511
24109
|
return items;
|
|
23512
24110
|
});
|
|
23513
24111
|
}
|
|
24112
|
+
/**
|
|
24113
|
+
* Whether `codec` is being published as SVC (a single stream carrying all spatial
|
|
24114
|
+
* layers) as opposed to rid based simulcast. VP9/AV1 are SVC unless the publisher
|
|
24115
|
+
* opted into simulcast, in which case each rid is an independent stream and the
|
|
24116
|
+
* layers can be enabled/disabled individually.
|
|
24117
|
+
*/
|
|
24118
|
+
isSvcPublish(codec) {
|
|
24119
|
+
return isSVCCodec(codec) && !isSVCSimulcast(codec, this.publishOptions);
|
|
24120
|
+
}
|
|
23514
24121
|
setPublishingQuality(maxQuality) {
|
|
23515
24122
|
const qualities = [];
|
|
23516
24123
|
for (let q = VideoQuality.LOW; q <= VideoQuality.HIGH; q += 1) {
|
|
@@ -23520,7 +24127,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
|
23520
24127
|
}));
|
|
23521
24128
|
}
|
|
23522
24129
|
this.log.debug("setting publishing quality. max quality ".concat(maxQuality), this.logContext);
|
|
23523
|
-
this.setPublishingLayers(
|
|
24130
|
+
this.setPublishingLayers(this.isSvcPublish(this.codec), qualities);
|
|
23524
24131
|
}
|
|
23525
24132
|
restartTrack(options) {
|
|
23526
24133
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -23764,12 +24371,20 @@ class LocalVideoTrack extends LocalTrack {
|
|
|
23764
24371
|
// browser will reenable disabled codec/layers after new codec has been published,
|
|
23765
24372
|
// so refresh subscribedCodecs after publish a new codec
|
|
23766
24373
|
setTimeout(() => {
|
|
23767
|
-
|
|
23768
|
-
this.setPublishingCodecs(this.subscribedCodecs);
|
|
23769
|
-
}
|
|
24374
|
+
this.refreshSubscribedCodecs();
|
|
23770
24375
|
}, refreshSubscribedCodecAfterNewCodec);
|
|
23771
24376
|
});
|
|
23772
24377
|
}
|
|
24378
|
+
/** @interal */
|
|
24379
|
+
refreshSubscribedCodecs() {
|
|
24380
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
24381
|
+
if (this.subscribedCodecs) {
|
|
24382
|
+
return this.setPublishingCodecs(this.subscribedCodecs).catch(e => this.log.warn("failed to refresh codec for track", Object.assign(Object.assign({}, this.logContext), {
|
|
24383
|
+
error: e
|
|
24384
|
+
})));
|
|
24385
|
+
}
|
|
24386
|
+
});
|
|
24387
|
+
}
|
|
23773
24388
|
/**
|
|
23774
24389
|
* @internal
|
|
23775
24390
|
* Sets codecs that should be publishing, returns new codecs that have not yet
|
|
@@ -23785,7 +24400,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
|
23785
24400
|
}));
|
|
23786
24401
|
// only enable simulcast codec for preference codec setted
|
|
23787
24402
|
if (!this.codec && codecs.length > 0) {
|
|
23788
|
-
yield this.setPublishingLayers(
|
|
24403
|
+
yield this.setPublishingLayers(this.isSvcPublish(codecs[0].codec), codecs[0].qualities);
|
|
23789
24404
|
return [];
|
|
23790
24405
|
}
|
|
23791
24406
|
this.subscribedCodecs = codecs;
|
|
@@ -23796,7 +24411,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
|
23796
24411
|
_a = false;
|
|
23797
24412
|
const codec = _d;
|
|
23798
24413
|
if (!this.codec || this.codec === codec.codec) {
|
|
23799
|
-
yield this.setPublishingLayers(
|
|
24414
|
+
yield this.setPublishingLayers(this.isSvcPublish(codec.codec), codec.qualities);
|
|
23800
24415
|
} else {
|
|
23801
24416
|
const simulcastCodecInfo = this.simulcastCodecs.get(codec.codec);
|
|
23802
24417
|
this.log.debug("try setPublishingCodec for ".concat(codec.codec), Object.assign(Object.assign({}, this.logContext), {
|
|
@@ -23811,7 +24426,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
|
23811
24426
|
}
|
|
23812
24427
|
} else if (simulcastCodecInfo.encodings) {
|
|
23813
24428
|
this.log.debug("try setPublishingLayersForSender ".concat(codec.codec), this.logContext);
|
|
23814
|
-
yield setPublishingLayersForSender(simulcastCodecInfo.sender, simulcastCodecInfo.encodings, codec.qualities, this.senderLock,
|
|
24429
|
+
yield setPublishingLayersForSender(simulcastCodecInfo.sender, simulcastCodecInfo.encodings, codec.qualities, this.senderLock, this.isSvcPublish(codec.codec), this.log, this.logContext);
|
|
23815
24430
|
}
|
|
23816
24431
|
}
|
|
23817
24432
|
}
|
|
@@ -24071,6 +24686,10 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
24071
24686
|
get pendingReconnect() {
|
|
24072
24687
|
return !!this.reconnectTimeout;
|
|
24073
24688
|
}
|
|
24689
|
+
get serverVersion() {
|
|
24690
|
+
var _a, _b, _c;
|
|
24691
|
+
return ((_b = (_a = this.latestJoinResponse) === null || _a === void 0 ? void 0 : _a.serverInfo) === null || _b === void 0 ? void 0 : _b.version) || ((_c = this.latestJoinResponse) === null || _c === void 0 ? void 0 : _c.serverVersion) || undefined;
|
|
24692
|
+
}
|
|
24074
24693
|
get reliableChannel() {
|
|
24075
24694
|
return this.dataChannels.reliable;
|
|
24076
24695
|
}
|
|
@@ -24110,6 +24729,13 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
24110
24729
|
this.midToTrackId = {};
|
|
24111
24730
|
/** used to indicate whether the browser is currently waiting to reconnect */
|
|
24112
24731
|
this.isWaitingForNetworkReconnect = false;
|
|
24732
|
+
/**
|
|
24733
|
+
* Abort handlers for the in-flight `negotiate()` calls, which a single central
|
|
24734
|
+
* Closing/Restarting listener pair fans out to. Registering a listener pair per call instead
|
|
24735
|
+
* accumulates them on the engine emitter and trips its max-listener warning under
|
|
24736
|
+
* renegotiation bursts.
|
|
24737
|
+
*/
|
|
24738
|
+
this.pendingNegotiationAborts = new Set();
|
|
24113
24739
|
this.handleDataChannel = _a => __awaiter(this, [_a], void 0, function (_ref) {
|
|
24114
24740
|
var _this = this;
|
|
24115
24741
|
let channel = _ref.channel;
|
|
@@ -24123,7 +24749,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
24123
24749
|
}();
|
|
24124
24750
|
});
|
|
24125
24751
|
this.handleDataMessage = message => __awaiter(this, void 0, void 0, function* () {
|
|
24126
|
-
var _a, _b, _c, _d
|
|
24752
|
+
var _a, _b, _c, _d;
|
|
24127
24753
|
// make sure to respect incoming data message order by processing message events one after the other
|
|
24128
24754
|
const unlock = yield this.dataProcessLock.lock();
|
|
24129
24755
|
try {
|
|
@@ -24148,20 +24774,29 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
24148
24774
|
this.log.error('Received encrypted packet but E2EE not set up');
|
|
24149
24775
|
return;
|
|
24150
24776
|
}
|
|
24151
|
-
|
|
24777
|
+
let decryptedData;
|
|
24778
|
+
try {
|
|
24779
|
+
decryptedData = yield this.e2eeManager.handleEncryptedData(dp.value.value.encryptedValue, dp.value.value.iv, dp.participantIdentity, dp.value.value.keyIndex);
|
|
24780
|
+
} catch (err) {
|
|
24781
|
+
this.log.debug('failed to decrypt data packet', {
|
|
24782
|
+
error: err,
|
|
24783
|
+
participantIdentity: dp.participantIdentity
|
|
24784
|
+
});
|
|
24785
|
+
return;
|
|
24786
|
+
}
|
|
24152
24787
|
const decryptedPacket = EncryptedPacketPayload.fromBinary(decryptedData.payload);
|
|
24153
24788
|
const newDp = new DataPacket({
|
|
24154
24789
|
value: decryptedPacket.value,
|
|
24155
24790
|
participantIdentity: dp.participantIdentity,
|
|
24156
24791
|
participantSid: dp.participantSid
|
|
24157
24792
|
});
|
|
24158
|
-
if (((
|
|
24793
|
+
if (((_c = newDp.value) === null || _c === void 0 ? void 0 : _c.case) === 'user') {
|
|
24159
24794
|
// compatibility
|
|
24160
24795
|
applyUserDataCompat(newDp, newDp.value.value);
|
|
24161
24796
|
}
|
|
24162
24797
|
this.emit(EngineEvent.DataPacketReceived, newDp, dp.value.value.encryptionType);
|
|
24163
24798
|
} else {
|
|
24164
|
-
if (((
|
|
24799
|
+
if (((_d = dp.value) === null || _d === void 0 ? void 0 : _d.case) === 'user') {
|
|
24165
24800
|
// compatibility
|
|
24166
24801
|
applyUserDataCompat(dp, dp.value.value);
|
|
24167
24802
|
}
|
|
@@ -24346,6 +24981,14 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
24346
24981
|
this.client.onRequestResponse = response => this.emit(EngineEvent.SignalRequestResponse, response);
|
|
24347
24982
|
this.client.onParticipantUpdate = updates => this.emit(EngineEvent.ParticipantUpdate, updates);
|
|
24348
24983
|
this.client.onJoined = joinResponse => this.emit(EngineEvent.Joined, joinResponse);
|
|
24984
|
+
const abortPendingNegotiations = () => {
|
|
24985
|
+
// Iterate a copy: each handler removes itself from the set as its negotiation settles.
|
|
24986
|
+
for (const abort of Array.from(this.pendingNegotiationAborts)) {
|
|
24987
|
+
abort();
|
|
24988
|
+
}
|
|
24989
|
+
};
|
|
24990
|
+
this.on(EngineEvent.Closing, abortPendingNegotiations);
|
|
24991
|
+
this.on(EngineEvent.Restarting, abortPendingNegotiations);
|
|
24349
24992
|
}
|
|
24350
24993
|
/** @internal */
|
|
24351
24994
|
get logContext() {
|
|
@@ -24662,8 +25305,13 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
24662
25305
|
sdp: sd.sdp,
|
|
24663
25306
|
midToTrackId
|
|
24664
25307
|
});
|
|
24665
|
-
|
|
25308
|
+
// in dual PC mode the publisher answer carries no mapping (the server's publisher
|
|
25309
|
+
// transport has no sending tracks) and must not clobber the subscriber offer mapping
|
|
25310
|
+
if (this.pcManager.mode === 'publisher-only') {
|
|
25311
|
+
this.midToTrackId = midToTrackId;
|
|
25312
|
+
}
|
|
24666
25313
|
yield this.pcManager.setPublisherAnswer(sd, offerId);
|
|
25314
|
+
this.emit(EngineEvent.RequestSubscribedCodecRefresh);
|
|
24667
25315
|
});
|
|
24668
25316
|
// add candidate on trickle
|
|
24669
25317
|
this.client.onTrickle = (candidate, target) => {
|
|
@@ -24730,7 +25378,9 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
24730
25378
|
};
|
|
24731
25379
|
this.client.onMediaSectionsRequirement = requirement => {
|
|
24732
25380
|
this.addMediaSections(requirement.numAudios, requirement.numVideos);
|
|
24733
|
-
this.negotiate()
|
|
25381
|
+
this.negotiate().catch(err => {
|
|
25382
|
+
this.log.error(err);
|
|
25383
|
+
});
|
|
24734
25384
|
};
|
|
24735
25385
|
this.client.onPublishDataTrackResponse = event => {
|
|
24736
25386
|
this.emit(EngineEvent.PublishDataTrackResponse, event);
|
|
@@ -25483,8 +26133,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
25483
26133
|
if (this.isClosed) {
|
|
25484
26134
|
reject(new NegotiationError('cannot negotiate on closed engine'));
|
|
25485
26135
|
}
|
|
25486
|
-
this.
|
|
25487
|
-
this.on(EngineEvent.Restarting, handleClosed);
|
|
26136
|
+
this.pendingNegotiationAborts.add(handleClosed);
|
|
25488
26137
|
this.pcManager.publisher.off(PCEvents.RTPVideoPayloadTypes, this.onRtpMapAvailable);
|
|
25489
26138
|
this.pcManager.publisher.once(PCEvents.RTPVideoPayloadTypes, this.onRtpMapAvailable);
|
|
25490
26139
|
try {
|
|
@@ -25507,8 +26156,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
25507
26156
|
reject(new Error(String(e)));
|
|
25508
26157
|
}
|
|
25509
26158
|
} finally {
|
|
25510
|
-
this.
|
|
25511
|
-
this.off(EngineEvent.Restarting, handleClosed);
|
|
26159
|
+
this.pendingNegotiationAborts.delete(handleClosed);
|
|
25512
26160
|
}
|
|
25513
26161
|
}));
|
|
25514
26162
|
});
|
|
@@ -26309,10 +26957,10 @@ class TextStreamReader extends BaseStreamReader {
|
|
|
26309
26957
|
let compressed;
|
|
26310
26958
|
switch (streamHeader.compression) {
|
|
26311
26959
|
case DataStream_CompressionType.DEFLATE_RAW:
|
|
26312
|
-
if (!
|
|
26960
|
+
if (!isDeflateRawCompressionSupported()) {
|
|
26313
26961
|
// NOTE: this shouldn't really ever happen, if this warning is logged then the sender
|
|
26314
26962
|
// isn't properly abiding by the data streams v2 protocol.
|
|
26315
|
-
livekitLogger.warn("Data stream ".concat(streamHeader.streamId, " received with deflate-raw compression, but this browser does not
|
|
26963
|
+
livekitLogger.warn("Data stream ".concat(streamHeader.streamId, " received with deflate-raw compression, but this browser does not support deflate-raw decompression. Dropping..."));
|
|
26316
26964
|
return;
|
|
26317
26965
|
}
|
|
26318
26966
|
compressed = true;
|
|
@@ -26380,10 +27028,10 @@ class TextStreamReader extends BaseStreamReader {
|
|
|
26380
27028
|
let compressed;
|
|
26381
27029
|
switch (streamHeader.compression) {
|
|
26382
27030
|
case DataStream_CompressionType.DEFLATE_RAW:
|
|
26383
|
-
if (!
|
|
27031
|
+
if (!isDeflateRawCompressionSupported()) {
|
|
26384
27032
|
// NOTE: this shouldn't really ever happen, if this warning is logged then the sender
|
|
26385
27033
|
// isn't properly abiding by the data streams v2 protocol.
|
|
26386
|
-
livekitLogger.warn("Data stream ".concat(streamHeader.streamId, " received with deflate-raw compression, but this browser does not
|
|
27034
|
+
livekitLogger.warn("Data stream ".concat(streamHeader.streamId, " received with deflate-raw compression, but this browser does not support deflate-raw decompression. Dropping..."));
|
|
26387
27035
|
return;
|
|
26388
27036
|
}
|
|
26389
27037
|
compressed = true;
|
|
@@ -26748,7 +27396,7 @@ class OutgoingDataStreamManager {
|
|
|
26748
27396
|
attributes: options === null || options === void 0 ? void 0 : options.attributes,
|
|
26749
27397
|
encryptionType: ((_c = this.engine.e2eeManager) === null || _c === void 0 ? void 0 : _c.isDataChannelEncryptionEnabled) ? Encryption_Type.GCM : Encryption_Type.NONE
|
|
26750
27398
|
};
|
|
26751
|
-
const compressEligible = compress &&
|
|
27399
|
+
const compressEligible = compress && isDeflateRawCompressionSupported() && this.allRecipientsSupportV2(options === null || options === void 0 ? void 0 : options.destinationIdentities) && this.allRecipientsSupportCompression(options === null || options === void 0 ? void 0 : options.destinationIdentities);
|
|
26752
27400
|
let compressedStream = compressEligible ? MaybeCollectedStream.fromStream(readableFromBytes(textInBytes).pipeThrough(deflateRawTransform())) : null;
|
|
26753
27401
|
// Phase 1: Try to send as a single packet data stream
|
|
26754
27402
|
const noAttachments = !(options === null || options === void 0 ? void 0 : options.attachments) || options.attachments.length === 0;
|
|
@@ -26857,7 +27505,7 @@ class OutgoingDataStreamManager {
|
|
|
26857
27505
|
encryptionType: ((_e = this.engine.e2eeManager) === null || _e === void 0 ? void 0 : _e.isDataChannelEncryptionEnabled) ? Encryption_Type.GCM : Encryption_Type.NONE
|
|
26858
27506
|
};
|
|
26859
27507
|
const progressMonitorTap = progressReportingStream(bytes.length, options === null || options === void 0 ? void 0 : options.onProgress);
|
|
26860
|
-
const compressEligible = compress &&
|
|
27508
|
+
const compressEligible = compress && isDeflateRawCompressionSupported() && this.allRecipientsSupportV2(destinationIdentities) && this.allRecipientsSupportCompression(destinationIdentities);
|
|
26861
27509
|
let compressedStream = compressEligible ? MaybeCollectedStream.fromStream(readableFromBytes(bytes).pipeThrough(progressMonitorTap).pipeThrough(deflateRawTransform())) : null;
|
|
26862
27510
|
// Phase 1: Try to send as a single packet data stream
|
|
26863
27511
|
if (this.allRecipientsSupportV2(destinationIdentities)) {
|
|
@@ -27054,7 +27702,7 @@ class OutgoingDataStreamManager {
|
|
|
27054
27702
|
return __awaiter(this, void 0, void 0, function* () {
|
|
27055
27703
|
var _a, _b, _c, _d, _e;
|
|
27056
27704
|
const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
|
|
27057
|
-
const compress = ((_a = options === null || options === void 0 ? void 0 : options.compress) !== null && _a !== void 0 ? _a : true) &&
|
|
27705
|
+
const compress = ((_a = options === null || options === void 0 ? void 0 : options.compress) !== null && _a !== void 0 ? _a : true) && isDeflateRawCompressionSupported() && this.allRecipientsSupportV2(destinationIdentities) && this.allRecipientsSupportCompression(destinationIdentities);
|
|
27058
27706
|
const info = {
|
|
27059
27707
|
id: streamId,
|
|
27060
27708
|
name: file.name,
|
|
@@ -29725,20 +30373,37 @@ class RpcClientManager extends eventsExports.EventEmitter {
|
|
|
29725
30373
|
completionFuture,
|
|
29726
30374
|
participantIdentity: destinationIdentity
|
|
29727
30375
|
});
|
|
29728
|
-
|
|
29729
|
-
|
|
29730
|
-
|
|
29731
|
-
_this.pendingResponses.delete(id);
|
|
29732
|
-
(_a = completionFuture.reject) === null || _a === void 0 ? void 0 : _a.call(completionFuture, RpcError.builtIn('RESPONSE_TIMEOUT'));
|
|
29733
|
-
}, responseTimeoutMs);
|
|
30376
|
+
// Observe the future before publishing: a slow send can outlast the ack timer.
|
|
30377
|
+
// Keep the returned promise rejected for callers, while marking its rejection
|
|
30378
|
+
// handled until performRpc has finished publishing and can return it.
|
|
29734
30379
|
const completionPromise = completionFuture.promise.finally(() => {
|
|
29735
|
-
|
|
30380
|
+
if (responseTimeoutId !== null) {
|
|
30381
|
+
clearTimeout(responseTimeoutId);
|
|
30382
|
+
}
|
|
29736
30383
|
if (_this.pendingAcks.has(id)) {
|
|
29737
30384
|
_this.log.warn('RPC response received before ack', id);
|
|
29738
30385
|
_this.pendingAcks.delete(id);
|
|
29739
30386
|
clearTimeout(ackTimeoutId);
|
|
29740
30387
|
}
|
|
29741
30388
|
});
|
|
30389
|
+
completionPromise.catch(() => {});
|
|
30390
|
+
try {
|
|
30391
|
+
yield _this.publishRpcRequest(destinationIdentity, id, method, payload, effectiveTimeoutMs, remoteClientProtocol);
|
|
30392
|
+
} catch (e) {
|
|
30393
|
+
// The caller receives the publish error. Do not leave an ack timer that
|
|
30394
|
+
// later rejects a future the caller never received.
|
|
30395
|
+
clearTimeout(ackTimeoutId);
|
|
30396
|
+
_this.pendingAcks.delete(id);
|
|
30397
|
+
_this.pendingResponses.delete(id);
|
|
30398
|
+
throw e;
|
|
30399
|
+
}
|
|
30400
|
+
if (_this.pendingResponses.has(id)) {
|
|
30401
|
+
responseTimeoutId = setTimeout(() => {
|
|
30402
|
+
var _a;
|
|
30403
|
+
_this.pendingResponses.delete(id);
|
|
30404
|
+
(_a = completionFuture.reject) === null || _a === void 0 ? void 0 : _a.call(completionFuture, RpcError.builtIn('RESPONSE_TIMEOUT'));
|
|
30405
|
+
}, responseTimeoutMs);
|
|
30406
|
+
}
|
|
29742
30407
|
return [id, completionPromise];
|
|
29743
30408
|
}();
|
|
29744
30409
|
});
|
|
@@ -30091,7 +30756,7 @@ class RpcServerManager extends eventsExports.EventEmitter {
|
|
|
30091
30756
|
* gets the volume of attached audio elements (loudest)
|
|
30092
30757
|
*/
|
|
30093
30758
|
getVolume() {
|
|
30094
|
-
if (this.elementVolume) {
|
|
30759
|
+
if (this.elementVolume !== undefined) {
|
|
30095
30760
|
return this.elementVolume;
|
|
30096
30761
|
}
|
|
30097
30762
|
if (isReactNative()) {
|
|
@@ -30140,7 +30805,7 @@ class RpcServerManager extends eventsExports.EventEmitter {
|
|
|
30140
30805
|
element.volume = 0;
|
|
30141
30806
|
element.muted = true;
|
|
30142
30807
|
}
|
|
30143
|
-
if (this.elementVolume) {
|
|
30808
|
+
if (this.elementVolume !== undefined) {
|
|
30144
30809
|
// make sure volume setting is being applied to the newly attached element
|
|
30145
30810
|
this.setVolume(this.elementVolume);
|
|
30146
30811
|
}
|
|
@@ -30200,7 +30865,7 @@ class RpcServerManager extends eventsExports.EventEmitter {
|
|
|
30200
30865
|
this.gainNode = context.createGain();
|
|
30201
30866
|
lastNode.connect(this.gainNode);
|
|
30202
30867
|
this.gainNode.connect(context.destination);
|
|
30203
|
-
if (this.elementVolume) {
|
|
30868
|
+
if (this.elementVolume !== undefined) {
|
|
30204
30869
|
this.gainNode.gain.setTargetAtTime(this.elementVolume, 0, 0.1);
|
|
30205
30870
|
}
|
|
30206
30871
|
// try to resume the context if it isn't running already
|
|
@@ -31773,7 +32438,7 @@ class Participant extends eventsExports.EventEmitter {
|
|
|
31773
32438
|
}
|
|
31774
32439
|
publish(track, opts, isStereo) {
|
|
31775
32440
|
return __awaiter(this, void 0, void 0, function* () {
|
|
31776
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
32441
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
31777
32442
|
if (!this.hasPermissionsToPublish(track)) {
|
|
31778
32443
|
throw new PublishTrackError('failed to publish track, insufficient permissions', 403);
|
|
31779
32444
|
}
|
|
@@ -31876,7 +32541,12 @@ class Participant extends eventsExports.EventEmitter {
|
|
|
31876
32541
|
req.height = dims.height;
|
|
31877
32542
|
// for svc codecs, disable simulcast and use vp8 for backup codec
|
|
31878
32543
|
if (isLocalVideoTrack(track)) {
|
|
31879
|
-
if (
|
|
32544
|
+
if (isSVCSimulcast(videoCodec, opts) && (usesLegacySVCEncodings() || !isSVCSimulcastSupportedByServer((_e = this.engine) === null || _e === void 0 ? void 0 : _e.serverVersion))) {
|
|
32545
|
+
opts.simulcast = false;
|
|
32546
|
+
this.log.info('SVC simulcast is not supported, disabling simulcast.', getLogContextFromTrack(track));
|
|
32547
|
+
}
|
|
32548
|
+
const svcSimulcast = isSVCSimulcast(videoCodec, opts);
|
|
32549
|
+
if (isSVCCodec(videoCodec) && !svcSimulcast) {
|
|
31880
32550
|
if (track.source === Track.Source.ScreenShare) {
|
|
31881
32551
|
// vp9 svc with screenshare cannot encode multiple spatial layers
|
|
31882
32552
|
// doing so reduces publish resolution to minimal resolution
|
|
@@ -31892,12 +32562,16 @@ class Participant extends eventsExports.EventEmitter {
|
|
|
31892
32562
|
}
|
|
31893
32563
|
}
|
|
31894
32564
|
// set scalabilityMode to 'L3T3_KEY' by default
|
|
31895
|
-
opts.scalabilityMode = (
|
|
32565
|
+
opts.scalabilityMode = (_f = opts.scalabilityMode) !== null && _f !== void 0 ? _f : 'L3T3_KEY';
|
|
31896
32566
|
}
|
|
31897
|
-
|
|
32567
|
+
const primaryCodec = new SimulcastCodec({
|
|
31898
32568
|
codec: videoCodec,
|
|
31899
32569
|
cid: track.mediaStreamTrack.id
|
|
31900
|
-
})
|
|
32570
|
+
});
|
|
32571
|
+
if (svcSimulcast) {
|
|
32572
|
+
primaryCodec.videoLayerMode = VideoLayer_Mode.ONE_SPATIAL_LAYER_PER_STREAM;
|
|
32573
|
+
}
|
|
32574
|
+
req.simulcastCodecs = [primaryCodec];
|
|
31901
32575
|
// set up backup
|
|
31902
32576
|
if (opts.backupCodec === true) {
|
|
31903
32577
|
opts.backupCodec = {
|
|
@@ -31918,19 +32592,19 @@ class Participant extends eventsExports.EventEmitter {
|
|
|
31918
32592
|
}
|
|
31919
32593
|
}
|
|
31920
32594
|
encodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, req.width, req.height, opts);
|
|
31921
|
-
req.layers = videoLayersFromEncodings(req.width, req.height, encodings, isSVCCodec(opts.videoCodec));
|
|
32595
|
+
req.layers = videoLayersFromEncodings(req.width, req.height, encodings, isSVCCodec(opts.videoCodec) && !isSVCSimulcast(opts.videoCodec, opts));
|
|
31922
32596
|
} else if (track.kind === Track.Kind.Audio) {
|
|
31923
32597
|
encodings = [{
|
|
31924
|
-
maxBitrate: (
|
|
31925
|
-
priority: (
|
|
31926
|
-
networkPriority: (
|
|
32598
|
+
maxBitrate: (_g = opts.audioPreset) === null || _g === void 0 ? void 0 : _g.maxBitrate,
|
|
32599
|
+
priority: (_j = (_h = opts.audioPreset) === null || _h === void 0 ? void 0 : _h.priority) !== null && _j !== void 0 ? _j : 'high',
|
|
32600
|
+
networkPriority: (_l = (_k = opts.audioPreset) === null || _k === void 0 ? void 0 : _k.priority) !== null && _l !== void 0 ? _l : 'high'
|
|
31927
32601
|
}];
|
|
31928
32602
|
}
|
|
31929
32603
|
if (!this.engine || this.engine.isClosed) {
|
|
31930
32604
|
throw new UnexpectedConnectionState('cannot publish track when not connected');
|
|
31931
32605
|
}
|
|
31932
32606
|
const negotiate = () => __awaiter(this, void 0, void 0, function* () {
|
|
31933
|
-
var _a, _b
|
|
32607
|
+
var _a, _b;
|
|
31934
32608
|
if (!this.engine.pcManager) {
|
|
31935
32609
|
throw new UnexpectedConnectionState('pcManager is not ready');
|
|
31936
32610
|
}
|
|
@@ -31967,13 +32641,9 @@ class Participant extends eventsExports.EventEmitter {
|
|
|
31967
32641
|
});
|
|
31968
32642
|
}
|
|
31969
32643
|
} else if (track.codec && isVideoCodec(track.codec)) {
|
|
31970
|
-
// Apply start bitrate for all video codecs to prevent initial blurriness
|
|
31971
|
-
//
|
|
31972
|
-
|
|
31973
|
-
const targetBitrate = isSVCCodec(track.codec) ? (_d = (_c = encodings[0]) === null || _c === void 0 ? void 0 : _c.maxBitrate) !== null && _d !== void 0 ? _d : 0 : encodings.reduce((sum, enc) => {
|
|
31974
|
-
var _a;
|
|
31975
|
-
return sum + ((_a = enc.maxBitrate) !== null && _a !== void 0 ? _a : 0);
|
|
31976
|
-
}, 0);
|
|
32644
|
+
// Apply start bitrate for all video codecs to prevent initial blurriness,
|
|
32645
|
+
// see computeStartTargetBitrate
|
|
32646
|
+
const targetBitrate = computeStartTargetBitrate(track.codec, opts, encodings);
|
|
31977
32647
|
if (targetBitrate > 0) {
|
|
31978
32648
|
this.engine.pcManager.publisher.setTrackCodecBitrate({
|
|
31979
32649
|
cid: req.cid,
|
|
@@ -33446,7 +34116,7 @@ class Room extends eventsExports.EventEmitter {
|
|
|
33446
34116
|
this.abortController = undefined;
|
|
33447
34117
|
resolve();
|
|
33448
34118
|
} catch (error) {
|
|
33449
|
-
if (this.regionUrlProvider && error instanceof ConnectionError && error
|
|
34119
|
+
if (this.regionUrlProvider && error instanceof ConnectionError && canFailOverToAnotherRegion(error)) {
|
|
33450
34120
|
let nextUrl = null;
|
|
33451
34121
|
try {
|
|
33452
34122
|
this.log.debug('Fetching next region');
|
|
@@ -33495,6 +34165,8 @@ class Room extends eventsExports.EventEmitter {
|
|
|
33495
34165
|
const _yield$engine$join = yield engine.join(url, token, {
|
|
33496
34166
|
autoSubscribe: connectOptions.autoSubscribe,
|
|
33497
34167
|
adaptiveStream: typeof roomOptions.adaptiveStream === 'object' ? true : roomOptions.adaptiveStream,
|
|
34168
|
+
disableIceLite: connectOptions.disableIceLite,
|
|
34169
|
+
subscriberAllowPause: connectOptions.subscriberAllowPause,
|
|
33498
34170
|
clientInfoCapabilities: this.getClientInfoCapabilities(roomOptions),
|
|
33499
34171
|
maxRetries: connectOptions.maxRetries,
|
|
33500
34172
|
e2eeEnabled: !!this.e2eeManager,
|
|
@@ -33933,7 +34605,7 @@ class Room extends eventsExports.EventEmitter {
|
|
|
33933
34605
|
// find the participant
|
|
33934
34606
|
const participant = this.remoteParticipants.get(packet.participantIdentity);
|
|
33935
34607
|
if (packet.value.case === 'user') {
|
|
33936
|
-
this.handleUserPacket(participant, packet.value.value, packet.kind, encryptionType);
|
|
34608
|
+
this.handleUserPacket(participant, packet.value.value, packet.kind, encryptionType, packet.participantIdentity);
|
|
33937
34609
|
} else if (packet.value.case === 'transcription') {
|
|
33938
34610
|
this.handleTranscription(participant, packet.value.value);
|
|
33939
34611
|
} else if (packet.value.case === 'sipDtmf') {
|
|
@@ -33964,8 +34636,8 @@ class Room extends eventsExports.EventEmitter {
|
|
|
33964
34636
|
this.rpcClientManager.handleIncomingRpcAck(packet.value.value.requestId);
|
|
33965
34637
|
}
|
|
33966
34638
|
};
|
|
33967
|
-
this.handleUserPacket = (participant, userPacket, kind, encryptionType) => {
|
|
33968
|
-
this.emit(RoomEvent.DataReceived, userPacket.payload, participant, kind, userPacket.topic, encryptionType);
|
|
34639
|
+
this.handleUserPacket = (participant, userPacket, kind, encryptionType, participantIdentity) => {
|
|
34640
|
+
this.emit(RoomEvent.DataReceived, userPacket.payload, participant, kind, userPacket.topic, encryptionType, participantIdentity);
|
|
33969
34641
|
// also emit on the participant
|
|
33970
34642
|
participant === null || participant === void 0 ? void 0 : participant.emit(ParticipantEvent.DataReceived, userPacket.payload, kind, encryptionType);
|
|
33971
34643
|
};
|
|
@@ -34212,8 +34884,8 @@ class Room extends eventsExports.EventEmitter {
|
|
|
34212
34884
|
});
|
|
34213
34885
|
this.registerRpcDataStreamHandler();
|
|
34214
34886
|
this.rpcClientManager = new RpcClientManager(this.log, this.outgoingDataStreamManager, this.getRemoteParticipantClientProtocol, () => {
|
|
34215
|
-
var _a
|
|
34216
|
-
return (
|
|
34887
|
+
var _a;
|
|
34888
|
+
return (_a = this.engine) === null || _a === void 0 ? void 0 : _a.serverVersion;
|
|
34217
34889
|
});
|
|
34218
34890
|
this.rpcClientManager.on('sendDataPacket', _ref2 => {
|
|
34219
34891
|
let packet = _ref2.packet;
|
|
@@ -34540,6 +35212,12 @@ class Room extends eventsExports.EventEmitter {
|
|
|
34540
35212
|
updatedAtInMs: Date.now(),
|
|
34541
35213
|
maxAgeInMs: DEFAULT_MAX_AGE_MS
|
|
34542
35214
|
});
|
|
35215
|
+
}).on(EngineEvent.RequestSubscribedCodecRefresh, () => {
|
|
35216
|
+
for (const videoPub of this.localParticipant.videoTrackPublications.values()) {
|
|
35217
|
+
if (isLocalVideoTrack(videoPub.track)) {
|
|
35218
|
+
videoPub.track.refreshSubscribedCodecs();
|
|
35219
|
+
}
|
|
35220
|
+
}
|
|
34543
35221
|
});
|
|
34544
35222
|
if (this.localParticipant) {
|
|
34545
35223
|
this.localParticipant.setupEngine(this.engine);
|
|
@@ -34636,8 +35314,9 @@ class Room extends eventsExports.EventEmitter {
|
|
|
34636
35314
|
let req;
|
|
34637
35315
|
switch (scenario) {
|
|
34638
35316
|
case 'signal-reconnect':
|
|
35317
|
+
const reconnectDelay = typeof arg === 'number' ? arg : 0;
|
|
34639
35318
|
// @ts-expect-error function is private
|
|
34640
|
-
yield this.engine.client.handleOnClose('simulate disconnect');
|
|
35319
|
+
yield this.engine.client.handleOnClose('simulate disconnect', undefined, reconnectDelay);
|
|
34641
35320
|
break;
|
|
34642
35321
|
case 'fail-on-v1-path':
|
|
34643
35322
|
this.engine.failNextV1Path();
|
|
@@ -35318,7 +35997,7 @@ class Room extends eventsExports.EventEmitter {
|
|
|
35318
35997
|
}
|
|
35319
35998
|
// Advertise deflate-raw decompression support so peers know they can send us compressed data
|
|
35320
35999
|
// streams (gated separately from clientProtocol — see the data streams v2 spec).
|
|
35321
|
-
if (
|
|
36000
|
+
if (isDeflateRawCompressionSupported()) {
|
|
35322
36001
|
capabilities.push(ClientInfo_Capability.CAP_COMPRESSION_DEFLATE_RAW);
|
|
35323
36002
|
}
|
|
35324
36003
|
return capabilities;
|
|
@@ -36368,212 +37047,186 @@ class TokenSourceFixed {}
|
|
|
36368
37047
|
* and {@link TokenSourceCustom}.
|
|
36369
37048
|
*/
|
|
36370
37049
|
class TokenSourceConfigurable {}new TextEncoder();
|
|
36371
|
-
const decoder = new TextDecoder()
|
|
36372
|
-
|
|
36373
|
-
|
|
36374
|
-
}
|
|
36375
|
-
|
|
36376
|
-
|
|
36377
|
-
|
|
36378
|
-
|
|
37050
|
+
const decoder = new TextDecoder(),
|
|
37051
|
+
strictDecoder = new TextDecoder("utf-8", {
|
|
37052
|
+
fatal: true
|
|
37053
|
+
});
|
|
37054
|
+
function decodeBase64(encoded) {
|
|
37055
|
+
let url = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
37056
|
+
if (Uint8Array.fromBase64) return Uint8Array.fromBase64(encoded, {
|
|
37057
|
+
alphabet: url ? "base64url" : "base64"
|
|
37058
|
+
});
|
|
37059
|
+
if (url) {
|
|
37060
|
+
if (encoded.includes("+") || encoded.includes("/")) throw new TypeError("Invalid base64url");
|
|
37061
|
+
encoded = encoded.replace(/-/g, "+").replace(/_/g, "/");
|
|
36379
37062
|
}
|
|
37063
|
+
const binary = atob(encoded),
|
|
37064
|
+
bytes = new Uint8Array(binary.length);
|
|
37065
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
36380
37066
|
return bytes;
|
|
36381
|
-
}function decode(input) {
|
|
36382
|
-
if (Uint8Array.fromBase64) {
|
|
36383
|
-
return Uint8Array.fromBase64(typeof input === 'string' ? input : decoder.decode(input), {
|
|
36384
|
-
alphabet: 'base64url'
|
|
36385
|
-
});
|
|
36386
|
-
}
|
|
36387
|
-
let encoded = input;
|
|
36388
|
-
if (encoded instanceof Uint8Array) {
|
|
36389
|
-
encoded = decoder.decode(encoded);
|
|
36390
|
-
}
|
|
36391
|
-
encoded = encoded.replace(/-/g, '+').replace(/_/g, '/');
|
|
36392
|
-
try {
|
|
36393
|
-
return decodeBase64(encoded);
|
|
36394
|
-
} catch (_unused) {
|
|
36395
|
-
throw new TypeError('The input to be decoded is not correctly encoded.');
|
|
36396
|
-
}
|
|
36397
37067
|
}class JOSEError extends Error {
|
|
36398
37068
|
constructor(message, options) {
|
|
36399
37069
|
var _Error$captureStackTr;
|
|
36400
|
-
super(message, options);
|
|
36401
|
-
_defineProperty(this, "code", 'ERR_JOSE_GENERIC');
|
|
36402
|
-
this.name = this.constructor.name;
|
|
36403
|
-
(_Error$captureStackTr = Error.captureStackTrace) === null || _Error$captureStackTr === void 0 || _Error$captureStackTr.call(Error, this, this.constructor);
|
|
37070
|
+
super(message, options), _defineProperty(this, "code", "ERR_JOSE_GENERIC"), this.name = this.constructor.name, (_Error$captureStackTr = Error.captureStackTrace) === null || _Error$captureStackTr === void 0 ? void 0 : _Error$captureStackTr.call(Error, this, this.constructor);
|
|
36404
37071
|
}
|
|
36405
37072
|
}
|
|
36406
|
-
_defineProperty(JOSEError, "code",
|
|
37073
|
+
_defineProperty(JOSEError, "code", "ERR_JOSE_GENERIC");
|
|
36407
37074
|
class JWTClaimValidationFailed extends JOSEError {
|
|
36408
37075
|
constructor(message, payload) {
|
|
36409
|
-
let claim = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] :
|
|
36410
|
-
let reason = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] :
|
|
37076
|
+
let claim = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "unspecified";
|
|
37077
|
+
let reason = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "unspecified";
|
|
36411
37078
|
super(message, {
|
|
36412
37079
|
cause: {
|
|
36413
37080
|
claim,
|
|
36414
37081
|
reason,
|
|
36415
37082
|
payload
|
|
36416
37083
|
}
|
|
36417
|
-
});
|
|
36418
|
-
_defineProperty(this, "code", 'ERR_JWT_CLAIM_VALIDATION_FAILED');
|
|
36419
|
-
_defineProperty(this, "claim", void 0);
|
|
36420
|
-
_defineProperty(this, "reason", void 0);
|
|
36421
|
-
_defineProperty(this, "payload", void 0);
|
|
36422
|
-
this.claim = claim;
|
|
36423
|
-
this.reason = reason;
|
|
36424
|
-
this.payload = payload;
|
|
37084
|
+
}), _defineProperty(this, "code", "ERR_JWT_CLAIM_VALIDATION_FAILED"), _defineProperty(this, "claim", void 0), _defineProperty(this, "reason", void 0), _defineProperty(this, "payload", void 0), this.claim = claim, this.reason = reason, this.payload = payload;
|
|
36425
37085
|
}
|
|
36426
37086
|
}
|
|
36427
|
-
_defineProperty(JWTClaimValidationFailed, "code",
|
|
37087
|
+
_defineProperty(JWTClaimValidationFailed, "code", "ERR_JWT_CLAIM_VALIDATION_FAILED");
|
|
36428
37088
|
class JWTExpired extends JOSEError {
|
|
36429
37089
|
constructor(message, payload) {
|
|
36430
|
-
let claim = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] :
|
|
36431
|
-
let reason = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] :
|
|
37090
|
+
let claim = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "unspecified";
|
|
37091
|
+
let reason = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : "unspecified";
|
|
36432
37092
|
super(message, {
|
|
36433
37093
|
cause: {
|
|
36434
37094
|
claim,
|
|
36435
37095
|
reason,
|
|
36436
37096
|
payload
|
|
36437
37097
|
}
|
|
36438
|
-
});
|
|
36439
|
-
_defineProperty(this, "code", 'ERR_JWT_EXPIRED');
|
|
36440
|
-
_defineProperty(this, "claim", void 0);
|
|
36441
|
-
_defineProperty(this, "reason", void 0);
|
|
36442
|
-
_defineProperty(this, "payload", void 0);
|
|
36443
|
-
this.claim = claim;
|
|
36444
|
-
this.reason = reason;
|
|
36445
|
-
this.payload = payload;
|
|
37098
|
+
}), _defineProperty(this, "code", "ERR_JWT_EXPIRED"), _defineProperty(this, "claim", void 0), _defineProperty(this, "reason", void 0), _defineProperty(this, "payload", void 0), this.claim = claim, this.reason = reason, this.payload = payload;
|
|
36446
37099
|
}
|
|
36447
37100
|
}
|
|
36448
|
-
_defineProperty(JWTExpired, "code",
|
|
37101
|
+
_defineProperty(JWTExpired, "code", "ERR_JWT_EXPIRED");
|
|
36449
37102
|
class JOSEAlgNotAllowed extends JOSEError {
|
|
36450
37103
|
constructor() {
|
|
36451
37104
|
super(...arguments);
|
|
36452
|
-
_defineProperty(this, "code",
|
|
37105
|
+
_defineProperty(this, "code", "ERR_JOSE_ALG_NOT_ALLOWED");
|
|
36453
37106
|
}
|
|
36454
37107
|
}
|
|
36455
|
-
_defineProperty(JOSEAlgNotAllowed, "code",
|
|
37108
|
+
_defineProperty(JOSEAlgNotAllowed, "code", "ERR_JOSE_ALG_NOT_ALLOWED");
|
|
36456
37109
|
class JOSENotSupported extends JOSEError {
|
|
36457
37110
|
constructor() {
|
|
36458
37111
|
super(...arguments);
|
|
36459
|
-
_defineProperty(this, "code",
|
|
37112
|
+
_defineProperty(this, "code", "ERR_JOSE_NOT_SUPPORTED");
|
|
36460
37113
|
}
|
|
36461
37114
|
}
|
|
36462
|
-
_defineProperty(JOSENotSupported, "code",
|
|
37115
|
+
_defineProperty(JOSENotSupported, "code", "ERR_JOSE_NOT_SUPPORTED");
|
|
36463
37116
|
class JWEDecryptionFailed extends JOSEError {
|
|
36464
37117
|
constructor() {
|
|
36465
|
-
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] :
|
|
37118
|
+
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "decryption operation failed";
|
|
36466
37119
|
let options = arguments.length > 1 ? arguments[1] : undefined;
|
|
36467
37120
|
super(message, options);
|
|
36468
|
-
_defineProperty(this, "code",
|
|
37121
|
+
_defineProperty(this, "code", "ERR_JWE_DECRYPTION_FAILED");
|
|
36469
37122
|
}
|
|
36470
37123
|
}
|
|
36471
|
-
_defineProperty(JWEDecryptionFailed, "code",
|
|
37124
|
+
_defineProperty(JWEDecryptionFailed, "code", "ERR_JWE_DECRYPTION_FAILED");
|
|
36472
37125
|
class JWEInvalid extends JOSEError {
|
|
36473
37126
|
constructor() {
|
|
36474
37127
|
super(...arguments);
|
|
36475
|
-
_defineProperty(this, "code",
|
|
37128
|
+
_defineProperty(this, "code", "ERR_JWE_INVALID");
|
|
36476
37129
|
}
|
|
36477
37130
|
}
|
|
36478
|
-
_defineProperty(JWEInvalid, "code",
|
|
37131
|
+
_defineProperty(JWEInvalid, "code", "ERR_JWE_INVALID");
|
|
36479
37132
|
class JWSInvalid extends JOSEError {
|
|
36480
37133
|
constructor() {
|
|
36481
37134
|
super(...arguments);
|
|
36482
|
-
_defineProperty(this, "code",
|
|
37135
|
+
_defineProperty(this, "code", "ERR_JWS_INVALID");
|
|
36483
37136
|
}
|
|
36484
37137
|
}
|
|
36485
|
-
_defineProperty(JWSInvalid, "code",
|
|
37138
|
+
_defineProperty(JWSInvalid, "code", "ERR_JWS_INVALID");
|
|
36486
37139
|
class JWTInvalid extends JOSEError {
|
|
36487
37140
|
constructor() {
|
|
36488
37141
|
super(...arguments);
|
|
36489
|
-
_defineProperty(this, "code",
|
|
37142
|
+
_defineProperty(this, "code", "ERR_JWT_INVALID");
|
|
36490
37143
|
}
|
|
36491
37144
|
}
|
|
36492
|
-
_defineProperty(JWTInvalid, "code",
|
|
37145
|
+
_defineProperty(JWTInvalid, "code", "ERR_JWT_INVALID");
|
|
36493
37146
|
class JWKInvalid extends JOSEError {
|
|
36494
37147
|
constructor() {
|
|
36495
37148
|
super(...arguments);
|
|
36496
|
-
_defineProperty(this, "code",
|
|
37149
|
+
_defineProperty(this, "code", "ERR_JWK_INVALID");
|
|
36497
37150
|
}
|
|
36498
37151
|
}
|
|
36499
|
-
_defineProperty(JWKInvalid, "code",
|
|
37152
|
+
_defineProperty(JWKInvalid, "code", "ERR_JWK_INVALID");
|
|
36500
37153
|
class JWKSInvalid extends JOSEError {
|
|
36501
37154
|
constructor() {
|
|
36502
37155
|
super(...arguments);
|
|
36503
|
-
_defineProperty(this, "code",
|
|
37156
|
+
_defineProperty(this, "code", "ERR_JWKS_INVALID");
|
|
36504
37157
|
}
|
|
36505
37158
|
}
|
|
36506
|
-
_defineProperty(JWKSInvalid, "code",
|
|
37159
|
+
_defineProperty(JWKSInvalid, "code", "ERR_JWKS_INVALID");
|
|
36507
37160
|
class JWKSNoMatchingKey extends JOSEError {
|
|
36508
37161
|
constructor() {
|
|
36509
|
-
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] :
|
|
37162
|
+
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "no applicable key found in the JSON Web Key Set";
|
|
36510
37163
|
let options = arguments.length > 1 ? arguments[1] : undefined;
|
|
36511
37164
|
super(message, options);
|
|
36512
|
-
_defineProperty(this, "code",
|
|
37165
|
+
_defineProperty(this, "code", "ERR_JWKS_NO_MATCHING_KEY");
|
|
36513
37166
|
}
|
|
36514
37167
|
}
|
|
36515
|
-
_defineProperty(JWKSNoMatchingKey, "code",
|
|
37168
|
+
_defineProperty(JWKSNoMatchingKey, "code", "ERR_JWKS_NO_MATCHING_KEY");
|
|
36516
37169
|
class JWKSMultipleMatchingKeys extends JOSEError {
|
|
36517
37170
|
constructor() {
|
|
36518
|
-
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] :
|
|
37171
|
+
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "multiple matching keys found in the JSON Web Key Set";
|
|
36519
37172
|
let options = arguments.length > 1 ? arguments[1] : undefined;
|
|
36520
37173
|
super(message, options);
|
|
36521
|
-
_defineProperty(this, Symbol.asyncIterator,
|
|
36522
|
-
_defineProperty(this, "code",
|
|
37174
|
+
_defineProperty(this, Symbol.asyncIterator, _wrapAsyncGenerator(function* () {}));
|
|
37175
|
+
_defineProperty(this, "code", "ERR_JWKS_MULTIPLE_MATCHING_KEYS");
|
|
36523
37176
|
}
|
|
36524
37177
|
}
|
|
36525
|
-
_defineProperty(JWKSMultipleMatchingKeys, "code",
|
|
37178
|
+
_defineProperty(JWKSMultipleMatchingKeys, "code", "ERR_JWKS_MULTIPLE_MATCHING_KEYS");
|
|
36526
37179
|
class JWKSTimeout extends JOSEError {
|
|
36527
37180
|
constructor() {
|
|
36528
|
-
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] :
|
|
37181
|
+
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "request timed out";
|
|
36529
37182
|
let options = arguments.length > 1 ? arguments[1] : undefined;
|
|
36530
37183
|
super(message, options);
|
|
36531
|
-
_defineProperty(this, "code",
|
|
37184
|
+
_defineProperty(this, "code", "ERR_JWKS_TIMEOUT");
|
|
36532
37185
|
}
|
|
36533
37186
|
}
|
|
36534
|
-
_defineProperty(JWKSTimeout, "code",
|
|
37187
|
+
_defineProperty(JWKSTimeout, "code", "ERR_JWKS_TIMEOUT");
|
|
36535
37188
|
class JWSSignatureVerificationFailed extends JOSEError {
|
|
36536
37189
|
constructor() {
|
|
36537
|
-
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] :
|
|
37190
|
+
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "signature verification failed";
|
|
36538
37191
|
let options = arguments.length > 1 ? arguments[1] : undefined;
|
|
36539
37192
|
super(message, options);
|
|
36540
|
-
_defineProperty(this, "code",
|
|
37193
|
+
_defineProperty(this, "code", "ERR_JWS_SIGNATURE_VERIFICATION_FAILED");
|
|
36541
37194
|
}
|
|
36542
37195
|
}
|
|
36543
|
-
_defineProperty(JWSSignatureVerificationFailed, "code",
|
|
36544
|
-
function
|
|
36545
|
-
|
|
36546
|
-
return
|
|
36547
|
-
}
|
|
36548
|
-
|
|
36549
|
-
|
|
36550
|
-
|
|
36551
|
-
let proto = input;
|
|
36552
|
-
while (Object.getPrototypeOf(proto) !== null) {
|
|
36553
|
-
proto = Object.getPrototypeOf(proto);
|
|
37196
|
+
_defineProperty(JWSSignatureVerificationFailed, "code", "ERR_JWS_SIGNATURE_VERIFICATION_FAILED");const invalid = "The input to be decoded is not correctly encoded.";
|
|
37197
|
+
function decode(input) {
|
|
37198
|
+
try {
|
|
37199
|
+
return decodeBase64(typeof input == "string" ? input : decoder.decode(input), !0);
|
|
37200
|
+
} catch (cause) {
|
|
37201
|
+
throw new TypeError(invalid, {
|
|
37202
|
+
cause
|
|
37203
|
+
});
|
|
36554
37204
|
}
|
|
36555
|
-
|
|
37205
|
+
}function isObject(input) {
|
|
37206
|
+
if (typeof input != "object" || input === null || Object.prototype.toString.call(input) !== "[object Object]") return false;
|
|
37207
|
+
const prototype = Object.getPrototypeOf(input);
|
|
37208
|
+
return prototype === null || Object.getPrototypeOf(prototype) === null;
|
|
36556
37209
|
}function decodeJwt(jwt) {
|
|
36557
|
-
if (typeof jwt
|
|
36558
|
-
const _jwt$split = jwt.split(
|
|
37210
|
+
if (typeof jwt != "string") throw new JWTInvalid("JWTs must use Compact JWS serialization, JWT must be a string");
|
|
37211
|
+
const _jwt$split = jwt.split("."),
|
|
36559
37212
|
payload = _jwt$split[1],
|
|
36560
37213
|
length = _jwt$split.length;
|
|
36561
|
-
if (length === 5) throw new JWTInvalid(
|
|
36562
|
-
if (length !== 3) throw new JWTInvalid(
|
|
36563
|
-
if (!payload) throw new JWTInvalid(
|
|
37214
|
+
if (length === 5) throw new JWTInvalid("Only JWTs using Compact JWS serialization can be decoded");
|
|
37215
|
+
if (length !== 3) throw new JWTInvalid("Invalid JWT");
|
|
37216
|
+
if (!payload) throw new JWTInvalid("JWTs must contain a payload");
|
|
36564
37217
|
let decoded;
|
|
36565
37218
|
try {
|
|
36566
37219
|
decoded = decode(payload);
|
|
36567
37220
|
} catch (_unused) {
|
|
36568
|
-
throw new JWTInvalid(
|
|
37221
|
+
throw new JWTInvalid("Failed to base64url decode the payload");
|
|
36569
37222
|
}
|
|
36570
37223
|
let result;
|
|
36571
37224
|
try {
|
|
36572
|
-
result = JSON.parse(
|
|
37225
|
+
result = JSON.parse(strictDecoder.decode(decoded));
|
|
36573
37226
|
} catch (_unused2) {
|
|
36574
|
-
throw new JWTInvalid(
|
|
37227
|
+
throw new JWTInvalid("Failed to parse the decoded payload as JSON");
|
|
36575
37228
|
}
|
|
36576
|
-
if (!isObject(result)) throw new JWTInvalid(
|
|
37229
|
+
if (!isObject(result)) throw new JWTInvalid("Invalid JWT Claims Set");
|
|
36577
37230
|
return result;
|
|
36578
37231
|
}const ONE_SECOND_IN_MILLISECONDS = 1000;
|
|
36579
37232
|
const ONE_MINUTE_IN_MILLISECONDS = 60 * ONE_SECOND_IN_MILLISECONDS;
|
|
@@ -36981,4 +37634,4 @@ const serializers = {
|
|
|
36981
37634
|
json,
|
|
36982
37635
|
raw,
|
|
36983
37636
|
custom
|
|
36984
|
-
};export{AudioPresets,BackupCodecPolicy,BaseKeyProvider,CLIENT_PROTOCOL_DATA_STREAM_RPC,CLIENT_PROTOCOL_DATA_STREAM_V2,CLIENT_PROTOCOL_DEFAULT,CheckStatus,Checker,ConnectionCheck,ConnectionError,ConnectionErrorReason,ConnectionQuality,ConnectionState,CriticalTimers,CryptorError,CryptorErrorReason,CryptorEvent,DataPacket_Kind,DataStreamError,DataStreamErrorReason,DataTrackPacket,DefaultReconnectPolicy,DeviceUnsupportedError,DisconnectReason,EncryptionEvent,Encryption_Type,EngineEvent,ExternalE2EEKeyProvider,FrameMetadataManager,KeyHandlerEvent,KeyProviderEvent,LivekitError,LivekitReasonedError,LocalAudioTrack,LocalDataTrack,LocalParticipant,LocalTrack,LocalTrackPublication,LocalTrackRecorder,LocalVideoTrack,LogLevel,LoggerNames,MediaDeviceFailure,_ as Mutex,NegotiationError,PacketTrailerManager,Participant,ParticipantEvent,ParticipantInfo_Kind as ParticipantKind,PublishDataError,PublishTrackError,RemoteAudioTrack,RemoteDataTrack,RemoteParticipant,RemoteTrack,RemoteTrackPublication,RemoteVideoTrack,Room,RoomEvent,RpcError,ScreenSharePresets,SignalReconnectError,SignalRequestError,SimulatedError,SubscriptionError,TokenSource,TokenSourceConfigurable,TokenSourceFixed,Track,TrackEvent,TrackInvalidError,TrackPublication,TrackType,UnexpectedConnectionState,UnsupportedServer,VideoPreset,VideoPresets,VideoPresets43,VideoQuality,areTokenSourceFetchOptionsEqual,asEncryptablePacket,attachToElement,attributeTypings as attributes,audioCodecs,clientProtocol,compareVersions,createAudioAnalyser,createE2EEKey,createKeyMaterialFromBuffer,createKeyMaterialFromString,createLocalAudioTrack,createLocalScreenTracks,createLocalTracks,createLocalVideoTrack,decodeTokenPayload,deriveKeys,detachTrack,facingModeFromDeviceLabel,facingModeFromLocalTrack,getBrowser,getEmptyAudioStreamTrack,getEmptyVideoStreamTrack,getLogger,importKey,isAudioCodec,isAudioTrack,isBackupCodec,isBackupVideoCodec,isBrowserSupported,isE2EESupported,isInsertableStreamSupported,isLocalParticipant,isLocalTrack,isRemoteParticipant,isRemoteTrack,isSVCCodec,isScriptTransformSupported,isSerializer,isVideoCodec,isVideoFrame,isVideoTrack,needsRbspUnescaping,parseRbsp,protocolVersion,ratchet,serializers,setLogExtension,setLogLevel,supportsAV1,supportsAdaptiveStream,supportsAudioOutputSelection,supportsDynacast,supportsH265,supportsVP9,version,videoCodecs,writeRbsp};//# sourceMappingURL=livekit-client.esm.mjs.map
|
|
37637
|
+
};export{AudioPresets,BackupCodecPolicy,BaseKeyProvider,CLIENT_PROTOCOL_DATA_STREAM_RPC,CLIENT_PROTOCOL_DATA_STREAM_V2,CLIENT_PROTOCOL_DEFAULT,CheckStatus,Checker,ConnectionCheck,ConnectionError,ConnectionErrorReason,ConnectionQuality,ConnectionState,CriticalTimers,CryptorError,CryptorErrorReason,CryptorEvent,DataPacket_Kind,DataStreamError,DataStreamErrorReason,DataTrackPacket,DefaultReconnectPolicy,DeviceUnsupportedError,DisconnectReason,EncryptionEvent,Encryption_Type,EngineEvent,ExternalE2EEKeyProvider,FrameMetadataManager,KeyHandlerEvent,KeyProviderEvent,LivekitError,LivekitReasonedError,LocalAudioTrack,LocalDataTrack,LocalParticipant,LocalTrack,LocalTrackPublication,LocalTrackRecorder,LocalVideoTrack,LogLevel,LoggerNames,MediaDeviceFailure,_ as Mutex,NegotiationError,PacketTrailerManager,Participant,ParticipantEvent,ParticipantInfo_Kind as ParticipantKind,PublishDataError,PublishTrackError,RemoteAudioTrack,RemoteDataTrack,RemoteParticipant,RemoteTrack,RemoteTrackPublication,RemoteVideoTrack,Room,RoomEvent,RpcError,ScreenSharePresets,SignalReconnectError,SignalRequestError,SimulatedError,SubscriptionError,TokenSource,TokenSourceConfigurable,TokenSourceFixed,Track,TrackEvent,TrackInvalidError,TrackPublication,TrackType,UnexpectedConnectionState,UnsupportedServer,VideoPreset,VideoPresets,VideoPresets43,VideoQuality,areTokenSourceFetchOptionsEqual,asEncryptablePacket,attachToElement,attributeTypings as attributes,audioCodecs,canFailOverToAnotherRegion,clientProtocol,compareVersions,createAudioAnalyser,createE2EEKey,createKeyMaterialFromBuffer,createKeyMaterialFromString,createLocalAudioTrack,createLocalScreenTracks,createLocalTracks,createLocalVideoTrack,decodeTokenPayload,deriveKeys,detachTrack,facingModeFromDeviceLabel,facingModeFromLocalTrack,getBrowser,getEmptyAudioStreamTrack,getEmptyVideoStreamTrack,getLogger,importKey,isAudioCodec,isAudioTrack,isBackupCodec,isBackupVideoCodec,isBrowserSupported,isE2EESupported,isInsertableStreamSupported,isLocalParticipant,isLocalTrack,isRemoteParticipant,isRemoteTrack,isSVCCodec,isScriptTransformSupported,isSerializer,isVideoCodec,isVideoFrame,isVideoTrack,needsRbspUnescaping,parseRbsp,protocolVersion,ratchet,serializers,setLogExtension,setLogLevel,supportsAV1,supportsAdaptiveStream,supportsAudioOutputSelection,supportsDynacast,supportsH265,supportsVP9,version,videoCodecs,writeRbsp};//# sourceMappingURL=livekit-client.esm.mjs.map
|