@webex/internal-media-core 1.35.2 → 1.35.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -4926,6 +4926,10 @@ exports.LocalTrackEvents = void 0;
4926
4926
  * Fires when there has been a change in the underlying track.
4927
4927
  */
4928
4928
  LocalTrackEvents["UnderlyingTrackChange"] = "underlying-track-change";
4929
+ /**
4930
+ * Fires when the applyConstraints() has been called for the track.
4931
+ */
4932
+ LocalTrackEvents["TrackConstraintsChange"] = "track-constraints-change";
4929
4933
  })(exports.LocalTrackEvents || (exports.LocalTrackEvents = {}));
4930
4934
  // TBD: Fix this once types are published separately
4931
4935
  // export type TrackEffect = BaseMicrophoneEffect | BaseCameraEffect;
@@ -5114,7 +5118,7 @@ class LocalTrack extends EventEmitter$2 {
5114
5118
  return effect;
5115
5119
  }
5116
5120
  /**
5117
- * Cleanup local microphone track.
5121
+ * Cleanup the local microphone track.
5118
5122
  */
5119
5123
  disposeEffects() {
5120
5124
  if (this.effects.size > 0) {
@@ -5124,6 +5128,57 @@ class LocalTrack extends EventEmitter$2 {
5124
5128
  this.emit(exports.LocalTrackEvents.UnderlyingTrackChange);
5125
5129
  }
5126
5130
  }
5131
+ /**
5132
+ * Apply constraints to the track.
5133
+ *
5134
+ * @param constraints - The constraints to apply to the track.
5135
+ * @returns A promise which resolves when the constraints have been successfully applied.
5136
+ */
5137
+ applyConstraints(constraints) {
5138
+ return __awaiter$1(this, void 0, void 0, function* () {
5139
+ logger$3.log("Applying constraints to local track:", constraints);
5140
+ var ret = this.underlyingTrack.applyConstraints(constraints).then(() => {
5141
+ this.emit(exports.LocalTrackEvents.TrackConstraintsChange);
5142
+ });
5143
+ return ret;
5144
+ });
5145
+ }
5146
+ /**
5147
+ * Get the current constraints of the track.
5148
+ *
5149
+ * @returns The constraints of the track.
5150
+ */
5151
+ getConstraints() {
5152
+ return this.underlyingTrack.getConstraints();
5153
+ }
5154
+ /**
5155
+ * Get the current settings of the track.
5156
+ *
5157
+ * @returns The settings of the track.
5158
+ */
5159
+ getSettings() {
5160
+ return this.underlyingTrack.getSettings();
5161
+ }
5162
+ /**
5163
+ * Check the resolution and then return how many layers will be active.
5164
+ *
5165
+ * @returns The active layers count.
5166
+ */
5167
+ getNumActiveSimulcastLayers() {
5168
+ var activeSimulcastLayersNumber = 0;
5169
+ if (this.trackState.type === 'audio') {
5170
+ return activeSimulcastLayersNumber;
5171
+ }
5172
+ var videoHeight = this.underlyingTrack.getSettings().height;
5173
+ if (videoHeight <= 180) {
5174
+ activeSimulcastLayersNumber = 1;
5175
+ } else if (videoHeight <= 360) {
5176
+ activeSimulcastLayersNumber = 2;
5177
+ } else {
5178
+ activeSimulcastLayersNumber = 3;
5179
+ }
5180
+ return activeSimulcastLayersNumber;
5181
+ }
5127
5182
  }
5128
5183
  LocalTrack.Events = exports.LocalTrackEvents;
5129
5184
 
@@ -8552,6 +8607,44 @@ class PeerConnection extends EventEmitter$2 {
8552
8607
  get iceGatheringState() {
8553
8608
  return this.pc.iceGatheringState;
8554
8609
  }
8610
+ /**
8611
+ * Returns the type of a connection that has been established.
8612
+ *
8613
+ * @returns The connection type which would be `ConnectionType`.
8614
+ */
8615
+ getCurrentConnectionType() {
8616
+ var _a;
8617
+ return __awaiter$1(this, void 0, void 0, function* () {
8618
+ // make sure this method only can be called when the ice connection is established;
8619
+ var isIceConnected = this.pc.iceConnectionState === 'connected' || this.pc.iceConnectionState === 'completed';
8620
+ if (!isIceConnected) {
8621
+ throw new Error('Ice connection is not established');
8622
+ }
8623
+ var succeededLocalCandidateIds = new Set();
8624
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8625
+ var localCandidateStatsReports = [];
8626
+ (yield this.pc.getStats()).forEach(report => {
8627
+ var _a;
8628
+ // collect all local candidate ids from `candidate-pair` stats reports with `succeeded` state.
8629
+ if (report.type === 'candidate-pair' && ((_a = report.state) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'succeeded') {
8630
+ succeededLocalCandidateIds.add(report.localCandidateId);
8631
+ }
8632
+ // collect all `local-candidate` stats.
8633
+ if (report.type === 'local-candidate') {
8634
+ localCandidateStatsReports.push(report);
8635
+ }
8636
+ });
8637
+ // find the `local-candidate` stats which report id contains in `succeededLocalCandidateIds`.
8638
+ var localCandidate = localCandidateStatsReports.find(report => succeededLocalCandidateIds.has(report.id));
8639
+ if (!localCandidate) {
8640
+ return 'unknown';
8641
+ }
8642
+ if (localCandidate.relayProtocol) {
8643
+ return "TURN-".concat(localCandidate.relayProtocol.toUpperCase());
8644
+ }
8645
+ return (_a = localCandidate.protocol) === null || _a === void 0 ? void 0 : _a.toUpperCase();
8646
+ });
8647
+ }
8555
8648
  }
8556
8649
  PeerConnection.Events = PeerConnectionEvents;
8557
8650
 
@@ -12132,7 +12225,7 @@ function injectContentTypes(sdp, contentTypeMap) {
12132
12225
  });
12133
12226
  }
12134
12227
  function injectJmpAttributes(parsedSdp, csiMap, streamSignalingMode) {
12135
- parsedSdp.avMedia.filter(mLine => mLine.direction === 'sendrecv' || mLine.direction === 'sendonly').forEach(mLine => {
12228
+ parsedSdp.avMedia.filter(mLine => mLine.direction === 'sendrecv' || mLine.direction === 'inactive').forEach(mLine => {
12136
12229
  if (!mLine.otherLines.find(line => line instanceof JmpLine)) {
12137
12230
  mLine.addLine(new JmpLine());
12138
12231
  }
@@ -12149,11 +12242,15 @@ function injectJmpAttributes(parsedSdp, csiMap, streamSignalingMode) {
12149
12242
  }
12150
12243
  });
12151
12244
  }
12245
+ function hasSimulcast(av) {
12246
+ return !!av.simulcast || av.ssrcGroups.map(sg => sg.semantics).some(sem => sem === 'SIM');
12247
+ }
12152
12248
  class SendOnlyTransceiver extends Transceiver {
12153
12249
  constructor(rtcpRtpTransceiver, csi) {
12154
12250
  super(rtcpRtpTransceiver);
12155
12251
  this.requested = false;
12156
12252
  this.csi = csi;
12253
+ this.direction = 'sendrecv';
12157
12254
  this.handleTrackChange = this.handleTrackChange.bind(this);
12158
12255
  }
12159
12256
  handleTrackChange() {
@@ -12173,6 +12270,7 @@ class SendOnlyTransceiver extends Transceiver {
12173
12270
  var _a;
12174
12271
  return __awaiter(this, void 0, void 0, function* () {
12175
12272
  _super.replaceTransceiver.call(this, newRtcRtpTransceiver);
12273
+ newRtcRtpTransceiver.direction = this.direction;
12176
12274
  if (this.requested) {
12177
12275
  yield this.sender.replaceTrack(((_a = this.publishedTrack) === null || _a === void 0 ? void 0 : _a.underlyingTrack) || null);
12178
12276
  }
@@ -12242,8 +12340,8 @@ class SendOnlyTransceiver extends Transceiver {
12242
12340
  return this.replacePublishedTrack();
12243
12341
  }
12244
12342
  setActive(enabled) {
12245
- var direction = enabled ? 'sendrecv' : 'inactive';
12246
- this._rtcRtpTransceiver.direction = direction;
12343
+ this.direction = enabled ? 'sendrecv' : 'inactive';
12344
+ this._rtcRtpTransceiver.direction = this.direction;
12247
12345
  return this._rtcRtpTransceiver.direction !== this._rtcRtpTransceiver.currentDirection;
12248
12346
  }
12249
12347
  getStats() {
@@ -14142,11 +14240,14 @@ var defaultMultistreamConnectionOptions = {
14142
14240
  streamSignalingMode: 'SSRC',
14143
14241
  bundlePolicy: 'max-compat',
14144
14242
  iceServers: undefined,
14145
- disableContentSimulcast: true
14243
+ disableContentSimulcast: true,
14244
+ enableMainAudio: true,
14245
+ enableMainVideo: true
14146
14246
  };
14147
14247
  class MultistreamConnection extends EventEmitter {
14148
14248
  constructor() {
14149
14249
  var userOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
14250
+ var _a, _b;
14150
14251
  super();
14151
14252
  this.sendTransceivers = new Map();
14152
14253
  this.recvTransceivers = new Map();
@@ -14154,6 +14255,7 @@ class MultistreamConnection extends EventEmitter {
14154
14255
  this.pendingJmpTasks = [];
14155
14256
  this.metricsCallback = () => {};
14156
14257
  this.overuseUpdateCallback = () => {};
14258
+ this.customCodecParameters = new Map();
14157
14259
  this.midMap = new Map();
14158
14260
  this.currentMid = 0;
14159
14261
  this.options = Object.assign(Object.assign({}, defaultMultistreamConnectionOptions), userOptions);
@@ -14167,6 +14269,8 @@ class MultistreamConnection extends EventEmitter {
14167
14269
  var videoMainEncodingOptions = this.getVideoEncodingOptions(MediaContent$1.Main);
14168
14270
  this.createSendTransceiver(MediaType.VideoMain, mainSceneId, videoMainEncodingOptions);
14169
14271
  this.createSendTransceiver(MediaType.AudioMain, mainSceneId);
14272
+ (_a = this.sendTransceivers.get(MediaType.VideoMain)) === null || _a === void 0 ? void 0 : _a.setActive(this.options.enableMainVideo);
14273
+ (_b = this.sendTransceivers.get(MediaType.AudioMain)) === null || _b === void 0 ? void 0 : _b.setActive(this.options.enableMainAudio);
14170
14274
  if (this.options.floorControlledPresentation) {
14171
14275
  var videoPresentationEncodingOptions = this.getVideoEncodingOptions(MediaContent$1.Slides);
14172
14276
  var contentSceneId = generateSceneId();
@@ -14288,9 +14392,11 @@ class MultistreamConnection extends EventEmitter {
14288
14392
  this.jmpSessions.set(mediaType, jmpSession);
14289
14393
  }
14290
14394
  sendSourceWarnings(mediaType, requests) {
14395
+ var _a;
14291
14396
  if (getMediaFamily$1(mediaType) === MediaFamily.Video) {
14292
14397
  var sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
14293
14398
  var signaler = this.streamSignalerManager.getEgressStreamSignalerOrThrow(sendTransceiver.mid);
14399
+ var activeSimulcastLayerNumber = ((_a = sendTransceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.getNumActiveSimulcastLayers()) || 0;
14294
14400
  var sourceWarnings = [];
14295
14401
  requests.forEach(_ref5 => {
14296
14402
  var {
@@ -14310,6 +14416,12 @@ class MultistreamConnection extends EventEmitter {
14310
14416
  state: 'invalid source',
14311
14417
  csi: sendTransceiver.csi
14312
14418
  });
14419
+ } else if (signaler.getEncodingIndexForStreamId(id) > activeSimulcastLayerNumber) {
14420
+ sourceWarnings.push({
14421
+ id,
14422
+ state: 'no source',
14423
+ csi: sendTransceiver.csi
14424
+ });
14313
14425
  }
14314
14426
  });
14315
14427
  });
@@ -14486,22 +14598,19 @@ class MultistreamConnection extends EventEmitter {
14486
14598
  });
14487
14599
  }
14488
14600
  addTrackListeners(mediaType, track) {
14489
- var onTrackMute = event => {
14490
- var sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
14491
- var signaler = this.streamSignalerManager.getEgressStreamSignaler(sendTransceiver.mid);
14492
- if (!signaler) {
14493
- return;
14601
+ var onTrackResolutionChange = () => {
14602
+ var sources = this.getVideoSources(mediaType);
14603
+ if (sources != null) {
14604
+ this.sendSourceIndication(mediaType, 1, sources);
14494
14605
  }
14495
- if (this.getPublishedTracks().includes(track)) {
14496
- if (getMediaFamily$1(mediaType) === MediaFamily.Audio) {
14497
- this.sendSourceIndication(mediaType, +!event.trackState.muted);
14498
- } else {
14499
- var state = event.trackState.muted ? 'avatar' : 'live';
14500
- var sources = signaler.getSenderIds().map(id => ({
14501
- id,
14502
- state,
14503
- csi: sendTransceiver.csi
14504
- }));
14606
+ };
14607
+ track.on(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
14608
+ var onTrackMute = event => {
14609
+ if (getMediaFamily$1(mediaType) === MediaFamily.Audio) {
14610
+ this.sendSourceIndication(mediaType, +!event.trackState.muted);
14611
+ } else {
14612
+ var sources = this.getVideoSources(mediaType);
14613
+ if (sources != null) {
14505
14614
  this.sendSourceIndication(mediaType, +!event.trackState.muted, sources);
14506
14615
  }
14507
14616
  }
@@ -14511,28 +14620,47 @@ class MultistreamConnection extends EventEmitter {
14511
14620
  if (!event.isPublished) {
14512
14621
  track.off(LocalTrack.Events.Muted, onTrackMute);
14513
14622
  track.off(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
14623
+ track.off(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
14514
14624
  }
14515
- var sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
14516
- var signaler = this.streamSignalerManager.getEgressStreamSignaler(sendTransceiver.mid);
14517
- if (!signaler) {
14518
- return;
14519
- }
14520
- if (!event.trackState.muted) {
14521
- if (getMediaFamily$1(mediaType) === MediaFamily.Audio) {
14522
- this.sendSourceIndication(mediaType, +event.isPublished);
14523
- } else {
14524
- var state = event.isPublished ? 'live' : 'no source';
14525
- var sources = signaler.getSenderIds().map(id => ({
14526
- id,
14527
- state,
14528
- csi: sendTransceiver.csi
14529
- }));
14625
+ if (getMediaFamily$1(mediaType) === MediaFamily.Audio) {
14626
+ this.sendSourceIndication(mediaType, +event.isPublished);
14627
+ } else {
14628
+ var sources = this.getVideoSources(mediaType);
14629
+ if (sources != null) {
14530
14630
  this.sendSourceIndication(mediaType, +event.isPublished, sources);
14531
14631
  }
14532
14632
  }
14533
14633
  };
14534
14634
  track.on(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
14535
14635
  }
14636
+ getVideoSources(mediaType) {
14637
+ var _a, _b, _c;
14638
+ var sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
14639
+ var signaler = this.streamSignalerManager.getEgressStreamSignaler(sendTransceiver.mid);
14640
+ if (!signaler) {
14641
+ return null;
14642
+ }
14643
+ var activeSimulcastLayerNumber = ((_a = sendTransceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.getNumActiveSimulcastLayers()) || 0;
14644
+ var published = (_b = sendTransceiver.publishedTrack) === null || _b === void 0 ? void 0 : _b.published;
14645
+ var muted = ((_c = sendTransceiver.publishedTrack) === null || _c === void 0 ? void 0 : _c.muted) === true;
14646
+ return signaler.getSenderIds().map(id => {
14647
+ var state;
14648
+ if (!published) {
14649
+ state = 'no source';
14650
+ } else if (muted) {
14651
+ state = 'avatar';
14652
+ } else if (activeSimulcastLayerNumber <= signaler.getEncodingIndexForStreamId(id)) {
14653
+ state = 'no source';
14654
+ } else {
14655
+ state = 'live';
14656
+ }
14657
+ return {
14658
+ id,
14659
+ state,
14660
+ csi: sendTransceiver.csi
14661
+ };
14662
+ });
14663
+ }
14536
14664
  createReceiveSlot(mediaType) {
14537
14665
  return __awaiter(this, void 0, void 0, function* () {
14538
14666
  var rtcRtpTransceiver = this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
@@ -14547,20 +14675,7 @@ class MultistreamConnection extends EventEmitter {
14547
14675
  return ingressSignaler.getReceiverId();
14548
14676
  });
14549
14677
  if (this.pc.getRemoteDescription()) {
14550
- yield this.pc.createOffer().then(offer => {
14551
- if (!offer.sdp) {
14552
- throw new Error('No SDP offer');
14553
- }
14554
- offer.sdp = this.preProcessLocalOffer(offer.sdp);
14555
- return this.pc.setLocalDescription(offer);
14556
- }).then(() => {
14557
- var _a;
14558
- var answer = this.preProcessRemoteAnswer((_a = this.pc.getRemoteDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
14559
- return this.pc.setRemoteDescription({
14560
- type: 'answer',
14561
- sdp: answer
14562
- });
14563
- });
14678
+ yield this.doLocalOfferAnswer();
14564
14679
  }
14565
14680
  this.recvTransceivers.set(mediaType, [...(this.recvTransceivers.get(mediaType) || []), recvOnlyTransceiver]);
14566
14681
  return recvOnlyTransceiver.receiveSlot;
@@ -14608,10 +14723,31 @@ class MultistreamConnection extends EventEmitter {
14608
14723
  }
14609
14724
  setAnswer(answer) {
14610
14725
  return __awaiter(this, void 0, void 0, function* () {
14726
+ var isInitialAnswer = !this.pc.getRemoteDescription();
14611
14727
  var sdp = this.preProcessRemoteAnswer(answer);
14612
14728
  return this.pc.setRemoteDescription({
14613
14729
  type: 'answer',
14614
14730
  sdp
14731
+ }).then(() => {
14732
+ if (isInitialAnswer && this.customCodecParameters.size > 0) {
14733
+ this.doLocalOfferAnswer();
14734
+ }
14735
+ });
14736
+ });
14737
+ }
14738
+ doLocalOfferAnswer() {
14739
+ var _a;
14740
+ return __awaiter(this, void 0, void 0, function* () {
14741
+ var offer = yield this.pc.createOffer();
14742
+ if (!offer.sdp) {
14743
+ throw new Error('No SDP offer');
14744
+ }
14745
+ offer.sdp = this.preProcessLocalOffer(offer.sdp);
14746
+ yield this.pc.setLocalDescription(offer);
14747
+ var answer = this.preProcessRemoteAnswer((_a = this.pc.getRemoteDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
14748
+ return this.pc.setRemoteDescription({
14749
+ type: 'answer',
14750
+ sdp: answer
14615
14751
  });
14616
14752
  });
14617
14753
  }
@@ -14632,7 +14768,7 @@ class MultistreamConnection extends EventEmitter {
14632
14768
  });
14633
14769
  parsed.avMedia.filter(av => av.direction === 'sendrecv').forEach(av => {
14634
14770
  var egressSignaler = this.streamSignalerManager.getOrCreateEgressStreamSignaler(av.mid);
14635
- var simulcastEnabled = !!av.simulcast;
14771
+ var simulcastEnabled = hasSimulcast(av);
14636
14772
  var rtxEnabled = av.type === 'video';
14637
14773
  egressSignaler.signalStreams(simulcastEnabled, rtxEnabled, av);
14638
14774
  if (av.type === 'video') {
@@ -14641,6 +14777,22 @@ class MultistreamConnection extends EventEmitter {
14641
14777
  ci.fmtParams.set('max-fs', "".concat(defaultMaxVideoEncodeFrameSize));
14642
14778
  });
14643
14779
  }
14780
+ var mediaType = [...this.sendTransceivers.keys()].find(key => {
14781
+ var _a;
14782
+ return ((_a = this.sendTransceivers.get(key)) === null || _a === void 0 ? void 0 : _a.mid) === av.mid;
14783
+ });
14784
+ if (mediaType && this.customCodecParameters.has(mediaType)) {
14785
+ [...av.codecs.values()].filter(ci => ci.name === (av.type === 'audio' ? 'opus' : 'H264')).forEach(ci => {
14786
+ var _a;
14787
+ (_a = this.customCodecParameters.get(mediaType)) === null || _a === void 0 ? void 0 : _a.forEach((value, param) => {
14788
+ if (value === null) {
14789
+ ci.fmtParams.delete(param);
14790
+ } else {
14791
+ ci.fmtParams.set(param, "".concat(value));
14792
+ }
14793
+ });
14794
+ });
14795
+ }
14644
14796
  });
14645
14797
  if (getBrowserDetails().name !== 'Firefox') {
14646
14798
  setupBundle(parsed, this.options.bundlePolicy, this.midMap);
@@ -14690,6 +14842,31 @@ class MultistreamConnection extends EventEmitter {
14690
14842
  getPublishedTracks() {
14691
14843
  return [...this.sendTransceivers.values()].map(transceiver => transceiver.publishedTrack).filter(Boolean);
14692
14844
  }
14845
+ setCodecParameters(mediaType, parameters) {
14846
+ return __awaiter(this, void 0, void 0, function* () {
14847
+ var currentParams = this.customCodecParameters.get(mediaType) || new Map();
14848
+ Object.entries(parameters).forEach(_ref7 => {
14849
+ var [param, value] = _ref7;
14850
+ currentParams.set(param, value);
14851
+ });
14852
+ this.customCodecParameters.set(mediaType, currentParams);
14853
+ if (this.pc.getRemoteDescription()) {
14854
+ yield this.doLocalOfferAnswer();
14855
+ }
14856
+ });
14857
+ }
14858
+ deleteCodecParameters(mediaType, parameters) {
14859
+ return __awaiter(this, void 0, void 0, function* () {
14860
+ var currentParams = this.customCodecParameters.get(mediaType) || new Map();
14861
+ parameters.forEach(param => {
14862
+ currentParams.set(param, null);
14863
+ });
14864
+ this.customCodecParameters.set(mediaType, currentParams);
14865
+ if (this.pc.getRemoteDescription()) {
14866
+ yield this.doLocalOfferAnswer();
14867
+ }
14868
+ });
14869
+ }
14693
14870
  requestMedia(mediaType, mediaRequests) {
14694
14871
  var _a;
14695
14872
  var task = () => {
@@ -14765,8 +14942,8 @@ class MultistreamConnection extends EventEmitter {
14765
14942
  }
14766
14943
  preProcessStats(stats) {
14767
14944
  return __awaiter(this, void 0, void 0, function* () {
14768
- yield Promise.all([...this.sendTransceivers.entries()].map(_ref7 => {
14769
- var [mediaType, transceiver] = _ref7;
14945
+ yield Promise.all([...this.sendTransceivers.entries()].map(_ref8 => {
14946
+ var [mediaType, transceiver] = _ref8;
14770
14947
  return __awaiter(this, void 0, void 0, function* () {
14771
14948
  (yield transceiver.getStats()).forEach(senderStats => {
14772
14949
  var _a;
@@ -14784,8 +14961,8 @@ class MultistreamConnection extends EventEmitter {
14784
14961
  });
14785
14962
  });
14786
14963
  }));
14787
- yield Promise.all([...this.recvTransceivers.entries()].map(_ref8 => {
14788
- var [mediaType, transceivers] = _ref8;
14964
+ yield Promise.all([...this.recvTransceivers.entries()].map(_ref9 => {
14965
+ var [mediaType, transceivers] = _ref9;
14789
14966
  return __awaiter(this, void 0, void 0, function* () {
14790
14967
  yield Promise.all(transceivers.map(transceiver => __awaiter(this, void 0, void 0, function* () {
14791
14968
  (yield transceiver.getStats()).forEach(receiverStats => {
@@ -23908,6 +24085,14 @@ class MultistreamRoapMediaConnection extends EventEmitter$4 {
23908
24085
  }
23909
24086
  this.roap.roapMessageReceived(roapMessage);
23910
24087
  }
24088
+ enableMultistreamAudio(enabled) {
24089
+ this.log('enableMultistreamAudio()', 'called');
24090
+ var sdpNegotiationNeeded = this.multistreamConnection.enableMultistreamAudio(enabled);
24091
+ if (sdpNegotiationNeeded) {
24092
+ return this.roap.initiateOffer();
24093
+ }
24094
+ return Promise.resolve();
24095
+ }
23911
24096
  publishTrack(track) {
23912
24097
  this.log('publishTrack()', 'called');
23913
24098
  return this.multistreamConnection.publishTrack(track);
package/dist/esm/index.js CHANGED
@@ -4915,6 +4915,10 @@ var LocalTrackEvents;
4915
4915
  * Fires when there has been a change in the underlying track.
4916
4916
  */
4917
4917
  LocalTrackEvents["UnderlyingTrackChange"] = "underlying-track-change";
4918
+ /**
4919
+ * Fires when the applyConstraints() has been called for the track.
4920
+ */
4921
+ LocalTrackEvents["TrackConstraintsChange"] = "track-constraints-change";
4918
4922
  })(LocalTrackEvents || (LocalTrackEvents = {}));
4919
4923
  // TBD: Fix this once types are published separately
4920
4924
  // export type TrackEffect = BaseMicrophoneEffect | BaseCameraEffect;
@@ -5103,7 +5107,7 @@ class LocalTrack extends EventEmitter$2 {
5103
5107
  return effect;
5104
5108
  }
5105
5109
  /**
5106
- * Cleanup local microphone track.
5110
+ * Cleanup the local microphone track.
5107
5111
  */
5108
5112
  disposeEffects() {
5109
5113
  if (this.effects.size > 0) {
@@ -5113,6 +5117,57 @@ class LocalTrack extends EventEmitter$2 {
5113
5117
  this.emit(LocalTrackEvents.UnderlyingTrackChange);
5114
5118
  }
5115
5119
  }
5120
+ /**
5121
+ * Apply constraints to the track.
5122
+ *
5123
+ * @param constraints - The constraints to apply to the track.
5124
+ * @returns A promise which resolves when the constraints have been successfully applied.
5125
+ */
5126
+ applyConstraints(constraints) {
5127
+ return __awaiter$1(this, void 0, void 0, function* () {
5128
+ logger$3.log("Applying constraints to local track:", constraints);
5129
+ var ret = this.underlyingTrack.applyConstraints(constraints).then(() => {
5130
+ this.emit(LocalTrackEvents.TrackConstraintsChange);
5131
+ });
5132
+ return ret;
5133
+ });
5134
+ }
5135
+ /**
5136
+ * Get the current constraints of the track.
5137
+ *
5138
+ * @returns The constraints of the track.
5139
+ */
5140
+ getConstraints() {
5141
+ return this.underlyingTrack.getConstraints();
5142
+ }
5143
+ /**
5144
+ * Get the current settings of the track.
5145
+ *
5146
+ * @returns The settings of the track.
5147
+ */
5148
+ getSettings() {
5149
+ return this.underlyingTrack.getSettings();
5150
+ }
5151
+ /**
5152
+ * Check the resolution and then return how many layers will be active.
5153
+ *
5154
+ * @returns The active layers count.
5155
+ */
5156
+ getNumActiveSimulcastLayers() {
5157
+ var activeSimulcastLayersNumber = 0;
5158
+ if (this.trackState.type === 'audio') {
5159
+ return activeSimulcastLayersNumber;
5160
+ }
5161
+ var videoHeight = this.underlyingTrack.getSettings().height;
5162
+ if (videoHeight <= 180) {
5163
+ activeSimulcastLayersNumber = 1;
5164
+ } else if (videoHeight <= 360) {
5165
+ activeSimulcastLayersNumber = 2;
5166
+ } else {
5167
+ activeSimulcastLayersNumber = 3;
5168
+ }
5169
+ return activeSimulcastLayersNumber;
5170
+ }
5116
5171
  }
5117
5172
  LocalTrack.Events = LocalTrackEvents;
5118
5173
 
@@ -8541,6 +8596,44 @@ class PeerConnection extends EventEmitter$2 {
8541
8596
  get iceGatheringState() {
8542
8597
  return this.pc.iceGatheringState;
8543
8598
  }
8599
+ /**
8600
+ * Returns the type of a connection that has been established.
8601
+ *
8602
+ * @returns The connection type which would be `ConnectionType`.
8603
+ */
8604
+ getCurrentConnectionType() {
8605
+ var _a;
8606
+ return __awaiter$1(this, void 0, void 0, function* () {
8607
+ // make sure this method only can be called when the ice connection is established;
8608
+ var isIceConnected = this.pc.iceConnectionState === 'connected' || this.pc.iceConnectionState === 'completed';
8609
+ if (!isIceConnected) {
8610
+ throw new Error('Ice connection is not established');
8611
+ }
8612
+ var succeededLocalCandidateIds = new Set();
8613
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8614
+ var localCandidateStatsReports = [];
8615
+ (yield this.pc.getStats()).forEach(report => {
8616
+ var _a;
8617
+ // collect all local candidate ids from `candidate-pair` stats reports with `succeeded` state.
8618
+ if (report.type === 'candidate-pair' && ((_a = report.state) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'succeeded') {
8619
+ succeededLocalCandidateIds.add(report.localCandidateId);
8620
+ }
8621
+ // collect all `local-candidate` stats.
8622
+ if (report.type === 'local-candidate') {
8623
+ localCandidateStatsReports.push(report);
8624
+ }
8625
+ });
8626
+ // find the `local-candidate` stats which report id contains in `succeededLocalCandidateIds`.
8627
+ var localCandidate = localCandidateStatsReports.find(report => succeededLocalCandidateIds.has(report.id));
8628
+ if (!localCandidate) {
8629
+ return 'unknown';
8630
+ }
8631
+ if (localCandidate.relayProtocol) {
8632
+ return "TURN-".concat(localCandidate.relayProtocol.toUpperCase());
8633
+ }
8634
+ return (_a = localCandidate.protocol) === null || _a === void 0 ? void 0 : _a.toUpperCase();
8635
+ });
8636
+ }
8544
8637
  }
8545
8638
  PeerConnection.Events = PeerConnectionEvents;
8546
8639
 
@@ -12121,7 +12214,7 @@ function injectContentTypes(sdp, contentTypeMap) {
12121
12214
  });
12122
12215
  }
12123
12216
  function injectJmpAttributes(parsedSdp, csiMap, streamSignalingMode) {
12124
- parsedSdp.avMedia.filter(mLine => mLine.direction === 'sendrecv' || mLine.direction === 'sendonly').forEach(mLine => {
12217
+ parsedSdp.avMedia.filter(mLine => mLine.direction === 'sendrecv' || mLine.direction === 'inactive').forEach(mLine => {
12125
12218
  if (!mLine.otherLines.find(line => line instanceof JmpLine)) {
12126
12219
  mLine.addLine(new JmpLine());
12127
12220
  }
@@ -12138,11 +12231,15 @@ function injectJmpAttributes(parsedSdp, csiMap, streamSignalingMode) {
12138
12231
  }
12139
12232
  });
12140
12233
  }
12234
+ function hasSimulcast(av) {
12235
+ return !!av.simulcast || av.ssrcGroups.map(sg => sg.semantics).some(sem => sem === 'SIM');
12236
+ }
12141
12237
  class SendOnlyTransceiver extends Transceiver {
12142
12238
  constructor(rtcpRtpTransceiver, csi) {
12143
12239
  super(rtcpRtpTransceiver);
12144
12240
  this.requested = false;
12145
12241
  this.csi = csi;
12242
+ this.direction = 'sendrecv';
12146
12243
  this.handleTrackChange = this.handleTrackChange.bind(this);
12147
12244
  }
12148
12245
  handleTrackChange() {
@@ -12162,6 +12259,7 @@ class SendOnlyTransceiver extends Transceiver {
12162
12259
  var _a;
12163
12260
  return __awaiter(this, void 0, void 0, function* () {
12164
12261
  _super.replaceTransceiver.call(this, newRtcRtpTransceiver);
12262
+ newRtcRtpTransceiver.direction = this.direction;
12165
12263
  if (this.requested) {
12166
12264
  yield this.sender.replaceTrack(((_a = this.publishedTrack) === null || _a === void 0 ? void 0 : _a.underlyingTrack) || null);
12167
12265
  }
@@ -12231,8 +12329,8 @@ class SendOnlyTransceiver extends Transceiver {
12231
12329
  return this.replacePublishedTrack();
12232
12330
  }
12233
12331
  setActive(enabled) {
12234
- var direction = enabled ? 'sendrecv' : 'inactive';
12235
- this._rtcRtpTransceiver.direction = direction;
12332
+ this.direction = enabled ? 'sendrecv' : 'inactive';
12333
+ this._rtcRtpTransceiver.direction = this.direction;
12236
12334
  return this._rtcRtpTransceiver.direction !== this._rtcRtpTransceiver.currentDirection;
12237
12335
  }
12238
12336
  getStats() {
@@ -14131,11 +14229,14 @@ var defaultMultistreamConnectionOptions = {
14131
14229
  streamSignalingMode: 'SSRC',
14132
14230
  bundlePolicy: 'max-compat',
14133
14231
  iceServers: undefined,
14134
- disableContentSimulcast: true
14232
+ disableContentSimulcast: true,
14233
+ enableMainAudio: true,
14234
+ enableMainVideo: true
14135
14235
  };
14136
14236
  class MultistreamConnection extends EventEmitter {
14137
14237
  constructor() {
14138
14238
  var userOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
14239
+ var _a, _b;
14139
14240
  super();
14140
14241
  this.sendTransceivers = new Map();
14141
14242
  this.recvTransceivers = new Map();
@@ -14143,6 +14244,7 @@ class MultistreamConnection extends EventEmitter {
14143
14244
  this.pendingJmpTasks = [];
14144
14245
  this.metricsCallback = () => {};
14145
14246
  this.overuseUpdateCallback = () => {};
14247
+ this.customCodecParameters = new Map();
14146
14248
  this.midMap = new Map();
14147
14249
  this.currentMid = 0;
14148
14250
  this.options = Object.assign(Object.assign({}, defaultMultistreamConnectionOptions), userOptions);
@@ -14156,6 +14258,8 @@ class MultistreamConnection extends EventEmitter {
14156
14258
  var videoMainEncodingOptions = this.getVideoEncodingOptions(MediaContent$1.Main);
14157
14259
  this.createSendTransceiver(MediaType$1.VideoMain, mainSceneId, videoMainEncodingOptions);
14158
14260
  this.createSendTransceiver(MediaType$1.AudioMain, mainSceneId);
14261
+ (_a = this.sendTransceivers.get(MediaType$1.VideoMain)) === null || _a === void 0 ? void 0 : _a.setActive(this.options.enableMainVideo);
14262
+ (_b = this.sendTransceivers.get(MediaType$1.AudioMain)) === null || _b === void 0 ? void 0 : _b.setActive(this.options.enableMainAudio);
14159
14263
  if (this.options.floorControlledPresentation) {
14160
14264
  var videoPresentationEncodingOptions = this.getVideoEncodingOptions(MediaContent$1.Slides);
14161
14265
  var contentSceneId = generateSceneId();
@@ -14277,9 +14381,11 @@ class MultistreamConnection extends EventEmitter {
14277
14381
  this.jmpSessions.set(mediaType, jmpSession);
14278
14382
  }
14279
14383
  sendSourceWarnings(mediaType, requests) {
14384
+ var _a;
14280
14385
  if (getMediaFamily$1(mediaType) === MediaFamily$1.Video) {
14281
14386
  var sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
14282
14387
  var signaler = this.streamSignalerManager.getEgressStreamSignalerOrThrow(sendTransceiver.mid);
14388
+ var activeSimulcastLayerNumber = ((_a = sendTransceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.getNumActiveSimulcastLayers()) || 0;
14283
14389
  var sourceWarnings = [];
14284
14390
  requests.forEach(_ref5 => {
14285
14391
  var {
@@ -14299,6 +14405,12 @@ class MultistreamConnection extends EventEmitter {
14299
14405
  state: 'invalid source',
14300
14406
  csi: sendTransceiver.csi
14301
14407
  });
14408
+ } else if (signaler.getEncodingIndexForStreamId(id) > activeSimulcastLayerNumber) {
14409
+ sourceWarnings.push({
14410
+ id,
14411
+ state: 'no source',
14412
+ csi: sendTransceiver.csi
14413
+ });
14302
14414
  }
14303
14415
  });
14304
14416
  });
@@ -14475,22 +14587,19 @@ class MultistreamConnection extends EventEmitter {
14475
14587
  });
14476
14588
  }
14477
14589
  addTrackListeners(mediaType, track) {
14478
- var onTrackMute = event => {
14479
- var sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
14480
- var signaler = this.streamSignalerManager.getEgressStreamSignaler(sendTransceiver.mid);
14481
- if (!signaler) {
14482
- return;
14590
+ var onTrackResolutionChange = () => {
14591
+ var sources = this.getVideoSources(mediaType);
14592
+ if (sources != null) {
14593
+ this.sendSourceIndication(mediaType, 1, sources);
14483
14594
  }
14484
- if (this.getPublishedTracks().includes(track)) {
14485
- if (getMediaFamily$1(mediaType) === MediaFamily$1.Audio) {
14486
- this.sendSourceIndication(mediaType, +!event.trackState.muted);
14487
- } else {
14488
- var state = event.trackState.muted ? 'avatar' : 'live';
14489
- var sources = signaler.getSenderIds().map(id => ({
14490
- id,
14491
- state,
14492
- csi: sendTransceiver.csi
14493
- }));
14595
+ };
14596
+ track.on(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
14597
+ var onTrackMute = event => {
14598
+ if (getMediaFamily$1(mediaType) === MediaFamily$1.Audio) {
14599
+ this.sendSourceIndication(mediaType, +!event.trackState.muted);
14600
+ } else {
14601
+ var sources = this.getVideoSources(mediaType);
14602
+ if (sources != null) {
14494
14603
  this.sendSourceIndication(mediaType, +!event.trackState.muted, sources);
14495
14604
  }
14496
14605
  }
@@ -14500,28 +14609,47 @@ class MultistreamConnection extends EventEmitter {
14500
14609
  if (!event.isPublished) {
14501
14610
  track.off(LocalTrack.Events.Muted, onTrackMute);
14502
14611
  track.off(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
14612
+ track.off(LocalTrack.Events.TrackConstraintsChange, onTrackResolutionChange);
14503
14613
  }
14504
- var sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
14505
- var signaler = this.streamSignalerManager.getEgressStreamSignaler(sendTransceiver.mid);
14506
- if (!signaler) {
14507
- return;
14508
- }
14509
- if (!event.trackState.muted) {
14510
- if (getMediaFamily$1(mediaType) === MediaFamily$1.Audio) {
14511
- this.sendSourceIndication(mediaType, +event.isPublished);
14512
- } else {
14513
- var state = event.isPublished ? 'live' : 'no source';
14514
- var sources = signaler.getSenderIds().map(id => ({
14515
- id,
14516
- state,
14517
- csi: sendTransceiver.csi
14518
- }));
14614
+ if (getMediaFamily$1(mediaType) === MediaFamily$1.Audio) {
14615
+ this.sendSourceIndication(mediaType, +event.isPublished);
14616
+ } else {
14617
+ var sources = this.getVideoSources(mediaType);
14618
+ if (sources != null) {
14519
14619
  this.sendSourceIndication(mediaType, +event.isPublished, sources);
14520
14620
  }
14521
14621
  }
14522
14622
  };
14523
14623
  track.on(LocalTrack.Events.PublishedStateUpdate, onTrackPublish);
14524
14624
  }
14625
+ getVideoSources(mediaType) {
14626
+ var _a, _b, _c;
14627
+ var sendTransceiver = this.getSendTransceiverOrThrow(mediaType);
14628
+ var signaler = this.streamSignalerManager.getEgressStreamSignaler(sendTransceiver.mid);
14629
+ if (!signaler) {
14630
+ return null;
14631
+ }
14632
+ var activeSimulcastLayerNumber = ((_a = sendTransceiver.publishedTrack) === null || _a === void 0 ? void 0 : _a.getNumActiveSimulcastLayers()) || 0;
14633
+ var published = (_b = sendTransceiver.publishedTrack) === null || _b === void 0 ? void 0 : _b.published;
14634
+ var muted = ((_c = sendTransceiver.publishedTrack) === null || _c === void 0 ? void 0 : _c.muted) === true;
14635
+ return signaler.getSenderIds().map(id => {
14636
+ var state;
14637
+ if (!published) {
14638
+ state = 'no source';
14639
+ } else if (muted) {
14640
+ state = 'avatar';
14641
+ } else if (activeSimulcastLayerNumber <= signaler.getEncodingIndexForStreamId(id)) {
14642
+ state = 'no source';
14643
+ } else {
14644
+ state = 'live';
14645
+ }
14646
+ return {
14647
+ id,
14648
+ state,
14649
+ csi: sendTransceiver.csi
14650
+ };
14651
+ });
14652
+ }
14525
14653
  createReceiveSlot(mediaType) {
14526
14654
  return __awaiter(this, void 0, void 0, function* () {
14527
14655
  var rtcRtpTransceiver = this.pc.addTransceiver(toMediaStreamTrackKind(mediaType), {
@@ -14536,20 +14664,7 @@ class MultistreamConnection extends EventEmitter {
14536
14664
  return ingressSignaler.getReceiverId();
14537
14665
  });
14538
14666
  if (this.pc.getRemoteDescription()) {
14539
- yield this.pc.createOffer().then(offer => {
14540
- if (!offer.sdp) {
14541
- throw new Error('No SDP offer');
14542
- }
14543
- offer.sdp = this.preProcessLocalOffer(offer.sdp);
14544
- return this.pc.setLocalDescription(offer);
14545
- }).then(() => {
14546
- var _a;
14547
- var answer = this.preProcessRemoteAnswer((_a = this.pc.getRemoteDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
14548
- return this.pc.setRemoteDescription({
14549
- type: 'answer',
14550
- sdp: answer
14551
- });
14552
- });
14667
+ yield this.doLocalOfferAnswer();
14553
14668
  }
14554
14669
  this.recvTransceivers.set(mediaType, [...(this.recvTransceivers.get(mediaType) || []), recvOnlyTransceiver]);
14555
14670
  return recvOnlyTransceiver.receiveSlot;
@@ -14597,10 +14712,31 @@ class MultistreamConnection extends EventEmitter {
14597
14712
  }
14598
14713
  setAnswer(answer) {
14599
14714
  return __awaiter(this, void 0, void 0, function* () {
14715
+ var isInitialAnswer = !this.pc.getRemoteDescription();
14600
14716
  var sdp = this.preProcessRemoteAnswer(answer);
14601
14717
  return this.pc.setRemoteDescription({
14602
14718
  type: 'answer',
14603
14719
  sdp
14720
+ }).then(() => {
14721
+ if (isInitialAnswer && this.customCodecParameters.size > 0) {
14722
+ this.doLocalOfferAnswer();
14723
+ }
14724
+ });
14725
+ });
14726
+ }
14727
+ doLocalOfferAnswer() {
14728
+ var _a;
14729
+ return __awaiter(this, void 0, void 0, function* () {
14730
+ var offer = yield this.pc.createOffer();
14731
+ if (!offer.sdp) {
14732
+ throw new Error('No SDP offer');
14733
+ }
14734
+ offer.sdp = this.preProcessLocalOffer(offer.sdp);
14735
+ yield this.pc.setLocalDescription(offer);
14736
+ var answer = this.preProcessRemoteAnswer((_a = this.pc.getRemoteDescription()) === null || _a === void 0 ? void 0 : _a.sdp);
14737
+ return this.pc.setRemoteDescription({
14738
+ type: 'answer',
14739
+ sdp: answer
14604
14740
  });
14605
14741
  });
14606
14742
  }
@@ -14621,7 +14757,7 @@ class MultistreamConnection extends EventEmitter {
14621
14757
  });
14622
14758
  parsed.avMedia.filter(av => av.direction === 'sendrecv').forEach(av => {
14623
14759
  var egressSignaler = this.streamSignalerManager.getOrCreateEgressStreamSignaler(av.mid);
14624
- var simulcastEnabled = !!av.simulcast;
14760
+ var simulcastEnabled = hasSimulcast(av);
14625
14761
  var rtxEnabled = av.type === 'video';
14626
14762
  egressSignaler.signalStreams(simulcastEnabled, rtxEnabled, av);
14627
14763
  if (av.type === 'video') {
@@ -14630,6 +14766,22 @@ class MultistreamConnection extends EventEmitter {
14630
14766
  ci.fmtParams.set('max-fs', "".concat(defaultMaxVideoEncodeFrameSize));
14631
14767
  });
14632
14768
  }
14769
+ var mediaType = [...this.sendTransceivers.keys()].find(key => {
14770
+ var _a;
14771
+ return ((_a = this.sendTransceivers.get(key)) === null || _a === void 0 ? void 0 : _a.mid) === av.mid;
14772
+ });
14773
+ if (mediaType && this.customCodecParameters.has(mediaType)) {
14774
+ [...av.codecs.values()].filter(ci => ci.name === (av.type === 'audio' ? 'opus' : 'H264')).forEach(ci => {
14775
+ var _a;
14776
+ (_a = this.customCodecParameters.get(mediaType)) === null || _a === void 0 ? void 0 : _a.forEach((value, param) => {
14777
+ if (value === null) {
14778
+ ci.fmtParams.delete(param);
14779
+ } else {
14780
+ ci.fmtParams.set(param, "".concat(value));
14781
+ }
14782
+ });
14783
+ });
14784
+ }
14633
14785
  });
14634
14786
  if (getBrowserDetails().name !== 'Firefox') {
14635
14787
  setupBundle(parsed, this.options.bundlePolicy, this.midMap);
@@ -14679,6 +14831,31 @@ class MultistreamConnection extends EventEmitter {
14679
14831
  getPublishedTracks() {
14680
14832
  return [...this.sendTransceivers.values()].map(transceiver => transceiver.publishedTrack).filter(Boolean);
14681
14833
  }
14834
+ setCodecParameters(mediaType, parameters) {
14835
+ return __awaiter(this, void 0, void 0, function* () {
14836
+ var currentParams = this.customCodecParameters.get(mediaType) || new Map();
14837
+ Object.entries(parameters).forEach(_ref7 => {
14838
+ var [param, value] = _ref7;
14839
+ currentParams.set(param, value);
14840
+ });
14841
+ this.customCodecParameters.set(mediaType, currentParams);
14842
+ if (this.pc.getRemoteDescription()) {
14843
+ yield this.doLocalOfferAnswer();
14844
+ }
14845
+ });
14846
+ }
14847
+ deleteCodecParameters(mediaType, parameters) {
14848
+ return __awaiter(this, void 0, void 0, function* () {
14849
+ var currentParams = this.customCodecParameters.get(mediaType) || new Map();
14850
+ parameters.forEach(param => {
14851
+ currentParams.set(param, null);
14852
+ });
14853
+ this.customCodecParameters.set(mediaType, currentParams);
14854
+ if (this.pc.getRemoteDescription()) {
14855
+ yield this.doLocalOfferAnswer();
14856
+ }
14857
+ });
14858
+ }
14682
14859
  requestMedia(mediaType, mediaRequests) {
14683
14860
  var _a;
14684
14861
  var task = () => {
@@ -14754,8 +14931,8 @@ class MultistreamConnection extends EventEmitter {
14754
14931
  }
14755
14932
  preProcessStats(stats) {
14756
14933
  return __awaiter(this, void 0, void 0, function* () {
14757
- yield Promise.all([...this.sendTransceivers.entries()].map(_ref7 => {
14758
- var [mediaType, transceiver] = _ref7;
14934
+ yield Promise.all([...this.sendTransceivers.entries()].map(_ref8 => {
14935
+ var [mediaType, transceiver] = _ref8;
14759
14936
  return __awaiter(this, void 0, void 0, function* () {
14760
14937
  (yield transceiver.getStats()).forEach(senderStats => {
14761
14938
  var _a;
@@ -14773,8 +14950,8 @@ class MultistreamConnection extends EventEmitter {
14773
14950
  });
14774
14951
  });
14775
14952
  }));
14776
- yield Promise.all([...this.recvTransceivers.entries()].map(_ref8 => {
14777
- var [mediaType, transceivers] = _ref8;
14953
+ yield Promise.all([...this.recvTransceivers.entries()].map(_ref9 => {
14954
+ var [mediaType, transceivers] = _ref9;
14778
14955
  return __awaiter(this, void 0, void 0, function* () {
14779
14956
  yield Promise.all(transceivers.map(transceiver => __awaiter(this, void 0, void 0, function* () {
14780
14957
  (yield transceiver.getStats()).forEach(receiverStats => {
@@ -23897,6 +24074,14 @@ class MultistreamRoapMediaConnection extends EventEmitter$4 {
23897
24074
  }
23898
24075
  this.roap.roapMessageReceived(roapMessage);
23899
24076
  }
24077
+ enableMultistreamAudio(enabled) {
24078
+ this.log('enableMultistreamAudio()', 'called');
24079
+ var sdpNegotiationNeeded = this.multistreamConnection.enableMultistreamAudio(enabled);
24080
+ if (sdpNegotiationNeeded) {
24081
+ return this.roap.initiateOffer();
24082
+ }
24083
+ return Promise.resolve();
24084
+ }
23900
24085
  publishTrack(track) {
23901
24086
  this.log('publishTrack()', 'called');
23902
24087
  return this.multistreamConnection.publishTrack(track);
@@ -27,6 +27,7 @@ export declare class MultistreamRoapMediaConnection extends EventEmitter {
27
27
  getStats(): Promise<RTCStatsReport>;
28
28
  getTransceiverStats(): Promise<TransceiverStats>;
29
29
  roapMessageReceived(roapMessage: RoapMessage): void;
30
+ enableMultistreamAudio(enabled: boolean): Promise<void>;
30
31
  publishTrack(track: LocalTrack): Promise<void>;
31
32
  unpublishTrack(track: LocalTrack): Promise<void>;
32
33
  createReceiveSlot(mediaType: MediaType): Promise<ReceiveSlot>;
@@ -1 +1 @@
1
- {"version":3,"file":"MultistreamRoapMediaConnection.d.ts","sourceRoot":"","sources":["../../../src/MediaConnection/MultistreamRoapMediaConnection.ts"],"names":[],"mappings":";AAAA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAElC,OAAO,EAEL,UAAU,EACV,YAAY,EAGZ,WAAW,EACX,gBAAgB,EACjB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAA6C,SAAS,EAAC,MAAM,yBAAyB,CAAC;AAG9F,OAAO,EAAQ,eAAe,EAAE,WAAW,EAAmB,MAAM,cAAc,CAAC;AAKnF,OAAO,EAAC,2BAA2B,EAAC,MAAM,UAAU,CAAC;AAGrD,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,iBAAiB,GAClB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,cAAc,EACd,SAAS,EACT,WAAW,EACX,SAAS,EACT,WAAW,EACX,MAAM,EACN,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAGjC,qBAAa,8BAA+B,SAAQ,YAAY;IAC9D,OAAO,CAAC,EAAE,CAAC,CAAS;IAEpB,OAAO,CAAC,OAAO,CAAC,CAAS;IAEzB,OAAO,CAAC,qBAAqB,CAAwB;IAErD,OAAO,CAAC,IAAI,CAAO;IAEnB,OAAO,CAAC,qBAAqB,CAAS;gBAS1B,qBAAqB,EAAE,2BAA2B,EAAE,OAAO,CAAC,EAAE,MAAM;IAehF,OAAO,CAAC,mBAAmB;IAqC3B,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,2BAA2B;IAyCnC,OAAO,CAAC,UAAU;IA4BX,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB9B,KAAK,IAAI,IAAI;IAOpB,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,eAAe;IAiBhB,SAAS,CAAC,UAAU,EAAE,YAAY,EAAE,EAAE,aAAa,UAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA2B1E,kBAAkB,IAAI,eAAe;IAWrC,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC;IAOnC,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAShD,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAanD,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9C,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhD,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAM7D,YAAY,CAAC,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,IAAI;IAM9E,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,kBAAkB;CAkB3B"}
1
+ {"version":3,"file":"MultistreamRoapMediaConnection.d.ts","sourceRoot":"","sources":["../../../src/MediaConnection/MultistreamRoapMediaConnection.ts"],"names":[],"mappings":";AAAA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAElC,OAAO,EAEL,UAAU,EACV,YAAY,EAGZ,WAAW,EACX,gBAAgB,EACjB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAA6C,SAAS,EAAC,MAAM,yBAAyB,CAAC;AAG9F,OAAO,EAAQ,eAAe,EAAE,WAAW,EAAmB,MAAM,cAAc,CAAC;AAKnF,OAAO,EAAC,2BAA2B,EAAC,MAAM,UAAU,CAAC;AAGrD,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,iBAAiB,GAClB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,cAAc,EACd,SAAS,EACT,WAAW,EACX,SAAS,EACT,WAAW,EACX,MAAM,EACN,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAGjC,qBAAa,8BAA+B,SAAQ,YAAY;IAC9D,OAAO,CAAC,EAAE,CAAC,CAAS;IAEpB,OAAO,CAAC,OAAO,CAAC,CAAS;IAEzB,OAAO,CAAC,qBAAqB,CAAwB;IAErD,OAAO,CAAC,IAAI,CAAO;IAEnB,OAAO,CAAC,qBAAqB,CAAS;gBAS1B,qBAAqB,EAAE,2BAA2B,EAAE,OAAO,CAAC,EAAE,MAAM;IAehF,OAAO,CAAC,mBAAmB;IAqC3B,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,2BAA2B;IAyCnC,OAAO,CAAC,UAAU;IA4BX,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB9B,KAAK,IAAI,IAAI;IAOpB,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,eAAe;IAiBhB,SAAS,CAAC,UAAU,EAAE,YAAY,EAAE,EAAE,aAAa,UAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA2B1E,kBAAkB,IAAI,eAAe;IAWrC,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC;IAOnC,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAShD,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAanD,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvD,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9C,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhD,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;IAM7D,YAAY,CAAC,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,IAAI;IAM9E,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,kBAAkB;CAkB3B"}
@@ -20,5 +20,7 @@ export interface MediaConnectionConfig {
20
20
  }
21
21
  export interface MultistreamConnectionConfig {
22
22
  iceServers: Array<RTCIceServer>;
23
+ enableMainAudio: boolean;
24
+ enableMainVideo: boolean;
23
25
  }
24
26
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/MediaConnection/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAoE;IAC7F,gBAAgB,CAAC,EAAE,OAAO,CAAuE;IACjG,kBAAkB,CAAC,EAAE,OAAO,CAAoE;IAChG,eAAe,CAAC,EAAE;QAChB,KAAK,EAAE,MAAM,CAA6E;QAC1F,KAAK,EAAE,MAAM,CAA6E;KAC3F,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,CACmE;IACxF,iBAAiB,CAAC,EAAE,MAAM,CAAqE;IAC/F,aAAa,CAAC,EAAE,OAAO,CACkC;IACzD,UAAU,CAAC,EAAE,OAAO,CAC4C;IAChE,SAAS,CAAC,EAAE,MAAM,CAEkD;CACrE;AAED,MAAM,WAAW,qBAAqB;IAEpC,UAAU,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAChC,wBAAwB,EAAE,OAAO,CAmBM;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,MAAM,WAAW,2BAA2B;IAE1C,UAAU,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;CACjC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/MediaConnection/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAoE;IAC7F,gBAAgB,CAAC,EAAE,OAAO,CAAuE;IACjG,kBAAkB,CAAC,EAAE,OAAO,CAAoE;IAChG,eAAe,CAAC,EAAE;QAChB,KAAK,EAAE,MAAM,CAA6E;QAC1F,KAAK,EAAE,MAAM,CAA6E;KAC3F,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,CACmE;IACxF,iBAAiB,CAAC,EAAE,MAAM,CAAqE;IAC/F,aAAa,CAAC,EAAE,OAAO,CACkC;IACzD,UAAU,CAAC,EAAE,OAAO,CAC4C;IAChE,SAAS,CAAC,EAAE,MAAM,CAEkD;CACrE;AAED,MAAM,WAAW,qBAAqB;IAEpC,UAAU,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAChC,wBAAwB,EAAE,OAAO,CAmBM;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,MAAM,WAAW,2BAA2B;IAC1C,UAAU,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAChC,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;CAC1B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/internal-media-core",
3
- "version": "1.35.2",
3
+ "version": "1.35.3",
4
4
  "files": [
5
5
  "dist/cjs",
6
6
  "dist/esm",
@@ -47,7 +47,7 @@
47
47
  "@babel/runtime": "^7.18.9",
48
48
  "@webex/json-multistream": "1.20.2",
49
49
  "@webex/ts-sdp": "1.3.0",
50
- "@webex/web-client-media-engine": "1.38.4",
50
+ "@webex/web-client-media-engine": "1.40.2",
51
51
  "detectrtc": "^1.4.1",
52
52
  "events": "^3.3.0",
53
53
  "typed-emitter": "^2.1.0",