livekit-client 2.22.3 → 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 +2 -1
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +602 -247
- 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 +2 -1
- 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/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 +8 -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/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 +2 -0
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +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 +32 -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 -9
- 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 -111
- 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 -231
- 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 -21
- package/dist/ts4.2/e2ee/worker/FrameCryptor.d.ts +209 -209
- 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 -66
- 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 -262
- 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 -53
- 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 -100
- 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 -214
- 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/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 +24 -5
- package/src/room/Room.test.ts +32 -6
- package/src/room/Room.ts +26 -6
- 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/publishUtils.ts +0 -19
- 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 +10 -3
- 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/utils.test.ts +201 -2
- package/src/room/track/utils.ts +88 -0
- package/src/room/utils.test.ts +124 -0
- package/src/room/utils.ts +70 -0
- package/src/test/compressionStreamStubs.ts +53 -0
|
@@ -5473,6 +5473,9 @@ const ClientInfo_SDK = /* @__PURE__ */proto3.makeEnum("livekit.ClientInfo.SDK",
|
|
|
5473
5473
|
}, {
|
|
5474
5474
|
no: 14,
|
|
5475
5475
|
name: "ESP32"
|
|
5476
|
+
}, {
|
|
5477
|
+
no: 15,
|
|
5478
|
+
name: "DOTNET"
|
|
5476
5479
|
}]);
|
|
5477
5480
|
const ClientInfo_Capability = /* @__PURE__ */proto3.makeEnum("livekit.ClientInfo.Capability", [{
|
|
5478
5481
|
no: 0,
|
|
@@ -5841,6 +5844,9 @@ const EncodingOptionsPreset = /* @__PURE__ */proto3.makeEnum("livekit.EncodingOp
|
|
|
5841
5844
|
}, {
|
|
5842
5845
|
no: 7,
|
|
5843
5846
|
name: "PORTRAIT_H264_1080P_60"
|
|
5847
|
+
}, {
|
|
5848
|
+
no: 8,
|
|
5849
|
+
name: "PASSTHROUGH"
|
|
5844
5850
|
}]);
|
|
5845
5851
|
const EncodedFileType = /* @__PURE__ */proto3.makeEnum("livekit.EncodedFileType", [{
|
|
5846
5852
|
no: 0,
|
|
@@ -7825,6 +7831,11 @@ const SyncState = /* @__PURE__ */proto3.makeMessageType("livekit.SyncState", ()
|
|
|
7825
7831
|
kind: "message",
|
|
7826
7832
|
T: PublishDataTrackResponse,
|
|
7827
7833
|
repeated: true
|
|
7834
|
+
}, {
|
|
7835
|
+
no: 9,
|
|
7836
|
+
name: "data_subscription",
|
|
7837
|
+
kind: "message",
|
|
7838
|
+
T: UpdateDataSubscription
|
|
7828
7839
|
}]);
|
|
7829
7840
|
const DataChannelReceiveState = /* @__PURE__ */proto3.makeMessageType("livekit.DataChannelReceiveState", () => [{
|
|
7830
7841
|
no: 1,
|
|
@@ -12279,7 +12290,7 @@ function getMatch(exp, ua) {
|
|
|
12279
12290
|
}
|
|
12280
12291
|
function getOSVersion(ua) {
|
|
12281
12292
|
return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
|
|
12282
|
-
}var version$1 = "2.22.
|
|
12293
|
+
}var version$1 = "2.22.4";const version = version$1;
|
|
12283
12294
|
const protocolVersion = 17;
|
|
12284
12295
|
/** Initial client protocol. */
|
|
12285
12296
|
const CLIENT_PROTOCOL_DEFAULT = 0;
|
|
@@ -12360,6 +12371,32 @@ class ConnectionError extends LivekitReasonedError {
|
|
|
12360
12371
|
return new ConnectionError(message, ConnectionErrorReason.ServiceNotFound, undefined, serviceName);
|
|
12361
12372
|
}
|
|
12362
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
|
+
}
|
|
12363
12400
|
class DeviceUnsupportedError extends LivekitError {
|
|
12364
12401
|
constructor(message) {
|
|
12365
12402
|
super(21, message !== null && message !== void 0 ? message : 'device is unsupported');
|
|
@@ -12693,7 +12730,7 @@ var RoomEvent;
|
|
|
12693
12730
|
* Data packets provides the ability to use LiveKit to send/receive arbitrary payloads.
|
|
12694
12731
|
* All participants in the room will receive the messages sent to the room.
|
|
12695
12732
|
*
|
|
12696
|
-
* 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)
|
|
12697
12734
|
*/
|
|
12698
12735
|
RoomEvent["DataReceived"] = "dataReceived";
|
|
12699
12736
|
/**
|
|
@@ -13051,6 +13088,7 @@ var EngineEvent;
|
|
|
13051
13088
|
EngineEvent["Joined"] = "joined";
|
|
13052
13089
|
EngineEvent["TokenRefreshed"] = "tokenRefreshed";
|
|
13053
13090
|
EngineEvent["ServerRegionsReported"] = "serverRegionsReported";
|
|
13091
|
+
EngineEvent["RequestSubscribedCodecRefresh"] = "requestSubscribedCodecRefresh";
|
|
13054
13092
|
})(EngineEvent || (EngineEvent = {}));
|
|
13055
13093
|
var TrackEvent;
|
|
13056
13094
|
(function (TrackEvent) {
|
|
@@ -13745,6 +13783,85 @@ function areDimensionsSmaller(a, b) {
|
|
|
13745
13783
|
function layerDimensionsFor(trackInfo, quality) {
|
|
13746
13784
|
var _a;
|
|
13747
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
|
+
});
|
|
13748
13865
|
}const BACKGROUND_REACTION_DELAY = 5000;
|
|
13749
13866
|
// keep old audio elements when detached, we would re-use them since on iOS
|
|
13750
13867
|
// Safari tracks which audio elements have been "blessed" by the user.
|
|
@@ -14384,6 +14501,32 @@ function isSafariBased() {
|
|
|
14384
14501
|
const b = getBrowser();
|
|
14385
14502
|
return (b === null || b === void 0 ? void 0 : b.name) === 'Safari' || (b === null || b === void 0 ? void 0 : b.os) === 'iOS';
|
|
14386
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
|
+
}
|
|
14387
14530
|
function isSafari17Based() {
|
|
14388
14531
|
const b = getBrowser();
|
|
14389
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;
|
|
@@ -14875,6 +15018,35 @@ function extractMaxAgeFromRequestHeaders(headers) {
|
|
|
14875
15018
|
function isCompressionStreamSupported() {
|
|
14876
15019
|
return typeof CompressionStream !== 'undefined';
|
|
14877
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
|
+
}
|
|
14878
15050
|
function isPublisherOfferWithJoinSupported() {
|
|
14879
15051
|
// we have connectivity issue about publisher offer with join on firefox #1919
|
|
14880
15052
|
return isCompressionStreamSupported() && !isFireFox();
|
|
@@ -15877,11 +16049,38 @@ class HTMLElementInfo {
|
|
|
15877
16049
|
}
|
|
15878
16050
|
}
|
|
15879
16051
|
function isElementInPiP(el) {
|
|
15880
|
-
var _a
|
|
16052
|
+
var _a;
|
|
15881
16053
|
// Simple video PiP
|
|
15882
16054
|
if (document.pictureInPictureElement === el) return true;
|
|
15883
|
-
// Document PiP
|
|
15884
|
-
|
|
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
|
+
}
|
|
15885
16084
|
return false;
|
|
15886
16085
|
}
|
|
15887
16086
|
// does not account for occlusion by other elements or opacity property
|
|
@@ -18576,7 +18775,7 @@ class SignalClient {
|
|
|
18576
18775
|
const rtcUrl = createRtcUrl(url, params, useV0Path).toString();
|
|
18577
18776
|
const validateUrl = createValidateUrl(rtcUrl).toString();
|
|
18578
18777
|
return new Promise((resolve, reject) => __awaiter(_this2, void 0, void 0, function* () {
|
|
18579
|
-
var _a, _b;
|
|
18778
|
+
var _a, _b, _c, _d, _e;
|
|
18580
18779
|
try {
|
|
18581
18780
|
let alreadyAborted = false;
|
|
18582
18781
|
const abortHandler = eventOrError => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -18683,38 +18882,56 @@ class SignalClient {
|
|
|
18683
18882
|
const signalReader = connection.readable.getReader();
|
|
18684
18883
|
this.streamWriter = connection.writable.getWriter();
|
|
18685
18884
|
// wsTimeout only guarded the upgrade; guard the first-message read with
|
|
18686
|
-
// its own
|
|
18687
|
-
|
|
18688
|
-
|
|
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;
|
|
18689
18890
|
try {
|
|
18690
|
-
|
|
18691
|
-
|
|
18692
|
-
|
|
18693
|
-
|
|
18694
|
-
|
|
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
|
+
}
|
|
18695
18918
|
} catch (e) {
|
|
18696
|
-
// 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
|
|
18697
18920
|
// so we surface the timeout instead of leaking an open connection.
|
|
18698
18921
|
signalReader.releaseLock();
|
|
18699
18922
|
reject(e);
|
|
18700
18923
|
this.close();
|
|
18701
18924
|
return;
|
|
18702
|
-
} finally {
|
|
18703
|
-
clearTimeout(firstMessageTimeout);
|
|
18704
18925
|
}
|
|
18705
18926
|
signalReader.releaseLock();
|
|
18706
|
-
if (!firstMessage.value) {
|
|
18707
|
-
throw ConnectionError.internal('no message received as first message');
|
|
18708
|
-
}
|
|
18709
|
-
const firstSignalResponse = parseSignalResponse(firstMessage.value);
|
|
18710
18927
|
// Validate the first message
|
|
18711
|
-
const validation = this.validateFirstMessage(firstSignalResponse, (
|
|
18928
|
+
const validation = this.validateFirstMessage(firstSignalResponse, (_d = opts.reconnect) !== null && _d !== void 0 ? _d : false);
|
|
18712
18929
|
if (!validation.isValid) {
|
|
18713
18930
|
reject(validation.error);
|
|
18714
18931
|
return;
|
|
18715
18932
|
}
|
|
18716
18933
|
// Handle join response
|
|
18717
|
-
if (((
|
|
18934
|
+
if (((_e = firstSignalResponse.message) === null || _e === void 0 ? void 0 : _e.case) === 'join') {
|
|
18718
18935
|
// Set up ping configuration
|
|
18719
18936
|
this.pingTimeoutDuration = firstSignalResponse.message.value.pingTimeout;
|
|
18720
18937
|
this.pingIntervalDuration = firstSignalResponse.message.value.pingInterval;
|
|
@@ -18728,9 +18945,7 @@ class SignalClient {
|
|
|
18728
18945
|
this.onJoined(firstSignalResponse.message.value);
|
|
18729
18946
|
}
|
|
18730
18947
|
}
|
|
18731
|
-
|
|
18732
|
-
const firstMessageToProcess = validation.shouldProcessFirstMessage ? firstSignalResponse : undefined;
|
|
18733
|
-
this.handleSignalConnected(connection, wsTimeout, attemptId, firstMessageToProcess);
|
|
18948
|
+
this.handleSignalConnected(connection, wsTimeout, attemptId);
|
|
18734
18949
|
resolve(validation.response);
|
|
18735
18950
|
} catch (e) {
|
|
18736
18951
|
reject(e);
|
|
@@ -18744,11 +18959,8 @@ class SignalClient {
|
|
|
18744
18959
|
}();
|
|
18745
18960
|
});
|
|
18746
18961
|
}
|
|
18747
|
-
startReadingLoop(signalReader
|
|
18962
|
+
startReadingLoop(signalReader) {
|
|
18748
18963
|
return __awaiter(this, void 0, void 0, function* () {
|
|
18749
|
-
if (firstMessage) {
|
|
18750
|
-
this.handleSignalResponse(firstMessage);
|
|
18751
|
-
}
|
|
18752
18964
|
const attemptId = this.attemptId;
|
|
18753
18965
|
while (true) {
|
|
18754
18966
|
if (this.signalLatency) {
|
|
@@ -19184,6 +19396,7 @@ class SignalClient {
|
|
|
19184
19396
|
return __awaiter(this, arguments, void 0, function (reason) {
|
|
19185
19397
|
var _this6 = this;
|
|
19186
19398
|
let attemptId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.attemptId;
|
|
19399
|
+
let simulateReconnectDelay = arguments.length > 2 ? arguments[2] : undefined;
|
|
19187
19400
|
return function* () {
|
|
19188
19401
|
const onCloseCallback = _this6.onClose;
|
|
19189
19402
|
if (!_this6.sendLifecycleInput({
|
|
@@ -19205,6 +19418,10 @@ class SignalClient {
|
|
|
19205
19418
|
_this6.log.info("websocket connection closed: ".concat(reason), {
|
|
19206
19419
|
reason
|
|
19207
19420
|
});
|
|
19421
|
+
if (simulateReconnectDelay) {
|
|
19422
|
+
_this6.log.info("waiting for ".concat(simulateReconnectDelay, "ms until reconnecting signal"));
|
|
19423
|
+
yield sleep(simulateReconnectDelay);
|
|
19424
|
+
}
|
|
19208
19425
|
if (onCloseCallback) {
|
|
19209
19426
|
onCloseCallback(reason);
|
|
19210
19427
|
}
|
|
@@ -19265,7 +19482,7 @@ class SignalClient {
|
|
|
19265
19482
|
* @param firstMessage Optional first message to process
|
|
19266
19483
|
* @internal
|
|
19267
19484
|
*/
|
|
19268
|
-
handleSignalConnected(connection, timeoutHandle, attemptId
|
|
19485
|
+
handleSignalConnected(connection, timeoutHandle, attemptId) {
|
|
19269
19486
|
clearTimeout(timeoutHandle);
|
|
19270
19487
|
const established = this.sendLifecycleInput(this.lifecycleState === 'reconnecting' ? {
|
|
19271
19488
|
type: 'reconnectComplete',
|
|
@@ -19287,7 +19504,7 @@ class SignalClient {
|
|
|
19287
19504
|
}
|
|
19288
19505
|
this.log.info('signal connected');
|
|
19289
19506
|
this.startPingInterval();
|
|
19290
|
-
this.startReadingLoop(connection.readable.getReader()
|
|
19507
|
+
this.startReadingLoop(connection.readable.getReader());
|
|
19291
19508
|
}
|
|
19292
19509
|
/**
|
|
19293
19510
|
* Validates the first message received from the signal server
|
|
@@ -19297,28 +19514,18 @@ class SignalClient {
|
|
|
19297
19514
|
* @internal
|
|
19298
19515
|
*/
|
|
19299
19516
|
validateFirstMessage(firstSignalResponse, isReconnect) {
|
|
19300
|
-
var _a, _b, _c, _d
|
|
19517
|
+
var _a, _b, _c, _d;
|
|
19301
19518
|
if (((_a = firstSignalResponse.message) === null || _a === void 0 ? void 0 : _a.case) === 'join') {
|
|
19302
19519
|
return {
|
|
19303
19520
|
isValid: true,
|
|
19304
19521
|
response: firstSignalResponse.message.value
|
|
19305
19522
|
};
|
|
19306
|
-
} else if (this.lifecycleState === 'reconnecting' && ((_b = firstSignalResponse.message) === null || _b === void 0 ? void 0 : _b.case)
|
|
19307
|
-
|
|
19308
|
-
|
|
19309
|
-
|
|
19310
|
-
|
|
19311
|
-
|
|
19312
|
-
} else {
|
|
19313
|
-
// in reconnecting, any message received means signal reconnected and we still need to process it
|
|
19314
|
-
this.log.debug('declaring signal reconnected without reconnect response received');
|
|
19315
|
-
return {
|
|
19316
|
-
isValid: true,
|
|
19317
|
-
response: undefined,
|
|
19318
|
-
shouldProcessFirstMessage: true
|
|
19319
|
-
};
|
|
19320
|
-
}
|
|
19321
|
-
} 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') {
|
|
19322
19529
|
return {
|
|
19323
19530
|
isValid: false,
|
|
19324
19531
|
error: ConnectionError.leaveRequest('Received leave request while trying to (re)connect', firstSignalResponse.message.value.reason)
|
|
@@ -19327,7 +19534,7 @@ class SignalClient {
|
|
|
19327
19534
|
// non-reconnect case, should receive join response first
|
|
19328
19535
|
return {
|
|
19329
19536
|
isValid: false,
|
|
19330
|
-
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"))
|
|
19331
19538
|
};
|
|
19332
19539
|
}
|
|
19333
19540
|
return {
|
|
@@ -19432,6 +19639,12 @@ function createConnectionParams(token, info, opts) {
|
|
|
19432
19639
|
if (opts.adaptiveStream) {
|
|
19433
19640
|
params.set('adaptive_stream', '1');
|
|
19434
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
|
+
}
|
|
19435
19648
|
if (opts.reconnectReason) {
|
|
19436
19649
|
params.set('reconnect_reason', opts.reconnectReason.toString());
|
|
19437
19650
|
}
|
|
@@ -19450,7 +19663,9 @@ function createJoinRequestConnectionParams(token, info, opts, publisherOffer) {
|
|
|
19450
19663
|
clientInfo: info,
|
|
19451
19664
|
connectionSettings: new ConnectionSettings({
|
|
19452
19665
|
autoSubscribe: !!opts.autoSubscribe,
|
|
19453
|
-
adaptiveStream: !!opts.adaptiveStream
|
|
19666
|
+
adaptiveStream: !!opts.adaptiveStream,
|
|
19667
|
+
disableIceLite: !!opts.disableIceLite,
|
|
19668
|
+
subscriberAllowPause: opts.subscriberAllowPause
|
|
19454
19669
|
}),
|
|
19455
19670
|
reconnect: !!opts.reconnect,
|
|
19456
19671
|
participantSid: opts.sid ? opts.sid : undefined,
|
|
@@ -20291,40 +20506,112 @@ function requireLib() {
|
|
|
20291
20506
|
const startBitrateMultiplier = 0.9;
|
|
20292
20507
|
/** Maximum x-google-start-bitrate in kbps. 1 Mbps prevents BWE from starting too aggressively. */
|
|
20293
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;
|
|
20294
20514
|
const debounceInterval = 20;
|
|
20295
20515
|
/**
|
|
20296
|
-
*
|
|
20297
|
-
* This SDP munging is used for a bitrate setting that cannot be applied through
|
|
20298
|
-
* `RTCRtpEncodingParameters`.
|
|
20516
|
+
* Codec payload for `codec` in this media section, when the section carries `cid`.
|
|
20299
20517
|
*
|
|
20300
|
-
* Returns `undefined` when the section does not belong to the track, `0` when
|
|
20301
|
-
*
|
|
20302
|
-
* 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.
|
|
20303
20520
|
*
|
|
20304
20521
|
* @internal
|
|
20305
20522
|
*/
|
|
20306
|
-
function
|
|
20307
|
-
let isScreenShare = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
20523
|
+
function findTrackCodecPayload(media, cid, codec) {
|
|
20308
20524
|
var _a, _b, _c;
|
|
20309
20525
|
if (!((_a = media.msid) === null || _a === void 0 ? void 0 : _a.includes(cid))) {
|
|
20310
20526
|
return undefined;
|
|
20311
20527
|
}
|
|
20312
|
-
|
|
20313
|
-
|
|
20314
|
-
|
|
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;
|
|
20548
|
+
}
|
|
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
|
+
}
|
|
20315
20599
|
}
|
|
20316
|
-
|
|
20317
|
-
|
|
20318
|
-
|
|
20319
|
-
|
|
20320
|
-
|
|
20321
|
-
|
|
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) {
|
|
20322
20611
|
const fmtp = media.fmtp.find(entry => entry.payload === codecPayload);
|
|
20323
20612
|
if (fmtp) {
|
|
20324
|
-
//
|
|
20325
|
-
//
|
|
20326
|
-
// This forces every track sharing that payload to use the initial track's
|
|
20327
|
-
// 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.
|
|
20328
20615
|
if (!fmtp.config.includes('x-google-start-bitrate')) {
|
|
20329
20616
|
fmtp.config += ";x-google-start-bitrate=".concat(startBitrate);
|
|
20330
20617
|
}
|
|
@@ -20335,7 +20622,7 @@ function applyVideoStartBitrate(media, cid, codec, maxbr) {
|
|
|
20335
20622
|
config: "x-google-start-bitrate=".concat(startBitrate)
|
|
20336
20623
|
});
|
|
20337
20624
|
}
|
|
20338
|
-
return
|
|
20625
|
+
return true;
|
|
20339
20626
|
}
|
|
20340
20627
|
const PCEvents = {
|
|
20341
20628
|
NegotiationStarted: 'negotiationStarted',
|
|
@@ -20363,11 +20650,20 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20363
20650
|
this.iceLog = livekitLogger;
|
|
20364
20651
|
this.ddExtID = 0;
|
|
20365
20652
|
this.latestOfferId = 0;
|
|
20653
|
+
this.answeredOfferId = 0;
|
|
20366
20654
|
this.latestAcknowledgedOfferId = 0;
|
|
20367
20655
|
this.pendingCandidates = [];
|
|
20368
20656
|
this.restartingIce = false;
|
|
20369
20657
|
this.renegotiate = false;
|
|
20370
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;
|
|
20371
20667
|
this.remoteStereoMids = [];
|
|
20372
20668
|
this.remoteNackMids = [];
|
|
20373
20669
|
// debounced negotiate interface
|
|
@@ -20476,7 +20772,7 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20476
20772
|
}
|
|
20477
20773
|
setRemoteDescription(sd, offerId) {
|
|
20478
20774
|
return __awaiter(this, void 0, void 0, function* () {
|
|
20479
|
-
var _a
|
|
20775
|
+
var _a;
|
|
20480
20776
|
if (sd.type === 'answer' && this.latestOfferId > 0 && offerId > 0 && offerId !== this.latestOfferId) {
|
|
20481
20777
|
this.log.warn('ignoring answer for old offer', {
|
|
20482
20778
|
offerId,
|
|
@@ -20484,6 +20780,29 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20484
20780
|
});
|
|
20485
20781
|
return false;
|
|
20486
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;
|
|
20487
20806
|
let mungedSDP = undefined;
|
|
20488
20807
|
if (sd.type === 'offer') {
|
|
20489
20808
|
let _extractStereoAndNack = extractStereoAndNackAudioFromOffer(sd),
|
|
@@ -20557,6 +20876,8 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20557
20876
|
mungedSDP = libExports.write(sdpParsed);
|
|
20558
20877
|
}
|
|
20559
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;
|
|
20560
20881
|
if (this.pendingCandidates.length > 0) {
|
|
20561
20882
|
this.iceLog.debug('flushing queued ICE candidates', {
|
|
20562
20883
|
count: this.pendingCandidates.length
|
|
@@ -20664,6 +20985,12 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20664
20985
|
sdp: offer.sdp
|
|
20665
20986
|
});
|
|
20666
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;
|
|
20667
20994
|
sdpParsed.media.forEach(media => {
|
|
20668
20995
|
ensureIPAddrMatchVersion(media);
|
|
20669
20996
|
if (media.type === 'audio') {
|
|
@@ -20673,12 +21000,17 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20673
21000
|
if (!trackbr.cid) {
|
|
20674
21001
|
return false;
|
|
20675
21002
|
}
|
|
20676
|
-
const codecPayload =
|
|
21003
|
+
const codecPayload = findTrackCodecPayload(media, trackbr.cid, trackbr.codec);
|
|
20677
21004
|
if (codecPayload === undefined) {
|
|
20678
21005
|
return false;
|
|
20679
21006
|
}
|
|
20680
|
-
if (codecPayload > 0
|
|
20681
|
-
|
|
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
|
+
}
|
|
20682
21014
|
}
|
|
20683
21015
|
return true;
|
|
20684
21016
|
});
|
|
@@ -20700,7 +21032,13 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
|
20700
21032
|
});
|
|
20701
21033
|
return;
|
|
20702
21034
|
}
|
|
20703
|
-
|
|
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
|
+
}
|
|
20704
21042
|
this.onOffer(offer, this.latestOfferId);
|
|
20705
21043
|
} finally {
|
|
20706
21044
|
unlock();
|
|
@@ -21096,6 +21434,19 @@ function conformBundledCodecFmtp(media, isPlaceholder) {
|
|
|
21096
21434
|
}
|
|
21097
21435
|
}
|
|
21098
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
|
+
}
|
|
21099
21450
|
function extractStereoAndNackAudioFromOffer(offer) {
|
|
21100
21451
|
var _a;
|
|
21101
21452
|
const stereoMids = [];
|
|
@@ -21187,6 +21538,7 @@ const roomOptionDefaults = {
|
|
|
21187
21538
|
};
|
|
21188
21539
|
const roomConnectOptionDefaults = {
|
|
21189
21540
|
autoSubscribe: true,
|
|
21541
|
+
disableIceLite: false,
|
|
21190
21542
|
maxRetries: 1,
|
|
21191
21543
|
peerConnectionTimeout: 15000,
|
|
21192
21544
|
websocketTimeout: 15000
|
|
@@ -21400,7 +21752,9 @@ class PCTransportManager {
|
|
|
21400
21752
|
try {
|
|
21401
21753
|
if (this.isPublisherConnectionRequired && this.publisher.getConnectionState() !== 'connected' && this.publisher.getConnectionState() !== 'connecting') {
|
|
21402
21754
|
this.log.debug('negotiation required, start negotiating');
|
|
21403
|
-
this.publisher.negotiate()
|
|
21755
|
+
this.publisher.negotiate().catch(err => {
|
|
21756
|
+
this.log.error(err);
|
|
21757
|
+
});
|
|
21404
21758
|
}
|
|
21405
21759
|
yield Promise.all((_a = this.requiredTransports) === null || _a === void 0 ? void 0 : _a.map(transport => this.ensureTransportConnected(transport, abortController, timeout)));
|
|
21406
21760
|
} finally {
|
|
@@ -22438,21 +22792,29 @@ class LocalTrack extends Track {
|
|
|
22438
22792
|
var _this = this;
|
|
22439
22793
|
let timeout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_DIMENSIONS_TIMEOUT;
|
|
22440
22794
|
return function* () {
|
|
22441
|
-
var _a;
|
|
22442
22795
|
if (_this.kind === Track.Kind.Audio) {
|
|
22443
22796
|
throw new Error('cannot get dimensions for audio tracks');
|
|
22444
22797
|
}
|
|
22445
|
-
if (((_a = getBrowser()) === null || _a === void 0 ? void 0 : _a.os) === 'iOS') {
|
|
22446
|
-
// browsers report wrong initial resolution on iOS.
|
|
22447
|
-
// when slightly delaying the call to .getSettings(), the correct resolution is being reported
|
|
22448
|
-
yield sleep(10);
|
|
22449
|
-
}
|
|
22450
22798
|
const started = Date.now();
|
|
22451
|
-
|
|
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) {
|
|
22452
22811
|
const dims = _this.dimensions;
|
|
22453
22812
|
if (dims) {
|
|
22454
22813
|
return dims;
|
|
22455
22814
|
}
|
|
22815
|
+
if (Date.now() - started >= timeout) {
|
|
22816
|
+
break;
|
|
22817
|
+
}
|
|
22456
22818
|
yield sleep(50);
|
|
22457
22819
|
}
|
|
22458
22820
|
throw new TrackInvalidError('unable to get track dimensions after timeout');
|
|
@@ -23155,24 +23517,6 @@ const computeDefaultScreenShareSimulcastPresets = fromPreset => {
|
|
|
23155
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);
|
|
23156
23518
|
});
|
|
23157
23519
|
};
|
|
23158
|
-
// /**
|
|
23159
|
-
// *
|
|
23160
|
-
// * @internal
|
|
23161
|
-
// * @experimental
|
|
23162
|
-
// */
|
|
23163
|
-
// const computeDefaultMultiCodecSimulcastEncodings = (width: number, height: number) => {
|
|
23164
|
-
// // use vp8 as a default
|
|
23165
|
-
// const vp8 = determineAppropriateEncoding(false, width, height);
|
|
23166
|
-
// const vp9 = { ...vp8, maxBitrate: vp8.maxBitrate * 0.9 };
|
|
23167
|
-
// const h264 = { ...vp8, maxBitrate: vp8.maxBitrate * 1.1 };
|
|
23168
|
-
// const av1 = { ...vp8, maxBitrate: vp8.maxBitrate * 0.7 };
|
|
23169
|
-
// return {
|
|
23170
|
-
// vp8,
|
|
23171
|
-
// vp9,
|
|
23172
|
-
// h264,
|
|
23173
|
-
// av1,
|
|
23174
|
-
// };
|
|
23175
|
-
// };
|
|
23176
23520
|
const videoRids = ['q', 'h', 'f'];
|
|
23177
23521
|
/* @internal */
|
|
23178
23522
|
function computeVideoEncodings(isScreenShare, width, height, options) {
|
|
@@ -24027,12 +24371,20 @@ class LocalVideoTrack extends LocalTrack {
|
|
|
24027
24371
|
// browser will reenable disabled codec/layers after new codec has been published,
|
|
24028
24372
|
// so refresh subscribedCodecs after publish a new codec
|
|
24029
24373
|
setTimeout(() => {
|
|
24030
|
-
|
|
24031
|
-
this.setPublishingCodecs(this.subscribedCodecs);
|
|
24032
|
-
}
|
|
24374
|
+
this.refreshSubscribedCodecs();
|
|
24033
24375
|
}, refreshSubscribedCodecAfterNewCodec);
|
|
24034
24376
|
});
|
|
24035
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
|
+
}
|
|
24036
24388
|
/**
|
|
24037
24389
|
* @internal
|
|
24038
24390
|
* Sets codecs that should be publishing, returns new codecs that have not yet
|
|
@@ -24377,6 +24729,13 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
24377
24729
|
this.midToTrackId = {};
|
|
24378
24730
|
/** used to indicate whether the browser is currently waiting to reconnect */
|
|
24379
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();
|
|
24380
24739
|
this.handleDataChannel = _a => __awaiter(this, [_a], void 0, function (_ref) {
|
|
24381
24740
|
var _this = this;
|
|
24382
24741
|
let channel = _ref.channel;
|
|
@@ -24622,6 +24981,14 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
24622
24981
|
this.client.onRequestResponse = response => this.emit(EngineEvent.SignalRequestResponse, response);
|
|
24623
24982
|
this.client.onParticipantUpdate = updates => this.emit(EngineEvent.ParticipantUpdate, updates);
|
|
24624
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);
|
|
24625
24992
|
}
|
|
24626
24993
|
/** @internal */
|
|
24627
24994
|
get logContext() {
|
|
@@ -24944,6 +25311,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
24944
25311
|
this.midToTrackId = midToTrackId;
|
|
24945
25312
|
}
|
|
24946
25313
|
yield this.pcManager.setPublisherAnswer(sd, offerId);
|
|
25314
|
+
this.emit(EngineEvent.RequestSubscribedCodecRefresh);
|
|
24947
25315
|
});
|
|
24948
25316
|
// add candidate on trickle
|
|
24949
25317
|
this.client.onTrickle = (candidate, target) => {
|
|
@@ -25010,7 +25378,9 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
25010
25378
|
};
|
|
25011
25379
|
this.client.onMediaSectionsRequirement = requirement => {
|
|
25012
25380
|
this.addMediaSections(requirement.numAudios, requirement.numVideos);
|
|
25013
|
-
this.negotiate()
|
|
25381
|
+
this.negotiate().catch(err => {
|
|
25382
|
+
this.log.error(err);
|
|
25383
|
+
});
|
|
25014
25384
|
};
|
|
25015
25385
|
this.client.onPublishDataTrackResponse = event => {
|
|
25016
25386
|
this.emit(EngineEvent.PublishDataTrackResponse, event);
|
|
@@ -25763,8 +26133,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
25763
26133
|
if (this.isClosed) {
|
|
25764
26134
|
reject(new NegotiationError('cannot negotiate on closed engine'));
|
|
25765
26135
|
}
|
|
25766
|
-
this.
|
|
25767
|
-
this.on(EngineEvent.Restarting, handleClosed);
|
|
26136
|
+
this.pendingNegotiationAborts.add(handleClosed);
|
|
25768
26137
|
this.pcManager.publisher.off(PCEvents.RTPVideoPayloadTypes, this.onRtpMapAvailable);
|
|
25769
26138
|
this.pcManager.publisher.once(PCEvents.RTPVideoPayloadTypes, this.onRtpMapAvailable);
|
|
25770
26139
|
try {
|
|
@@ -25787,8 +26156,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
25787
26156
|
reject(new Error(String(e)));
|
|
25788
26157
|
}
|
|
25789
26158
|
} finally {
|
|
25790
|
-
this.
|
|
25791
|
-
this.off(EngineEvent.Restarting, handleClosed);
|
|
26159
|
+
this.pendingNegotiationAborts.delete(handleClosed);
|
|
25792
26160
|
}
|
|
25793
26161
|
}));
|
|
25794
26162
|
});
|
|
@@ -26589,10 +26957,10 @@ class TextStreamReader extends BaseStreamReader {
|
|
|
26589
26957
|
let compressed;
|
|
26590
26958
|
switch (streamHeader.compression) {
|
|
26591
26959
|
case DataStream_CompressionType.DEFLATE_RAW:
|
|
26592
|
-
if (!
|
|
26960
|
+
if (!isDeflateRawCompressionSupported()) {
|
|
26593
26961
|
// NOTE: this shouldn't really ever happen, if this warning is logged then the sender
|
|
26594
26962
|
// isn't properly abiding by the data streams v2 protocol.
|
|
26595
|
-
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..."));
|
|
26596
26964
|
return;
|
|
26597
26965
|
}
|
|
26598
26966
|
compressed = true;
|
|
@@ -26660,10 +27028,10 @@ class TextStreamReader extends BaseStreamReader {
|
|
|
26660
27028
|
let compressed;
|
|
26661
27029
|
switch (streamHeader.compression) {
|
|
26662
27030
|
case DataStream_CompressionType.DEFLATE_RAW:
|
|
26663
|
-
if (!
|
|
27031
|
+
if (!isDeflateRawCompressionSupported()) {
|
|
26664
27032
|
// NOTE: this shouldn't really ever happen, if this warning is logged then the sender
|
|
26665
27033
|
// isn't properly abiding by the data streams v2 protocol.
|
|
26666
|
-
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..."));
|
|
26667
27035
|
return;
|
|
26668
27036
|
}
|
|
26669
27037
|
compressed = true;
|
|
@@ -27028,7 +27396,7 @@ class OutgoingDataStreamManager {
|
|
|
27028
27396
|
attributes: options === null || options === void 0 ? void 0 : options.attributes,
|
|
27029
27397
|
encryptionType: ((_c = this.engine.e2eeManager) === null || _c === void 0 ? void 0 : _c.isDataChannelEncryptionEnabled) ? Encryption_Type.GCM : Encryption_Type.NONE
|
|
27030
27398
|
};
|
|
27031
|
-
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);
|
|
27032
27400
|
let compressedStream = compressEligible ? MaybeCollectedStream.fromStream(readableFromBytes(textInBytes).pipeThrough(deflateRawTransform())) : null;
|
|
27033
27401
|
// Phase 1: Try to send as a single packet data stream
|
|
27034
27402
|
const noAttachments = !(options === null || options === void 0 ? void 0 : options.attachments) || options.attachments.length === 0;
|
|
@@ -27137,7 +27505,7 @@ class OutgoingDataStreamManager {
|
|
|
27137
27505
|
encryptionType: ((_e = this.engine.e2eeManager) === null || _e === void 0 ? void 0 : _e.isDataChannelEncryptionEnabled) ? Encryption_Type.GCM : Encryption_Type.NONE
|
|
27138
27506
|
};
|
|
27139
27507
|
const progressMonitorTap = progressReportingStream(bytes.length, options === null || options === void 0 ? void 0 : options.onProgress);
|
|
27140
|
-
const compressEligible = compress &&
|
|
27508
|
+
const compressEligible = compress && isDeflateRawCompressionSupported() && this.allRecipientsSupportV2(destinationIdentities) && this.allRecipientsSupportCompression(destinationIdentities);
|
|
27141
27509
|
let compressedStream = compressEligible ? MaybeCollectedStream.fromStream(readableFromBytes(bytes).pipeThrough(progressMonitorTap).pipeThrough(deflateRawTransform())) : null;
|
|
27142
27510
|
// Phase 1: Try to send as a single packet data stream
|
|
27143
27511
|
if (this.allRecipientsSupportV2(destinationIdentities)) {
|
|
@@ -27334,7 +27702,7 @@ class OutgoingDataStreamManager {
|
|
|
27334
27702
|
return __awaiter(this, void 0, void 0, function* () {
|
|
27335
27703
|
var _a, _b, _c, _d, _e;
|
|
27336
27704
|
const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
|
|
27337
|
-
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);
|
|
27338
27706
|
const info = {
|
|
27339
27707
|
id: streamId,
|
|
27340
27708
|
name: file.name,
|
|
@@ -30005,20 +30373,37 @@ class RpcClientManager extends eventsExports.EventEmitter {
|
|
|
30005
30373
|
completionFuture,
|
|
30006
30374
|
participantIdentity: destinationIdentity
|
|
30007
30375
|
});
|
|
30008
|
-
|
|
30009
|
-
|
|
30010
|
-
|
|
30011
|
-
_this.pendingResponses.delete(id);
|
|
30012
|
-
(_a = completionFuture.reject) === null || _a === void 0 ? void 0 : _a.call(completionFuture, RpcError.builtIn('RESPONSE_TIMEOUT'));
|
|
30013
|
-
}, 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.
|
|
30014
30379
|
const completionPromise = completionFuture.promise.finally(() => {
|
|
30015
|
-
|
|
30380
|
+
if (responseTimeoutId !== null) {
|
|
30381
|
+
clearTimeout(responseTimeoutId);
|
|
30382
|
+
}
|
|
30016
30383
|
if (_this.pendingAcks.has(id)) {
|
|
30017
30384
|
_this.log.warn('RPC response received before ack', id);
|
|
30018
30385
|
_this.pendingAcks.delete(id);
|
|
30019
30386
|
clearTimeout(ackTimeoutId);
|
|
30020
30387
|
}
|
|
30021
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
|
+
}
|
|
30022
30407
|
return [id, completionPromise];
|
|
30023
30408
|
}();
|
|
30024
30409
|
});
|
|
@@ -30371,7 +30756,7 @@ class RpcServerManager extends eventsExports.EventEmitter {
|
|
|
30371
30756
|
* gets the volume of attached audio elements (loudest)
|
|
30372
30757
|
*/
|
|
30373
30758
|
getVolume() {
|
|
30374
|
-
if (this.elementVolume) {
|
|
30759
|
+
if (this.elementVolume !== undefined) {
|
|
30375
30760
|
return this.elementVolume;
|
|
30376
30761
|
}
|
|
30377
30762
|
if (isReactNative()) {
|
|
@@ -30420,7 +30805,7 @@ class RpcServerManager extends eventsExports.EventEmitter {
|
|
|
30420
30805
|
element.volume = 0;
|
|
30421
30806
|
element.muted = true;
|
|
30422
30807
|
}
|
|
30423
|
-
if (this.elementVolume) {
|
|
30808
|
+
if (this.elementVolume !== undefined) {
|
|
30424
30809
|
// make sure volume setting is being applied to the newly attached element
|
|
30425
30810
|
this.setVolume(this.elementVolume);
|
|
30426
30811
|
}
|
|
@@ -30480,7 +30865,7 @@ class RpcServerManager extends eventsExports.EventEmitter {
|
|
|
30480
30865
|
this.gainNode = context.createGain();
|
|
30481
30866
|
lastNode.connect(this.gainNode);
|
|
30482
30867
|
this.gainNode.connect(context.destination);
|
|
30483
|
-
if (this.elementVolume) {
|
|
30868
|
+
if (this.elementVolume !== undefined) {
|
|
30484
30869
|
this.gainNode.gain.setTargetAtTime(this.elementVolume, 0, 0.1);
|
|
30485
30870
|
}
|
|
30486
30871
|
// try to resume the context if it isn't running already
|
|
@@ -33731,7 +34116,7 @@ class Room extends eventsExports.EventEmitter {
|
|
|
33731
34116
|
this.abortController = undefined;
|
|
33732
34117
|
resolve();
|
|
33733
34118
|
} catch (error) {
|
|
33734
|
-
if (this.regionUrlProvider && error instanceof ConnectionError && error
|
|
34119
|
+
if (this.regionUrlProvider && error instanceof ConnectionError && canFailOverToAnotherRegion(error)) {
|
|
33735
34120
|
let nextUrl = null;
|
|
33736
34121
|
try {
|
|
33737
34122
|
this.log.debug('Fetching next region');
|
|
@@ -33780,6 +34165,8 @@ class Room extends eventsExports.EventEmitter {
|
|
|
33780
34165
|
const _yield$engine$join = yield engine.join(url, token, {
|
|
33781
34166
|
autoSubscribe: connectOptions.autoSubscribe,
|
|
33782
34167
|
adaptiveStream: typeof roomOptions.adaptiveStream === 'object' ? true : roomOptions.adaptiveStream,
|
|
34168
|
+
disableIceLite: connectOptions.disableIceLite,
|
|
34169
|
+
subscriberAllowPause: connectOptions.subscriberAllowPause,
|
|
33783
34170
|
clientInfoCapabilities: this.getClientInfoCapabilities(roomOptions),
|
|
33784
34171
|
maxRetries: connectOptions.maxRetries,
|
|
33785
34172
|
e2eeEnabled: !!this.e2eeManager,
|
|
@@ -34218,7 +34605,7 @@ class Room extends eventsExports.EventEmitter {
|
|
|
34218
34605
|
// find the participant
|
|
34219
34606
|
const participant = this.remoteParticipants.get(packet.participantIdentity);
|
|
34220
34607
|
if (packet.value.case === 'user') {
|
|
34221
|
-
this.handleUserPacket(participant, packet.value.value, packet.kind, encryptionType);
|
|
34608
|
+
this.handleUserPacket(participant, packet.value.value, packet.kind, encryptionType, packet.participantIdentity);
|
|
34222
34609
|
} else if (packet.value.case === 'transcription') {
|
|
34223
34610
|
this.handleTranscription(participant, packet.value.value);
|
|
34224
34611
|
} else if (packet.value.case === 'sipDtmf') {
|
|
@@ -34249,8 +34636,8 @@ class Room extends eventsExports.EventEmitter {
|
|
|
34249
34636
|
this.rpcClientManager.handleIncomingRpcAck(packet.value.value.requestId);
|
|
34250
34637
|
}
|
|
34251
34638
|
};
|
|
34252
|
-
this.handleUserPacket = (participant, userPacket, kind, encryptionType) => {
|
|
34253
|
-
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);
|
|
34254
34641
|
// also emit on the participant
|
|
34255
34642
|
participant === null || participant === void 0 ? void 0 : participant.emit(ParticipantEvent.DataReceived, userPacket.payload, kind, encryptionType);
|
|
34256
34643
|
};
|
|
@@ -34825,6 +35212,12 @@ class Room extends eventsExports.EventEmitter {
|
|
|
34825
35212
|
updatedAtInMs: Date.now(),
|
|
34826
35213
|
maxAgeInMs: DEFAULT_MAX_AGE_MS
|
|
34827
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
|
+
}
|
|
34828
35221
|
});
|
|
34829
35222
|
if (this.localParticipant) {
|
|
34830
35223
|
this.localParticipant.setupEngine(this.engine);
|
|
@@ -34921,8 +35314,9 @@ class Room extends eventsExports.EventEmitter {
|
|
|
34921
35314
|
let req;
|
|
34922
35315
|
switch (scenario) {
|
|
34923
35316
|
case 'signal-reconnect':
|
|
35317
|
+
const reconnectDelay = typeof arg === 'number' ? arg : 0;
|
|
34924
35318
|
// @ts-expect-error function is private
|
|
34925
|
-
yield this.engine.client.handleOnClose('simulate disconnect');
|
|
35319
|
+
yield this.engine.client.handleOnClose('simulate disconnect', undefined, reconnectDelay);
|
|
34926
35320
|
break;
|
|
34927
35321
|
case 'fail-on-v1-path':
|
|
34928
35322
|
this.engine.failNextV1Path();
|
|
@@ -35603,7 +35997,7 @@ class Room extends eventsExports.EventEmitter {
|
|
|
35603
35997
|
}
|
|
35604
35998
|
// Advertise deflate-raw decompression support so peers know they can send us compressed data
|
|
35605
35999
|
// streams (gated separately from clientProtocol — see the data streams v2 spec).
|
|
35606
|
-
if (
|
|
36000
|
+
if (isDeflateRawCompressionSupported()) {
|
|
35607
36001
|
capabilities.push(ClientInfo_Capability.CAP_COMPRESSION_DEFLATE_RAW);
|
|
35608
36002
|
}
|
|
35609
36003
|
return capabilities;
|
|
@@ -36653,225 +37047,186 @@ class TokenSourceFixed {}
|
|
|
36653
37047
|
* and {@link TokenSourceCustom}.
|
|
36654
37048
|
*/
|
|
36655
37049
|
class TokenSourceConfigurable {}new TextEncoder();
|
|
36656
|
-
const decoder = new TextDecoder()
|
|
36657
|
-
|
|
36658
|
-
|
|
36659
|
-
});
|
|
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, "/");
|
|
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);
|
|
37066
|
+
return bytes;
|
|
37067
|
+
}class JOSEError extends Error {
|
|
36660
37068
|
constructor(message, options) {
|
|
36661
37069
|
var _Error$captureStackTr;
|
|
36662
|
-
super(message, options);
|
|
36663
|
-
_defineProperty(this, "code", 'ERR_JOSE_GENERIC');
|
|
36664
|
-
this.name = this.constructor.name;
|
|
36665
|
-
(_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);
|
|
36666
37071
|
}
|
|
36667
37072
|
}
|
|
36668
|
-
_defineProperty(JOSEError, "code",
|
|
37073
|
+
_defineProperty(JOSEError, "code", "ERR_JOSE_GENERIC");
|
|
36669
37074
|
class JWTClaimValidationFailed extends JOSEError {
|
|
36670
37075
|
constructor(message, payload) {
|
|
36671
|
-
let claim = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] :
|
|
36672
|
-
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";
|
|
36673
37078
|
super(message, {
|
|
36674
37079
|
cause: {
|
|
36675
37080
|
claim,
|
|
36676
37081
|
reason,
|
|
36677
37082
|
payload
|
|
36678
37083
|
}
|
|
36679
|
-
});
|
|
36680
|
-
_defineProperty(this, "code", 'ERR_JWT_CLAIM_VALIDATION_FAILED');
|
|
36681
|
-
_defineProperty(this, "claim", void 0);
|
|
36682
|
-
_defineProperty(this, "reason", void 0);
|
|
36683
|
-
_defineProperty(this, "payload", void 0);
|
|
36684
|
-
this.claim = claim;
|
|
36685
|
-
this.reason = reason;
|
|
36686
|
-
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;
|
|
36687
37085
|
}
|
|
36688
37086
|
}
|
|
36689
|
-
_defineProperty(JWTClaimValidationFailed, "code",
|
|
37087
|
+
_defineProperty(JWTClaimValidationFailed, "code", "ERR_JWT_CLAIM_VALIDATION_FAILED");
|
|
36690
37088
|
class JWTExpired extends JOSEError {
|
|
36691
37089
|
constructor(message, payload) {
|
|
36692
|
-
let claim = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] :
|
|
36693
|
-
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";
|
|
36694
37092
|
super(message, {
|
|
36695
37093
|
cause: {
|
|
36696
37094
|
claim,
|
|
36697
37095
|
reason,
|
|
36698
37096
|
payload
|
|
36699
37097
|
}
|
|
36700
|
-
});
|
|
36701
|
-
_defineProperty(this, "code", 'ERR_JWT_EXPIRED');
|
|
36702
|
-
_defineProperty(this, "claim", void 0);
|
|
36703
|
-
_defineProperty(this, "reason", void 0);
|
|
36704
|
-
_defineProperty(this, "payload", void 0);
|
|
36705
|
-
this.claim = claim;
|
|
36706
|
-
this.reason = reason;
|
|
36707
|
-
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;
|
|
36708
37099
|
}
|
|
36709
37100
|
}
|
|
36710
|
-
_defineProperty(JWTExpired, "code",
|
|
37101
|
+
_defineProperty(JWTExpired, "code", "ERR_JWT_EXPIRED");
|
|
36711
37102
|
class JOSEAlgNotAllowed extends JOSEError {
|
|
36712
37103
|
constructor() {
|
|
36713
37104
|
super(...arguments);
|
|
36714
|
-
_defineProperty(this, "code",
|
|
37105
|
+
_defineProperty(this, "code", "ERR_JOSE_ALG_NOT_ALLOWED");
|
|
36715
37106
|
}
|
|
36716
37107
|
}
|
|
36717
|
-
_defineProperty(JOSEAlgNotAllowed, "code",
|
|
37108
|
+
_defineProperty(JOSEAlgNotAllowed, "code", "ERR_JOSE_ALG_NOT_ALLOWED");
|
|
36718
37109
|
class JOSENotSupported extends JOSEError {
|
|
36719
37110
|
constructor() {
|
|
36720
37111
|
super(...arguments);
|
|
36721
|
-
_defineProperty(this, "code",
|
|
37112
|
+
_defineProperty(this, "code", "ERR_JOSE_NOT_SUPPORTED");
|
|
36722
37113
|
}
|
|
36723
37114
|
}
|
|
36724
|
-
_defineProperty(JOSENotSupported, "code",
|
|
37115
|
+
_defineProperty(JOSENotSupported, "code", "ERR_JOSE_NOT_SUPPORTED");
|
|
36725
37116
|
class JWEDecryptionFailed extends JOSEError {
|
|
36726
37117
|
constructor() {
|
|
36727
|
-
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] :
|
|
37118
|
+
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "decryption operation failed";
|
|
36728
37119
|
let options = arguments.length > 1 ? arguments[1] : undefined;
|
|
36729
37120
|
super(message, options);
|
|
36730
|
-
_defineProperty(this, "code",
|
|
37121
|
+
_defineProperty(this, "code", "ERR_JWE_DECRYPTION_FAILED");
|
|
36731
37122
|
}
|
|
36732
37123
|
}
|
|
36733
|
-
_defineProperty(JWEDecryptionFailed, "code",
|
|
37124
|
+
_defineProperty(JWEDecryptionFailed, "code", "ERR_JWE_DECRYPTION_FAILED");
|
|
36734
37125
|
class JWEInvalid extends JOSEError {
|
|
36735
37126
|
constructor() {
|
|
36736
37127
|
super(...arguments);
|
|
36737
|
-
_defineProperty(this, "code",
|
|
37128
|
+
_defineProperty(this, "code", "ERR_JWE_INVALID");
|
|
36738
37129
|
}
|
|
36739
37130
|
}
|
|
36740
|
-
_defineProperty(JWEInvalid, "code",
|
|
37131
|
+
_defineProperty(JWEInvalid, "code", "ERR_JWE_INVALID");
|
|
36741
37132
|
class JWSInvalid extends JOSEError {
|
|
36742
37133
|
constructor() {
|
|
36743
37134
|
super(...arguments);
|
|
36744
|
-
_defineProperty(this, "code",
|
|
37135
|
+
_defineProperty(this, "code", "ERR_JWS_INVALID");
|
|
36745
37136
|
}
|
|
36746
37137
|
}
|
|
36747
|
-
_defineProperty(JWSInvalid, "code",
|
|
37138
|
+
_defineProperty(JWSInvalid, "code", "ERR_JWS_INVALID");
|
|
36748
37139
|
class JWTInvalid extends JOSEError {
|
|
36749
37140
|
constructor() {
|
|
36750
37141
|
super(...arguments);
|
|
36751
|
-
_defineProperty(this, "code",
|
|
37142
|
+
_defineProperty(this, "code", "ERR_JWT_INVALID");
|
|
36752
37143
|
}
|
|
36753
37144
|
}
|
|
36754
|
-
_defineProperty(JWTInvalid, "code",
|
|
37145
|
+
_defineProperty(JWTInvalid, "code", "ERR_JWT_INVALID");
|
|
36755
37146
|
class JWKInvalid extends JOSEError {
|
|
36756
37147
|
constructor() {
|
|
36757
37148
|
super(...arguments);
|
|
36758
|
-
_defineProperty(this, "code",
|
|
37149
|
+
_defineProperty(this, "code", "ERR_JWK_INVALID");
|
|
36759
37150
|
}
|
|
36760
37151
|
}
|
|
36761
|
-
_defineProperty(JWKInvalid, "code",
|
|
37152
|
+
_defineProperty(JWKInvalid, "code", "ERR_JWK_INVALID");
|
|
36762
37153
|
class JWKSInvalid extends JOSEError {
|
|
36763
37154
|
constructor() {
|
|
36764
37155
|
super(...arguments);
|
|
36765
|
-
_defineProperty(this, "code",
|
|
37156
|
+
_defineProperty(this, "code", "ERR_JWKS_INVALID");
|
|
36766
37157
|
}
|
|
36767
37158
|
}
|
|
36768
|
-
_defineProperty(JWKSInvalid, "code",
|
|
37159
|
+
_defineProperty(JWKSInvalid, "code", "ERR_JWKS_INVALID");
|
|
36769
37160
|
class JWKSNoMatchingKey extends JOSEError {
|
|
36770
37161
|
constructor() {
|
|
36771
|
-
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";
|
|
36772
37163
|
let options = arguments.length > 1 ? arguments[1] : undefined;
|
|
36773
37164
|
super(message, options);
|
|
36774
|
-
_defineProperty(this, "code",
|
|
37165
|
+
_defineProperty(this, "code", "ERR_JWKS_NO_MATCHING_KEY");
|
|
36775
37166
|
}
|
|
36776
37167
|
}
|
|
36777
|
-
_defineProperty(JWKSNoMatchingKey, "code",
|
|
37168
|
+
_defineProperty(JWKSNoMatchingKey, "code", "ERR_JWKS_NO_MATCHING_KEY");
|
|
36778
37169
|
class JWKSMultipleMatchingKeys extends JOSEError {
|
|
36779
37170
|
constructor() {
|
|
36780
|
-
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";
|
|
36781
37172
|
let options = arguments.length > 1 ? arguments[1] : undefined;
|
|
36782
37173
|
super(message, options);
|
|
36783
37174
|
_defineProperty(this, Symbol.asyncIterator, _wrapAsyncGenerator(function* () {}));
|
|
36784
|
-
_defineProperty(this, "code",
|
|
37175
|
+
_defineProperty(this, "code", "ERR_JWKS_MULTIPLE_MATCHING_KEYS");
|
|
36785
37176
|
}
|
|
36786
37177
|
}
|
|
36787
|
-
_defineProperty(JWKSMultipleMatchingKeys, "code",
|
|
37178
|
+
_defineProperty(JWKSMultipleMatchingKeys, "code", "ERR_JWKS_MULTIPLE_MATCHING_KEYS");
|
|
36788
37179
|
class JWKSTimeout extends JOSEError {
|
|
36789
37180
|
constructor() {
|
|
36790
|
-
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] :
|
|
37181
|
+
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "request timed out";
|
|
36791
37182
|
let options = arguments.length > 1 ? arguments[1] : undefined;
|
|
36792
37183
|
super(message, options);
|
|
36793
|
-
_defineProperty(this, "code",
|
|
37184
|
+
_defineProperty(this, "code", "ERR_JWKS_TIMEOUT");
|
|
36794
37185
|
}
|
|
36795
37186
|
}
|
|
36796
|
-
_defineProperty(JWKSTimeout, "code",
|
|
37187
|
+
_defineProperty(JWKSTimeout, "code", "ERR_JWKS_TIMEOUT");
|
|
36797
37188
|
class JWSSignatureVerificationFailed extends JOSEError {
|
|
36798
37189
|
constructor() {
|
|
36799
|
-
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] :
|
|
37190
|
+
let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "signature verification failed";
|
|
36800
37191
|
let options = arguments.length > 1 ? arguments[1] : undefined;
|
|
36801
37192
|
super(message, options);
|
|
36802
|
-
_defineProperty(this, "code",
|
|
37193
|
+
_defineProperty(this, "code", "ERR_JWS_SIGNATURE_VERIFICATION_FAILED");
|
|
36803
37194
|
}
|
|
36804
37195
|
}
|
|
36805
|
-
_defineProperty(JWSSignatureVerificationFailed, "code",
|
|
36806
|
-
if (Uint8Array.fromBase64) {
|
|
36807
|
-
return Uint8Array.fromBase64(encoded);
|
|
36808
|
-
}
|
|
36809
|
-
const binary = atob(encoded);
|
|
36810
|
-
const bytes = new Uint8Array(binary.length);
|
|
36811
|
-
for (let i = 0; i < binary.length; i++) {
|
|
36812
|
-
bytes[i] = binary.charCodeAt(i);
|
|
36813
|
-
}
|
|
36814
|
-
return bytes;
|
|
36815
|
-
}const invalid = 'The input to be decoded is not correctly encoded.';
|
|
37196
|
+
_defineProperty(JWSSignatureVerificationFailed, "code", "ERR_JWS_SIGNATURE_VERIFICATION_FAILED");const invalid = "The input to be decoded is not correctly encoded.";
|
|
36816
37197
|
function decode(input) {
|
|
36817
|
-
if (Uint8Array.fromBase64) {
|
|
36818
|
-
try {
|
|
36819
|
-
return Uint8Array.fromBase64(typeof input === 'string' ? input : decoder.decode(input), {
|
|
36820
|
-
alphabet: 'base64url'
|
|
36821
|
-
});
|
|
36822
|
-
} catch (cause) {
|
|
36823
|
-
throw new TypeError(invalid, {
|
|
36824
|
-
cause
|
|
36825
|
-
});
|
|
36826
|
-
}
|
|
36827
|
-
}
|
|
36828
|
-
let encoded = input;
|
|
36829
|
-
if (encoded instanceof Uint8Array) {
|
|
36830
|
-
encoded = decoder.decode(encoded);
|
|
36831
|
-
}
|
|
36832
|
-
if (encoded.includes('+') || encoded.includes('/')) {
|
|
36833
|
-
throw new TypeError(invalid);
|
|
36834
|
-
}
|
|
36835
|
-
encoded = encoded.replace(/-/g, '+').replace(/_/g, '/');
|
|
36836
37198
|
try {
|
|
36837
|
-
return decodeBase64(
|
|
36838
|
-
} catch (
|
|
36839
|
-
throw new TypeError(invalid
|
|
37199
|
+
return decodeBase64(typeof input == "string" ? input : decoder.decode(input), !0);
|
|
37200
|
+
} catch (cause) {
|
|
37201
|
+
throw new TypeError(invalid, {
|
|
37202
|
+
cause
|
|
37203
|
+
});
|
|
36840
37204
|
}
|
|
36841
37205
|
}function isObject(input) {
|
|
36842
|
-
if (typeof input
|
|
36843
|
-
return false;
|
|
36844
|
-
}
|
|
37206
|
+
if (typeof input != "object" || input === null || Object.prototype.toString.call(input) !== "[object Object]") return false;
|
|
36845
37207
|
const prototype = Object.getPrototypeOf(input);
|
|
36846
|
-
|
|
36847
|
-
return true;
|
|
36848
|
-
}
|
|
36849
|
-
let proto = prototype;
|
|
36850
|
-
while (Object.getPrototypeOf(proto) !== null) {
|
|
36851
|
-
proto = Object.getPrototypeOf(proto);
|
|
36852
|
-
}
|
|
36853
|
-
return prototype === proto;
|
|
37208
|
+
return prototype === null || Object.getPrototypeOf(prototype) === null;
|
|
36854
37209
|
}function decodeJwt(jwt) {
|
|
36855
|
-
if (typeof jwt
|
|
36856
|
-
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("."),
|
|
36857
37212
|
payload = _jwt$split[1],
|
|
36858
37213
|
length = _jwt$split.length;
|
|
36859
|
-
if (length === 5) throw new JWTInvalid(
|
|
36860
|
-
if (length !== 3) throw new JWTInvalid(
|
|
36861
|
-
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");
|
|
36862
37217
|
let decoded;
|
|
36863
37218
|
try {
|
|
36864
37219
|
decoded = decode(payload);
|
|
36865
37220
|
} catch (_unused) {
|
|
36866
|
-
throw new JWTInvalid(
|
|
37221
|
+
throw new JWTInvalid("Failed to base64url decode the payload");
|
|
36867
37222
|
}
|
|
36868
37223
|
let result;
|
|
36869
37224
|
try {
|
|
36870
37225
|
result = JSON.parse(strictDecoder.decode(decoded));
|
|
36871
37226
|
} catch (_unused2) {
|
|
36872
|
-
throw new JWTInvalid(
|
|
37227
|
+
throw new JWTInvalid("Failed to parse the decoded payload as JSON");
|
|
36873
37228
|
}
|
|
36874
|
-
if (!isObject(result)) throw new JWTInvalid(
|
|
37229
|
+
if (!isObject(result)) throw new JWTInvalid("Invalid JWT Claims Set");
|
|
36875
37230
|
return result;
|
|
36876
37231
|
}const ONE_SECOND_IN_MILLISECONDS = 1000;
|
|
36877
37232
|
const ONE_MINUTE_IN_MILLISECONDS = 60 * ONE_SECOND_IN_MILLISECONDS;
|
|
@@ -37279,4 +37634,4 @@ const serializers = {
|
|
|
37279
37634
|
json,
|
|
37280
37635
|
raw,
|
|
37281
37636
|
custom
|
|
37282
|
-
};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
|