livekit-client 2.16.0 → 2.16.1

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.
Files changed (63) hide show
  1. package/README.md +105 -1
  2. package/dist/livekit-client.e2ee.worker.js +1 -1
  3. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  4. package/dist/livekit-client.e2ee.worker.mjs +1 -0
  5. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  6. package/dist/livekit-client.esm.mjs +1079 -1329
  7. package/dist/livekit-client.esm.mjs.map +1 -1
  8. package/dist/livekit-client.umd.js +1 -1
  9. package/dist/livekit-client.umd.js.map +1 -1
  10. package/dist/src/api/SignalClient.d.ts.map +1 -1
  11. package/dist/src/api/utils.d.ts +1 -0
  12. package/dist/src/api/utils.d.ts.map +1 -1
  13. package/dist/src/connectionHelper/checks/turn.d.ts.map +1 -1
  14. package/dist/src/connectionHelper/checks/websocket.d.ts.map +1 -1
  15. package/dist/src/room/PCTransportManager.d.ts.map +1 -1
  16. package/dist/src/room/RTCEngine.d.ts +5 -0
  17. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  18. package/dist/src/room/RegionUrlProvider.d.ts.map +1 -1
  19. package/dist/src/room/Room.d.ts +1 -1
  20. package/dist/src/room/Room.d.ts.map +1 -1
  21. package/dist/src/room/data-stream/outgoing/OutgoingDataStreamManager.d.ts +0 -1
  22. package/dist/src/room/data-stream/outgoing/OutgoingDataStreamManager.d.ts.map +1 -1
  23. package/dist/src/room/errors.d.ts +74 -5
  24. package/dist/src/room/errors.d.ts.map +1 -1
  25. package/dist/src/room/token-source/TokenSource.d.ts +10 -2
  26. package/dist/src/room/token-source/TokenSource.d.ts.map +1 -1
  27. package/dist/src/room/track/LocalTrack.d.ts +0 -4
  28. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  29. package/dist/src/room/track/TrackPublication.d.ts.map +1 -1
  30. package/dist/src/room/track/processor/types.d.ts +0 -6
  31. package/dist/src/room/track/processor/types.d.ts.map +1 -1
  32. package/dist/src/room/utils.d.ts +1 -1
  33. package/dist/src/room/utils.d.ts.map +1 -1
  34. package/dist/src/test/mocks.d.ts.map +1 -1
  35. package/dist/ts4.2/api/utils.d.ts +1 -0
  36. package/dist/ts4.2/room/RTCEngine.d.ts +5 -0
  37. package/dist/ts4.2/room/Room.d.ts +1 -1
  38. package/dist/ts4.2/room/data-stream/outgoing/OutgoingDataStreamManager.d.ts +0 -1
  39. package/dist/ts4.2/room/errors.d.ts +74 -5
  40. package/dist/ts4.2/room/token-source/TokenSource.d.ts +1 -1
  41. package/dist/ts4.2/room/track/LocalTrack.d.ts +0 -4
  42. package/dist/ts4.2/room/track/processor/types.d.ts +0 -6
  43. package/package.json +10 -6
  44. package/src/api/SignalClient.test.ts +12 -19
  45. package/src/api/SignalClient.ts +13 -28
  46. package/src/api/utils.ts +1 -1
  47. package/src/connectionHelper/checks/turn.ts +7 -0
  48. package/src/connectionHelper/checks/websocket.ts +40 -11
  49. package/src/room/PCTransport.ts +1 -1
  50. package/src/room/PCTransportManager.ts +4 -19
  51. package/src/room/RTCEngine.ts +56 -18
  52. package/src/room/RegionUrlProvider.test.ts +8 -9
  53. package/src/room/RegionUrlProvider.ts +13 -12
  54. package/src/room/Room.ts +14 -16
  55. package/src/room/data-stream/outgoing/OutgoingDataStreamManager.ts +0 -1
  56. package/src/room/errors.ts +144 -16
  57. package/src/room/participant/LocalParticipant.ts +1 -1
  58. package/src/room/token-source/TokenSource.ts +5 -1
  59. package/src/room/track/LocalTrack.ts +0 -4
  60. package/src/room/track/TrackPublication.ts +1 -1
  61. package/src/room/track/processor/types.ts +0 -6
  62. package/src/room/utils.ts +2 -1
  63. package/src/test/mocks.ts +0 -1
@@ -1,19 +1,4 @@
1
- function _mergeNamespaces(n, m) {
2
- m.forEach(function (e) {
3
- e && typeof e !== 'string' && !Array.isArray(e) && Object.keys(e).forEach(function (k) {
4
- if (k !== 'default' && !(k in n)) {
5
- var d = Object.getOwnPropertyDescriptor(e, k);
6
- Object.defineProperty(n, k, d.get ? d : {
7
- enumerable: true,
8
- get: function () { return e[k]; }
9
- });
10
- }
11
- });
12
- });
13
- return Object.freeze(n);
14
- }
15
-
16
- var e = Object.defineProperty;
1
+ function _mergeNamespaces(n, m){m.forEach(function(e){e&&typeof e!=='string'&&!Array.isArray(e)&&Object.keys(e).forEach(function(k){if(k!=='default'&&!(k in n)){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})});return Object.freeze(n);}var e = Object.defineProperty;
17
2
  var h = (i, s, t) => s in i ? e(i, s, {
18
3
  enumerable: true,
19
4
  configurable: true,
@@ -39,9 +24,7 @@ class _ {
39
24
  c = this._locking.then(() => s);
40
25
  return this._locking = this._locking.then(() => t), c;
41
26
  }
42
- }
43
-
44
- // Copyright 2021-2024 Buf Technologies, Inc.
27
+ }// Copyright 2021-2024 Buf Technologies, Inc.
45
28
  //
46
29
  // Licensed under the Apache License, Version 2.0 (the "License");
47
30
  // you may not use this file except in compliance with the License.
@@ -89,9 +72,7 @@ function assertFloat32(arg) {
89
72
  if (typeof arg !== "number") throw new Error("invalid float 32: " + typeof arg);
90
73
  if (!Number.isFinite(arg)) return;
91
74
  if (arg > FLOAT32_MAX || arg < FLOAT32_MIN) throw new Error("invalid float 32: " + arg); // eslint-disable-line @typescript-eslint/restrict-plus-operands -- we want the implicit conversion to string
92
- }
93
-
94
- // Copyright 2021-2024 Buf Technologies, Inc.
75
+ }// Copyright 2021-2024 Buf Technologies, Inc.
95
76
  //
96
77
  // Licensed under the Apache License, Version 2.0 (the "License");
97
78
  // you may not use this file except in compliance with the License.
@@ -178,9 +159,7 @@ function normalizeEnumValue(value) {
178
159
  return Object.assign(Object.assign({}, value), {
179
160
  localName: value.name
180
161
  });
181
- }
182
-
183
- // Copyright 2021-2024 Buf Technologies, Inc.
162
+ }// Copyright 2021-2024 Buf Technologies, Inc.
184
163
  //
185
164
  // Licensed under the Apache License, Version 2.0 (the "License");
186
165
  // you may not use this file except in compliance with the License.
@@ -312,9 +291,7 @@ class Message {
312
291
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-return
313
292
  return Object.getPrototypeOf(this).constructor;
314
293
  }
315
- }
316
-
317
- // Copyright 2021-2024 Buf Technologies, Inc.
294
+ }// Copyright 2021-2024 Buf Technologies, Inc.
318
295
  //
319
296
  // Licensed under the Apache License, Version 2.0 (the "License");
320
297
  // you may not use this file except in compliance with the License.
@@ -358,9 +335,7 @@ function makeMessageType(runtime, typeName, fields, opt) {
358
335
  }
359
336
  });
360
337
  return type;
361
- }
362
-
363
- // Copyright 2008 Google Inc. All rights reserved.
338
+ }// Copyright 2008 Google Inc. All rights reserved.
364
339
  //
365
340
  // Redistribution and use in source and binary forms, with or without
366
341
  // modification, are permitted provided that the following conditions are
@@ -676,9 +651,7 @@ function varint32read() {
676
651
  this.assertBounds();
677
652
  // Result can have 32 bits, convert it to unsigned
678
653
  return result >>> 0;
679
- }
680
-
681
- // Copyright 2021-2024 Buf Technologies, Inc.
654
+ }// Copyright 2021-2024 Buf Technologies, Inc.
682
655
  //
683
656
  // Licensed under the Apache License, Version 2.0 (the "License");
684
657
  // you may not use this file except in compliance with the License.
@@ -784,9 +757,7 @@ function makeInt64Support() {
784
757
  }
785
758
  };
786
759
  }
787
- const protoInt64 = makeInt64Support();
788
-
789
- // Copyright 2021-2024 Buf Technologies, Inc.
760
+ const protoInt64 = makeInt64Support();// Copyright 2021-2024 Buf Technologies, Inc.
790
761
  //
791
762
  // Licensed under the Apache License, Version 2.0 (the "License");
792
763
  // you may not use this file except in compliance with the License.
@@ -863,9 +834,7 @@ var LongType;
863
834
  * Field option `[jstype = JS_STRING]`.
864
835
  */
865
836
  LongType[LongType["STRING"] = 1] = "STRING";
866
- })(LongType || (LongType = {}));
867
-
868
- // Copyright 2021-2024 Buf Technologies, Inc.
837
+ })(LongType || (LongType = {}));// Copyright 2021-2024 Buf Technologies, Inc.
869
838
  //
870
839
  // Licensed under the Apache License, Version 2.0 (the "License");
871
840
  // you may not use this file except in compliance with the License.
@@ -962,9 +931,7 @@ function isScalarZeroValue(type, value) {
962
931
  return value == 0;
963
932
  // Loose comparison matches 0n, 0 and "0"
964
933
  }
965
- }
966
-
967
- // Copyright 2021-2024 Buf Technologies, Inc.
934
+ }// Copyright 2021-2024 Buf Technologies, Inc.
968
935
  //
969
936
  // Licensed under the Apache License, Version 2.0 (the "License");
970
937
  // you may not use this file except in compliance with the License.
@@ -1407,9 +1374,7 @@ class BinaryReader {
1407
1374
  string() {
1408
1375
  return this.textDecoder.decode(this.bytes());
1409
1376
  }
1410
- }
1411
-
1412
- // Copyright 2021-2024 Buf Technologies, Inc.
1377
+ }// Copyright 2021-2024 Buf Technologies, Inc.
1413
1378
  //
1414
1379
  // Licensed under the Apache License, Version 2.0 (the "License");
1415
1380
  // you may not use this file except in compliance with the License.
@@ -1488,9 +1453,7 @@ function filterUnknownFields(unknownFields, field) {
1488
1453
  return [];
1489
1454
  }
1490
1455
  return unknownFields.filter(uf => uf.no === field.no);
1491
- }
1492
-
1493
- // Copyright 2021-2024 Buf Technologies, Inc.
1456
+ }// Copyright 2021-2024 Buf Technologies, Inc.
1494
1457
  //
1495
1458
  // Licensed under the Apache License, Version 2.0 (the "License");
1496
1459
  // you may not use this file except in compliance with the License.
@@ -1617,9 +1580,7 @@ const protoBase64 = {
1617
1580
  }
1618
1581
  return base64;
1619
1582
  }
1620
- };
1621
-
1622
- // Copyright 2021-2024 Buf Technologies, Inc.
1583
+ };// Copyright 2021-2024 Buf Technologies, Inc.
1623
1584
  //
1624
1585
  // Licensed under the Apache License, Version 2.0 (the "License");
1625
1586
  // you may not use this file except in compliance with the License.
@@ -1699,9 +1660,7 @@ function hasExtension(message, extension) {
1699
1660
  }
1700
1661
  function assertExtendee(extension, message) {
1701
1662
  assert(extension.extendee.typeName == message.getType().typeName, "extension ".concat(extension.typeName, " can only be applied to message ").concat(extension.extendee.typeName));
1702
- }
1703
-
1704
- // Copyright 2021-2024 Buf Technologies, Inc.
1663
+ }// Copyright 2021-2024 Buf Technologies, Inc.
1705
1664
  //
1706
1665
  // Licensed under the Apache License, Version 2.0 (the "License");
1707
1666
  // you may not use this file except in compliance with the License.
@@ -1772,9 +1731,7 @@ function clearField(field, target) {
1772
1731
  break;
1773
1732
  }
1774
1733
  }
1775
- }
1776
-
1777
- // Copyright 2021-2024 Buf Technologies, Inc.
1734
+ }// Copyright 2021-2024 Buf Technologies, Inc.
1778
1735
  //
1779
1736
  // Licensed under the Apache License, Version 2.0 (the "License");
1780
1737
  // you may not use this file except in compliance with the License.
@@ -1817,9 +1774,7 @@ function isMessage(arg, type) {
1817
1774
  return false;
1818
1775
  }
1819
1776
  return type === undefined ? true : actualType.typeName == type.typeName;
1820
- }
1821
-
1822
- // Copyright 2021-2024 Buf Technologies, Inc.
1777
+ }// Copyright 2021-2024 Buf Technologies, Inc.
1823
1778
  //
1824
1779
  // Licensed under the Apache License, Version 2.0 (the "License");
1825
1780
  // you may not use this file except in compliance with the License.
@@ -1852,9 +1807,7 @@ function wrapField(type, value) {
1852
1807
  "google.protobuf.BoolValue": ScalarType.BOOL,
1853
1808
  "google.protobuf.StringValue": ScalarType.STRING,
1854
1809
  "google.protobuf.BytesValue": ScalarType.BYTES
1855
- });
1856
-
1857
- // Copyright 2021-2024 Buf Technologies, Inc.
1810
+ });// Copyright 2021-2024 Buf Technologies, Inc.
1858
1811
  //
1859
1812
  // Licensed under the Apache License, Version 2.0 (the "License");
1860
1813
  // you may not use this file except in compliance with the License.
@@ -2423,9 +2376,7 @@ function writeScalar$1(type, value) {
2423
2376
  assert(value instanceof Uint8Array);
2424
2377
  return protoBase64.enc(value);
2425
2378
  }
2426
- }
2427
-
2428
- // Copyright 2021-2024 Buf Technologies, Inc.
2379
+ }// Copyright 2021-2024 Buf Technologies, Inc.
2429
2380
  //
2430
2381
  // Licensed under the Apache License, Version 2.0 (the "License");
2431
2382
  // you may not use this file except in compliance with the License.
@@ -2832,9 +2783,7 @@ function scalarTypeInfo(type) {
2832
2783
  }
2833
2784
  const method = ScalarType[type].toLowerCase();
2834
2785
  return [wireType, method];
2835
- }
2836
-
2837
- // Copyright 2021-2024 Buf Technologies, Inc.
2786
+ }// Copyright 2021-2024 Buf Technologies, Inc.
2838
2787
  //
2839
2788
  // Licensed under the Apache License, Version 2.0 (the "License");
2840
2789
  // you may not use this file except in compliance with the License.
@@ -3068,9 +3017,7 @@ function cloneSingularField(value) {
3068
3017
  // converts any ArrayLike<number> to Uint8Array if necessary.
3069
3018
  function toU8Arr(input) {
3070
3019
  return input instanceof Uint8Array ? input : new Uint8Array(input);
3071
- }
3072
-
3073
- // Copyright 2021-2024 Buf Technologies, Inc.
3020
+ }// Copyright 2021-2024 Buf Technologies, Inc.
3074
3021
  //
3075
3022
  // Licensed under the Apache License, Version 2.0 (the "License");
3076
3023
  // you may not use this file except in compliance with the License.
@@ -3102,9 +3049,7 @@ function makeProtoRuntime(syntax, newFieldList, initFields) {
3102
3049
  return makeExtension(this, typeName, extendee, field);
3103
3050
  }
3104
3051
  };
3105
- }
3106
-
3107
- // Copyright 2021-2024 Buf Technologies, Inc.
3052
+ }// Copyright 2021-2024 Buf Technologies, Inc.
3108
3053
  //
3109
3054
  // Licensed under the Apache License, Version 2.0 (the "License");
3110
3055
  // you may not use this file except in compliance with the License.
@@ -3172,9 +3117,7 @@ class InternalFieldList {
3172
3117
  }
3173
3118
  return this.members;
3174
3119
  }
3175
- }
3176
-
3177
- // Copyright 2021-2024 Buf Technologies, Inc.
3120
+ }// Copyright 2021-2024 Buf Technologies, Inc.
3178
3121
  //
3179
3122
  // Licensed under the Apache License, Version 2.0 (the "License");
3180
3123
  // you may not use this file except in compliance with the License.
@@ -3289,9 +3232,7 @@ const safeObjectProperty = name => {
3289
3232
  return fallback(name);
3290
3233
  }
3291
3234
  return name;
3292
- };
3293
-
3294
- // Copyright 2021-2024 Buf Technologies, Inc.
3235
+ };// Copyright 2021-2024 Buf Technologies, Inc.
3295
3236
  //
3296
3237
  // Licensed under the Apache License, Version 2.0 (the "License");
3297
3238
  // you may not use this file except in compliance with the License.
@@ -3329,9 +3270,7 @@ class InternalOneofInfo {
3329
3270
  }
3330
3271
  return this._lookup[localName];
3331
3272
  }
3332
- }
3333
-
3334
- // Copyright 2021-2024 Buf Technologies, Inc.
3273
+ }// Copyright 2021-2024 Buf Technologies, Inc.
3335
3274
  //
3336
3275
  // Licensed under the Apache License, Version 2.0 (the "License");
3337
3276
  // you may not use this file except in compliance with the License.
@@ -3383,9 +3322,7 @@ function normalizeFieldInfos(fieldInfos, packedByDefault) {
3383
3322
  r.push(f);
3384
3323
  }
3385
3324
  return r;
3386
- }
3387
-
3388
- // Copyright 2021-2024 Buf Technologies, Inc.
3325
+ }// Copyright 2021-2024 Buf Technologies, Inc.
3389
3326
  //
3390
3327
  // Licensed under the Apache License, Version 2.0 (the "License");
3391
3328
  // you may not use this file except in compliance with the License.
@@ -3433,9 +3370,7 @@ target => {
3433
3370
  break;
3434
3371
  }
3435
3372
  }
3436
- });
3437
-
3438
- // Copyright 2021-2024 Buf Technologies, Inc.
3373
+ });// Copyright 2021-2024 Buf Technologies, Inc.
3439
3374
  //
3440
3375
  // Licensed under the Apache License, Version 2.0 (the "License");
3441
3376
  // you may not use this file except in compliance with the License.
@@ -3645,9 +3580,7 @@ Timestamp.fields = proto3.util.newFieldList(() => [{
3645
3580
  name: "nanos",
3646
3581
  kind: "scalar",
3647
3582
  T: 5 /* ScalarType.INT32 */
3648
- }]);
3649
-
3650
- const MetricsBatch = /* @__PURE__ */proto3.makeMessageType("livekit.MetricsBatch", () => [{
3583
+ }]);const MetricsBatch = /* @__PURE__ */proto3.makeMessageType("livekit.MetricsBatch", () => [{
3651
3584
  no: 1,
3652
3585
  name: "timestamp_ms",
3653
3586
  kind: "scalar",
@@ -7574,15 +7507,9 @@ const TokenSourceResponse = /* @__PURE__ */proto3.makeMessageType("livekit.Token
7574
7507
  kind: "scalar",
7575
7508
  T: 9
7576
7509
  /* ScalarType.STRING */
7577
- }]);
7578
-
7579
- function getDefaultExportFromCjs (x) {
7510
+ }]);function getDefaultExportFromCjs (x) {
7580
7511
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
7581
- }
7582
-
7583
- var loglevel$1 = {exports: {}};
7584
-
7585
- /*
7512
+ }var loglevel$1 = {exports: {}};/*
7586
7513
  * loglevel - https://github.com/pimterry/loglevel
7587
7514
  *
7588
7515
  * Copyright (c) 2013 Tim Perry
@@ -7902,11 +7829,7 @@ function requireLoglevel() {
7902
7829
  });
7903
7830
  })(loglevel$1);
7904
7831
  return loglevel$1.exports;
7905
- }
7906
-
7907
- var loglevelExports = requireLoglevel();
7908
-
7909
- var LogLevel;
7832
+ }var loglevelExports = requireLoglevel();var LogLevel;
7910
7833
  (function (LogLevel) {
7911
7834
  LogLevel[LogLevel["trace"] = 0] = "trace";
7912
7835
  LogLevel[LogLevel["debug"] = 1] = "debug";
@@ -7971,9 +7894,7 @@ function setLogExtension(extension, logger) {
7971
7894
  logR.setLevel(logR.getLevel());
7972
7895
  });
7973
7896
  }
7974
- const workerLogger = loglevelExports.getLogger('lk-e2ee');
7975
-
7976
- const maxRetryDelay = 7000;
7897
+ const workerLogger = loglevelExports.getLogger('lk-e2ee');const maxRetryDelay = 7000;
7977
7898
  const DEFAULT_RETRY_DELAYS_IN_MS = [0, 300, 2 * 2 * 300, 3 * 3 * 300, 4 * 4 * 300, maxRetryDelay, maxRetryDelay, maxRetryDelay, maxRetryDelay, maxRetryDelay];
7978
7899
  class DefaultReconnectPolicy {
7979
7900
  constructor(retryDelays) {
@@ -7985,9 +7906,7 @@ class DefaultReconnectPolicy {
7985
7906
  if (context.retryCount <= 1) return retryDelay;
7986
7907
  return retryDelay + Math.random() * 1000;
7987
7908
  }
7988
- }
7989
-
7990
- /******************************************************************************
7909
+ }/******************************************************************************
7991
7910
  Copyright (c) Microsoft Corporation.
7992
7911
 
7993
7912
  Permission to use, copy, modify, and/or distribute this software for any
@@ -8049,11 +7968,7 @@ function __asyncValues(o) {
8049
7968
  typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
8050
7969
  var e = new Error(message);
8051
7970
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
8052
- };
8053
-
8054
- var events = {exports: {}};
8055
-
8056
- var hasRequiredEvents;
7971
+ };var events = {exports: {}};var hasRequiredEvents;
8057
7972
  function requireEvents() {
8058
7973
  if (hasRequiredEvents) return events.exports;
8059
7974
  hasRequiredEvents = 1;
@@ -8434,11 +8349,7 @@ function requireEvents() {
8434
8349
  }
8435
8350
  }
8436
8351
  return events.exports;
8437
- }
8438
-
8439
- var eventsExports = requireEvents();
8440
-
8441
- /*
8352
+ }var eventsExports = requireEvents();/*
8442
8353
  * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
8443
8354
  *
8444
8355
  * Use of this source code is governed by a BSD-style license
@@ -8698,9 +8609,7 @@ function filterStats(result, track, outbound) {
8698
8609
  });
8699
8610
  });
8700
8611
  return filteredResult;
8701
- }
8702
-
8703
- /*
8612
+ }/*
8704
8613
  * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
8705
8614
  *
8706
8615
  * Use of this source code is governed by a BSD-style license
@@ -8877,9 +8786,7 @@ function shimGetUserMedia$2(window, browserDetails) {
8877
8786
  }, e => Promise.reject(shimError_(e))));
8878
8787
  };
8879
8788
  }
8880
- }
8881
-
8882
- /*
8789
+ }/*
8883
8790
  * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
8884
8791
  *
8885
8792
  * Use of this source code is governed by a BSD-style license
@@ -9429,22 +9336,7 @@ function fixNegotiationNeeded(window, browserDetails) {
9429
9336
  }
9430
9337
  return e;
9431
9338
  });
9432
- }
9433
-
9434
- var chromeShim = /*#__PURE__*/Object.freeze({
9435
- __proto__: null,
9436
- fixNegotiationNeeded: fixNegotiationNeeded,
9437
- shimAddTrackRemoveTrack: shimAddTrackRemoveTrack,
9438
- shimAddTrackRemoveTrackWithNative: shimAddTrackRemoveTrackWithNative,
9439
- shimGetSendersWithDtmf: shimGetSendersWithDtmf,
9440
- shimGetUserMedia: shimGetUserMedia$2,
9441
- shimMediaStream: shimMediaStream,
9442
- shimOnTrack: shimOnTrack$1,
9443
- shimPeerConnection: shimPeerConnection$1,
9444
- shimSenderReceiverGetStats: shimSenderReceiverGetStats
9445
- });
9446
-
9447
- /*
9339
+ }var chromeShim=/*#__PURE__*/Object.freeze({__proto__:null,fixNegotiationNeeded:fixNegotiationNeeded,shimAddTrackRemoveTrack:shimAddTrackRemoveTrack,shimAddTrackRemoveTrackWithNative:shimAddTrackRemoveTrackWithNative,shimGetSendersWithDtmf:shimGetSendersWithDtmf,shimGetUserMedia:shimGetUserMedia$2,shimMediaStream:shimMediaStream,shimOnTrack:shimOnTrack$1,shimPeerConnection:shimPeerConnection$1,shimSenderReceiverGetStats:shimSenderReceiverGetStats});/*
9448
9340
  * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
9449
9341
  *
9450
9342
  * Use of this source code is governed by a BSD-style license
@@ -9497,9 +9389,7 @@ function shimGetUserMedia$1(window, browserDetails) {
9497
9389
  };
9498
9390
  }
9499
9391
  }
9500
- }
9501
-
9502
- /*
9392
+ }/*
9503
9393
  * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.
9504
9394
  *
9505
9395
  * Use of this source code is governed by a BSD-style license
@@ -9532,9 +9422,7 @@ function shimGetDisplayMedia(window, preferredMediaSource) {
9532
9422
  }
9533
9423
  return window.navigator.mediaDevices.getUserMedia(constraints);
9534
9424
  };
9535
- }
9536
-
9537
- /*
9425
+ }/*
9538
9426
  * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
9539
9427
  *
9540
9428
  * Use of this source code is governed by a BSD-style license
@@ -9798,25 +9686,7 @@ function shimCreateAnswer(window) {
9798
9686
  }
9799
9687
  return origCreateAnswer.apply(this, arguments);
9800
9688
  };
9801
- }
9802
-
9803
- var firefoxShim = /*#__PURE__*/Object.freeze({
9804
- __proto__: null,
9805
- shimAddTransceiver: shimAddTransceiver,
9806
- shimCreateAnswer: shimCreateAnswer,
9807
- shimCreateOffer: shimCreateOffer,
9808
- shimGetDisplayMedia: shimGetDisplayMedia,
9809
- shimGetParameters: shimGetParameters,
9810
- shimGetUserMedia: shimGetUserMedia$1,
9811
- shimOnTrack: shimOnTrack,
9812
- shimPeerConnection: shimPeerConnection,
9813
- shimRTCDataChannel: shimRTCDataChannel,
9814
- shimReceiverGetStats: shimReceiverGetStats,
9815
- shimRemoveStream: shimRemoveStream,
9816
- shimSenderGetStats: shimSenderGetStats
9817
- });
9818
-
9819
- /*
9689
+ }var firefoxShim=/*#__PURE__*/Object.freeze({__proto__:null,shimAddTransceiver:shimAddTransceiver,shimCreateAnswer:shimCreateAnswer,shimCreateOffer:shimCreateOffer,shimGetDisplayMedia:shimGetDisplayMedia,shimGetParameters:shimGetParameters,shimGetUserMedia:shimGetUserMedia$1,shimOnTrack:shimOnTrack,shimPeerConnection:shimPeerConnection,shimRTCDataChannel:shimRTCDataChannel,shimReceiverGetStats:shimReceiverGetStats,shimRemoveStream:shimRemoveStream,shimSenderGetStats:shimSenderGetStats});/*
9820
9690
  * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
9821
9691
  *
9822
9692
  * Use of this source code is governed by a BSD-style license
@@ -10131,24 +10001,7 @@ function shimAudioContext(window) {
10131
10001
  return;
10132
10002
  }
10133
10003
  window.AudioContext = window.webkitAudioContext;
10134
- }
10135
-
10136
- var safariShim = /*#__PURE__*/Object.freeze({
10137
- __proto__: null,
10138
- shimAudioContext: shimAudioContext,
10139
- shimCallbacksAPI: shimCallbacksAPI,
10140
- shimConstraints: shimConstraints,
10141
- shimCreateOfferLegacy: shimCreateOfferLegacy,
10142
- shimGetUserMedia: shimGetUserMedia,
10143
- shimLocalStreamsAPI: shimLocalStreamsAPI,
10144
- shimRTCIceServerUrls: shimRTCIceServerUrls,
10145
- shimRemoteStreamsAPI: shimRemoteStreamsAPI,
10146
- shimTrackEventTransceiver: shimTrackEventTransceiver
10147
- });
10148
-
10149
- var sdp$1 = {exports: {}};
10150
-
10151
- /* eslint-env node */
10004
+ }var safariShim=/*#__PURE__*/Object.freeze({__proto__:null,shimAudioContext:shimAudioContext,shimCallbacksAPI:shimCallbacksAPI,shimConstraints:shimConstraints,shimCreateOfferLegacy:shimCreateOfferLegacy,shimGetUserMedia:shimGetUserMedia,shimLocalStreamsAPI:shimLocalStreamsAPI,shimRTCIceServerUrls:shimRTCIceServerUrls,shimRemoteStreamsAPI:shimRemoteStreamsAPI,shimTrackEventTransceiver:shimTrackEventTransceiver});var sdp$1 = {exports: {}};/* eslint-env node */
10152
10005
  var hasRequiredSdp;
10153
10006
  function requireSdp() {
10154
10007
  if (hasRequiredSdp) return sdp$1.exports;
@@ -10893,17 +10746,8 @@ function requireSdp() {
10893
10746
  }
10894
10747
  })(sdp$1);
10895
10748
  return sdp$1.exports;
10896
- }
10897
-
10898
- var sdpExports = requireSdp();
10899
- var SDPUtils = /*@__PURE__*/getDefaultExportFromCjs(sdpExports);
10900
-
10901
- var sdp = /*#__PURE__*/_mergeNamespaces({
10902
- __proto__: null,
10903
- default: SDPUtils
10904
- }, [sdpExports]);
10905
-
10906
- /*
10749
+ }var sdpExports = requireSdp();
10750
+ var SDPUtils = /*@__PURE__*/getDefaultExportFromCjs(sdpExports);var sdp=/*#__PURE__*/_mergeNamespaces({__proto__:null,default:SDPUtils},[sdpExports]);/*
10907
10751
  * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
10908
10752
  *
10909
10753
  * Use of this source code is governed by a BSD-style license
@@ -11317,21 +11161,7 @@ function shimParameterlessSetLocalDescription(window, browserDetails) {
11317
11161
  const func = desc.type === 'offer' ? this.createOffer : this.createAnswer;
11318
11162
  return func.apply(this).then(d => nativeSetLocalDescription.apply(this, [d]));
11319
11163
  };
11320
- }
11321
-
11322
- var commonShim = /*#__PURE__*/Object.freeze({
11323
- __proto__: null,
11324
- removeExtmapAllowMixed: removeExtmapAllowMixed,
11325
- shimAddIceCandidateNullOrEmpty: shimAddIceCandidateNullOrEmpty,
11326
- shimConnectionState: shimConnectionState,
11327
- shimMaxMessageSize: shimMaxMessageSize,
11328
- shimParameterlessSetLocalDescription: shimParameterlessSetLocalDescription,
11329
- shimRTCIceCandidate: shimRTCIceCandidate,
11330
- shimRTCIceCandidateRelayProtocol: shimRTCIceCandidateRelayProtocol,
11331
- shimSendThrowTypeError: shimSendThrowTypeError
11332
- });
11333
-
11334
- /*
11164
+ }var commonShim=/*#__PURE__*/Object.freeze({__proto__:null,removeExtmapAllowMixed:removeExtmapAllowMixed,shimAddIceCandidateNullOrEmpty:shimAddIceCandidateNullOrEmpty,shimConnectionState:shimConnectionState,shimMaxMessageSize:shimMaxMessageSize,shimParameterlessSetLocalDescription:shimParameterlessSetLocalDescription,shimRTCIceCandidate:shimRTCIceCandidate,shimRTCIceCandidateRelayProtocol:shimRTCIceCandidateRelayProtocol,shimSendThrowTypeError:shimSendThrowTypeError});/*
11335
11165
  * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
11336
11166
  *
11337
11167
  * Use of this source code is governed by a BSD-style license
@@ -11454,9 +11284,7 @@ function adapterFactory() {
11454
11284
  break;
11455
11285
  }
11456
11286
  return adapter;
11457
- }
11458
-
11459
- /*
11287
+ }/*
11460
11288
  * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
11461
11289
  *
11462
11290
  * Use of this source code is governed by a BSD-style license
@@ -11467,296 +11295,85 @@ function adapterFactory() {
11467
11295
 
11468
11296
  adapterFactory({
11469
11297
  window: typeof window === 'undefined' ? undefined : window
11470
- });
11471
-
11472
- const ENCRYPTION_ALGORITHM = 'AES-GCM';
11473
- // How many consecutive frames can fail decrypting before a particular key gets marked as invalid
11474
- const DECRYPTION_FAILURE_TOLERANCE = 10;
11475
- // flag set to indicate that e2ee has been setup for sender/receiver;
11476
- const E2EE_FLAG = 'lk_e2ee';
11477
- const SALT = 'LKFrameEncryptionKey';
11478
- const KEY_PROVIDER_DEFAULTS = {
11479
- sharedKey: false,
11480
- ratchetSalt: SALT,
11481
- ratchetWindowSize: 8,
11482
- failureTolerance: DECRYPTION_FAILURE_TOLERANCE,
11483
- keyringSize: 16
11484
- };
11485
-
11486
- var KeyProviderEvent;
11487
- (function (KeyProviderEvent) {
11488
- KeyProviderEvent["SetKey"] = "setKey";
11489
- /** Event for requesting to ratchet the key used to encrypt the stream */
11490
- KeyProviderEvent["RatchetRequest"] = "ratchetRequest";
11491
- /** Emitted when a key is ratcheted. Could be after auto-ratcheting on decryption failure or
11492
- * following a `RatchetRequest`, will contain the ratcheted key material */
11493
- KeyProviderEvent["KeyRatcheted"] = "keyRatcheted";
11494
- })(KeyProviderEvent || (KeyProviderEvent = {}));
11495
- var KeyHandlerEvent;
11496
- (function (KeyHandlerEvent) {
11497
- /** Emitted when a key has been ratcheted. Is emitted when any key has been ratcheted
11498
- * i.e. when the FrameCryptor tried to ratchet when decryption is failing */
11499
- KeyHandlerEvent["KeyRatcheted"] = "keyRatcheted";
11500
- })(KeyHandlerEvent || (KeyHandlerEvent = {}));
11501
- var EncryptionEvent;
11502
- (function (EncryptionEvent) {
11503
- EncryptionEvent["ParticipantEncryptionStatusChanged"] = "participantEncryptionStatusChanged";
11504
- EncryptionEvent["EncryptionError"] = "encryptionError";
11505
- })(EncryptionEvent || (EncryptionEvent = {}));
11506
- var CryptorEvent;
11507
- (function (CryptorEvent) {
11508
- CryptorEvent["Error"] = "cryptorError";
11509
- })(CryptorEvent || (CryptorEvent = {}));
11510
-
11511
- function isE2EESupported() {
11512
- return isInsertableStreamSupported() || isScriptTransformSupported();
11513
- }
11514
- function isScriptTransformSupported() {
11515
- // @ts-ignore
11516
- return typeof window.RTCRtpScriptTransform !== 'undefined';
11517
- }
11518
- function isInsertableStreamSupported() {
11519
- return typeof window.RTCRtpSender !== 'undefined' &&
11520
- // @ts-ignore
11521
- typeof window.RTCRtpSender.prototype.createEncodedStreams !== 'undefined';
11522
- }
11523
- function isVideoFrame(frame) {
11524
- return 'type' in frame;
11298
+ });// tiny, simplified version of https://github.com/lancedikson/bowser/blob/master/src/parser-browsers.js
11299
+ // reduced to only differentiate Chrome(ium) based browsers / Firefox / Safari
11300
+ const commonVersionIdentifier = /version\/(\d+(\.?_?\d+)+)/i;
11301
+ let browserDetails;
11302
+ /**
11303
+ * @internal
11304
+ */
11305
+ function getBrowser(userAgent) {
11306
+ let force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
11307
+ if (typeof userAgent === 'undefined' && typeof navigator === 'undefined') {
11308
+ return;
11309
+ }
11310
+ const ua = (userAgent !== null && userAgent !== void 0 ? userAgent : navigator.userAgent).toLowerCase();
11311
+ if (browserDetails === undefined || force) {
11312
+ const browser = browsersList.find(_ref => {
11313
+ let {
11314
+ test
11315
+ } = _ref;
11316
+ return test.test(ua);
11317
+ });
11318
+ browserDetails = browser === null || browser === void 0 ? void 0 : browser.describe(ua);
11319
+ }
11320
+ return browserDetails;
11525
11321
  }
11526
- function importKey(keyBytes_1) {
11527
- return __awaiter(this, arguments, void 0, function (keyBytes) {
11528
- let algorithm = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
11529
- name: ENCRYPTION_ALGORITHM
11322
+ const browsersList = [{
11323
+ test: /firefox|iceweasel|fxios/i,
11324
+ describe(ua) {
11325
+ const browser = {
11326
+ name: 'Firefox',
11327
+ version: getMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i, ua),
11328
+ os: ua.toLowerCase().includes('fxios') ? 'iOS' : undefined,
11329
+ osVersion: getOSVersion(ua)
11530
11330
  };
11531
- let usage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'encrypt';
11532
- return function* () {
11533
- // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey
11534
- return crypto.subtle.importKey('raw', keyBytes, algorithm, false, usage === 'derive' ? ['deriveBits', 'deriveKey'] : ['encrypt', 'decrypt']);
11535
- }();
11536
- });
11331
+ return browser;
11332
+ }
11333
+ }, {
11334
+ test: /chrom|crios|crmo/i,
11335
+ describe(ua) {
11336
+ const browser = {
11337
+ name: 'Chrome',
11338
+ version: getMatch(/(?:chrome|chromium|crios|crmo)\/(\d+(\.?_?\d+)+)/i, ua),
11339
+ os: ua.toLowerCase().includes('crios') ? 'iOS' : undefined,
11340
+ osVersion: getOSVersion(ua)
11341
+ };
11342
+ return browser;
11343
+ }
11344
+ }, /* Safari */
11345
+ {
11346
+ test: /safari|applewebkit/i,
11347
+ describe(ua) {
11348
+ const browser = {
11349
+ name: 'Safari',
11350
+ version: getMatch(commonVersionIdentifier, ua),
11351
+ os: ua.includes('mobile/') ? 'iOS' : 'macOS',
11352
+ osVersion: getOSVersion(ua)
11353
+ };
11354
+ return browser;
11355
+ }
11356
+ }];
11357
+ function getMatch(exp, ua) {
11358
+ let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
11359
+ const match = ua.match(exp);
11360
+ return match && match.length >= id && match[id] || '';
11537
11361
  }
11538
- function createKeyMaterialFromString(password) {
11539
- return __awaiter(this, void 0, void 0, function* () {
11540
- let enc = new TextEncoder();
11541
- const keyMaterial = yield crypto.subtle.importKey('raw', enc.encode(password), {
11542
- name: 'PBKDF2'
11543
- }, false, ['deriveBits', 'deriveKey']);
11544
- return keyMaterial;
11545
- });
11362
+ function getOSVersion(ua) {
11363
+ return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
11364
+ }var version$1 = "2.16.1";const version = version$1;
11365
+ const protocolVersion = 16;class LivekitError extends Error {
11366
+ constructor(code, message) {
11367
+ super(message || 'an error has occured');
11368
+ this.name = 'LiveKitError';
11369
+ this.code = code;
11370
+ }
11546
11371
  }
11547
- function createKeyMaterialFromBuffer(cryptoBuffer) {
11548
- return __awaiter(this, void 0, void 0, function* () {
11549
- const keyMaterial = yield crypto.subtle.importKey('raw', cryptoBuffer, 'HKDF', false, ['deriveBits', 'deriveKey']);
11550
- return keyMaterial;
11551
- });
11552
- }
11553
- function getAlgoOptions(algorithmName, salt) {
11554
- const textEncoder = new TextEncoder();
11555
- const encodedSalt = textEncoder.encode(salt);
11556
- switch (algorithmName) {
11557
- case 'HKDF':
11558
- return {
11559
- name: 'HKDF',
11560
- salt: encodedSalt,
11561
- hash: 'SHA-256',
11562
- info: new ArrayBuffer(128)
11563
- };
11564
- case 'PBKDF2':
11565
- {
11566
- return {
11567
- name: 'PBKDF2',
11568
- salt: encodedSalt,
11569
- hash: 'SHA-256',
11570
- iterations: 100000
11571
- };
11572
- }
11573
- default:
11574
- throw new Error("algorithm ".concat(algorithmName, " is currently unsupported"));
11575
- }
11576
- }
11577
- /**
11578
- * Derives a set of keys from the master key.
11579
- * See https://tools.ietf.org/html/draft-omara-sframe-00#section-4.3.1
11580
- */
11581
- function deriveKeys(material, salt) {
11582
- return __awaiter(this, void 0, void 0, function* () {
11583
- const algorithmOptions = getAlgoOptions(material.algorithm.name, salt);
11584
- // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveKey#HKDF
11585
- // https://developer.mozilla.org/en-US/docs/Web/API/HkdfParams
11586
- const encryptionKey = yield crypto.subtle.deriveKey(algorithmOptions, material, {
11587
- name: ENCRYPTION_ALGORITHM,
11588
- length: 128
11589
- }, false, ['encrypt', 'decrypt']);
11590
- return {
11591
- material,
11592
- encryptionKey
11593
- };
11594
- });
11595
- }
11596
- function createE2EEKey() {
11597
- return window.crypto.getRandomValues(new Uint8Array(32));
11598
- }
11599
- /**
11600
- * Ratchets a key. See
11601
- * https://tools.ietf.org/html/draft-omara-sframe-00#section-4.3.5.1
11602
- */
11603
- function ratchet(material, salt) {
11604
- return __awaiter(this, void 0, void 0, function* () {
11605
- const algorithmOptions = getAlgoOptions(material.algorithm.name, salt);
11606
- // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveBits
11607
- return crypto.subtle.deriveBits(algorithmOptions, material, 256);
11608
- });
11609
- }
11610
- function needsRbspUnescaping(frameData) {
11611
- for (var i = 0; i < frameData.length - 3; i++) {
11612
- if (frameData[i] == 0 && frameData[i + 1] == 0 && frameData[i + 2] == 3) return true;
11613
- }
11614
- return false;
11615
- }
11616
- function parseRbsp(stream) {
11617
- const dataOut = [];
11618
- var length = stream.length;
11619
- for (var i = 0; i < stream.length;) {
11620
- // Be careful about over/underflow here. byte_length_ - 3 can underflow, and
11621
- // i + 3 can overflow, but byte_length_ - i can't, because i < byte_length_
11622
- // above, and that expression will produce the number of bytes left in
11623
- // the stream including the byte at i.
11624
- if (length - i >= 3 && !stream[i] && !stream[i + 1] && stream[i + 2] == 3) {
11625
- // Two rbsp bytes.
11626
- dataOut.push(stream[i++]);
11627
- dataOut.push(stream[i++]);
11628
- // Skip the emulation byte.
11629
- i++;
11630
- } else {
11631
- // Single rbsp byte.
11632
- dataOut.push(stream[i++]);
11633
- }
11634
- }
11635
- return new Uint8Array(dataOut);
11636
- }
11637
- const kZerosInStartSequence = 2;
11638
- const kEmulationByte = 3;
11639
- function writeRbsp(data_in) {
11640
- const dataOut = [];
11641
- var numConsecutiveZeros = 0;
11642
- for (var i = 0; i < data_in.length; ++i) {
11643
- var byte = data_in[i];
11644
- if (byte <= kEmulationByte && numConsecutiveZeros >= kZerosInStartSequence) {
11645
- // Need to escape.
11646
- dataOut.push(kEmulationByte);
11647
- numConsecutiveZeros = 0;
11648
- }
11649
- dataOut.push(byte);
11650
- if (byte == 0) {
11651
- ++numConsecutiveZeros;
11652
- } else {
11653
- numConsecutiveZeros = 0;
11654
- }
11655
- }
11656
- return new Uint8Array(dataOut);
11657
- }
11658
- function asEncryptablePacket(packet) {
11659
- var _a, _b, _c, _d, _e;
11660
- if (((_a = packet.value) === null || _a === void 0 ? void 0 : _a.case) !== 'sipDtmf' && ((_b = packet.value) === null || _b === void 0 ? void 0 : _b.case) !== 'metrics' && ((_c = packet.value) === null || _c === void 0 ? void 0 : _c.case) !== 'speaker' && ((_d = packet.value) === null || _d === void 0 ? void 0 : _d.case) !== 'transcription' && ((_e = packet.value) === null || _e === void 0 ? void 0 : _e.case) !== 'encryptedPacket') {
11661
- return new EncryptedPacketPayload({
11662
- value: packet.value
11663
- });
11664
- }
11665
- return undefined;
11666
- }
11667
-
11668
- /**
11669
- * @experimental
11670
- */
11671
- class BaseKeyProvider extends eventsExports.EventEmitter {
11672
- constructor() {
11673
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
11674
- super();
11675
- /**
11676
- * Callback being invoked after a key has been ratcheted.
11677
- * Can happen when:
11678
- * - A decryption failure occurs and the key is auto-ratcheted
11679
- * - A ratchet request is sent (see {@link ratchetKey()})
11680
- * @param ratchetResult Contains the ratcheted chain key (exportable to other participants) and the derived new key material.
11681
- * @param participantId
11682
- * @param keyIndex
11683
- */
11684
- this.onKeyRatcheted = (ratchetResult, participantId, keyIndex) => {
11685
- livekitLogger.debug('key ratcheted event received', {
11686
- ratchetResult,
11687
- participantId,
11688
- keyIndex
11689
- });
11690
- };
11691
- this.keyInfoMap = new Map();
11692
- this.options = Object.assign(Object.assign({}, KEY_PROVIDER_DEFAULTS), options);
11693
- this.on(KeyProviderEvent.KeyRatcheted, this.onKeyRatcheted);
11694
- }
11695
- /**
11696
- * callback to invoke once a key has been set for a participant
11697
- * @param key
11698
- * @param participantIdentity
11699
- * @param keyIndex
11700
- */
11701
- onSetEncryptionKey(key, participantIdentity, keyIndex) {
11702
- const keyInfo = {
11703
- key,
11704
- participantIdentity,
11705
- keyIndex
11706
- };
11707
- if (!this.options.sharedKey && !participantIdentity) {
11708
- throw new Error('participant identity needs to be passed for encryption key if sharedKey option is false');
11709
- }
11710
- this.keyInfoMap.set("".concat(participantIdentity !== null && participantIdentity !== void 0 ? participantIdentity : 'shared', "-").concat(keyIndex !== null && keyIndex !== void 0 ? keyIndex : 0), keyInfo);
11711
- this.emit(KeyProviderEvent.SetKey, keyInfo);
11712
- }
11713
- getKeys() {
11714
- return Array.from(this.keyInfoMap.values());
11715
- }
11716
- getOptions() {
11717
- return this.options;
11718
- }
11719
- ratchetKey(participantIdentity, keyIndex) {
11720
- this.emit(KeyProviderEvent.RatchetRequest, participantIdentity, keyIndex);
11721
- }
11722
- }
11723
- /**
11724
- * A basic KeyProvider implementation intended for a single shared
11725
- * passphrase between all participants
11726
- * @experimental
11727
- */
11728
- class ExternalE2EEKeyProvider extends BaseKeyProvider {
11372
+ class SimulatedError extends LivekitError {
11729
11373
  constructor() {
11730
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
11731
- const opts = Object.assign(Object.assign({}, options), {
11732
- sharedKey: true,
11733
- // for a shared key provider failing to decrypt for a specific participant
11734
- // should not mark the key as invalid, so we accept wrong keys forever
11735
- // and won't try to auto-ratchet
11736
- ratchetWindowSize: 0,
11737
- failureTolerance: -1
11738
- });
11739
- super(opts);
11740
- }
11741
- /**
11742
- * Accepts a passphrase that's used to create the crypto keys.
11743
- * When passing in a string, PBKDF2 is used.
11744
- * When passing in an Array buffer of cryptographically random numbers, HKDF is being used. (recommended)
11745
- * @param key
11746
- */
11747
- setKey(key) {
11748
- return __awaiter(this, void 0, void 0, function* () {
11749
- const derivedKey = typeof key === 'string' ? yield createKeyMaterialFromString(key) : yield createKeyMaterialFromBuffer(key);
11750
- this.onSetEncryptionKey(derivedKey);
11751
- });
11752
- }
11753
- }
11754
-
11755
- class LivekitError extends Error {
11756
- constructor(code, message) {
11757
- super(message || 'an error has occured');
11758
- this.name = 'LiveKitError';
11759
- this.code = code;
11374
+ let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Simulated failure';
11375
+ super(-1, message);
11376
+ this.name = 'simulated';
11760
11377
  }
11761
11378
  }
11762
11379
  var ConnectionErrorReason;
@@ -11767,6 +11384,7 @@ var ConnectionErrorReason;
11767
11384
  ConnectionErrorReason[ConnectionErrorReason["Cancelled"] = 3] = "Cancelled";
11768
11385
  ConnectionErrorReason[ConnectionErrorReason["LeaveRequest"] = 4] = "LeaveRequest";
11769
11386
  ConnectionErrorReason[ConnectionErrorReason["Timeout"] = 5] = "Timeout";
11387
+ ConnectionErrorReason[ConnectionErrorReason["WebSocket"] = 6] = "WebSocket";
11770
11388
  })(ConnectionErrorReason || (ConnectionErrorReason = {}));
11771
11389
  class ConnectionError extends LivekitError {
11772
11390
  constructor(message, reason, status, context) {
@@ -11777,6 +11395,27 @@ class ConnectionError extends LivekitError {
11777
11395
  this.context = context;
11778
11396
  this.reasonName = ConnectionErrorReason[reason];
11779
11397
  }
11398
+ static notAllowed(message, status, context) {
11399
+ return new ConnectionError(message, ConnectionErrorReason.NotAllowed, status, context);
11400
+ }
11401
+ static timeout(message) {
11402
+ return new ConnectionError(message, ConnectionErrorReason.Timeout);
11403
+ }
11404
+ static leaveRequest(message, context) {
11405
+ return new ConnectionError(message, ConnectionErrorReason.LeaveRequest, undefined, context);
11406
+ }
11407
+ static internal(message, context) {
11408
+ return new ConnectionError(message, ConnectionErrorReason.InternalError, undefined, context);
11409
+ }
11410
+ static cancelled(message) {
11411
+ return new ConnectionError(message, ConnectionErrorReason.Cancelled);
11412
+ }
11413
+ static serverUnreachable(message, status) {
11414
+ return new ConnectionError(message, ConnectionErrorReason.ServerUnreachable, status);
11415
+ }
11416
+ static websocket(message, status, reason) {
11417
+ return new ConnectionError(message, ConnectionErrorReason.WebSocket, status, reason);
11418
+ }
11780
11419
  }
11781
11420
  class DeviceUnsupportedError extends LivekitError {
11782
11421
  constructor(message) {
@@ -11824,6 +11463,7 @@ class PublishTrackError extends LivekitError {
11824
11463
  class SignalRequestError extends LivekitError {
11825
11464
  constructor(message, reason) {
11826
11465
  super(15, message);
11466
+ this.name = 'SignalRequestError';
11827
11467
  this.reason = reason;
11828
11468
  this.reasonName = typeof reason === 'string' ? reason : RequestResponse_Reason[reason];
11829
11469
  }
@@ -11854,6 +11494,12 @@ class DataStreamError extends LivekitError {
11854
11494
  this.reasonName = DataStreamErrorReason[reason];
11855
11495
  }
11856
11496
  }
11497
+ class SignalReconnectError extends LivekitError {
11498
+ constructor(message) {
11499
+ super(18, message);
11500
+ this.name = 'SignalReconnectError';
11501
+ }
11502
+ }
11857
11503
  var MediaDeviceFailure;
11858
11504
  (function (MediaDeviceFailure) {
11859
11505
  // user rejected permissions
@@ -11880,25 +11526,26 @@ var MediaDeviceFailure;
11880
11526
  }
11881
11527
  }
11882
11528
  MediaDeviceFailure.getFailure = getFailure;
11883
- })(MediaDeviceFailure || (MediaDeviceFailure = {}));
11884
-
11885
- var CryptorErrorReason;
11886
- (function (CryptorErrorReason) {
11887
- CryptorErrorReason[CryptorErrorReason["InvalidKey"] = 0] = "InvalidKey";
11888
- CryptorErrorReason[CryptorErrorReason["MissingKey"] = 1] = "MissingKey";
11889
- CryptorErrorReason[CryptorErrorReason["InternalError"] = 2] = "InternalError";
11890
- })(CryptorErrorReason || (CryptorErrorReason = {}));
11891
- class CryptorError extends LivekitError {
11892
- constructor(message) {
11893
- let reason = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : CryptorErrorReason.InternalError;
11894
- let participantIdentity = arguments.length > 2 ? arguments[2] : undefined;
11895
- super(40, message);
11896
- this.reason = reason;
11897
- this.participantIdentity = participantIdentity;
11898
- }
11899
- }
11900
-
11901
- /**
11529
+ })(MediaDeviceFailure || (MediaDeviceFailure = {}));/**
11530
+ * Timers that can be overridden with platform specific implementations
11531
+ * that ensure that they are fired. These should be used when it is critical
11532
+ * that the timer fires on time.
11533
+ */
11534
+ class CriticalTimers {}
11535
+ CriticalTimers.setTimeout = function () {
11536
+ return setTimeout(...arguments);
11537
+ };
11538
+ CriticalTimers.setInterval =
11539
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
11540
+ function () {
11541
+ return setInterval(...arguments);
11542
+ };
11543
+ CriticalTimers.clearTimeout = function () {
11544
+ return clearTimeout(...arguments);
11545
+ };
11546
+ CriticalTimers.clearInterval = function () {
11547
+ return clearInterval(...arguments);
11548
+ };/**
11902
11549
  * Events are the primary way LiveKit notifies your application of changes.
11903
11550
  *
11904
11551
  * The following are events emitted by [[Room]], listen to room events like
@@ -12516,9 +12163,7 @@ var TrackEvent;
12516
12163
  * @internal
12517
12164
  */
12518
12165
  TrackEvent["PreConnectBufferFlushed"] = "preConnectBufferFlushed";
12519
- })(TrackEvent || (TrackEvent = {}));
12520
-
12521
- function cloneDeep(value) {
12166
+ })(TrackEvent || (TrackEvent = {}));function cloneDeep(value) {
12522
12167
  if (typeof value === 'undefined') {
12523
12168
  return value;
12524
12169
  }
@@ -12531,103 +12176,443 @@ function cloneDeep(value) {
12531
12176
  } else {
12532
12177
  return JSON.parse(JSON.stringify(value));
12533
12178
  }
12534
- }
12535
-
12536
- // tiny, simplified version of https://github.com/lancedikson/bowser/blob/master/src/parser-browsers.js
12537
- // reduced to only differentiate Chrome(ium) based browsers / Firefox / Safari
12538
- const commonVersionIdentifier = /version\/(\d+(\.?_?\d+)+)/i;
12539
- let browserDetails;
12179
+ }class VideoPreset {
12180
+ constructor(widthOrOptions, height, maxBitrate, maxFramerate, priority) {
12181
+ if (typeof widthOrOptions === 'object') {
12182
+ this.width = widthOrOptions.width;
12183
+ this.height = widthOrOptions.height;
12184
+ this.aspectRatio = widthOrOptions.aspectRatio;
12185
+ this.encoding = {
12186
+ maxBitrate: widthOrOptions.maxBitrate,
12187
+ maxFramerate: widthOrOptions.maxFramerate,
12188
+ priority: widthOrOptions.priority
12189
+ };
12190
+ } else if (height !== undefined && maxBitrate !== undefined) {
12191
+ this.width = widthOrOptions;
12192
+ this.height = height;
12193
+ this.aspectRatio = widthOrOptions / height;
12194
+ this.encoding = {
12195
+ maxBitrate,
12196
+ maxFramerate,
12197
+ priority
12198
+ };
12199
+ } else {
12200
+ throw new TypeError('Unsupported options: provide at least width, height and maxBitrate');
12201
+ }
12202
+ }
12203
+ get resolution() {
12204
+ return {
12205
+ width: this.width,
12206
+ height: this.height,
12207
+ frameRate: this.encoding.maxFramerate,
12208
+ aspectRatio: this.aspectRatio
12209
+ };
12210
+ }
12211
+ }
12212
+ // `red` is not technically a codec, but treated as one in signalling protocol
12213
+ const audioCodecs = ['opus', 'red'];
12214
+ const backupVideoCodecs = ['vp8', 'h264'];
12215
+ const videoCodecs = ['vp8', 'h264', 'vp9', 'av1', 'h265'];
12216
+ function isBackupVideoCodec(codec) {
12217
+ return !!backupVideoCodecs.find(backup => backup === codec);
12218
+ }
12219
+ /** @deprecated Use {@link isBackupVideoCodec} instead */
12220
+ const isBackupCodec = isBackupVideoCodec;
12221
+ var BackupCodecPolicy;
12222
+ (function (BackupCodecPolicy) {
12223
+ // codec regression is preferred, the sfu will try to regress codec if possible but not guaranteed
12224
+ BackupCodecPolicy[BackupCodecPolicy["PREFER_REGRESSION"] = 0] = "PREFER_REGRESSION";
12225
+ // multi-codec simulcast, publish both primary and backup codec at the same time
12226
+ BackupCodecPolicy[BackupCodecPolicy["SIMULCAST"] = 1] = "SIMULCAST";
12227
+ // always use backup codec only
12228
+ BackupCodecPolicy[BackupCodecPolicy["REGRESSION"] = 2] = "REGRESSION";
12229
+ })(BackupCodecPolicy || (BackupCodecPolicy = {}));
12230
+ var AudioPresets;
12231
+ (function (AudioPresets) {
12232
+ AudioPresets.telephone = {
12233
+ maxBitrate: 12000
12234
+ };
12235
+ AudioPresets.speech = {
12236
+ maxBitrate: 24000
12237
+ };
12238
+ AudioPresets.music = {
12239
+ maxBitrate: 48000
12240
+ };
12241
+ AudioPresets.musicStereo = {
12242
+ maxBitrate: 64000
12243
+ };
12244
+ AudioPresets.musicHighQuality = {
12245
+ maxBitrate: 96000
12246
+ };
12247
+ AudioPresets.musicHighQualityStereo = {
12248
+ maxBitrate: 128000
12249
+ };
12250
+ })(AudioPresets || (AudioPresets = {}));
12540
12251
  /**
12541
- * @internal
12252
+ * Sane presets for video resolution/encoding
12542
12253
  */
12543
- function getBrowser(userAgent) {
12544
- let force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
12545
- if (typeof userAgent === 'undefined' && typeof navigator === 'undefined') {
12546
- return;
12254
+ const VideoPresets = {
12255
+ h90: new VideoPreset(160, 90, 90000, 20),
12256
+ h180: new VideoPreset(320, 180, 160000, 20),
12257
+ h216: new VideoPreset(384, 216, 180000, 20),
12258
+ h360: new VideoPreset(640, 360, 450000, 20),
12259
+ h540: new VideoPreset(960, 540, 800000, 25),
12260
+ h720: new VideoPreset(1280, 720, 1700000, 30),
12261
+ h1080: new VideoPreset(1920, 1080, 3000000, 30),
12262
+ h1440: new VideoPreset(2560, 1440, 5000000, 30),
12263
+ h2160: new VideoPreset(3840, 2160, 8000000, 30)
12264
+ };
12265
+ /**
12266
+ * Four by three presets
12267
+ */
12268
+ const VideoPresets43 = {
12269
+ h120: new VideoPreset(160, 120, 70000, 20),
12270
+ h180: new VideoPreset(240, 180, 125000, 20),
12271
+ h240: new VideoPreset(320, 240, 140000, 20),
12272
+ h360: new VideoPreset(480, 360, 330000, 20),
12273
+ h480: new VideoPreset(640, 480, 500000, 20),
12274
+ h540: new VideoPreset(720, 540, 600000, 25),
12275
+ h720: new VideoPreset(960, 720, 1300000, 30),
12276
+ h1080: new VideoPreset(1440, 1080, 2300000, 30),
12277
+ h1440: new VideoPreset(1920, 1440, 3800000, 30)
12278
+ };
12279
+ const ScreenSharePresets = {
12280
+ h360fps3: new VideoPreset(640, 360, 200000, 3, 'medium'),
12281
+ h360fps15: new VideoPreset(640, 360, 400000, 15, 'medium'),
12282
+ h720fps5: new VideoPreset(1280, 720, 800000, 5, 'medium'),
12283
+ h720fps15: new VideoPreset(1280, 720, 1500000, 15, 'medium'),
12284
+ h720fps30: new VideoPreset(1280, 720, 2000000, 30, 'medium'),
12285
+ h1080fps15: new VideoPreset(1920, 1080, 2500000, 15, 'medium'),
12286
+ h1080fps30: new VideoPreset(1920, 1080, 5000000, 30, 'medium'),
12287
+ // original resolution, without resizing
12288
+ original: new VideoPreset(0, 0, 7000000, 30, 'medium')
12289
+ };function mergeDefaultOptions(options, audioDefaults, videoDefaults) {
12290
+ var _a, _b;
12291
+ var _c, _d;
12292
+ const {
12293
+ optionsWithoutProcessor,
12294
+ audioProcessor,
12295
+ videoProcessor
12296
+ } = extractProcessorsFromOptions(options !== null && options !== void 0 ? options : {});
12297
+ const defaultAudioProcessor = audioDefaults === null || audioDefaults === void 0 ? void 0 : audioDefaults.processor;
12298
+ const defaultVideoProcessor = videoDefaults === null || videoDefaults === void 0 ? void 0 : videoDefaults.processor;
12299
+ const clonedOptions = optionsWithoutProcessor !== null && optionsWithoutProcessor !== void 0 ? optionsWithoutProcessor : {};
12300
+ if (clonedOptions.audio === true) clonedOptions.audio = {};
12301
+ if (clonedOptions.video === true) clonedOptions.video = {};
12302
+ // use defaults
12303
+ if (clonedOptions.audio) {
12304
+ mergeObjectWithoutOverwriting(clonedOptions.audio, audioDefaults);
12305
+ (_a = (_c = clonedOptions.audio).deviceId) !== null && _a !== void 0 ? _a : _c.deviceId = {
12306
+ ideal: 'default'
12307
+ };
12308
+ if (audioProcessor || defaultAudioProcessor) {
12309
+ clonedOptions.audio.processor = audioProcessor !== null && audioProcessor !== void 0 ? audioProcessor : defaultAudioProcessor;
12310
+ }
12547
12311
  }
12548
- const ua = (userAgent !== null && userAgent !== void 0 ? userAgent : navigator.userAgent).toLowerCase();
12549
- if (browserDetails === undefined || force) {
12550
- const browser = browsersList.find(_ref => {
12551
- let {
12552
- test
12553
- } = _ref;
12554
- return test.test(ua);
12312
+ if (clonedOptions.video) {
12313
+ mergeObjectWithoutOverwriting(clonedOptions.video, videoDefaults);
12314
+ (_b = (_d = clonedOptions.video).deviceId) !== null && _b !== void 0 ? _b : _d.deviceId = {
12315
+ ideal: 'default'
12316
+ };
12317
+ if (videoProcessor || defaultVideoProcessor) {
12318
+ clonedOptions.video.processor = videoProcessor !== null && videoProcessor !== void 0 ? videoProcessor : defaultVideoProcessor;
12319
+ }
12320
+ }
12321
+ return clonedOptions;
12322
+ }
12323
+ function mergeObjectWithoutOverwriting(mainObject, objectToMerge) {
12324
+ Object.keys(objectToMerge).forEach(key => {
12325
+ if (mainObject[key] === undefined) mainObject[key] = objectToMerge[key];
12326
+ });
12327
+ return mainObject;
12328
+ }
12329
+ function constraintsForOptions(options) {
12330
+ var _a, _b;
12331
+ var _c, _d;
12332
+ const constraints = {};
12333
+ if (options.video) {
12334
+ // default video options
12335
+ if (typeof options.video === 'object') {
12336
+ const videoOptions = {};
12337
+ const target = videoOptions;
12338
+ const source = options.video;
12339
+ Object.keys(source).forEach(key => {
12340
+ switch (key) {
12341
+ case 'resolution':
12342
+ // flatten VideoResolution fields
12343
+ mergeObjectWithoutOverwriting(target, source.resolution);
12344
+ break;
12345
+ default:
12346
+ target[key] = source[key];
12347
+ }
12348
+ });
12349
+ constraints.video = videoOptions;
12350
+ (_a = (_c = constraints.video).deviceId) !== null && _a !== void 0 ? _a : _c.deviceId = {
12351
+ ideal: 'default'
12352
+ };
12353
+ } else {
12354
+ constraints.video = options.video ? {
12355
+ deviceId: {
12356
+ ideal: 'default'
12357
+ }
12358
+ } : false;
12359
+ }
12360
+ } else {
12361
+ constraints.video = false;
12362
+ }
12363
+ if (options.audio) {
12364
+ if (typeof options.audio === 'object') {
12365
+ constraints.audio = options.audio;
12366
+ (_b = (_d = constraints.audio).deviceId) !== null && _b !== void 0 ? _b : _d.deviceId = {
12367
+ ideal: 'default'
12368
+ };
12369
+ } else {
12370
+ constraints.audio = {
12371
+ deviceId: {
12372
+ ideal: 'default'
12373
+ }
12374
+ };
12375
+ }
12376
+ } else {
12377
+ constraints.audio = false;
12378
+ }
12379
+ return constraints;
12380
+ }
12381
+ /**
12382
+ * This function detects silence on a given [[Track]] instance.
12383
+ * Returns true if the track seems to be entirely silent.
12384
+ */
12385
+ function detectSilence(track_1) {
12386
+ return __awaiter(this, arguments, void 0, function (track) {
12387
+ let timeOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;
12388
+ return function* () {
12389
+ const ctx = getNewAudioContext();
12390
+ if (ctx) {
12391
+ const analyser = ctx.createAnalyser();
12392
+ analyser.fftSize = 2048;
12393
+ const bufferLength = analyser.frequencyBinCount;
12394
+ const dataArray = new Uint8Array(bufferLength);
12395
+ const source = ctx.createMediaStreamSource(new MediaStream([track.mediaStreamTrack]));
12396
+ source.connect(analyser);
12397
+ yield sleep(timeOffset);
12398
+ analyser.getByteTimeDomainData(dataArray);
12399
+ const someNoise = dataArray.some(sample => sample !== 128 && sample !== 0);
12400
+ ctx.close();
12401
+ return !someNoise;
12402
+ }
12403
+ return false;
12404
+ }();
12405
+ });
12406
+ }
12407
+ /**
12408
+ * @internal
12409
+ */
12410
+ function getNewAudioContext() {
12411
+ var _a;
12412
+ const AudioContext =
12413
+ // @ts-ignore
12414
+ typeof window !== 'undefined' && (window.AudioContext || window.webkitAudioContext);
12415
+ if (AudioContext) {
12416
+ const audioContext = new AudioContext({
12417
+ latencyHint: 'interactive'
12555
12418
  });
12556
- browserDetails = browser === null || browser === void 0 ? void 0 : browser.describe(ua);
12419
+ // If the audio context is suspended, we need to resume it when the user clicks on the page
12420
+ if (audioContext.state === 'suspended' && typeof window !== 'undefined' && ((_a = window.document) === null || _a === void 0 ? void 0 : _a.body)) {
12421
+ const handleResume = () => __awaiter(this, void 0, void 0, function* () {
12422
+ var _a;
12423
+ try {
12424
+ if (audioContext.state === 'suspended') {
12425
+ yield audioContext.resume();
12426
+ }
12427
+ } catch (e) {
12428
+ console.warn('Error trying to auto-resume audio context', e);
12429
+ } finally {
12430
+ (_a = window.document.body) === null || _a === void 0 ? void 0 : _a.removeEventListener('click', handleResume);
12431
+ }
12432
+ });
12433
+ // https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/statechange_event
12434
+ audioContext.addEventListener('statechange', () => {
12435
+ var _a;
12436
+ if (audioContext.state === 'closed') {
12437
+ (_a = window.document.body) === null || _a === void 0 ? void 0 : _a.removeEventListener('click', handleResume);
12438
+ }
12439
+ });
12440
+ window.document.body.addEventListener('click', handleResume);
12441
+ }
12442
+ return audioContext;
12443
+ }
12444
+ }
12445
+ /**
12446
+ * @internal
12447
+ */
12448
+ function kindToSource(kind) {
12449
+ if (kind === 'audioinput') {
12450
+ return Track.Source.Microphone;
12451
+ } else if (kind === 'videoinput') {
12452
+ return Track.Source.Camera;
12453
+ } else {
12454
+ return Track.Source.Unknown;
12455
+ }
12456
+ }
12457
+ /**
12458
+ * @internal
12459
+ */
12460
+ function sourceToKind(source) {
12461
+ if (source === Track.Source.Microphone) {
12462
+ return 'audioinput';
12463
+ } else if (source === Track.Source.Camera) {
12464
+ return 'videoinput';
12465
+ } else {
12466
+ return undefined;
12467
+ }
12468
+ }
12469
+ /**
12470
+ * @internal
12471
+ */
12472
+ function screenCaptureToDisplayMediaStreamOptions(options) {
12473
+ var _a, _b;
12474
+ let videoConstraints = (_a = options.video) !== null && _a !== void 0 ? _a : true;
12475
+ // treat 0 as uncapped
12476
+ if (options.resolution && options.resolution.width > 0 && options.resolution.height > 0) {
12477
+ videoConstraints = typeof videoConstraints === 'boolean' ? {} : videoConstraints;
12478
+ if (isSafari()) {
12479
+ videoConstraints = Object.assign(Object.assign({}, videoConstraints), {
12480
+ width: {
12481
+ max: options.resolution.width
12482
+ },
12483
+ height: {
12484
+ max: options.resolution.height
12485
+ },
12486
+ frameRate: options.resolution.frameRate
12487
+ });
12488
+ } else {
12489
+ videoConstraints = Object.assign(Object.assign({}, videoConstraints), {
12490
+ width: {
12491
+ ideal: options.resolution.width
12492
+ },
12493
+ height: {
12494
+ ideal: options.resolution.height
12495
+ },
12496
+ frameRate: options.resolution.frameRate
12497
+ });
12498
+ }
12499
+ }
12500
+ return {
12501
+ audio: (_b = options.audio) !== null && _b !== void 0 ? _b : false,
12502
+ video: videoConstraints,
12503
+ // @ts-expect-error support for experimental display media features
12504
+ controller: options.controller,
12505
+ selfBrowserSurface: options.selfBrowserSurface,
12506
+ surfaceSwitching: options.surfaceSwitching,
12507
+ systemAudio: options.systemAudio,
12508
+ preferCurrentTab: options.preferCurrentTab
12509
+ };
12510
+ }
12511
+ function mimeTypeToVideoCodecString(mimeType) {
12512
+ return mimeType.split('/')[1].toLowerCase();
12513
+ }
12514
+ function getTrackPublicationInfo(tracks) {
12515
+ const infos = [];
12516
+ tracks.forEach(track => {
12517
+ if (track.track !== undefined) {
12518
+ infos.push(new TrackPublishedResponse({
12519
+ cid: track.track.mediaStreamID,
12520
+ track: track.trackInfo
12521
+ }));
12522
+ }
12523
+ });
12524
+ return infos;
12525
+ }
12526
+ function getLogContextFromTrack(track) {
12527
+ if ('mediaStreamTrack' in track) {
12528
+ return {
12529
+ trackID: track.sid,
12530
+ source: track.source,
12531
+ muted: track.isMuted,
12532
+ enabled: track.mediaStreamTrack.enabled,
12533
+ kind: track.kind,
12534
+ streamID: track.mediaStreamID,
12535
+ streamTrackID: track.mediaStreamTrack.id
12536
+ };
12537
+ } else {
12538
+ return {
12539
+ trackID: track.trackSid,
12540
+ enabled: track.isEnabled,
12541
+ muted: track.isMuted,
12542
+ trackInfo: Object.assign({
12543
+ mimeType: track.mimeType,
12544
+ name: track.trackName,
12545
+ encrypted: track.isEncrypted,
12546
+ kind: track.kind,
12547
+ source: track.source
12548
+ }, track.track ? getLogContextFromTrack(track.track) : {})
12549
+ };
12550
+ }
12551
+ }
12552
+ function supportsSynchronizationSources() {
12553
+ return typeof RTCRtpReceiver !== 'undefined' && 'getSynchronizationSources' in RTCRtpReceiver;
12554
+ }
12555
+ function diffAttributes(oldValues, newValues) {
12556
+ var _a;
12557
+ if (oldValues === undefined) {
12558
+ oldValues = {};
12559
+ }
12560
+ if (newValues === undefined) {
12561
+ newValues = {};
12562
+ }
12563
+ const allKeys = [...Object.keys(newValues), ...Object.keys(oldValues)];
12564
+ const diff = {};
12565
+ for (const key of allKeys) {
12566
+ if (oldValues[key] !== newValues[key]) {
12567
+ diff[key] = (_a = newValues[key]) !== null && _a !== void 0 ? _a : '';
12568
+ }
12557
12569
  }
12558
- return browserDetails;
12570
+ return diff;
12559
12571
  }
12560
- const browsersList = [{
12561
- test: /firefox|iceweasel|fxios/i,
12562
- describe(ua) {
12563
- const browser = {
12564
- name: 'Firefox',
12565
- version: getMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i, ua),
12566
- os: ua.toLowerCase().includes('fxios') ? 'iOS' : undefined,
12567
- osVersion: getOSVersion(ua)
12568
- };
12569
- return browser;
12572
+ /** @internal */
12573
+ function extractProcessorsFromOptions(options) {
12574
+ const newOptions = Object.assign({}, options);
12575
+ let audioProcessor;
12576
+ let videoProcessor;
12577
+ if (typeof newOptions.audio === 'object' && newOptions.audio.processor) {
12578
+ audioProcessor = newOptions.audio.processor;
12579
+ newOptions.audio = Object.assign(Object.assign({}, newOptions.audio), {
12580
+ processor: undefined
12581
+ });
12570
12582
  }
12571
- }, {
12572
- test: /chrom|crios|crmo/i,
12573
- describe(ua) {
12574
- const browser = {
12575
- name: 'Chrome',
12576
- version: getMatch(/(?:chrome|chromium|crios|crmo)\/(\d+(\.?_?\d+)+)/i, ua),
12577
- os: ua.toLowerCase().includes('crios') ? 'iOS' : undefined,
12578
- osVersion: getOSVersion(ua)
12579
- };
12580
- return browser;
12583
+ if (typeof newOptions.video === 'object' && newOptions.video.processor) {
12584
+ videoProcessor = newOptions.video.processor;
12585
+ newOptions.video = Object.assign(Object.assign({}, newOptions.video), {
12586
+ processor: undefined
12587
+ });
12581
12588
  }
12582
- }, /* Safari */
12583
- {
12584
- test: /safari|applewebkit/i,
12585
- describe(ua) {
12586
- const browser = {
12587
- name: 'Safari',
12588
- version: getMatch(commonVersionIdentifier, ua),
12589
- os: ua.includes('mobile/') ? 'iOS' : 'macOS',
12590
- osVersion: getOSVersion(ua)
12591
- };
12592
- return browser;
12589
+ return {
12590
+ audioProcessor,
12591
+ videoProcessor,
12592
+ optionsWithoutProcessor: cloneDeep(newOptions)
12593
+ };
12594
+ }
12595
+ function getTrackSourceFromProto(source) {
12596
+ switch (source) {
12597
+ case TrackSource.CAMERA:
12598
+ return Track.Source.Camera;
12599
+ case TrackSource.MICROPHONE:
12600
+ return Track.Source.Microphone;
12601
+ case TrackSource.SCREEN_SHARE:
12602
+ return Track.Source.ScreenShare;
12603
+ case TrackSource.SCREEN_SHARE_AUDIO:
12604
+ return Track.Source.ScreenShareAudio;
12605
+ default:
12606
+ return Track.Source.Unknown;
12593
12607
  }
12594
- }];
12595
- function getMatch(exp, ua) {
12596
- let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
12597
- const match = ua.match(exp);
12598
- return match && match.length >= id && match[id] || '';
12599
12608
  }
12600
- function getOSVersion(ua) {
12601
- return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
12609
+ function areDimensionsSmaller(a, b) {
12610
+ return a.width * a.height < b.width * b.height;
12602
12611
  }
12603
-
12604
- var version$1 = "2.16.0";
12605
-
12606
- const version = version$1;
12607
- const protocolVersion = 16;
12608
-
12609
- /**
12610
- * Timers that can be overridden with platform specific implementations
12611
- * that ensure that they are fired. These should be used when it is critical
12612
- * that the timer fires on time.
12613
- */
12614
- class CriticalTimers {}
12615
- CriticalTimers.setTimeout = function () {
12616
- return setTimeout(...arguments);
12617
- };
12618
- CriticalTimers.setInterval =
12619
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
12620
- function () {
12621
- return setInterval(...arguments);
12622
- };
12623
- CriticalTimers.clearTimeout = function () {
12624
- return clearTimeout(...arguments);
12625
- };
12626
- CriticalTimers.clearInterval = function () {
12627
- return clearInterval(...arguments);
12628
- };
12629
-
12630
- const BACKGROUND_REACTION_DELAY = 5000;
12612
+ function layerDimensionsFor(trackInfo, quality) {
12613
+ var _a;
12614
+ return (_a = trackInfo.layers) === null || _a === void 0 ? void 0 : _a.find(l => l.quality === quality);
12615
+ }const BACKGROUND_REACTION_DELAY = 5000;
12631
12616
  // keep old audio elements when detached, we would re-use them since on iOS
12632
12617
  // Safari tracks which audio elements have been "blessed" by the user.
12633
12618
  const recycledElements = [];
@@ -13006,121 +12991,7 @@ function detachTrack(track, element) {
13006
12991
  }
13007
12992
  }
13008
12993
  Track.streamStateFromProto = streamStateFromProto;
13009
- })(Track || (Track = {}));
13010
-
13011
- class VideoPreset {
13012
- constructor(widthOrOptions, height, maxBitrate, maxFramerate, priority) {
13013
- if (typeof widthOrOptions === 'object') {
13014
- this.width = widthOrOptions.width;
13015
- this.height = widthOrOptions.height;
13016
- this.aspectRatio = widthOrOptions.aspectRatio;
13017
- this.encoding = {
13018
- maxBitrate: widthOrOptions.maxBitrate,
13019
- maxFramerate: widthOrOptions.maxFramerate,
13020
- priority: widthOrOptions.priority
13021
- };
13022
- } else if (height !== undefined && maxBitrate !== undefined) {
13023
- this.width = widthOrOptions;
13024
- this.height = height;
13025
- this.aspectRatio = widthOrOptions / height;
13026
- this.encoding = {
13027
- maxBitrate,
13028
- maxFramerate,
13029
- priority
13030
- };
13031
- } else {
13032
- throw new TypeError('Unsupported options: provide at least width, height and maxBitrate');
13033
- }
13034
- }
13035
- get resolution() {
13036
- return {
13037
- width: this.width,
13038
- height: this.height,
13039
- frameRate: this.encoding.maxFramerate,
13040
- aspectRatio: this.aspectRatio
13041
- };
13042
- }
13043
- }
13044
- // `red` is not technically a codec, but treated as one in signalling protocol
13045
- const audioCodecs = ['opus', 'red'];
13046
- const backupVideoCodecs = ['vp8', 'h264'];
13047
- const videoCodecs = ['vp8', 'h264', 'vp9', 'av1', 'h265'];
13048
- function isBackupVideoCodec(codec) {
13049
- return !!backupVideoCodecs.find(backup => backup === codec);
13050
- }
13051
- /** @deprecated Use {@link isBackupVideoCodec} instead */
13052
- const isBackupCodec = isBackupVideoCodec;
13053
- var BackupCodecPolicy;
13054
- (function (BackupCodecPolicy) {
13055
- // codec regression is preferred, the sfu will try to regress codec if possible but not guaranteed
13056
- BackupCodecPolicy[BackupCodecPolicy["PREFER_REGRESSION"] = 0] = "PREFER_REGRESSION";
13057
- // multi-codec simulcast, publish both primary and backup codec at the same time
13058
- BackupCodecPolicy[BackupCodecPolicy["SIMULCAST"] = 1] = "SIMULCAST";
13059
- // always use backup codec only
13060
- BackupCodecPolicy[BackupCodecPolicy["REGRESSION"] = 2] = "REGRESSION";
13061
- })(BackupCodecPolicy || (BackupCodecPolicy = {}));
13062
- var AudioPresets;
13063
- (function (AudioPresets) {
13064
- AudioPresets.telephone = {
13065
- maxBitrate: 12000
13066
- };
13067
- AudioPresets.speech = {
13068
- maxBitrate: 24000
13069
- };
13070
- AudioPresets.music = {
13071
- maxBitrate: 48000
13072
- };
13073
- AudioPresets.musicStereo = {
13074
- maxBitrate: 64000
13075
- };
13076
- AudioPresets.musicHighQuality = {
13077
- maxBitrate: 96000
13078
- };
13079
- AudioPresets.musicHighQualityStereo = {
13080
- maxBitrate: 128000
13081
- };
13082
- })(AudioPresets || (AudioPresets = {}));
13083
- /**
13084
- * Sane presets for video resolution/encoding
13085
- */
13086
- const VideoPresets = {
13087
- h90: new VideoPreset(160, 90, 90000, 20),
13088
- h180: new VideoPreset(320, 180, 160000, 20),
13089
- h216: new VideoPreset(384, 216, 180000, 20),
13090
- h360: new VideoPreset(640, 360, 450000, 20),
13091
- h540: new VideoPreset(960, 540, 800000, 25),
13092
- h720: new VideoPreset(1280, 720, 1700000, 30),
13093
- h1080: new VideoPreset(1920, 1080, 3000000, 30),
13094
- h1440: new VideoPreset(2560, 1440, 5000000, 30),
13095
- h2160: new VideoPreset(3840, 2160, 8000000, 30)
13096
- };
13097
- /**
13098
- * Four by three presets
13099
- */
13100
- const VideoPresets43 = {
13101
- h120: new VideoPreset(160, 120, 70000, 20),
13102
- h180: new VideoPreset(240, 180, 125000, 20),
13103
- h240: new VideoPreset(320, 240, 140000, 20),
13104
- h360: new VideoPreset(480, 360, 330000, 20),
13105
- h480: new VideoPreset(640, 480, 500000, 20),
13106
- h540: new VideoPreset(720, 540, 600000, 25),
13107
- h720: new VideoPreset(960, 720, 1300000, 30),
13108
- h1080: new VideoPreset(1440, 1080, 2300000, 30),
13109
- h1440: new VideoPreset(1920, 1440, 3800000, 30)
13110
- };
13111
- const ScreenSharePresets = {
13112
- h360fps3: new VideoPreset(640, 360, 200000, 3, 'medium'),
13113
- h360fps15: new VideoPreset(640, 360, 400000, 15, 'medium'),
13114
- h720fps5: new VideoPreset(1280, 720, 800000, 5, 'medium'),
13115
- h720fps15: new VideoPreset(1280, 720, 1500000, 15, 'medium'),
13116
- h720fps30: new VideoPreset(1280, 720, 2000000, 30, 'medium'),
13117
- h1080fps15: new VideoPreset(1920, 1080, 2500000, 15, 'medium'),
13118
- h1080fps30: new VideoPreset(1920, 1080, 5000000, 30, 'medium'),
13119
- // original resolution, without resizing
13120
- original: new VideoPreset(0, 0, 7000000, 30, 'medium')
13121
- };
13122
-
13123
- const separator = '|';
12994
+ })(Track || (Track = {}));const separator = '|';
13124
12995
  const ddExtensionURI = 'https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension';
13125
12996
  function unpackStreamId(packed) {
13126
12997
  const parts = packed.split(separator);
@@ -13669,345 +13540,346 @@ function splitUtf8(s, n) {
13669
13540
  }
13670
13541
  function extractMaxAgeFromRequestHeaders(headers) {
13671
13542
  var _a;
13672
- const cacheControl = headers.get('Cache-Control');
13673
- if (cacheControl) {
13674
- const maxAge = (_a = cacheControl.match(/(?:^|[,\s])max-age=(\d+)/)) === null || _a === void 0 ? void 0 : _a[1];
13675
- if (maxAge) {
13676
- return parseInt(maxAge, 10);
13677
- }
13678
- }
13679
- return undefined;
13680
- }
13681
-
13682
- function mergeDefaultOptions(options, audioDefaults, videoDefaults) {
13683
- var _a, _b;
13684
- var _c, _d;
13685
- const {
13686
- optionsWithoutProcessor,
13687
- audioProcessor,
13688
- videoProcessor
13689
- } = extractProcessorsFromOptions(options !== null && options !== void 0 ? options : {});
13690
- const defaultAudioProcessor = audioDefaults === null || audioDefaults === void 0 ? void 0 : audioDefaults.processor;
13691
- const defaultVideoProcessor = videoDefaults === null || videoDefaults === void 0 ? void 0 : videoDefaults.processor;
13692
- const clonedOptions = optionsWithoutProcessor !== null && optionsWithoutProcessor !== void 0 ? optionsWithoutProcessor : {};
13693
- if (clonedOptions.audio === true) clonedOptions.audio = {};
13694
- if (clonedOptions.video === true) clonedOptions.video = {};
13695
- // use defaults
13696
- if (clonedOptions.audio) {
13697
- mergeObjectWithoutOverwriting(clonedOptions.audio, audioDefaults);
13698
- (_a = (_c = clonedOptions.audio).deviceId) !== null && _a !== void 0 ? _a : _c.deviceId = {
13699
- ideal: 'default'
13700
- };
13701
- if (audioProcessor || defaultAudioProcessor) {
13702
- clonedOptions.audio.processor = audioProcessor !== null && audioProcessor !== void 0 ? audioProcessor : defaultAudioProcessor;
13703
- }
13704
- }
13705
- if (clonedOptions.video) {
13706
- mergeObjectWithoutOverwriting(clonedOptions.video, videoDefaults);
13707
- (_b = (_d = clonedOptions.video).deviceId) !== null && _b !== void 0 ? _b : _d.deviceId = {
13708
- ideal: 'default'
13709
- };
13710
- if (videoProcessor || defaultVideoProcessor) {
13711
- clonedOptions.video.processor = videoProcessor !== null && videoProcessor !== void 0 ? videoProcessor : defaultVideoProcessor;
13543
+ const cacheControl = headers.get('Cache-Control');
13544
+ if (cacheControl) {
13545
+ const maxAge = (_a = cacheControl.match(/(?:^|[,\s])max-age=(\d+)/)) === null || _a === void 0 ? void 0 : _a[1];
13546
+ if (maxAge) {
13547
+ return parseInt(maxAge, 10);
13712
13548
  }
13713
13549
  }
13714
- return clonedOptions;
13715
- }
13716
- function mergeObjectWithoutOverwriting(mainObject, objectToMerge) {
13717
- Object.keys(objectToMerge).forEach(key => {
13718
- if (mainObject[key] === undefined) mainObject[key] = objectToMerge[key];
13550
+ return undefined;
13551
+ }function createRtcUrl(url, searchParams) {
13552
+ const urlObj = new URL(toWebsocketUrl(url));
13553
+ searchParams.forEach((value, key) => {
13554
+ urlObj.searchParams.set(key, value);
13719
13555
  });
13720
- return mainObject;
13556
+ return appendUrlPath(urlObj, 'rtc');
13721
13557
  }
13722
- function constraintsForOptions(options) {
13723
- var _a, _b;
13724
- var _c, _d;
13725
- const constraints = {};
13726
- if (options.video) {
13727
- // default video options
13728
- if (typeof options.video === 'object') {
13729
- const videoOptions = {};
13730
- const target = videoOptions;
13731
- const source = options.video;
13732
- Object.keys(source).forEach(key => {
13733
- switch (key) {
13734
- case 'resolution':
13735
- // flatten VideoResolution fields
13736
- mergeObjectWithoutOverwriting(target, source.resolution);
13737
- break;
13738
- default:
13739
- target[key] = source[key];
13740
- }
13741
- });
13742
- constraints.video = videoOptions;
13743
- (_a = (_c = constraints.video).deviceId) !== null && _a !== void 0 ? _a : _c.deviceId = {
13744
- ideal: 'default'
13745
- };
13746
- } else {
13747
- constraints.video = options.video ? {
13748
- deviceId: {
13749
- ideal: 'default'
13750
- }
13751
- } : false;
13752
- }
13753
- } else {
13754
- constraints.video = false;
13558
+ function createValidateUrl(rtcWsUrl) {
13559
+ const urlObj = new URL(toHttpUrl(rtcWsUrl));
13560
+ return appendUrlPath(urlObj, 'validate');
13561
+ }
13562
+ function ensureTrailingSlash(path) {
13563
+ return path.endsWith('/') ? path : "".concat(path, "/");
13564
+ }
13565
+ function appendUrlPath(urlObj, path) {
13566
+ urlObj.pathname = "".concat(ensureTrailingSlash(urlObj.pathname)).concat(path);
13567
+ return urlObj.toString();
13568
+ }
13569
+ function parseSignalResponse(value) {
13570
+ if (typeof value === 'string') {
13571
+ return SignalResponse.fromJson(JSON.parse(value), {
13572
+ ignoreUnknownFields: true
13573
+ });
13574
+ } else if (value instanceof ArrayBuffer) {
13575
+ return SignalResponse.fromBinary(new Uint8Array(value));
13755
13576
  }
13756
- if (options.audio) {
13757
- if (typeof options.audio === 'object') {
13758
- constraints.audio = options.audio;
13759
- (_b = (_d = constraints.audio).deviceId) !== null && _b !== void 0 ? _b : _d.deviceId = {
13760
- ideal: 'default'
13761
- };
13762
- } else {
13763
- constraints.audio = {
13764
- deviceId: {
13765
- ideal: 'default'
13766
- }
13767
- };
13768
- }
13769
- } else {
13770
- constraints.audio = false;
13577
+ throw new Error("could not decode websocket message: ".concat(typeof value));
13578
+ }
13579
+ function getAbortReasonAsString(signal) {
13580
+ let defaultMessage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Unknown reason';
13581
+ if (!(signal instanceof AbortSignal)) {
13582
+ return defaultMessage;
13771
13583
  }
13772
- return constraints;
13584
+ const reason = signal.reason;
13585
+ switch (typeof reason) {
13586
+ case 'string':
13587
+ return reason;
13588
+ case 'object':
13589
+ return reason instanceof Error ? reason.message : defaultMessage;
13590
+ default:
13591
+ return 'toString' in reason ? reason.toString() : defaultMessage;
13592
+ }
13593
+ }const ENCRYPTION_ALGORITHM = 'AES-GCM';
13594
+ // How many consecutive frames can fail decrypting before a particular key gets marked as invalid
13595
+ const DECRYPTION_FAILURE_TOLERANCE = 10;
13596
+ // flag set to indicate that e2ee has been setup for sender/receiver;
13597
+ const E2EE_FLAG = 'lk_e2ee';
13598
+ const SALT = 'LKFrameEncryptionKey';
13599
+ const KEY_PROVIDER_DEFAULTS = {
13600
+ sharedKey: false,
13601
+ ratchetSalt: SALT,
13602
+ ratchetWindowSize: 8,
13603
+ failureTolerance: DECRYPTION_FAILURE_TOLERANCE,
13604
+ keyringSize: 16
13605
+ };var KeyProviderEvent;
13606
+ (function (KeyProviderEvent) {
13607
+ KeyProviderEvent["SetKey"] = "setKey";
13608
+ /** Event for requesting to ratchet the key used to encrypt the stream */
13609
+ KeyProviderEvent["RatchetRequest"] = "ratchetRequest";
13610
+ /** Emitted when a key is ratcheted. Could be after auto-ratcheting on decryption failure or
13611
+ * following a `RatchetRequest`, will contain the ratcheted key material */
13612
+ KeyProviderEvent["KeyRatcheted"] = "keyRatcheted";
13613
+ })(KeyProviderEvent || (KeyProviderEvent = {}));
13614
+ var KeyHandlerEvent;
13615
+ (function (KeyHandlerEvent) {
13616
+ /** Emitted when a key has been ratcheted. Is emitted when any key has been ratcheted
13617
+ * i.e. when the FrameCryptor tried to ratchet when decryption is failing */
13618
+ KeyHandlerEvent["KeyRatcheted"] = "keyRatcheted";
13619
+ })(KeyHandlerEvent || (KeyHandlerEvent = {}));
13620
+ var EncryptionEvent;
13621
+ (function (EncryptionEvent) {
13622
+ EncryptionEvent["ParticipantEncryptionStatusChanged"] = "participantEncryptionStatusChanged";
13623
+ EncryptionEvent["EncryptionError"] = "encryptionError";
13624
+ })(EncryptionEvent || (EncryptionEvent = {}));
13625
+ var CryptorEvent;
13626
+ (function (CryptorEvent) {
13627
+ CryptorEvent["Error"] = "cryptorError";
13628
+ })(CryptorEvent || (CryptorEvent = {}));function isE2EESupported() {
13629
+ return isInsertableStreamSupported() || isScriptTransformSupported();
13773
13630
  }
13774
- /**
13775
- * This function detects silence on a given [[Track]] instance.
13776
- * Returns true if the track seems to be entirely silent.
13777
- */
13778
- function detectSilence(track_1) {
13779
- return __awaiter(this, arguments, void 0, function (track) {
13780
- let timeOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;
13631
+ function isScriptTransformSupported() {
13632
+ // @ts-ignore
13633
+ return typeof window.RTCRtpScriptTransform !== 'undefined';
13634
+ }
13635
+ function isInsertableStreamSupported() {
13636
+ return typeof window.RTCRtpSender !== 'undefined' &&
13637
+ // @ts-ignore
13638
+ typeof window.RTCRtpSender.prototype.createEncodedStreams !== 'undefined';
13639
+ }
13640
+ function isVideoFrame(frame) {
13641
+ return 'type' in frame;
13642
+ }
13643
+ function importKey(keyBytes_1) {
13644
+ return __awaiter(this, arguments, void 0, function (keyBytes) {
13645
+ let algorithm = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
13646
+ name: ENCRYPTION_ALGORITHM
13647
+ };
13648
+ let usage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'encrypt';
13781
13649
  return function* () {
13782
- const ctx = getNewAudioContext();
13783
- if (ctx) {
13784
- const analyser = ctx.createAnalyser();
13785
- analyser.fftSize = 2048;
13786
- const bufferLength = analyser.frequencyBinCount;
13787
- const dataArray = new Uint8Array(bufferLength);
13788
- const source = ctx.createMediaStreamSource(new MediaStream([track.mediaStreamTrack]));
13789
- source.connect(analyser);
13790
- yield sleep(timeOffset);
13791
- analyser.getByteTimeDomainData(dataArray);
13792
- const someNoise = dataArray.some(sample => sample !== 128 && sample !== 0);
13793
- ctx.close();
13794
- return !someNoise;
13795
- }
13796
- return false;
13650
+ // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey
13651
+ return crypto.subtle.importKey('raw', keyBytes, algorithm, false, usage === 'derive' ? ['deriveBits', 'deriveKey'] : ['encrypt', 'decrypt']);
13797
13652
  }();
13798
13653
  });
13799
13654
  }
13800
- /**
13801
- * @internal
13802
- */
13803
- function getNewAudioContext() {
13804
- var _a;
13805
- const AudioContext =
13806
- // @ts-ignore
13807
- typeof window !== 'undefined' && (window.AudioContext || window.webkitAudioContext);
13808
- if (AudioContext) {
13809
- const audioContext = new AudioContext({
13810
- latencyHint: 'interactive'
13811
- });
13812
- // If the audio context is suspended, we need to resume it when the user clicks on the page
13813
- if (audioContext.state === 'suspended' && typeof window !== 'undefined' && ((_a = window.document) === null || _a === void 0 ? void 0 : _a.body)) {
13814
- const handleResume = () => __awaiter(this, void 0, void 0, function* () {
13815
- var _a;
13816
- try {
13817
- if (audioContext.state === 'suspended') {
13818
- yield audioContext.resume();
13819
- }
13820
- } catch (e) {
13821
- console.warn('Error trying to auto-resume audio context', e);
13822
- } finally {
13823
- (_a = window.document.body) === null || _a === void 0 ? void 0 : _a.removeEventListener('click', handleResume);
13824
- }
13825
- });
13826
- // https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/statechange_event
13827
- audioContext.addEventListener('statechange', () => {
13828
- var _a;
13829
- if (audioContext.state === 'closed') {
13830
- (_a = window.document.body) === null || _a === void 0 ? void 0 : _a.removeEventListener('click', handleResume);
13831
- }
13832
- });
13833
- window.document.body.addEventListener('click', handleResume);
13834
- }
13835
- return audioContext;
13836
- }
13655
+ function createKeyMaterialFromString(password) {
13656
+ return __awaiter(this, void 0, void 0, function* () {
13657
+ let enc = new TextEncoder();
13658
+ const keyMaterial = yield crypto.subtle.importKey('raw', enc.encode(password), {
13659
+ name: 'PBKDF2'
13660
+ }, false, ['deriveBits', 'deriveKey']);
13661
+ return keyMaterial;
13662
+ });
13837
13663
  }
13838
- /**
13839
- * @internal
13840
- */
13841
- function kindToSource(kind) {
13842
- if (kind === 'audioinput') {
13843
- return Track.Source.Microphone;
13844
- } else if (kind === 'videoinput') {
13845
- return Track.Source.Camera;
13846
- } else {
13847
- return Track.Source.Unknown;
13664
+ function createKeyMaterialFromBuffer(cryptoBuffer) {
13665
+ return __awaiter(this, void 0, void 0, function* () {
13666
+ const keyMaterial = yield crypto.subtle.importKey('raw', cryptoBuffer, 'HKDF', false, ['deriveBits', 'deriveKey']);
13667
+ return keyMaterial;
13668
+ });
13669
+ }
13670
+ function getAlgoOptions(algorithmName, salt) {
13671
+ const textEncoder = new TextEncoder();
13672
+ const encodedSalt = textEncoder.encode(salt);
13673
+ switch (algorithmName) {
13674
+ case 'HKDF':
13675
+ return {
13676
+ name: 'HKDF',
13677
+ salt: encodedSalt,
13678
+ hash: 'SHA-256',
13679
+ info: new ArrayBuffer(128)
13680
+ };
13681
+ case 'PBKDF2':
13682
+ {
13683
+ return {
13684
+ name: 'PBKDF2',
13685
+ salt: encodedSalt,
13686
+ hash: 'SHA-256',
13687
+ iterations: 100000
13688
+ };
13689
+ }
13690
+ default:
13691
+ throw new Error("algorithm ".concat(algorithmName, " is currently unsupported"));
13848
13692
  }
13849
13693
  }
13850
13694
  /**
13851
- * @internal
13695
+ * Derives a set of keys from the master key.
13696
+ * See https://tools.ietf.org/html/draft-omara-sframe-00#section-4.3.1
13852
13697
  */
13853
- function sourceToKind(source) {
13854
- if (source === Track.Source.Microphone) {
13855
- return 'audioinput';
13856
- } else if (source === Track.Source.Camera) {
13857
- return 'videoinput';
13858
- } else {
13859
- return undefined;
13860
- }
13698
+ function deriveKeys(material, salt) {
13699
+ return __awaiter(this, void 0, void 0, function* () {
13700
+ const algorithmOptions = getAlgoOptions(material.algorithm.name, salt);
13701
+ // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveKey#HKDF
13702
+ // https://developer.mozilla.org/en-US/docs/Web/API/HkdfParams
13703
+ const encryptionKey = yield crypto.subtle.deriveKey(algorithmOptions, material, {
13704
+ name: ENCRYPTION_ALGORITHM,
13705
+ length: 128
13706
+ }, false, ['encrypt', 'decrypt']);
13707
+ return {
13708
+ material,
13709
+ encryptionKey
13710
+ };
13711
+ });
13712
+ }
13713
+ function createE2EEKey() {
13714
+ return window.crypto.getRandomValues(new Uint8Array(32));
13861
13715
  }
13862
13716
  /**
13863
- * @internal
13717
+ * Ratchets a key. See
13718
+ * https://tools.ietf.org/html/draft-omara-sframe-00#section-4.3.5.1
13864
13719
  */
13865
- function screenCaptureToDisplayMediaStreamOptions(options) {
13866
- var _a, _b;
13867
- let videoConstraints = (_a = options.video) !== null && _a !== void 0 ? _a : true;
13868
- // treat 0 as uncapped
13869
- if (options.resolution && options.resolution.width > 0 && options.resolution.height > 0) {
13870
- videoConstraints = typeof videoConstraints === 'boolean' ? {} : videoConstraints;
13871
- if (isSafari()) {
13872
- videoConstraints = Object.assign(Object.assign({}, videoConstraints), {
13873
- width: {
13874
- max: options.resolution.width
13875
- },
13876
- height: {
13877
- max: options.resolution.height
13878
- },
13879
- frameRate: options.resolution.frameRate
13880
- });
13720
+ function ratchet(material, salt) {
13721
+ return __awaiter(this, void 0, void 0, function* () {
13722
+ const algorithmOptions = getAlgoOptions(material.algorithm.name, salt);
13723
+ // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/deriveBits
13724
+ return crypto.subtle.deriveBits(algorithmOptions, material, 256);
13725
+ });
13726
+ }
13727
+ function needsRbspUnescaping(frameData) {
13728
+ for (var i = 0; i < frameData.length - 3; i++) {
13729
+ if (frameData[i] == 0 && frameData[i + 1] == 0 && frameData[i + 2] == 3) return true;
13730
+ }
13731
+ return false;
13732
+ }
13733
+ function parseRbsp(stream) {
13734
+ const dataOut = [];
13735
+ var length = stream.length;
13736
+ for (var i = 0; i < stream.length;) {
13737
+ // Be careful about over/underflow here. byte_length_ - 3 can underflow, and
13738
+ // i + 3 can overflow, but byte_length_ - i can't, because i < byte_length_
13739
+ // above, and that expression will produce the number of bytes left in
13740
+ // the stream including the byte at i.
13741
+ if (length - i >= 3 && !stream[i] && !stream[i + 1] && stream[i + 2] == 3) {
13742
+ // Two rbsp bytes.
13743
+ dataOut.push(stream[i++]);
13744
+ dataOut.push(stream[i++]);
13745
+ // Skip the emulation byte.
13746
+ i++;
13881
13747
  } else {
13882
- videoConstraints = Object.assign(Object.assign({}, videoConstraints), {
13883
- width: {
13884
- ideal: options.resolution.width
13885
- },
13886
- height: {
13887
- ideal: options.resolution.height
13888
- },
13889
- frameRate: options.resolution.frameRate
13890
- });
13748
+ // Single rbsp byte.
13749
+ dataOut.push(stream[i++]);
13891
13750
  }
13892
13751
  }
13893
- return {
13894
- audio: (_b = options.audio) !== null && _b !== void 0 ? _b : false,
13895
- video: videoConstraints,
13896
- // @ts-expect-error support for experimental display media features
13897
- controller: options.controller,
13898
- selfBrowserSurface: options.selfBrowserSurface,
13899
- surfaceSwitching: options.surfaceSwitching,
13900
- systemAudio: options.systemAudio,
13901
- preferCurrentTab: options.preferCurrentTab
13902
- };
13903
- }
13904
- function mimeTypeToVideoCodecString(mimeType) {
13905
- return mimeType.split('/')[1].toLowerCase();
13752
+ return new Uint8Array(dataOut);
13906
13753
  }
13907
- function getTrackPublicationInfo(tracks) {
13908
- const infos = [];
13909
- tracks.forEach(track => {
13910
- if (track.track !== undefined) {
13911
- infos.push(new TrackPublishedResponse({
13912
- cid: track.track.mediaStreamID,
13913
- track: track.trackInfo
13914
- }));
13754
+ const kZerosInStartSequence = 2;
13755
+ const kEmulationByte = 3;
13756
+ function writeRbsp(data_in) {
13757
+ const dataOut = [];
13758
+ var numConsecutiveZeros = 0;
13759
+ for (var i = 0; i < data_in.length; ++i) {
13760
+ var byte = data_in[i];
13761
+ if (byte <= kEmulationByte && numConsecutiveZeros >= kZerosInStartSequence) {
13762
+ // Need to escape.
13763
+ dataOut.push(kEmulationByte);
13764
+ numConsecutiveZeros = 0;
13915
13765
  }
13916
- });
13917
- return infos;
13766
+ dataOut.push(byte);
13767
+ if (byte == 0) {
13768
+ ++numConsecutiveZeros;
13769
+ } else {
13770
+ numConsecutiveZeros = 0;
13771
+ }
13772
+ }
13773
+ return new Uint8Array(dataOut);
13918
13774
  }
13919
- function getLogContextFromTrack(track) {
13920
- if ('mediaStreamTrack' in track) {
13921
- return {
13922
- trackID: track.sid,
13923
- source: track.source,
13924
- muted: track.isMuted,
13925
- enabled: track.mediaStreamTrack.enabled,
13926
- kind: track.kind,
13927
- streamID: track.mediaStreamID,
13928
- streamTrackID: track.mediaStreamTrack.id
13775
+ function asEncryptablePacket(packet) {
13776
+ var _a, _b, _c, _d, _e;
13777
+ if (((_a = packet.value) === null || _a === void 0 ? void 0 : _a.case) !== 'sipDtmf' && ((_b = packet.value) === null || _b === void 0 ? void 0 : _b.case) !== 'metrics' && ((_c = packet.value) === null || _c === void 0 ? void 0 : _c.case) !== 'speaker' && ((_d = packet.value) === null || _d === void 0 ? void 0 : _d.case) !== 'transcription' && ((_e = packet.value) === null || _e === void 0 ? void 0 : _e.case) !== 'encryptedPacket') {
13778
+ return new EncryptedPacketPayload({
13779
+ value: packet.value
13780
+ });
13781
+ }
13782
+ return undefined;
13783
+ }/**
13784
+ * @experimental
13785
+ */
13786
+ class BaseKeyProvider extends eventsExports.EventEmitter {
13787
+ constructor() {
13788
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
13789
+ super();
13790
+ /**
13791
+ * Callback being invoked after a key has been ratcheted.
13792
+ * Can happen when:
13793
+ * - A decryption failure occurs and the key is auto-ratcheted
13794
+ * - A ratchet request is sent (see {@link ratchetKey()})
13795
+ * @param ratchetResult Contains the ratcheted chain key (exportable to other participants) and the derived new key material.
13796
+ * @param participantId
13797
+ * @param keyIndex
13798
+ */
13799
+ this.onKeyRatcheted = (ratchetResult, participantId, keyIndex) => {
13800
+ livekitLogger.debug('key ratcheted event received', {
13801
+ ratchetResult,
13802
+ participantId,
13803
+ keyIndex
13804
+ });
13929
13805
  };
13930
- } else {
13931
- return {
13932
- trackID: track.trackSid,
13933
- enabled: track.isEnabled,
13934
- muted: track.isMuted,
13935
- trackInfo: Object.assign({
13936
- mimeType: track.mimeType,
13937
- name: track.trackName,
13938
- encrypted: track.isEncrypted,
13939
- kind: track.kind,
13940
- source: track.source
13941
- }, track.track ? getLogContextFromTrack(track.track) : {})
13806
+ this.keyInfoMap = new Map();
13807
+ this.options = Object.assign(Object.assign({}, KEY_PROVIDER_DEFAULTS), options);
13808
+ this.on(KeyProviderEvent.KeyRatcheted, this.onKeyRatcheted);
13809
+ }
13810
+ /**
13811
+ * callback to invoke once a key has been set for a participant
13812
+ * @param key
13813
+ * @param participantIdentity
13814
+ * @param keyIndex
13815
+ */
13816
+ onSetEncryptionKey(key, participantIdentity, keyIndex) {
13817
+ const keyInfo = {
13818
+ key,
13819
+ participantIdentity,
13820
+ keyIndex
13942
13821
  };
13822
+ if (!this.options.sharedKey && !participantIdentity) {
13823
+ throw new Error('participant identity needs to be passed for encryption key if sharedKey option is false');
13824
+ }
13825
+ this.keyInfoMap.set("".concat(participantIdentity !== null && participantIdentity !== void 0 ? participantIdentity : 'shared', "-").concat(keyIndex !== null && keyIndex !== void 0 ? keyIndex : 0), keyInfo);
13826
+ this.emit(KeyProviderEvent.SetKey, keyInfo);
13943
13827
  }
13944
- }
13945
- function supportsSynchronizationSources() {
13946
- return typeof RTCRtpReceiver !== 'undefined' && 'getSynchronizationSources' in RTCRtpReceiver;
13947
- }
13948
- function diffAttributes(oldValues, newValues) {
13949
- var _a;
13950
- if (oldValues === undefined) {
13951
- oldValues = {};
13828
+ getKeys() {
13829
+ return Array.from(this.keyInfoMap.values());
13952
13830
  }
13953
- if (newValues === undefined) {
13954
- newValues = {};
13831
+ getOptions() {
13832
+ return this.options;
13955
13833
  }
13956
- const allKeys = [...Object.keys(newValues), ...Object.keys(oldValues)];
13957
- const diff = {};
13958
- for (const key of allKeys) {
13959
- if (oldValues[key] !== newValues[key]) {
13960
- diff[key] = (_a = newValues[key]) !== null && _a !== void 0 ? _a : '';
13961
- }
13834
+ ratchetKey(participantIdentity, keyIndex) {
13835
+ this.emit(KeyProviderEvent.RatchetRequest, participantIdentity, keyIndex);
13962
13836
  }
13963
- return diff;
13964
13837
  }
13965
- /** @internal */
13966
- function extractProcessorsFromOptions(options) {
13967
- const newOptions = Object.assign({}, options);
13968
- let audioProcessor;
13969
- let videoProcessor;
13970
- if (typeof newOptions.audio === 'object' && newOptions.audio.processor) {
13971
- audioProcessor = newOptions.audio.processor;
13972
- newOptions.audio = Object.assign(Object.assign({}, newOptions.audio), {
13973
- processor: undefined
13838
+ /**
13839
+ * A basic KeyProvider implementation intended for a single shared
13840
+ * passphrase between all participants
13841
+ * @experimental
13842
+ */
13843
+ class ExternalE2EEKeyProvider extends BaseKeyProvider {
13844
+ constructor() {
13845
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
13846
+ const opts = Object.assign(Object.assign({}, options), {
13847
+ sharedKey: true,
13848
+ // for a shared key provider failing to decrypt for a specific participant
13849
+ // should not mark the key as invalid, so we accept wrong keys forever
13850
+ // and won't try to auto-ratchet
13851
+ ratchetWindowSize: 0,
13852
+ failureTolerance: -1
13974
13853
  });
13854
+ super(opts);
13975
13855
  }
13976
- if (typeof newOptions.video === 'object' && newOptions.video.processor) {
13977
- videoProcessor = newOptions.video.processor;
13978
- newOptions.video = Object.assign(Object.assign({}, newOptions.video), {
13979
- processor: undefined
13856
+ /**
13857
+ * Accepts a passphrase that's used to create the crypto keys.
13858
+ * When passing in a string, PBKDF2 is used.
13859
+ * When passing in an Array buffer of cryptographically random numbers, HKDF is being used. (recommended)
13860
+ * @param key
13861
+ */
13862
+ setKey(key) {
13863
+ return __awaiter(this, void 0, void 0, function* () {
13864
+ const derivedKey = typeof key === 'string' ? yield createKeyMaterialFromString(key) : yield createKeyMaterialFromBuffer(key);
13865
+ this.onSetEncryptionKey(derivedKey);
13980
13866
  });
13981
13867
  }
13982
- return {
13983
- audioProcessor,
13984
- videoProcessor,
13985
- optionsWithoutProcessor: cloneDeep(newOptions)
13986
- };
13987
- }
13988
- function getTrackSourceFromProto(source) {
13989
- switch (source) {
13990
- case TrackSource.CAMERA:
13991
- return Track.Source.Camera;
13992
- case TrackSource.MICROPHONE:
13993
- return Track.Source.Microphone;
13994
- case TrackSource.SCREEN_SHARE:
13995
- return Track.Source.ScreenShare;
13996
- case TrackSource.SCREEN_SHARE_AUDIO:
13997
- return Track.Source.ScreenShareAudio;
13998
- default:
13999
- return Track.Source.Unknown;
13868
+ }var CryptorErrorReason;
13869
+ (function (CryptorErrorReason) {
13870
+ CryptorErrorReason[CryptorErrorReason["InvalidKey"] = 0] = "InvalidKey";
13871
+ CryptorErrorReason[CryptorErrorReason["MissingKey"] = 1] = "MissingKey";
13872
+ CryptorErrorReason[CryptorErrorReason["InternalError"] = 2] = "InternalError";
13873
+ })(CryptorErrorReason || (CryptorErrorReason = {}));
13874
+ class CryptorError extends LivekitError {
13875
+ constructor(message) {
13876
+ let reason = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : CryptorErrorReason.InternalError;
13877
+ let participantIdentity = arguments.length > 2 ? arguments[2] : undefined;
13878
+ super(40, message);
13879
+ this.reason = reason;
13880
+ this.participantIdentity = participantIdentity;
14000
13881
  }
14001
- }
14002
- function areDimensionsSmaller(a, b) {
14003
- return a.width * a.height < b.width * b.height;
14004
- }
14005
- function layerDimensionsFor(trackInfo, quality) {
14006
- var _a;
14007
- return (_a = trackInfo.layers) === null || _a === void 0 ? void 0 : _a.find(l => l.quality === quality);
14008
- }
14009
-
14010
- /**
13882
+ }/**
14011
13883
  * @experimental
14012
13884
  */
14013
13885
  class E2EEManager extends eventsExports.EventEmitter {
@@ -14453,9 +14325,7 @@ class E2EEManager extends eventsExports.EventEmitter {
14453
14325
  // @ts-ignore
14454
14326
  sender[E2EE_FLAG] = true;
14455
14327
  }
14456
- }
14457
-
14458
- const CONNECTION_BACKOFF_MIN_MS = 500;
14328
+ }const CONNECTION_BACKOFF_MIN_MS = 500;
14459
14329
  const CONNECTION_BACKOFF_MAX_MS = 15000;
14460
14330
  /**
14461
14331
  * BackOffStrategy implements exponential backoff for connection failures.
@@ -14514,9 +14384,7 @@ class BackOffStrategy {
14514
14384
  this.failedConnectionAttempts.clear();
14515
14385
  }
14516
14386
  }
14517
- BackOffStrategy._instance = null;
14518
-
14519
- const defaultId = 'default';
14387
+ BackOffStrategy._instance = null;const defaultId = 'default';
14520
14388
  class DeviceManager {
14521
14389
  constructor() {
14522
14390
  this._previousDevices = [];
@@ -14607,9 +14475,7 @@ class DeviceManager {
14607
14475
  }
14608
14476
  }
14609
14477
  DeviceManager.mediaDeviceKinds = ['audioinput', 'audiooutput', 'videoinput'];
14610
- DeviceManager.userMediaPromiseMap = new Map();
14611
-
14612
- var QueueTaskStatus;
14478
+ DeviceManager.userMediaPromiseMap = new Map();var QueueTaskStatus;
14613
14479
  (function (QueueTaskStatus) {
14614
14480
  QueueTaskStatus[QueueTaskStatus["WAITING"] = 0] = "WAITING";
14615
14481
  QueueTaskStatus[QueueTaskStatus["RUNNING"] = 1] = "RUNNING";
@@ -14649,9 +14515,7 @@ class AsyncQueue {
14649
14515
  snapshot() {
14650
14516
  return Array.from(this.pendingTasks.values());
14651
14517
  }
14652
- }
14653
-
14654
- /**
14518
+ }/**
14655
14519
  * [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) with [Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API)
14656
14520
  *
14657
14521
  * @see https://web.dev/websocketstream/
@@ -14745,53 +14609,7 @@ class WebSocketStream {
14745
14609
  }
14746
14610
  this.close = closeWithInfo;
14747
14611
  }
14748
- }
14749
-
14750
- function createRtcUrl(url, searchParams) {
14751
- const urlObj = new URL(toWebsocketUrl(url));
14752
- searchParams.forEach((value, key) => {
14753
- urlObj.searchParams.set(key, value);
14754
- });
14755
- return appendUrlPath(urlObj, 'rtc');
14756
- }
14757
- function createValidateUrl(rtcWsUrl) {
14758
- const urlObj = new URL(toHttpUrl(rtcWsUrl));
14759
- return appendUrlPath(urlObj, 'validate');
14760
- }
14761
- function ensureTrailingSlash(path) {
14762
- return path.endsWith('/') ? path : "".concat(path, "/");
14763
- }
14764
- function appendUrlPath(urlObj, path) {
14765
- urlObj.pathname = "".concat(ensureTrailingSlash(urlObj.pathname)).concat(path);
14766
- return urlObj.toString();
14767
- }
14768
- function parseSignalResponse(value) {
14769
- if (typeof value === 'string') {
14770
- return SignalResponse.fromJson(JSON.parse(value), {
14771
- ignoreUnknownFields: true
14772
- });
14773
- } else if (value instanceof ArrayBuffer) {
14774
- return SignalResponse.fromBinary(new Uint8Array(value));
14775
- }
14776
- throw new Error("could not decode websocket message: ".concat(typeof value));
14777
- }
14778
- function getAbortReasonAsString(signal) {
14779
- let defaultMessage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Unknown reason';
14780
- if (!(signal instanceof AbortSignal)) {
14781
- return defaultMessage;
14782
- }
14783
- const reason = signal.reason;
14784
- switch (typeof reason) {
14785
- case 'string':
14786
- return reason;
14787
- case 'object':
14788
- return reason instanceof Error ? reason.message : defaultMessage;
14789
- default:
14790
- return 'toString' in reason ? reason.toString() : defaultMessage;
14791
- }
14792
- }
14793
-
14794
- const passThroughQueueSignals = ['syncState', 'trickle', 'offer', 'answer', 'simulate', 'leave'];
14612
+ }const passThroughQueueSignals = ['syncState', 'trickle', 'offer', 'answer', 'simulate', 'leave'];
14795
14613
  function canPassThroughQueue(req) {
14796
14614
  const canPass = passThroughQueueSignals.indexOf(req.case) >= 0;
14797
14615
  livekitLogger.trace('request allowed to bypass queue:', {
@@ -14918,7 +14736,7 @@ class SignalClient {
14918
14736
  this.close();
14919
14737
  }
14920
14738
  cleanupAbortHandlers();
14921
- reject(target instanceof AbortSignal ? target.reason : target);
14739
+ reject(ConnectionError.cancelled(reason));
14922
14740
  });
14923
14741
  abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.addEventListener('abort', abortHandler);
14924
14742
  const cleanupAbortHandlers = () => {
@@ -14926,7 +14744,7 @@ class SignalClient {
14926
14744
  abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.removeEventListener('abort', abortHandler);
14927
14745
  };
14928
14746
  const wsTimeout = setTimeout(() => {
14929
- abortHandler(new ConnectionError('room connection has timed out (signal)', ConnectionErrorReason.ServerUnreachable));
14747
+ abortHandler(ConnectionError.timeout('room connection has timed out (signal)'));
14930
14748
  }, opts.websocketTimeout);
14931
14749
  const handleSignalConnected = (connection, firstMessage) => {
14932
14750
  this.handleSignalConnected(connection, wsTimeout, firstMessage);
@@ -14947,7 +14765,7 @@ class SignalClient {
14947
14765
  this.ws.closed.then(closeInfo => {
14948
14766
  var _a;
14949
14767
  if (this.isEstablishingConnection) {
14950
- reject(new ConnectionError("Websocket got closed during a (re)connection attempt: ".concat(closeInfo.reason), ConnectionErrorReason.InternalError));
14768
+ reject(ConnectionError.internal("Websocket got closed during a (re)connection attempt: ".concat(closeInfo.reason)));
14951
14769
  }
14952
14770
  if (closeInfo.closeCode !== 1000) {
14953
14771
  this.log.warn("websocket closed", Object.assign(Object.assign({}, this.logContext), {
@@ -14963,7 +14781,7 @@ class SignalClient {
14963
14781
  return;
14964
14782
  }).catch(reason => {
14965
14783
  if (this.isEstablishingConnection) {
14966
- reject(new ConnectionError("Websocket error during a (re)connection attempt: ".concat(reason), ConnectionErrorReason.InternalError));
14784
+ reject(ConnectionError.internal("Websocket error during a (re)connection attempt: ".concat(reason)));
14967
14785
  }
14968
14786
  });
14969
14787
  const connection = yield this.ws.opened.catch(reason => __awaiter(this, void 0, void 0, function* () {
@@ -14988,7 +14806,7 @@ class SignalClient {
14988
14806
  const firstMessage = yield signalReader.read();
14989
14807
  signalReader.releaseLock();
14990
14808
  if (!firstMessage.value) {
14991
- throw new ConnectionError('no message received as first message', ConnectionErrorReason.InternalError);
14809
+ throw ConnectionError.internal('no message received as first message');
14992
14810
  }
14993
14811
  const firstSignalResponse = parseSignalResponse(firstMessage.value);
14994
14812
  // Validate the first message
@@ -15492,18 +15310,18 @@ class SignalClient {
15492
15310
  } else if (this.isEstablishingConnection && ((_d = firstSignalResponse.message) === null || _d === void 0 ? void 0 : _d.case) === 'leave') {
15493
15311
  return {
15494
15312
  isValid: false,
15495
- error: new ConnectionError('Received leave request while trying to (re)connect', ConnectionErrorReason.LeaveRequest, undefined, firstSignalResponse.message.value.reason)
15313
+ error: ConnectionError.leaveRequest('Received leave request while trying to (re)connect', firstSignalResponse.message.value.reason)
15496
15314
  };
15497
15315
  } else if (!isReconnect) {
15498
15316
  // non-reconnect case, should receive join response first
15499
15317
  return {
15500
15318
  isValid: false,
15501
- error: new ConnectionError("did not receive join response, got ".concat((_e = firstSignalResponse.message) === null || _e === void 0 ? void 0 : _e.case, " instead"), ConnectionErrorReason.InternalError)
15319
+ error: ConnectionError.internal("did not receive join response, got ".concat((_e = firstSignalResponse.message) === null || _e === void 0 ? void 0 : _e.case, " instead"))
15502
15320
  };
15503
15321
  }
15504
15322
  return {
15505
15323
  isValid: false,
15506
- error: new ConnectionError('Unexpected first message', ConnectionErrorReason.InternalError)
15324
+ error: ConnectionError.internal('Unexpected first message')
15507
15325
  };
15508
15326
  }
15509
15327
  /**
@@ -15519,14 +15337,17 @@ class SignalClient {
15519
15337
  const resp = yield fetch(validateUrl);
15520
15338
  if (resp.status.toFixed(0).startsWith('4')) {
15521
15339
  const msg = yield resp.text();
15522
- return new ConnectionError(msg, ConnectionErrorReason.NotAllowed, resp.status);
15340
+ return ConnectionError.notAllowed(msg, resp.status);
15523
15341
  } else if (reason instanceof ConnectionError) {
15524
15342
  return reason;
15525
15343
  } else {
15526
- return new ConnectionError("Encountered unknown websocket error during connection: ".concat(reason), ConnectionErrorReason.InternalError, resp.status);
15344
+ return ConnectionError.internal("Encountered unknown websocket error during connection: ".concat(reason), {
15345
+ status: resp.status,
15346
+ statusText: resp.statusText
15347
+ });
15527
15348
  }
15528
15349
  } catch (e) {
15529
- return e instanceof ConnectionError ? e : new ConnectionError(e instanceof Error ? e.message : 'server was not reachable', ConnectionErrorReason.ServerUnreachable);
15350
+ return e instanceof ConnectionError ? e : ConnectionError.serverUnreachable(e instanceof Error ? e.message : 'server was not reachable');
15530
15351
  }
15531
15352
  });
15532
15353
  }
@@ -15618,9 +15439,7 @@ function createJoinRequestConnectionParams(token, info, opts) {
15618
15439
  });
15619
15440
  params.set('join_request', btoa(new TextDecoder('utf-8').decode(wrappedJoinRequest.toBinary())));
15620
15441
  return params;
15621
- }
15622
-
15623
- class DataPacketBuffer {
15442
+ }class DataPacketBuffer {
15624
15443
  constructor() {
15625
15444
  this.buffer = [];
15626
15445
  this._totalSize = 0;
@@ -15661,9 +15480,7 @@ class DataPacketBuffer {
15661
15480
  get length() {
15662
15481
  return this.buffer.length;
15663
15482
  }
15664
- }
15665
-
15666
- class TTLMap {
15483
+ }class TTLMap {
15667
15484
  /**
15668
15485
  * @param ttl ttl of the key (ms)
15669
15486
  */
@@ -15747,15 +15564,7 @@ class TTLMap {
15747
15564
  }
15748
15565
  return result;
15749
15566
  }
15750
- }
15751
-
15752
- var lib = {};
15753
-
15754
- var parser = {};
15755
-
15756
- var grammar = {exports: {}};
15757
-
15758
- var hasRequiredGrammar;
15567
+ }var lib = {};var parser = {};var grammar = {exports: {}};var hasRequiredGrammar;
15759
15568
  function requireGrammar() {
15760
15569
  if (hasRequiredGrammar) return grammar.exports;
15761
15570
  hasRequiredGrammar = 1;
@@ -16196,9 +16005,7 @@ function requireGrammar() {
16196
16005
  });
16197
16006
  });
16198
16007
  return grammar.exports;
16199
- }
16200
-
16201
- var hasRequiredParser;
16008
+ }var hasRequiredParser;
16202
16009
  function requireParser() {
16203
16010
  if (hasRequiredParser) return parser;
16204
16011
  hasRequiredParser = 1;
@@ -16316,9 +16123,7 @@ function requireParser() {
16316
16123
  };
16317
16124
  })(parser);
16318
16125
  return parser;
16319
- }
16320
-
16321
- var writer;
16126
+ }var writer;
16322
16127
  var hasRequiredWriter;
16323
16128
  function requireWriter() {
16324
16129
  if (hasRequiredWriter) return writer;
@@ -16422,9 +16227,7 @@ function requireWriter() {
16422
16227
  return sdp.join('\r\n') + '\r\n';
16423
16228
  };
16424
16229
  return writer;
16425
- }
16426
-
16427
- var hasRequiredLib;
16230
+ }var hasRequiredLib;
16428
16231
  function requireLib() {
16429
16232
  if (hasRequiredLib) return lib;
16430
16233
  hasRequiredLib = 1;
@@ -16441,11 +16244,7 @@ function requireLib() {
16441
16244
  lib.parseImageAttributes = parser.parseImageAttributes;
16442
16245
  lib.parseSimulcastStreamList = parser.parseSimulcastStreamList;
16443
16246
  return lib;
16444
- }
16445
-
16446
- var libExports = requireLib();
16447
-
16448
- function r(r, e, n) {
16247
+ }var libExports = requireLib();function r(r, e, n) {
16449
16248
  var i, t, o;
16450
16249
  void 0 === e && (e = 50), void 0 === n && (n = {});
16451
16250
  var a = null != (i = n.isImmediate) && i,
@@ -16487,9 +16286,7 @@ function r(r, e, n) {
16487
16286
  return (0, e.reject)(r);
16488
16287
  }), l = [];
16489
16288
  }, d;
16490
- }
16491
-
16492
- /* The svc codec (av1/vp9) would use a very low bitrate at the begining and
16289
+ }/* The svc codec (av1/vp9) would use a very low bitrate at the begining and
16493
16290
  increase slowly by the bandwidth estimator until it reach the target bitrate. The
16494
16291
  process commonly cost more than 10 seconds cause subscriber will get blur video at
16495
16292
  the first few seconds. So we use a 70% of target bitrate here as the start bitrate to
@@ -17072,9 +16869,7 @@ function ensureIPAddrMatchVersion(media) {
17072
16869
  }
17073
16870
  function getMidString(mid) {
17074
16871
  return typeof mid === 'number' ? mid.toFixed(0) : mid;
17075
- }
17076
-
17077
- const defaultVideoCodec = 'vp8';
16872
+ }const defaultVideoCodec = 'vp8';
17078
16873
  const publishDefaults = {
17079
16874
  audioPreset: AudioPresets.music,
17080
16875
  dtx: true,
@@ -17116,9 +16911,7 @@ const roomConnectOptionDefaults = {
17116
16911
  maxRetries: 1,
17117
16912
  peerConnectionTimeout: 15000,
17118
16913
  websocketTimeout: 15000
17119
- };
17120
-
17121
- var PCTransportState;
16914
+ };var PCTransportState;
17122
16915
  (function (PCTransportState) {
17123
16916
  PCTransportState[PCTransportState["NEW"] = 0] = "NEW";
17124
16917
  PCTransportState[PCTransportState["CONNECTING"] = 1] = "CONNECTING";
@@ -17392,7 +17185,7 @@ class PCTransportManager {
17392
17185
  const abortHandler = () => {
17393
17186
  this.log.warn('abort transport connection', this.logContext);
17394
17187
  CriticalTimers.clearTimeout(connectTimeout);
17395
- reject(new ConnectionError('room connection has been cancelled', ConnectionErrorReason.Cancelled));
17188
+ reject(ConnectionError.cancelled('room connection has been cancelled'));
17396
17189
  };
17397
17190
  if (abortController === null || abortController === void 0 ? void 0 : abortController.signal.aborted) {
17398
17191
  abortHandler();
@@ -17400,12 +17193,12 @@ class PCTransportManager {
17400
17193
  abortController === null || abortController === void 0 ? void 0 : abortController.signal.addEventListener('abort', abortHandler);
17401
17194
  const connectTimeout = CriticalTimers.setTimeout(() => {
17402
17195
  abortController === null || abortController === void 0 ? void 0 : abortController.signal.removeEventListener('abort', abortHandler);
17403
- reject(new ConnectionError('could not establish pc connection', ConnectionErrorReason.InternalError));
17196
+ reject(ConnectionError.internal('could not establish pc connection'));
17404
17197
  }, timeout);
17405
17198
  while (this.state !== PCTransportState.CONNECTED) {
17406
17199
  yield sleep(50); // FIXME we shouldn't rely on `sleep` in the connection paths, as it invokes `setTimeout` which can be drastically throttled by browser implementations
17407
17200
  if (abortController === null || abortController === void 0 ? void 0 : abortController.signal.aborted) {
17408
- reject(new ConnectionError('room connection has been cancelled', ConnectionErrorReason.Cancelled));
17201
+ reject(ConnectionError.cancelled('room connection has been cancelled'));
17409
17202
  return;
17410
17203
  }
17411
17204
  }
@@ -17416,9 +17209,7 @@ class PCTransportManager {
17416
17209
  }();
17417
17210
  });
17418
17211
  }
17419
- }
17420
-
17421
- const DEFAULT_MAX_AGE_MS = 5000;
17212
+ }const DEFAULT_MAX_AGE_MS = 5000;
17422
17213
  const STOP_REFETCH_DELAY_MS = 30000;
17423
17214
  class RegionUrlProvider {
17424
17215
  static fetchRegionSettings(serverUrl, token, signal) {
@@ -17441,17 +17232,21 @@ class RegionUrlProvider {
17441
17232
  maxAgeInMs
17442
17233
  };
17443
17234
  } else {
17444
- throw new ConnectionError("Could not fetch region settings: ".concat(regionSettingsResponse.statusText), regionSettingsResponse.status === 401 ? ConnectionErrorReason.NotAllowed : ConnectionErrorReason.InternalError, regionSettingsResponse.status);
17235
+ if (regionSettingsResponse.status === 401) {
17236
+ throw ConnectionError.notAllowed("Could not fetch region settings: ".concat(regionSettingsResponse.statusText), regionSettingsResponse.status);
17237
+ } else {
17238
+ throw ConnectionError.internal("Could not fetch region settings: ".concat(regionSettingsResponse.statusText));
17239
+ }
17445
17240
  }
17446
17241
  } catch (e) {
17447
17242
  if (e instanceof ConnectionError) {
17448
17243
  // rethrow connection errors
17449
17244
  throw e;
17450
17245
  } else if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
17451
- throw new ConnectionError("Region fetching was aborted", ConnectionErrorReason.Cancelled);
17246
+ throw ConnectionError.cancelled("Region fetching was aborted");
17452
17247
  } else {
17453
- // wrap other errors as connection errors (e.g. timeouts)
17454
- throw new ConnectionError("Could not fetch region settings, ".concat(e instanceof Error ? "".concat(e.name, ": ").concat(e.message) : e), ConnectionErrorReason.ServerUnreachable, 500);
17248
+ // wrap other errors as connection errors
17249
+ throw ConnectionError.serverUnreachable("Could not fetch region settings, ".concat(e instanceof Error ? "".concat(e.name, ": ").concat(e.message) : e));
17455
17250
  }
17456
17251
  } finally {
17457
17252
  unlock();
@@ -17600,9 +17395,7 @@ RegionUrlProvider.connectionTrackers = new Map();
17600
17395
  RegionUrlProvider.fetchLock = new _();
17601
17396
  function getCloudConfigUrl(serverUrl) {
17602
17397
  return "".concat(serverUrl.protocol.replace('ws', 'http'), "//").concat(serverUrl.host, "/settings");
17603
- }
17604
-
17605
- // SPDX-FileCopyrightText: 2024 LiveKit, Inc.
17398
+ }// SPDX-FileCopyrightText: 2024 LiveKit, Inc.
17606
17399
  //
17607
17400
  // SPDX-License-Identifier: Apache-2.0
17608
17401
  /**
@@ -17714,9 +17507,7 @@ function truncateBytes(str, maxBytes) {
17714
17507
  }
17715
17508
  }
17716
17509
  return str.slice(0, low);
17717
- }
17718
-
17719
- const monitorFrequency = 2000;
17510
+ }const monitorFrequency = 2000;
17720
17511
  function computeBitrate(currentStats, prevStats) {
17721
17512
  if (!prevStats) {
17722
17513
  return 0;
@@ -17734,9 +17525,7 @@ function computeBitrate(currentStats, prevStats) {
17734
17525
  return 0;
17735
17526
  }
17736
17527
  return (bytesNow - bytesPrev) * 8 * 1000 / (currentStats.timestamp - prevStats.timestamp);
17737
- }
17738
-
17739
- // Check if MediaRecorder is available
17528
+ }// Check if MediaRecorder is available
17740
17529
  const isMediaRecorderAvailable = typeof MediaRecorder !== 'undefined';
17741
17530
  // Fallback class for environments without MediaRecorder
17742
17531
  class FallbackRecorder {
@@ -17802,9 +17591,7 @@ class LocalTrackRecorder extends RecorderBase {
17802
17591
  // Helper function to check if recording is supported
17803
17592
  function isRecordingSupported() {
17804
17593
  return isMediaRecorderAvailable;
17805
- }
17806
-
17807
- const DEFAULT_DIMENSIONS_TIMEOUT = 1000;
17594
+ }const DEFAULT_DIMENSIONS_TIMEOUT = 1000;
17808
17595
  const PRE_CONNECT_BUFFER_TIMEOUT = 10000;
17809
17596
  class LocalTrack extends Track {
17810
17597
  /** @internal */
@@ -18253,8 +18040,6 @@ class LocalTrack extends Track {
18253
18040
  * Sets a processor on this track.
18254
18041
  * See https://github.com/livekit/track-processors-js for example usage
18255
18042
  *
18256
- * @experimental
18257
- *
18258
18043
  * @param processor
18259
18044
  * @param showProcessedStreamLocally
18260
18045
  * @returns
@@ -18329,8 +18114,6 @@ class LocalTrack extends Track {
18329
18114
  * Stops the track processor
18330
18115
  * See https://github.com/livekit/track-processors-js for example usage
18331
18116
  *
18332
- * @experimental
18333
- * @returns
18334
18117
  */
18335
18118
  stopProcessor() {
18336
18119
  return __awaiter(this, arguments, void 0, function () {
@@ -18417,9 +18200,7 @@ class LocalTrack extends Track {
18417
18200
  var _a;
18418
18201
  return (_a = this.localTrackRecorder) === null || _a === void 0 ? void 0 : _a.mimeType;
18419
18202
  }
18420
- }
18421
-
18422
- class LocalAudioTrack extends LocalTrack {
18203
+ }class LocalAudioTrack extends LocalTrack {
18423
18204
  /**
18424
18205
  * boolean indicating whether enhanced noise cancellation is currently being used on this track
18425
18206
  */
@@ -18636,9 +18417,7 @@ class LocalAudioTrack extends LocalTrack {
18636
18417
  return trackIsSilent;
18637
18418
  });
18638
18419
  }
18639
- }
18640
-
18641
- /** @internal */
18420
+ }/** @internal */
18642
18421
  function mediaTrackToLocalTrack(mediaStreamTrack, constraints, loggerOptions) {
18643
18422
  switch (mediaStreamTrack.kind) {
18644
18423
  case 'audio':
@@ -18985,9 +18764,7 @@ function getDefaultDegradationPreference(track) {
18985
18764
  } else {
18986
18765
  return 'balanced';
18987
18766
  }
18988
- }
18989
-
18990
- const refreshSubscribedCodecAfterNewCodec = 5000;
18767
+ }const refreshSubscribedCodecAfterNewCodec = 5000;
18991
18768
  class LocalVideoTrack extends LocalTrack {
18992
18769
  get sender() {
18993
18770
  return this._sender;
@@ -19646,13 +19423,13 @@ function videoLayersFromEncodings(width, height, encodings, svc) {
19646
19423
  ssrc: 0
19647
19424
  });
19648
19425
  });
19649
- }
19650
-
19651
- const lossyDataChannel = '_lossy';
19426
+ }const lossyDataChannel = '_lossy';
19652
19427
  const reliableDataChannel = '_reliable';
19653
19428
  const minReconnectWait = 2 * 1000;
19654
19429
  const leaveReconnect = 'leave-reconnect';
19655
19430
  const reliabeReceiveStateTTL = 30000;
19431
+ const lossyDataChannelBufferThresholdMin = 8 * 1024;
19432
+ const lossyDataChannelBufferThresholdMax = 256 * 1024;
19656
19433
  var PCState;
19657
19434
  (function (PCState) {
19658
19435
  PCState[PCState["New"] = 0] = "New";
@@ -19696,6 +19473,9 @@ class RTCEngine extends eventsExports.EventEmitter {
19696
19473
  this.reliableDataSequence = 1;
19697
19474
  this.reliableMessageBuffer = new DataPacketBuffer();
19698
19475
  this.reliableReceivedState = new TTLMap(reliabeReceiveStateTTL);
19476
+ this.lossyDataStatCurrentBytes = 0;
19477
+ this.lossyDataStatByterate = 0;
19478
+ this.lossyDataDropCount = 0;
19699
19479
  this.midToTrackId = {};
19700
19480
  /** used to indicate whether the browser is currently waiting to reconnect */
19701
19481
  this.isWaitingForNetworkReconnect = false;
@@ -19993,6 +19773,7 @@ class RTCEngine extends eventsExports.EventEmitter {
19993
19773
  this.removeAllListeners();
19994
19774
  this.deregisterOnLineListener();
19995
19775
  this.clearPendingReconnect();
19776
+ this.cleanupLossyDataStats();
19996
19777
  yield this.cleanupPeerConnections();
19997
19778
  yield this.cleanupClient();
19998
19779
  } finally {
@@ -20028,6 +19809,15 @@ class RTCEngine extends eventsExports.EventEmitter {
20028
19809
  this.reliableReceivedState.clear();
20029
19810
  });
20030
19811
  }
19812
+ cleanupLossyDataStats() {
19813
+ this.lossyDataStatByterate = 0;
19814
+ this.lossyDataStatCurrentBytes = 0;
19815
+ if (this.lossyDataStatInterval) {
19816
+ clearInterval(this.lossyDataStatInterval);
19817
+ this.lossyDataStatInterval = undefined;
19818
+ }
19819
+ this.lossyDataDropCount = 0;
19820
+ }
20031
19821
  cleanupClient() {
20032
19822
  return __awaiter(this, void 0, void 0, function* () {
20033
19823
  yield this.client.close();
@@ -20041,7 +19831,7 @@ class RTCEngine extends eventsExports.EventEmitter {
20041
19831
  return new Promise((resolve, reject) => {
20042
19832
  const publicationTimeout = setTimeout(() => {
20043
19833
  delete this.pendingTrackResolvers[req.cid];
20044
- reject(new ConnectionError('publication of local track timed out, no response from server', ConnectionErrorReason.Timeout));
19834
+ reject(ConnectionError.timeout('publication of local track timed out, no response from server'));
20045
19835
  }, 10000);
20046
19836
  this.pendingTrackResolvers[req.cid] = {
20047
19837
  resolve: info => {
@@ -20344,6 +20134,17 @@ class RTCEngine extends eventsExports.EventEmitter {
20344
20134
  // handle buffer amount low events
20345
20135
  this.lossyDC.onbufferedamountlow = this.handleBufferedAmountLow;
20346
20136
  this.reliableDC.onbufferedamountlow = this.handleBufferedAmountLow;
20137
+ this.cleanupLossyDataStats();
20138
+ this.lossyDataStatInterval = setInterval(() => {
20139
+ this.lossyDataStatByterate = this.lossyDataStatCurrentBytes;
20140
+ this.lossyDataStatCurrentBytes = 0;
20141
+ const dc = this.dataChannelForKind(DataPacket_Kind.LOSSY);
20142
+ if (dc) {
20143
+ // control buffered latency to ~100ms
20144
+ const threshold = this.lossyDataStatByterate / 10;
20145
+ dc.bufferedAmountLowThreshold = Math.min(Math.max(threshold, lossyDataChannelBufferThresholdMin), lossyDataChannelBufferThresholdMax);
20146
+ }
20147
+ }, 1000);
20347
20148
  }
20348
20149
  createSender(track, opts, encodings) {
20349
20150
  return __awaiter(this, void 0, void 0, function* () {
@@ -20630,7 +20431,7 @@ class RTCEngine extends eventsExports.EventEmitter {
20630
20431
  } catch (e) {
20631
20432
  // TODO do we need a `failed` state here for the PC?
20632
20433
  this.pcState = PCState.Disconnected;
20633
- throw new ConnectionError("could not establish PC connection, ".concat(e.message), ConnectionErrorReason.InternalError);
20434
+ throw ConnectionError.internal("could not establish PC connection, ".concat(e.message));
20634
20435
  }
20635
20436
  });
20636
20437
  }
@@ -20697,14 +20498,24 @@ class RTCEngine extends eventsExports.EventEmitter {
20697
20498
  this.reliableDataSequence += 1;
20698
20499
  }
20699
20500
  const msg = packet.toBinary();
20700
- yield this.waitForBufferStatusLow(kind);
20701
20501
  const dc = this.dataChannelForKind(kind);
20702
20502
  if (dc) {
20703
20503
  if (kind === DataPacket_Kind.RELIABLE) {
20504
+ yield this.waitForBufferStatusLow(kind);
20704
20505
  this.reliableMessageBuffer.push({
20705
20506
  data: msg,
20706
20507
  sequence: packet.sequence
20707
20508
  });
20509
+ } else {
20510
+ // lossy channel, drop messages to reduce latency
20511
+ if (!this.isBufferStatusLow(kind)) {
20512
+ this.lossyDataDropCount += 1;
20513
+ if (this.lossyDataDropCount % 100 === 0) {
20514
+ this.log.warn("dropping lossy data channel messages, total dropped: ".concat(this.lossyDataDropCount), this.logContext);
20515
+ }
20516
+ return;
20517
+ }
20518
+ this.lossyDataStatCurrentBytes += msg.byteLength;
20708
20519
  }
20709
20520
  if (this.attemptingReconnect) {
20710
20521
  return;
@@ -20757,7 +20568,7 @@ class RTCEngine extends eventsExports.EventEmitter {
20757
20568
  const transport = subscriber ? _this2.pcManager.subscriber : _this2.pcManager.publisher;
20758
20569
  const transportName = subscriber ? 'Subscriber' : 'Publisher';
20759
20570
  if (!transport) {
20760
- throw new ConnectionError("".concat(transportName, " connection not set"), ConnectionErrorReason.InternalError);
20571
+ throw ConnectionError.internal("".concat(transportName, " connection not set"));
20761
20572
  }
20762
20573
  let needNegotiation = false;
20763
20574
  if (!subscriber && !_this2.dataChannelForKind(kind, subscriber)) {
@@ -20785,7 +20596,7 @@ class RTCEngine extends eventsExports.EventEmitter {
20785
20596
  }
20786
20597
  yield sleep(50);
20787
20598
  }
20788
- throw new ConnectionError("could not establish ".concat(transportName, " connection, state: ").concat(transport.getICEConnectionState()), ConnectionErrorReason.InternalError);
20599
+ throw ConnectionError.internal("could not establish ".concat(transportName, " connection, state: ").concat(transport.getICEConnectionState()));
20789
20600
  }();
20790
20601
  });
20791
20602
  }
@@ -20994,7 +20805,6 @@ class RTCEngine extends eventsExports.EventEmitter {
20994
20805
  }
20995
20806
  }
20996
20807
  }
20997
- class SignalReconnectError extends Error {}
20998
20808
  function supportOptionalDatachannel(protocol) {
20999
20809
  return protocol !== undefined && protocol > 13;
21000
20810
  }
@@ -21005,9 +20815,7 @@ function applyUserDataCompat(newObj, oldObj) {
21005
20815
  const destinationIdentities = newObj.destinationIdentities.length !== 0 ? newObj.destinationIdentities : oldObj.destinationIdentities;
21006
20816
  newObj.destinationIdentities = destinationIdentities;
21007
20817
  oldObj.destinationIdentities = destinationIdentities;
21008
- }
21009
-
21010
- class BaseStreamReader {
20818
+ }class BaseStreamReader {
21011
20819
  get info() {
21012
20820
  return this._info;
21013
20821
  }
@@ -21294,9 +21102,7 @@ class TextStreamReader extends BaseStreamReader {
21294
21102
  }();
21295
21103
  });
21296
21104
  }
21297
- }
21298
-
21299
- class IncomingDataStreamManager {
21105
+ }class IncomingDataStreamManager {
21300
21106
  constructor() {
21301
21107
  this.log = livekitLogger;
21302
21108
  this.byteStreamControllers = new Map();
@@ -21482,9 +21288,7 @@ class IncomingDataStreamManager {
21482
21288
  this.byteStreamControllers.delete(trailer.streamId);
21483
21289
  }
21484
21290
  }
21485
- }
21486
-
21487
- class BaseStreamWriter {
21291
+ }class BaseStreamWriter {
21488
21292
  constructor(writableStream, info, onClose) {
21489
21293
  this.writableStream = writableStream;
21490
21294
  this.defaultWriter = writableStream.getWriter();
@@ -21504,9 +21308,7 @@ class BaseStreamWriter {
21504
21308
  }
21505
21309
  }
21506
21310
  class TextStreamWriter extends BaseStreamWriter {}
21507
- class ByteStreamWriter extends BaseStreamWriter {}
21508
-
21509
- const STREAM_CHUNK_SIZE = 15000;
21311
+ class ByteStreamWriter extends BaseStreamWriter {}const STREAM_CHUNK_SIZE = 15000;
21510
21312
  /**
21511
21313
  * Manages sending custom user data via data channels.
21512
21314
  * @internal
@@ -21562,7 +21364,6 @@ class OutgoingDataStreamManager {
21562
21364
  }
21563
21365
  /**
21564
21366
  * @internal
21565
- * @experimental CAUTION, might get removed in a minor release
21566
21367
  */
21567
21368
  streamText(options) {
21568
21369
  return __awaiter(this, void 0, void 0, function* () {
@@ -21782,9 +21583,7 @@ class OutgoingDataStreamManager {
21782
21583
  return byteWriter;
21783
21584
  });
21784
21585
  }
21785
- }
21786
-
21787
- class RemoteTrack extends Track {
21586
+ }class RemoteTrack extends Track {
21788
21587
  constructor(mediaTrack, sid, kind, receiver, loggerOptions) {
21789
21588
  super(mediaTrack, kind, loggerOptions);
21790
21589
  this.sid = sid;
@@ -21905,9 +21704,7 @@ class RemoteTrack extends Track {
21905
21704
  };
21906
21705
  loop();
21907
21706
  }
21908
- }
21909
-
21910
- class RemoteAudioTrack extends RemoteTrack {
21707
+ }class RemoteAudioTrack extends RemoteTrack {
21911
21708
  constructor(mediaTrack, sid, receiver, audioContext, audioOutput, loggerOptions) {
21912
21709
  super(mediaTrack, sid, Track.Kind.Audio, receiver, loggerOptions);
21913
21710
  this.monitorReceiver = () => __awaiter(this, void 0, void 0, function* () {
@@ -22106,9 +21903,7 @@ class RemoteAudioTrack extends RemoteTrack {
22106
21903
  return receiverStats;
22107
21904
  });
22108
21905
  }
22109
- }
22110
-
22111
- const REACTION_DELAY = 100;
21906
+ }const REACTION_DELAY = 100;
22112
21907
  class RemoteVideoTrack extends RemoteTrack {
22113
21908
  constructor(mediaTrack, sid, receiver, adaptiveStreamSettings, loggerOptions) {
22114
21909
  super(mediaTrack, sid, Track.Kind.Video, receiver, loggerOptions);
@@ -22448,9 +22243,7 @@ function isElementInViewport(el, win) {
22448
22243
  left += el.offsetLeft;
22449
22244
  }
22450
22245
  return top < viewportWindow.pageYOffset + viewportWindow.innerHeight && left < viewportWindow.pageXOffset + viewportWindow.innerWidth && top + height > viewportWindow.pageYOffset && left + width > viewportWindow.pageXOffset && !hidden && display !== 'none';
22451
- }
22452
-
22453
- class TrackPublication extends eventsExports.EventEmitter {
22246
+ }class TrackPublication extends eventsExports.EventEmitter {
22454
22247
  constructor(kind, id, name, loggerOptions) {
22455
22248
  var _a;
22456
22249
  super();
@@ -22546,9 +22339,7 @@ class TrackPublication extends eventsExports.EventEmitter {
22546
22339
  PermissionStatus["Allowed"] = "allowed";
22547
22340
  PermissionStatus["NotAllowed"] = "not_allowed";
22548
22341
  })(TrackPublication.PermissionStatus || (TrackPublication.PermissionStatus = {}));
22549
- })(TrackPublication || (TrackPublication = {}));
22550
-
22551
- class LocalTrackPublication extends TrackPublication {
22342
+ })(TrackPublication || (TrackPublication = {}));class LocalTrackPublication extends TrackPublication {
22552
22343
  get isUpstreamPaused() {
22553
22344
  var _a;
22554
22345
  return (_a = this.track) === null || _a === void 0 ? void 0 : _a.isUpstreamPaused;
@@ -22658,9 +22449,7 @@ class LocalTrackPublication extends TrackPublication {
22658
22449
  return Array.from(features.values());
22659
22450
  } else return [];
22660
22451
  }
22661
- }
22662
-
22663
- /**
22452
+ }/**
22664
22453
  * Creates a local video and audio track at the same time. When acquiring both
22665
22454
  * audio and video tracks together, it'll display a single permission prompt to
22666
22455
  * the user instead of two separate ones.
@@ -22839,9 +22628,7 @@ function createLocalScreenTracks(options) {
22839
22628
  }
22840
22629
  return localTracks;
22841
22630
  });
22842
- }
22843
-
22844
- var ConnectionQuality;
22631
+ }var ConnectionQuality;
22845
22632
  (function (ConnectionQuality) {
22846
22633
  ConnectionQuality["Excellent"] = "excellent";
22847
22634
  ConnectionQuality["Good"] = "good";
@@ -23111,9 +22898,7 @@ class Participant extends eventsExports.EventEmitter {
23111
22898
  break;
23112
22899
  }
23113
22900
  }
23114
- }
23115
-
23116
- function trackPermissionToProto(perms) {
22901
+ }function trackPermissionToProto(perms) {
23117
22902
  var _a, _b, _c;
23118
22903
  if (!perms.participantSid && !perms.participantIdentity) {
23119
22904
  throw new Error('Invalid track permission, must provide at least one of participantIdentity and participantSid');
@@ -23124,9 +22909,7 @@ function trackPermissionToProto(perms) {
23124
22909
  allTracks: (_c = perms.allowAll) !== null && _c !== void 0 ? _c : false,
23125
22910
  trackSids: perms.allowedTrackSids || []
23126
22911
  });
23127
- }
23128
-
23129
- class LocalParticipant extends Participant {
22912
+ }class LocalParticipant extends Participant {
23130
22913
  /** @internal */
23131
22914
  constructor(sid, identity, engine, options, roomRpcHandlers, roomOutgoingDataStreamManager) {
23132
22915
  super(sid, identity, undefined, undefined, undefined, {
@@ -24648,7 +24431,7 @@ class LocalParticipant extends Participant {
24648
24431
  resolve: (responsePayload, responseError) => {
24649
24432
  clearTimeout(responseTimeoutId);
24650
24433
  if (this.pendingAcks.has(id)) {
24651
- console.warn('RPC response received before ack', id);
24434
+ this.log.warn('RPC response received before ack', id);
24652
24435
  this.pendingAcks.delete(id);
24653
24436
  clearTimeout(ackTimeoutId);
24654
24437
  }
@@ -24847,9 +24630,7 @@ class LocalParticipant extends Participant {
24847
24630
  }
24848
24631
  });
24849
24632
  }
24850
- }
24851
-
24852
- class RemoteTrackPublication extends TrackPublication {
24633
+ }class RemoteTrackPublication extends TrackPublication {
24853
24634
  constructor(kind, ti, autoSubscribe, loggerOptions) {
24854
24635
  super(kind, ti.sid, ti.name, loggerOptions);
24855
24636
  this.track = undefined;
@@ -25119,9 +24900,7 @@ class RemoteTrackPublication extends TrackPublication {
25119
24900
  }
25120
24901
  this.emit(TrackEvent.UpdateSettings, settings);
25121
24902
  }
25122
- }
25123
-
25124
- class RemoteParticipant extends Participant {
24903
+ }class RemoteParticipant extends Participant {
25125
24904
  /** @internal */
25126
24905
  static fromParticipantInfo(signalClient, pi, loggerOptions) {
25127
24906
  return new RemoteParticipant(signalClient, pi.sid, pi.identity, pi.name, pi.metadata, pi.attributes, loggerOptions, pi.kind);
@@ -25386,9 +25165,7 @@ class RemoteParticipant extends Participant {
25386
25165
  }));
25387
25166
  return super.emit(event, ...args);
25388
25167
  }
25389
- }
25390
-
25391
- var ConnectionState;
25168
+ }var ConnectionState;
25392
25169
  (function (ConnectionState) {
25393
25170
  ConnectionState["Disconnected"] = "disconnected";
25394
25171
  ConnectionState["Connecting"] = "connecting";
@@ -25454,7 +25231,7 @@ class Room extends eventsExports.EventEmitter {
25454
25231
  return this.connectFuture.promise;
25455
25232
  }
25456
25233
  this.setAndEmitConnectionState(ConnectionState.Connecting);
25457
- if (((_a = this.regionUrlProvider) === null || _a === void 0 ? void 0 : _a.getServerUrl().toString()) !== url) {
25234
+ if (((_a = this.regionUrlProvider) === null || _a === void 0 ? void 0 : _a.getServerUrl().toString()) !== ensureTrailingSlash(url)) {
25458
25235
  this.regionUrl = undefined;
25459
25236
  this.regionUrlProvider = undefined;
25460
25237
  }
@@ -25489,7 +25266,7 @@ class Room extends eventsExports.EventEmitter {
25489
25266
  try {
25490
25267
  yield BackOffStrategy.getInstance().getBackOffPromise(url);
25491
25268
  if (abortController.signal.aborted) {
25492
- throw new ConnectionError('Connection attempt aborted', ConnectionErrorReason.Cancelled);
25269
+ throw ConnectionError.cancelled('Connection attempt aborted');
25493
25270
  }
25494
25271
  yield this.attemptConnection(regionUrl !== null && regionUrl !== void 0 ? regionUrl : url, token, opts, abortController);
25495
25272
  this.abortController = undefined;
@@ -25626,7 +25403,7 @@ class Room extends eventsExports.EventEmitter {
25626
25403
  } catch (err) {
25627
25404
  yield this.engine.close();
25628
25405
  this.recreateEngine();
25629
- const resultingError = new ConnectionError("could not establish signal connection", abortController.signal.aborted ? ConnectionErrorReason.Cancelled : ConnectionErrorReason.ServerUnreachable);
25406
+ const resultingError = abortController.signal.aborted ? ConnectionError.cancelled('Signal connection aborted') : ConnectionError.serverUnreachable('could not establish signal connection');
25630
25407
  if (err instanceof Error) {
25631
25408
  resultingError.message = "".concat(resultingError.message, ": ").concat(err.message);
25632
25409
  }
@@ -25642,7 +25419,7 @@ class Room extends eventsExports.EventEmitter {
25642
25419
  if (abortController.signal.aborted) {
25643
25420
  yield this.engine.close();
25644
25421
  this.recreateEngine();
25645
- throw new ConnectionError("Connection attempt aborted", ConnectionErrorReason.Cancelled);
25422
+ throw ConnectionError.cancelled("Connection attempt aborted");
25646
25423
  }
25647
25424
  try {
25648
25425
  yield this.engine.waitForPCInitialConnection(this.connOptions.peerConnectionTimeout, abortController);
@@ -25658,7 +25435,7 @@ class Room extends eventsExports.EventEmitter {
25658
25435
  window.addEventListener('beforeunload', this.onPageLeave);
25659
25436
  }
25660
25437
  if (isWeb()) {
25661
- document.addEventListener('freeze', this.onPageLeave);
25438
+ window.addEventListener('freeze', this.onPageLeave);
25662
25439
  }
25663
25440
  this.setAndEmitConnectionState(ConnectionState.Connected);
25664
25441
  this.emit(RoomEvent.Connected);
@@ -25694,7 +25471,7 @@ class Room extends eventsExports.EventEmitter {
25694
25471
  _this2.log.warn(msg, _this2.logContext);
25695
25472
  (_a = _this2.abortController) === null || _a === void 0 ? void 0 : _a.abort(msg);
25696
25473
  // in case the abort controller didn't manage to cancel the connection attempt, reject the connect promise explicitly
25697
- (_c = (_b = _this2.connectFuture) === null || _b === void 0 ? void 0 : _b.reject) === null || _c === void 0 ? void 0 : _c.call(_b, new ConnectionError('Client initiated disconnect', ConnectionErrorReason.Cancelled));
25474
+ (_c = (_b = _this2.connectFuture) === null || _b === void 0 ? void 0 : _b.reject) === null || _c === void 0 ? void 0 : _c.call(_b, ConnectionError.cancelled('Client initiated disconnect'));
25698
25475
  _this2.connectFuture = undefined;
25699
25476
  }
25700
25477
  // close engine (also closes client)
@@ -26905,7 +26682,7 @@ class Room extends eventsExports.EventEmitter {
26905
26682
  });
26906
26683
  if (byteLength(response) > MAX_PAYLOAD_BYTES) {
26907
26684
  responseError = RpcError.builtIn('RESPONSE_PAYLOAD_TOO_LARGE');
26908
- console.warn("RPC Response payload too large for ".concat(method));
26685
+ this.log.warn("RPC Response payload too large for ".concat(method));
26909
26686
  } else {
26910
26687
  responsePayload = response;
26911
26688
  }
@@ -26913,7 +26690,7 @@ class Room extends eventsExports.EventEmitter {
26913
26690
  if (error instanceof RpcError) {
26914
26691
  responseError = error;
26915
26692
  } else {
26916
- console.warn("Uncaught error returned by RPC handler for ".concat(method, ". Returning APPLICATION_ERROR instead."), error);
26693
+ this.log.warn("Uncaught error returned by RPC handler for ".concat(method, ". Returning APPLICATION_ERROR instead."), error);
26917
26694
  responseError = RpcError.builtIn('APPLICATION_ERROR');
26918
26695
  }
26919
26696
  }
@@ -27334,9 +27111,7 @@ function mapArgs(args) {
27334
27111
  }
27335
27112
  return arg;
27336
27113
  });
27337
- }
27338
-
27339
- // This file was generated from JSON Schema using quicktype, do not modify it directly.
27114
+ }// This file was generated from JSON Schema using quicktype, do not modify it directly.
27340
27115
  // The code generation lives at https://github.com/livekit/attribute-definitions
27341
27116
  //
27342
27117
  // To parse this data:
@@ -27359,14 +27134,7 @@ class Convert {
27359
27134
  static transcriptionAttributesToJson(value) {
27360
27135
  return JSON.stringify(value);
27361
27136
  }
27362
- }
27363
-
27364
- var attributeTypings = /*#__PURE__*/Object.freeze({
27365
- __proto__: null,
27366
- Convert: Convert
27367
- });
27368
-
27369
- var CheckStatus;
27137
+ }var attributeTypings=/*#__PURE__*/Object.freeze({__proto__:null,Convert:Convert});var CheckStatus;
27370
27138
  (function (CheckStatus) {
27371
27139
  CheckStatus[CheckStatus["IDLE"] = 0] = "IDLE";
27372
27140
  CheckStatus[CheckStatus["RUNNING"] = 1] = "RUNNING";
@@ -27509,9 +27277,7 @@ class Checker extends eventsExports.EventEmitter {
27509
27277
  description: this.description
27510
27278
  };
27511
27279
  }
27512
- }
27513
-
27514
- /**
27280
+ }/**
27515
27281
  * Checks for connections quality to closests Cloud regions and determining the best quality
27516
27282
  */
27517
27283
  class CloudRegionCheck extends Checker {
@@ -27592,9 +27358,7 @@ class CloudRegionCheck extends Checker {
27592
27358
  return regionStats;
27593
27359
  });
27594
27360
  }
27595
- }
27596
-
27597
- const TEST_DURATION = 10000;
27361
+ }const TEST_DURATION = 10000;
27598
27362
  class ConnectionProtocolCheck extends Checker {
27599
27363
  get description() {
27600
27364
  return 'Connection via UDP vs TCP';
@@ -27704,9 +27468,7 @@ class ConnectionProtocolCheck extends Checker {
27704
27468
  return protocolStats;
27705
27469
  });
27706
27470
  }
27707
- }
27708
-
27709
- class PublishAudioCheck extends Checker {
27471
+ }class PublishAudioCheck extends Checker {
27710
27472
  get description() {
27711
27473
  return 'Can publish audio';
27712
27474
  }
@@ -27740,9 +27502,7 @@ class PublishAudioCheck extends Checker {
27740
27502
  this.appendMessage("published ".concat(numPackets, " audio packets"));
27741
27503
  });
27742
27504
  }
27743
- }
27744
-
27745
- class PublishVideoCheck extends Checker {
27505
+ }class PublishVideoCheck extends Checker {
27746
27506
  get description() {
27747
27507
  return 'Can publish video';
27748
27508
  }
@@ -27823,9 +27583,7 @@ class PublishVideoCheck extends Checker {
27823
27583
  video.remove();
27824
27584
  });
27825
27585
  }
27826
- }
27827
-
27828
- class ReconnectCheck extends Checker {
27586
+ }class ReconnectCheck extends Checker {
27829
27587
  get description() {
27830
27588
  return 'Resuming connection after interruption';
27831
27589
  }
@@ -27861,15 +27619,17 @@ class ReconnectCheck extends Checker {
27861
27619
  }
27862
27620
  });
27863
27621
  }
27864
- }
27865
-
27866
- class TURNCheck extends Checker {
27622
+ }class TURNCheck extends Checker {
27867
27623
  get description() {
27868
27624
  return 'Can connect via TURN';
27869
27625
  }
27870
27626
  perform() {
27871
27627
  return __awaiter(this, void 0, void 0, function* () {
27872
- var _a, _b;
27628
+ var _a, _b, _c;
27629
+ if (isCloud(new URL(this.url))) {
27630
+ this.appendMessage('Using region specific url');
27631
+ this.url = (_a = yield new RegionUrlProvider(this.url, this.token).getNextBestRegionUrl()) !== null && _a !== void 0 ? _a : this.url;
27632
+ }
27873
27633
  const signalClient = new SignalClient();
27874
27634
  const joinRes = yield signalClient.join(this.url, this.token, {
27875
27635
  autoSubscribe: true,
@@ -27902,7 +27662,7 @@ class TURNCheck extends Checker {
27902
27662
  this.appendWarning('TURN is configured server side, but TURN/TLS is unavailable.');
27903
27663
  }
27904
27664
  yield signalClient.close();
27905
- if (((_b = (_a = this.connectOptions) === null || _a === void 0 ? void 0 : _a.rtcConfig) === null || _b === void 0 ? void 0 : _b.iceServers) || hasTURN) {
27665
+ if (((_c = (_b = this.connectOptions) === null || _b === void 0 ? void 0 : _b.rtcConfig) === null || _c === void 0 ? void 0 : _c.iceServers) || hasTURN) {
27906
27666
  yield this.room.connect(this.url, this.token, {
27907
27667
  rtcConfig: {
27908
27668
  iceTransportPolicy: 'relay'
@@ -27915,9 +27675,7 @@ class TURNCheck extends Checker {
27915
27675
  }
27916
27676
  });
27917
27677
  }
27918
- }
27919
-
27920
- class WebRTCCheck extends Checker {
27678
+ }class WebRTCCheck extends Checker {
27921
27679
  get description() {
27922
27680
  return 'Establishing WebRTC connection';
27923
27681
  }
@@ -27989,9 +27747,7 @@ function isIPPrivate(address) {
27989
27747
  }
27990
27748
  }
27991
27749
  return false;
27992
- }
27993
-
27994
- class WebSocketCheck extends Checker {
27750
+ }class WebSocketCheck extends Checker {
27995
27751
  get description() {
27996
27752
  return 'Connecting to signal connection via WebSocket';
27997
27753
  }
@@ -28002,23 +27758,44 @@ class WebSocketCheck extends Checker {
28002
27758
  this.appendWarning('Server is insecure, clients may block connections to it');
28003
27759
  }
28004
27760
  let signalClient = new SignalClient();
28005
- const joinRes = yield signalClient.join(this.url, this.token, {
28006
- autoSubscribe: true,
28007
- maxRetries: 0,
28008
- e2eeEnabled: false,
28009
- websocketTimeout: 15000,
28010
- singlePeerConnection: false
28011
- });
28012
- this.appendMessage("Connected to server, version ".concat(joinRes.serverVersion, "."));
28013
- if (((_a = joinRes.serverInfo) === null || _a === void 0 ? void 0 : _a.edition) === ServerInfo_Edition.Cloud && ((_b = joinRes.serverInfo) === null || _b === void 0 ? void 0 : _b.region)) {
28014
- this.appendMessage("LiveKit Cloud: ".concat((_c = joinRes.serverInfo) === null || _c === void 0 ? void 0 : _c.region));
27761
+ let joinRes;
27762
+ try {
27763
+ joinRes = yield signalClient.join(this.url, this.token, {
27764
+ autoSubscribe: true,
27765
+ maxRetries: 0,
27766
+ e2eeEnabled: false,
27767
+ websocketTimeout: 15000,
27768
+ singlePeerConnection: false
27769
+ });
27770
+ } catch (e) {
27771
+ if (isCloud(new URL(this.url))) {
27772
+ this.appendMessage("Initial connection failed with error ".concat(e.message, ". Retrying with region fallback"));
27773
+ const regionProvider = new RegionUrlProvider(this.url, this.token);
27774
+ const regionUrl = yield regionProvider.getNextBestRegionUrl();
27775
+ if (regionUrl) {
27776
+ joinRes = yield signalClient.join(regionUrl, this.token, {
27777
+ autoSubscribe: true,
27778
+ maxRetries: 0,
27779
+ e2eeEnabled: false,
27780
+ websocketTimeout: 15000,
27781
+ singlePeerConnection: false
27782
+ });
27783
+ this.appendMessage("Fallback to region worked. To avoid initial connections failing, ensure you're calling room.prepareConnection() ahead of time");
27784
+ }
27785
+ }
27786
+ }
27787
+ if (joinRes) {
27788
+ this.appendMessage("Connected to server, version ".concat(joinRes.serverVersion, "."));
27789
+ if (((_a = joinRes.serverInfo) === null || _a === void 0 ? void 0 : _a.edition) === ServerInfo_Edition.Cloud && ((_b = joinRes.serverInfo) === null || _b === void 0 ? void 0 : _b.region)) {
27790
+ this.appendMessage("LiveKit Cloud: ".concat((_c = joinRes.serverInfo) === null || _c === void 0 ? void 0 : _c.region));
27791
+ }
27792
+ } else {
27793
+ this.appendError("Websocket connection could not be established");
28015
27794
  }
28016
27795
  yield signalClient.close();
28017
27796
  });
28018
27797
  }
28019
- }
28020
-
28021
- class ConnectionCheck extends eventsExports.EventEmitter {
27798
+ }class ConnectionCheck extends eventsExports.EventEmitter {
28022
27799
  constructor(url, token) {
28023
27800
  let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
28024
27801
  super();
@@ -28106,9 +27883,7 @@ class ConnectionCheck extends eventsExports.EventEmitter {
28106
27883
  return this.createAndRunCheck(CloudRegionCheck);
28107
27884
  });
28108
27885
  }
28109
- }
28110
-
28111
- /** A Fixed TokenSource is a token source that takes no parameters and returns a completely
27886
+ }/** A Fixed TokenSource is a token source that takes no parameters and returns a completely
28112
27887
  * independently derived value on each fetch() call.
28113
27888
  *
28114
27889
  * The most common downstream implementer is {@link TokenSourceLiteral}.
@@ -28125,9 +27900,7 @@ class TokenSourceFixed {}
28125
27900
  * A few common downstream implementers are {@link TokenSourceEndpoint}
28126
27901
  * and {@link TokenSourceCustom}.
28127
27902
  */
28128
- class TokenSourceConfigurable {}
28129
-
28130
- function _defineProperty(e, r, t) {
27903
+ class TokenSourceConfigurable {}function _defineProperty(e, r, t) {
28131
27904
  return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
28132
27905
  value: t,
28133
27906
  enumerable: true,
@@ -28148,12 +27921,8 @@ function _toPrimitive(t, r) {
28148
27921
  function _toPropertyKey(t) {
28149
27922
  var i = _toPrimitive(t, "string");
28150
27923
  return "symbol" == typeof i ? i : i + "";
28151
- }
28152
-
28153
- new TextEncoder();
28154
- const decoder = new TextDecoder();
28155
-
28156
- function decodeBase64(encoded) {
27924
+ }new TextEncoder();
27925
+ const decoder = new TextDecoder();function decodeBase64(encoded) {
28157
27926
  if (Uint8Array.fromBase64) {
28158
27927
  return Uint8Array.fromBase64(encoded);
28159
27928
  }
@@ -28163,9 +27932,7 @@ function decodeBase64(encoded) {
28163
27932
  bytes[i] = binary.charCodeAt(i);
28164
27933
  }
28165
27934
  return bytes;
28166
- }
28167
-
28168
- function decode(input) {
27935
+ }function decode(input) {
28169
27936
  if (Uint8Array.fromBase64) {
28170
27937
  return Uint8Array.fromBase64(typeof input === 'string' ? input : decoder.decode(input), {
28171
27938
  alphabet: 'base64url'
@@ -28175,15 +27942,13 @@ function decode(input) {
28175
27942
  if (encoded instanceof Uint8Array) {
28176
27943
  encoded = decoder.decode(encoded);
28177
27944
  }
28178
- encoded = encoded.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '');
27945
+ encoded = encoded.replace(/-/g, '+').replace(/_/g, '/');
28179
27946
  try {
28180
27947
  return decodeBase64(encoded);
28181
27948
  } catch (_unused) {
28182
27949
  throw new TypeError('The input to be decoded is not correctly encoded.');
28183
27950
  }
28184
- }
28185
-
28186
- class JOSEError extends Error {
27951
+ }class JOSEError extends Error {
28187
27952
  constructor(message, options) {
28188
27953
  var _Error$captureStackTr;
28189
27954
  super(message, options);
@@ -28329,12 +28094,8 @@ class JWSSignatureVerificationFailed extends JOSEError {
28329
28094
  _defineProperty(this, "code", 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED');
28330
28095
  }
28331
28096
  }
28332
- _defineProperty(JWSSignatureVerificationFailed, "code", 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED');
28333
-
28334
- function isObjectLike(value) {
28335
- return typeof value === 'object' && value !== null;
28336
- }
28337
- var isObject = input => {
28097
+ _defineProperty(JWSSignatureVerificationFailed, "code", 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED');const isObjectLike = value => typeof value === 'object' && value !== null;
28098
+ function isObject(input) {
28338
28099
  if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') {
28339
28100
  return false;
28340
28101
  }
@@ -28346,9 +28107,7 @@ var isObject = input => {
28346
28107
  proto = Object.getPrototypeOf(proto);
28347
28108
  }
28348
28109
  return Object.getPrototypeOf(input) === proto;
28349
- };
28350
-
28351
- function decodeJwt(jwt) {
28110
+ }function decodeJwt(jwt) {
28352
28111
  if (typeof jwt !== 'string') throw new JWTInvalid('JWTs must use Compact JWS serialization, JWT must be a string');
28353
28112
  const {
28354
28113
  1: payload,
@@ -28371,9 +28130,7 @@ function decodeJwt(jwt) {
28371
28130
  }
28372
28131
  if (!isObject(result)) throw new JWTInvalid('Invalid JWT Claims Set');
28373
28132
  return result;
28374
- }
28375
-
28376
- const ONE_SECOND_IN_MILLISECONDS = 1000;
28133
+ }const ONE_SECOND_IN_MILLISECONDS = 1000;
28377
28134
  const ONE_MINUTE_IN_MILLISECONDS = 60 * ONE_SECOND_IN_MILLISECONDS;
28378
28135
  function isResponseTokenValid(response) {
28379
28136
  const jwtPayload = decodeTokenPayload(response.participantToken);
@@ -28422,9 +28179,7 @@ function areTokenSourceFetchOptionsEqual(a, b) {
28422
28179
  }
28423
28180
  }
28424
28181
  return true;
28425
- }
28426
-
28427
- /** A TokenSourceCached is a TokenSource which caches the last {@link TokenSourceResponseObject} value and returns it
28182
+ }/** A TokenSourceCached is a TokenSource which caches the last {@link TokenSourceResponseObject} value and returns it
28428
28183
  * until a) it expires or b) the {@link TokenSourceFetchOptions} provided to .fetch(...) change. */
28429
28184
  class TokenSourceCached extends TokenSourceConfigurable {
28430
28185
  constructor() {
@@ -28629,7 +28384,7 @@ const TokenSource = {
28629
28384
  /**
28630
28385
  * TokenSource.endpoint creates a token source that fetches credentials from a given URL using
28631
28386
  * the standard endpoint format:
28632
- * FIXME: add docs link here in the future!
28387
+ * @see https://cloud.livekit.io/projects/p_/sandbox/templates/token-server
28633
28388
  */
28634
28389
  endpoint(url) {
28635
28390
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -28648,9 +28403,7 @@ const TokenSource = {
28648
28403
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
28649
28404
  return new TokenSourceSandboxTokenServer(sandboxId, options);
28650
28405
  }
28651
- };
28652
-
28653
- /**
28406
+ };/**
28654
28407
  * Try to analyze the local track to determine the facing mode of a track.
28655
28408
  *
28656
28409
  * @remarks
@@ -28729,7 +28482,4 @@ function facingModeFromDeviceLabel(deviceLabel) {
28729
28482
  function isFacingModeValue(item) {
28730
28483
  const allowedValues = ['user', 'environment', 'left', 'right'];
28731
28484
  return item === undefined || allowedValues.includes(item);
28732
- }
28733
-
28734
- export { AudioPresets, BackupCodecPolicy, BaseKeyProvider, CheckStatus, Checker, ConnectionCheck, ConnectionError, ConnectionErrorReason, ConnectionQuality, ConnectionState, CriticalTimers, CryptorError, CryptorErrorReason, CryptorEvent, DataPacket_Kind, DataStreamError, DataStreamErrorReason, DefaultReconnectPolicy, DeviceUnsupportedError, DisconnectReason, EncryptionEvent, Encryption_Type, EngineEvent, ExternalE2EEKeyProvider, KeyHandlerEvent, KeyProviderEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalTrackRecorder, LocalVideoTrack, LogLevel, LoggerNames, MediaDeviceFailure, _ as Mutex, NegotiationError, Participant, ParticipantEvent, ParticipantInfo_Kind as ParticipantKind, PublishDataError, PublishTrackError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, RpcError, ScreenSharePresets, SignalRequestError, SubscriptionError, TokenSource, TokenSourceConfigurable, TokenSourceFixed, Track, TrackEvent, TrackInvalidError, TrackPublication, TrackType, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, areTokenSourceFetchOptionsEqual, asEncryptablePacket, attachToElement, attributeTypings as attributes, audioCodecs, 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, isScriptTransformSupported, isVideoCodec, isVideoFrame, isVideoTrack, needsRbspUnescaping, parseRbsp, protocolVersion, ratchet, setLogExtension, setLogLevel, supportsAV1, supportsAdaptiveStream, supportsAudioOutputSelection, supportsDynacast, supportsVP9, version, videoCodecs, writeRbsp };
28735
- //# sourceMappingURL=livekit-client.esm.mjs.map
28485
+ }export{AudioPresets,BackupCodecPolicy,BaseKeyProvider,CheckStatus,Checker,ConnectionCheck,ConnectionError,ConnectionErrorReason,ConnectionQuality,ConnectionState,CriticalTimers,CryptorError,CryptorErrorReason,CryptorEvent,DataPacket_Kind,DataStreamError,DataStreamErrorReason,DefaultReconnectPolicy,DeviceUnsupportedError,DisconnectReason,EncryptionEvent,Encryption_Type,EngineEvent,ExternalE2EEKeyProvider,KeyHandlerEvent,KeyProviderEvent,LivekitError,LocalAudioTrack,LocalParticipant,LocalTrack,LocalTrackPublication,LocalTrackRecorder,LocalVideoTrack,LogLevel,LoggerNames,MediaDeviceFailure,_ as Mutex,NegotiationError,Participant,ParticipantEvent,ParticipantInfo_Kind as ParticipantKind,PublishDataError,PublishTrackError,RemoteAudioTrack,RemoteParticipant,RemoteTrack,RemoteTrackPublication,RemoteVideoTrack,Room,RoomEvent,RpcError,ScreenSharePresets,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,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,isScriptTransformSupported,isVideoCodec,isVideoFrame,isVideoTrack,needsRbspUnescaping,parseRbsp,protocolVersion,ratchet,setLogExtension,setLogLevel,supportsAV1,supportsAdaptiveStream,supportsAudioOutputSelection,supportsDynacast,supportsVP9,version,videoCodecs,writeRbsp};//# sourceMappingURL=livekit-client.esm.mjs.map