livekit-client 2.20.0 → 2.20.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 (116) hide show
  1. package/dist/livekit-client.e2ee.worker.js +1 -1
  2. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  3. package/dist/livekit-client.e2ee.worker.mjs +8 -4
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +156 -16
  6. package/dist/livekit-client.esm.mjs.map +1 -1
  7. package/dist/livekit-client.fm.worker.js +1 -1
  8. package/dist/livekit-client.fm.worker.js.map +1 -1
  9. package/dist/livekit-client.fm.worker.mjs +8 -0
  10. package/dist/livekit-client.fm.worker.mjs.map +1 -1
  11. package/dist/livekit-client.umd.js +1 -1
  12. package/dist/livekit-client.umd.js.map +1 -1
  13. package/dist/src/api/SignalClient.d.ts.map +1 -1
  14. package/dist/src/e2ee/E2eeManager.d.ts +1 -0
  15. package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
  16. package/dist/src/e2ee/types.d.ts +1 -0
  17. package/dist/src/e2ee/types.d.ts.map +1 -1
  18. package/dist/src/e2ee/utils.d.ts +1 -0
  19. package/dist/src/e2ee/utils.d.ts.map +1 -1
  20. package/dist/src/e2ee/worker/DataCryptor.d.ts +1 -0
  21. package/dist/src/e2ee/worker/DataCryptor.d.ts.map +1 -1
  22. package/dist/src/e2ee/worker/FrameCryptor.d.ts +1 -0
  23. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  24. package/dist/src/e2ee/worker/naluUtils.d.ts +1 -0
  25. package/dist/src/e2ee/worker/naluUtils.d.ts.map +1 -1
  26. package/dist/src/e2ee/worker/sifPayload.d.ts +1 -0
  27. package/dist/src/e2ee/worker/sifPayload.d.ts.map +1 -1
  28. package/dist/src/frameMetadata/frameMetadata.d.ts +1 -0
  29. package/dist/src/frameMetadata/frameMetadata.d.ts.map +1 -1
  30. package/dist/src/frameMetadata/types.d.ts +1 -0
  31. package/dist/src/frameMetadata/types.d.ts.map +1 -1
  32. package/dist/src/room/PCTransport.d.ts +40 -1
  33. package/dist/src/room/PCTransport.d.ts.map +1 -1
  34. package/dist/src/room/RTCEngine.d.ts +1 -0
  35. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  36. package/dist/src/room/Room.d.ts +1 -0
  37. package/dist/src/room/Room.d.ts.map +1 -1
  38. package/dist/src/room/data-track/depacketizer.d.ts.map +1 -1
  39. package/dist/src/room/data-track/frame.d.ts +1 -0
  40. package/dist/src/room/data-track/frame.d.ts.map +1 -1
  41. package/dist/src/room/data-track/outgoing/types.d.ts +1 -0
  42. package/dist/src/room/data-track/outgoing/types.d.ts.map +1 -1
  43. package/dist/src/room/data-track/packet/extensions.d.ts +1 -0
  44. package/dist/src/room/data-track/packet/extensions.d.ts.map +1 -1
  45. package/dist/src/room/data-track/packet/index.d.ts +1 -0
  46. package/dist/src/room/data-track/packet/index.d.ts.map +1 -1
  47. package/dist/src/room/data-track/packet/serializable.d.ts +1 -0
  48. package/dist/src/room/data-track/packet/serializable.d.ts.map +1 -1
  49. package/dist/src/room/participant/LocalParticipant.d.ts +1 -0
  50. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  51. package/dist/src/room/participant/Participant.d.ts +1 -0
  52. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  53. package/dist/src/room/track/Track.d.ts +1 -0
  54. package/dist/src/room/track/Track.d.ts.map +1 -1
  55. package/dist/src/room/track/record.d.ts.map +1 -1
  56. package/dist/src/room/utils.d.ts +1 -0
  57. package/dist/src/room/utils.d.ts.map +1 -1
  58. package/dist/src/type-polyfills/non-shared-typed-arrays.d.ts +2 -0
  59. package/dist/src/type-polyfills/non-shared-typed-arrays.d.ts.map +1 -0
  60. package/dist/src/utils/dataPacketBuffer.d.ts +1 -0
  61. package/dist/src/utils/dataPacketBuffer.d.ts.map +1 -1
  62. package/dist/ts4.2/e2ee/E2eeManager.d.ts +1 -0
  63. package/dist/ts4.2/e2ee/types.d.ts +1 -0
  64. package/dist/ts4.2/e2ee/utils.d.ts +1 -0
  65. package/dist/ts4.2/e2ee/worker/DataCryptor.d.ts +1 -0
  66. package/dist/ts4.2/e2ee/worker/FrameCryptor.d.ts +1 -0
  67. package/dist/ts4.2/e2ee/worker/naluUtils.d.ts +1 -0
  68. package/dist/ts4.2/e2ee/worker/sifPayload.d.ts +1 -0
  69. package/dist/ts4.2/frameMetadata/frameMetadata.d.ts +1 -0
  70. package/dist/ts4.2/frameMetadata/types.d.ts +1 -0
  71. package/dist/ts4.2/room/PCTransport.d.ts +40 -1
  72. package/dist/ts4.2/room/RTCEngine.d.ts +1 -0
  73. package/dist/ts4.2/room/Room.d.ts +1 -0
  74. package/dist/ts4.2/room/data-track/frame.d.ts +1 -0
  75. package/dist/ts4.2/room/data-track/outgoing/types.d.ts +1 -0
  76. package/dist/ts4.2/room/data-track/packet/extensions.d.ts +1 -0
  77. package/dist/ts4.2/room/data-track/packet/index.d.ts +1 -0
  78. package/dist/ts4.2/room/data-track/packet/serializable.d.ts +1 -0
  79. package/dist/ts4.2/room/participant/LocalParticipant.d.ts +1 -0
  80. package/dist/ts4.2/room/participant/Participant.d.ts +1 -0
  81. package/dist/ts4.2/room/track/Track.d.ts +1 -0
  82. package/dist/ts4.2/room/utils.d.ts +1 -0
  83. package/dist/ts4.2/type-polyfills/non-shared-typed-arrays.d.ts +2 -0
  84. package/dist/ts4.2/utils/dataPacketBuffer.d.ts +1 -0
  85. package/package.json +2 -2
  86. package/src/api/SignalClient.ts +1 -0
  87. package/src/e2ee/E2eeManager.ts +3 -1
  88. package/src/e2ee/types.ts +1 -0
  89. package/src/e2ee/utils.ts +1 -0
  90. package/src/e2ee/worker/DataCryptor.ts +1 -0
  91. package/src/e2ee/worker/FrameCryptor.test.ts +1 -0
  92. package/src/e2ee/worker/FrameCryptor.ts +1 -0
  93. package/src/e2ee/worker/ParticipantKeyHandler.test.ts +1 -0
  94. package/src/e2ee/worker/e2ee.worker.ts +1 -0
  95. package/src/e2ee/worker/naluUtils.ts +1 -0
  96. package/src/e2ee/worker/sifPayload.ts +1 -0
  97. package/src/frameMetadata/frameMetadata.test.ts +83 -0
  98. package/src/frameMetadata/frameMetadata.ts +8 -0
  99. package/src/frameMetadata/types.ts +1 -0
  100. package/src/room/PCTransport.test.ts +150 -0
  101. package/src/room/PCTransport.ts +113 -0
  102. package/src/room/RTCEngine.ts +1 -0
  103. package/src/room/Room.ts +1 -0
  104. package/src/room/data-track/depacketizer.ts +1 -0
  105. package/src/room/data-track/frame.ts +1 -0
  106. package/src/room/data-track/outgoing/types.ts +1 -0
  107. package/src/room/data-track/packet/extensions.ts +1 -0
  108. package/src/room/data-track/packet/index.ts +1 -0
  109. package/src/room/data-track/packet/serializable.ts +1 -0
  110. package/src/room/participant/LocalParticipant.ts +1 -0
  111. package/src/room/participant/Participant.ts +1 -0
  112. package/src/room/track/Track.ts +1 -0
  113. package/src/room/track/record.ts +1 -0
  114. package/src/room/utils.ts +1 -0
  115. package/src/type-polyfills/{non-shared-typed-arrays.d.ts → non-shared-typed-arrays.ts} +6 -1
  116. package/src/utils/dataPacketBuffer.ts +2 -0
@@ -8937,10 +8937,15 @@ function detectBrowser(window) {
8937
8937
  return brand.brand === 'Chromium';
8938
8938
  });
8939
8939
  if (chromium) {
8940
- return {
8941
- browser: 'chrome',
8942
- version: parseInt(chromium.version, 10)
8943
- };
8940
+ const version = parseInt(chromium.version, 10);
8941
+ // navigator.userAgentData was introduced in Chromium 90
8942
+ // so any Chromium brand reporting a version below 90 is invalid
8943
+ if (version >= 90) {
8944
+ return {
8945
+ browser: 'chrome',
8946
+ version
8947
+ };
8948
+ }
8944
8949
  }
8945
8950
  }
8946
8951
  if (navigator.mozGetUserMedia) {
@@ -9049,6 +9054,9 @@ function filterStats(result, track, outbound) {
9049
9054
  /* eslint-env node */
9050
9055
  const logging = log$4;
9051
9056
  function shimGetUserMedia$2(window, browserDetails) {
9057
+ if (browserDetails.version >= 64) {
9058
+ return;
9059
+ }
9052
9060
  const navigator = window && window.navigator;
9053
9061
  if (!navigator.mediaDevices) {
9054
9062
  return;
@@ -9202,6 +9210,8 @@ function shimGetUserMedia$2(window, browserDetails) {
9202
9210
  // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia
9203
9211
  // function which returns a Promise, it does not accept spec-style
9204
9212
  // constraints.
9213
+ // Fixed in M64 too, see
9214
+ // https://groups.google.com/g/discuss-webrtc/c/DMPTKcXVUQ4/m/85FaASoFBwAJ?
9205
9215
  if (navigator.mediaDevices.getUserMedia) {
9206
9216
  const origGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);
9207
9217
  navigator.mediaDevices.getUserMedia = function (cs) {
@@ -9787,6 +9797,9 @@ function fixNegotiationNeeded(window, browserDetails) {
9787
9797
  /* eslint-env node */
9788
9798
  function shimGetUserMedia$1(window, browserDetails) {
9789
9799
  const navigator = window && window.navigator;
9800
+ if (!navigator.mediaDevices) {
9801
+ return;
9802
+ }
9790
9803
  const MediaStreamTrack = window && window.MediaStreamTrack;
9791
9804
  navigator.getUserMedia = function (constraints, onSuccess, onError) {
9792
9805
  // Replace Firefox 44+'s deprecation warning with unprefixed version.
@@ -9840,10 +9853,10 @@ function shimGetUserMedia$1(window, browserDetails) {
9840
9853
  /* eslint-env node */
9841
9854
 
9842
9855
  function shimGetDisplayMedia(window, preferredMediaSource) {
9843
- if (window.navigator.mediaDevices && 'getDisplayMedia' in window.navigator.mediaDevices) {
9856
+ if (!window.navigator.mediaDevices) {
9844
9857
  return;
9845
9858
  }
9846
- if (!window.navigator.mediaDevices) {
9859
+ if (window.navigator.mediaDevices && 'getDisplayMedia' in window.navigator.mediaDevices) {
9847
9860
  return;
9848
9861
  }
9849
9862
  window.navigator.mediaDevices.getDisplayMedia = function getDisplayMedia(constraints) {
@@ -10023,13 +10036,17 @@ function shimRTCDataChannel(window) {
10023
10036
  window.RTCDataChannel = window.DataChannel;
10024
10037
  }
10025
10038
  }
10026
- function shimAddTransceiver(window) {
10039
+ function shimAddTransceiver(window, browserDetails) {
10027
10040
  // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647
10028
10041
  // Firefox ignores the init sendEncodings options passed to addTransceiver
10029
10042
  // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918
10030
10043
  if (!(typeof window === 'object' && window.RTCPeerConnection)) {
10031
10044
  return;
10032
10045
  }
10046
+ // Fixed by https://bugzilla.mozilla.org/show_bug.cgi?id=1401592 in FF110.
10047
+ if (browserDetails.version >= 110) {
10048
+ return;
10049
+ }
10033
10050
  const origAddTransceiver = window.RTCPeerConnection.prototype.addTransceiver;
10034
10051
  if (origAddTransceiver) {
10035
10052
  window.RTCPeerConnection.prototype.addTransceiver = function addTransceiver() {
@@ -10089,10 +10106,14 @@ function shimAddTransceiver(window) {
10089
10106
  };
10090
10107
  }
10091
10108
  }
10092
- function shimGetParameters(window) {
10109
+ function shimGetParameters(window, browserDetails) {
10093
10110
  if (!(typeof window === 'object' && window.RTCRtpSender)) {
10094
10111
  return;
10095
10112
  }
10113
+ // Fixed by https://bugzilla.mozilla.org/show_bug.cgi?id=1401592 in FF110.
10114
+ if (browserDetails.version >= 110) {
10115
+ return;
10116
+ }
10096
10117
  const origGetParameters = window.RTCRtpSender.prototype.getParameters;
10097
10118
  if (origGetParameters) {
10098
10119
  window.RTCRtpSender.prototype.getParameters = function getParameters() {
@@ -10104,13 +10125,17 @@ function shimGetParameters(window) {
10104
10125
  };
10105
10126
  }
10106
10127
  }
10107
- function shimCreateOffer(window) {
10128
+ function shimCreateOffer(window, browserDetails) {
10108
10129
  // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647
10109
10130
  // Firefox ignores the init sendEncodings options passed to addTransceiver
10110
10131
  // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918
10111
10132
  if (!(typeof window === 'object' && window.RTCPeerConnection)) {
10112
10133
  return;
10113
10134
  }
10135
+ // Fixed by https://bugzilla.mozilla.org/show_bug.cgi?id=1401592 in FF110.
10136
+ if (browserDetails.version >= 110) {
10137
+ return;
10138
+ }
10114
10139
  const origCreateOffer = window.RTCPeerConnection.prototype.createOffer;
10115
10140
  window.RTCPeerConnection.prototype.createOffer = function createOffer() {
10116
10141
  if (this.setParametersPromises && this.setParametersPromises.length) {
@@ -10123,13 +10148,17 @@ function shimCreateOffer(window) {
10123
10148
  return origCreateOffer.apply(this, arguments);
10124
10149
  };
10125
10150
  }
10126
- function shimCreateAnswer(window) {
10151
+ function shimCreateAnswer(window, browserDetails) {
10127
10152
  // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647
10128
10153
  // Firefox ignores the init sendEncodings options passed to addTransceiver
10129
10154
  // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918
10130
10155
  if (!(typeof window === 'object' && window.RTCPeerConnection)) {
10131
10156
  return;
10132
10157
  }
10158
+ // Fixed by https://bugzilla.mozilla.org/show_bug.cgi?id=1401592 in FF110.
10159
+ if (browserDetails.version >= 110) {
10160
+ return;
10161
+ }
10133
10162
  const origCreateAnswer = window.RTCPeerConnection.prototype.createAnswer;
10134
10163
  window.RTCPeerConnection.prototype.createAnswer = function createAnswer() {
10135
10164
  if (this.setParametersPromises && this.setParametersPromises.length) {
@@ -11291,6 +11320,15 @@ function shimMaxMessageSize(window, browserDetails) {
11291
11320
  if (!window.RTCPeerConnection) {
11292
11321
  return;
11293
11322
  }
11323
+ if (browserDetails.browser === 'chrome' && browserDetails.version > 102) {
11324
+ // Unified plan is supported so no need to do anything.
11325
+ return;
11326
+ }
11327
+ if (browserDetails.browser === 'firefox' && browserDetails.version >= 113) {
11328
+ // Native RTCSctpTransport, see
11329
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1278299
11330
+ return;
11331
+ }
11294
11332
  if (!('sctp' in window.RTCPeerConnection.prototype)) {
11295
11333
  Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', {
11296
11334
  get() {
@@ -11427,7 +11465,7 @@ function shimSendThrowTypeError(window, browserDetails) {
11427
11465
  if (!(window.RTCPeerConnection && 'createDataChannel' in window.RTCPeerConnection.prototype)) {
11428
11466
  return;
11429
11467
  }
11430
- if (browserDetails.browser === 'chrome' && browserDetails.version > 149) {
11468
+ if (browserDetails.browser === 'chrome' && browserDetails.version >= 149) {
11431
11469
  // Fixed by https://issues.chromium.org/issues/490588131
11432
11470
  return;
11433
11471
  }
@@ -11706,10 +11744,10 @@ function adapterFactory() {
11706
11744
  shimSenderGetStats(window);
11707
11745
  shimReceiverGetStats(window);
11708
11746
  shimRTCDataChannel(window);
11709
- shimAddTransceiver(window);
11710
- shimGetParameters(window);
11711
- shimCreateOffer(window);
11712
- shimCreateAnswer(window);
11747
+ shimAddTransceiver(window, browserDetails);
11748
+ shimGetParameters(window, browserDetails);
11749
+ shimCreateOffer(window, browserDetails);
11750
+ shimCreateAnswer(window, browserDetails);
11713
11751
  shimRTCIceCandidate(window);
11714
11752
  shimConnectionState(window);
11715
11753
  shimMaxMessageSize(window, browserDetails);
@@ -11843,7 +11881,7 @@ function getMatch(exp, ua) {
11843
11881
  }
11844
11882
  function getOSVersion(ua) {
11845
11883
  return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
11846
- }var version$1 = "2.20.0";const version = version$1;
11884
+ }var version$1 = "2.20.1";const version = version$1;
11847
11885
  const protocolVersion = 17;
11848
11886
  /** Initial client protocol. */
11849
11887
  const CLIENT_PROTOCOL_DEFAULT = 0;
@@ -18215,6 +18253,15 @@ class PCTransport extends eventsExports.EventEmitter {
18215
18253
  });
18216
18254
  }
18217
18255
  });
18256
+ // The server's answer sets per-track codec params (e.g. opus `usedtx`) on
18257
+ // the sections mapped to a published track, but leaves the pre-populated
18258
+ // recvonly placeholder sections with defaults. Conform the placeholders so
18259
+ // each shared payload type is consistent across the bundle, otherwise
18260
+ // libwebrtc flags a "bundled payload type collision".
18261
+ const placeholderMids = this.getPlaceholderMids();
18262
+ if (placeholderMids.size > 0) {
18263
+ conformBundledCodecFmtp(sdpParsed.media, media => placeholderMids.has(getMidString(media.mid)));
18264
+ }
18218
18265
  mungedSDP = libExports.write(sdpParsed);
18219
18266
  }
18220
18267
  yield this.setMungedSDP(sd, mungedSDP, true);
@@ -18359,6 +18406,15 @@ class PCTransport extends eventsExports.EventEmitter {
18359
18406
  });
18360
18407
  }
18361
18408
  });
18409
+ // Conform the placeholder sections (pre-populated, or reverted after an
18410
+ // unpublish) so every shared payload type carries identical fmtp across the
18411
+ // bundle, otherwise libwebrtc flags a "bundled payload type collision".
18412
+ // Detection is by transceiver (mids are stable across renegotiations) since
18413
+ // an unpublished section keeps its `a=msid`.
18414
+ const placeholderMids = this.getPlaceholderMids();
18415
+ if (placeholderMids.size > 0) {
18416
+ conformBundledCodecFmtp(sdpParsed.media, media => placeholderMids.has(getMidString(media.mid)));
18417
+ }
18362
18418
  if (this.latestOfferId > offerId) {
18363
18419
  this.log.warn('latestOfferId mismatch', Object.assign(Object.assign({}, this.logContext), {
18364
18420
  latestOfferId: this.latestOfferId,
@@ -18388,6 +18444,17 @@ class PCTransport extends eventsExports.EventEmitter {
18388
18444
  return answer;
18389
18445
  });
18390
18446
  }
18447
+ /**
18448
+ * Returns the mids of transceivers that carry no outgoing track on this
18449
+ * (publisher) connection: the pre-populated placeholders added by
18450
+ * `RTCEngine.applyInitialPublisherLayout`, plus any transceiver that was used
18451
+ * for a track and reverted on unpublish. Their codec fmtp is conformed to the
18452
+ * published tracks so a shared payload type stays consistent across the bundle.
18453
+ */
18454
+ getPlaceholderMids() {
18455
+ var _a, _b;
18456
+ return placeholderMidsFromTransceivers((_b = (_a = this._pc) === null || _a === void 0 ? void 0 : _a.getTransceivers()) !== null && _b !== void 0 ? _b : []);
18457
+ }
18391
18458
  createDataChannel(label, dataChannelDict) {
18392
18459
  return this.pc.createDataChannel(label, dataChannelDict);
18393
18460
  }
@@ -18610,6 +18677,79 @@ function ensureAudioNackAndStereo(media, stereoMids, nackMids) {
18610
18677
  }
18611
18678
  }
18612
18679
  }
18680
+ /**
18681
+ * Returns the mids of transceivers that carry no outgoing track: the
18682
+ * pre-populated placeholders added by `RTCEngine.applyInitialPublisherLayout`,
18683
+ * plus any transceiver that was used for a track and reverted on unpublish. The
18684
+ * `sender.track` check is the reliable signal — an unpublished section keeps its
18685
+ * `a=msid` (and its stale send-derived fmtp), so it can't be told apart from a
18686
+ * real send by SDP alone. Transceiver mids are stable across renegotiations, so
18687
+ * this works for every offer/answer after the first.
18688
+ * @internal
18689
+ */
18690
+ function placeholderMidsFromTransceivers(transceivers) {
18691
+ const mids = new Set();
18692
+ for (const transceiver of transceivers) {
18693
+ if (transceiver.mid && !transceiver.sender.track) {
18694
+ mids.add(transceiver.mid);
18695
+ }
18696
+ }
18697
+ return mids;
18698
+ }
18699
+ /**
18700
+ * Within a BUNDLE group a payload type must map to identical codec parameters
18701
+ * across every m-line. When the same payload type carries different fmtp between
18702
+ * sections — e.g. opus `usedtx=1` on the published microphone but not on the
18703
+ * pre-populated recvonly placeholders, or H.265 with different `level-id` between
18704
+ * a published video track and a placeholder — libwebrtc flags a "bundled payload
18705
+ * type collision".
18706
+ *
18707
+ * Rewrite the placeholder sections so every shared payload type carries the
18708
+ * same fmtp. Real (non-placeholder) sections always win the canonical value, so
18709
+ * a published track's encoder parameters are never altered. When no real
18710
+ * section declares a payload type — e.g. a placeholder that was reused for a
18711
+ * track and then reverted to recvonly keeps its send-derived `level-id` while
18712
+ * fresh placeholders use the default — the placeholders still converge on the
18713
+ * first value seen, so two placeholders can't disagree either. Only placeholder
18714
+ * sections are ever rewritten, and it is codec-agnostic (opus, H.265, ...).
18715
+ * `isPlaceholder` identifies the sections to conform.
18716
+ * @internal
18717
+ */
18718
+ function conformBundledCodecFmtp(media, isPlaceholder) {
18719
+ var _a, _b;
18720
+ // Canonical fmtp per payload type. Payload types are unique within a BUNDLE
18721
+ // group, so keying by payload alone (across audio and video) is safe. A real
18722
+ // section's value always takes precedence; otherwise the first placeholder
18723
+ // value seen is used so divergent placeholders still converge.
18724
+ const canonicalByPayload = new Map();
18725
+ const fromRealSection = new Set();
18726
+ for (const m of media) {
18727
+ const placeholder = isPlaceholder(m);
18728
+ for (const fmtp of (_a = m.fmtp) !== null && _a !== void 0 ? _a : []) {
18729
+ if (!placeholder) {
18730
+ canonicalByPayload.set(fmtp.payload, fmtp.config);
18731
+ fromRealSection.add(fmtp.payload);
18732
+ } else if (!canonicalByPayload.has(fmtp.payload)) {
18733
+ canonicalByPayload.set(fmtp.payload, fmtp.config);
18734
+ }
18735
+ }
18736
+ }
18737
+ if (canonicalByPayload.size === 0) {
18738
+ return;
18739
+ }
18740
+ // Conform placeholder sections to the canonical fmtp for each shared payload.
18741
+ for (const m of media) {
18742
+ if (!isPlaceholder(m)) {
18743
+ continue;
18744
+ }
18745
+ for (const fmtp of (_b = m.fmtp) !== null && _b !== void 0 ? _b : []) {
18746
+ const config = canonicalByPayload.get(fmtp.payload);
18747
+ if (config !== undefined && fmtp.config !== config) {
18748
+ fmtp.config = config;
18749
+ }
18750
+ }
18751
+ }
18752
+ }
18613
18753
  function extractStereoAndNackAudioFromOffer(offer) {
18614
18754
  var _a;
18615
18755
  const stereoMids = [];