twilio-video 3.0.0-preview.1 → 3.0.0-preview.2

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 (34) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +1 -1
  3. package/dist/twilio-video.js +236 -32
  4. package/dist/twilio-video.min.js +14 -14
  5. package/es5/room.js +2 -2
  6. package/es5/signaling/v2/peerconnection.js +14 -1
  7. package/es5/signaling/v2/peerconnection.js.map +1 -1
  8. package/es5/signaling/v2/peerconnectionmanager.js +12 -0
  9. package/es5/signaling/v2/peerconnectionmanager.js.map +1 -1
  10. package/es5/signaling/v2/remoteparticipant.js +3 -0
  11. package/es5/signaling/v2/remoteparticipant.js.map +1 -1
  12. package/es5/signaling/v2/room.js +8 -8
  13. package/es5/signaling/v2/room.js.map +1 -1
  14. package/es5/signaling/v3/remoteparticipant.js +7 -5
  15. package/es5/signaling/v3/remoteparticipant.js.map +1 -1
  16. package/es5/signaling/v3/remotetrackpublication.js +115 -2
  17. package/es5/signaling/v3/remotetrackpublication.js.map +1 -1
  18. package/es5/signaling/v3/room.js +53 -1
  19. package/es5/signaling/v3/room.js.map +1 -1
  20. package/es5/webrtc/getstats.js +11 -9
  21. package/es5/webrtc/getstats.js.map +1 -1
  22. package/es5/webrtc/index.js +6 -1
  23. package/es5/webrtc/index.js.map +1 -1
  24. package/lib/room.js +2 -2
  25. package/lib/signaling/v2/peerconnection.js +12 -1
  26. package/lib/signaling/v2/peerconnectionmanager.js +13 -0
  27. package/lib/signaling/v2/remoteparticipant.js +3 -0
  28. package/lib/signaling/v2/room.js +8 -8
  29. package/lib/signaling/v3/remoteparticipant.js +8 -4
  30. package/lib/signaling/v3/remotetrackpublication.js +120 -1
  31. package/lib/signaling/v3/room.js +55 -2
  32. package/lib/webrtc/getstats.js +11 -9
  33. package/lib/webrtc/index.js +7 -1
  34. package/package.json +4 -2
package/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@ The Twilio Programmable Video SDKs use [Semantic Versioning](http://www.semver.o
2
2
 
3
3
  **Version 1.x reached End of Life on September 8th, 2021.** See the changelog entry [here](https://www.twilio.com/changelog/end-of-life-complete-for-unsupported-versions-of-the-programmable-video-sdk). Support for the 1.x version ended on December 4th, 2020.
4
4
 
5
+ 3.0.0-preview.2 (August 18, 2022)
6
+ =================================
7
+
8
+ Changes
9
+ -------
10
+
11
+ - `Room.getStats()`, which was broken in `3.0.0-preview.1`, has been fixed in this release. Note that the values reported
12
+ are best-effort approximations based off of the raw WebRTC statistics. (VIDEO-8756)
13
+
5
14
  3.0.0-preview.1 (July 25, 2022)
6
15
  ===============================
7
16
 
package/README.md CHANGED
@@ -74,7 +74,7 @@ Releases of twilio-video.js are hosted on a CDN, and you can include these
74
74
  directly in your web app using a <script> tag.
75
75
 
76
76
  ```html
77
- <script src="//sdk.twilio.com/js/video/releases/3.0.0-preview.1/twilio-video.min.js"></script>
77
+ <script src="//sdk.twilio.com/js/video/releases/3.0.0-preview.2/twilio-video.min.js"></script>
78
78
 
79
79
  ```
80
80
 
@@ -1,4 +1,4 @@
1
- /*! twilio-video.js 3.0.0-preview.1
1
+ /*! twilio-video.js 3.0.0-preview.2
2
2
 
3
3
  The following license applies to all parts of this software except as
4
4
  documented below.
@@ -9625,8 +9625,8 @@ var Room = /** @class */ (function (_super) {
9625
9625
  };
9626
9626
  /**
9627
9627
  * Get the {@link Room}'s media statistics. This is not supported in Safari 12.0 or below
9628
- * due to this bug : https://bugs.webkit.org/show_bug.cgi?id=192601
9629
- *
9628
+ * due to this bug : https://bugs.webkit.org/show_bug.cgi?id=192601. Note that the values
9629
+ * reported are best-effort approximations based off of the raw WebRTC statistics.
9630
9630
  * @returns {Promise.<Array<StatsReport>>}
9631
9631
  */
9632
9632
  Room.prototype.getStats = function () {
@@ -12840,7 +12840,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from) {
12840
12840
  return to;
12841
12841
  };
12842
12842
  var DefaultBackoff = require('../../util/backoff');
12843
- var _a = require('../../webrtc'), DefaultRTCIceCandidate = _a.RTCIceCandidate, DefaultRTCPeerConnection = _a.RTCPeerConnection, DefaultRTCSessionDescription = _a.RTCSessionDescription, getStatistics = _a.getStats;
12843
+ var _a = require('../../webrtc'), DefaultRTCIceCandidate = _a.RTCIceCandidate, DefaultRTCPeerConnection = _a.RTCPeerConnection, DefaultRTCSessionDescription = _a.RTCSessionDescription, getStatistics = _a.getStats, getTrackStatistics = _a.getTrackStats;
12844
12844
  var util = require('../../webrtc/util');
12845
12845
  var _b = require('../../util/constants'), DEFAULT_ICE_GATHERING_TIMEOUT_MS = _b.DEFAULT_ICE_GATHERING_TIMEOUT_MS, DEFAULT_LOG_LEVEL = _b.DEFAULT_LOG_LEVEL, DEFAULT_SESSION_TIMEOUT_SEC = _b.DEFAULT_SESSION_TIMEOUT_SEC, iceRestartBackoffConfig = _b.iceRestartBackoffConfig;
12846
12846
  var _c = require('../../util/sdp'), addOrRewriteNewTrackIds = _c.addOrRewriteNewTrackIds, addOrRewriteTrackIds = _c.addOrRewriteTrackIds, createCodecMapForMediaSection = _c.createCodecMapForMediaSection, disableRtx = _c.disableRtx, enableDtxForOpus = _c.enableDtxForOpus, filterLocalCodecs = _c.filterLocalCodecs, getMediaSections = _c.getMediaSections, removeSSRCAttributes = _c.removeSSRCAttributes, revertSimulcast = _c.revertSimulcast, setCodecPreferences = _c.setCodecPreferences, setSimulcast = _c.setSimulcast;
@@ -14380,6 +14380,19 @@ var PeerConnectionV2 = /** @class */ (function (_super) {
14380
14380
  });
14381
14381
  });
14382
14382
  };
14383
+ /**
14384
+ * Get the statistics for a given remote MediaStreamTrack
14385
+ * @param {MediaStreamTrack} mediaStreamTrack
14386
+ * @returns {Promise<StandardizedTrackStatsReport>}
14387
+ */
14388
+ PeerConnectionV2.prototype.getRemoteTrackStats = function (mediaStreamTrack) {
14389
+ var _this = this;
14390
+ return getTrackStatistics(this._peerConnection, mediaStreamTrack, { isRemote: true })
14391
+ .then(function (_a) {
14392
+ var _b = __read(_a, 1), stats = _b[0];
14393
+ return rewriteTrackId(_this, stats);
14394
+ });
14395
+ };
14383
14396
  /**
14384
14397
  * Get the {@link PeerConnectionV2}'s media statistics.
14385
14398
  * @returns {Promise<StandardizedStatsResponse>}
@@ -15030,6 +15043,18 @@ var PeerConnectionManager = /** @class */ (function (_super) {
15030
15043
  return _this;
15031
15044
  });
15032
15045
  };
15046
+ /**
15047
+ * Get the statistics for a remote MediaStreamTrack.
15048
+ * @param {MediaStreamTrack} mediaStreamTrack
15049
+ * @returns {Promise<Map<PeerConnectionV2#id, StandardizedTrackStatsReport>>}
15050
+ */
15051
+ PeerConnectionManager.prototype.getRemoteTrackStats = function (mediaStreamTrack) {
15052
+ var peerConnections = Array.from(this._peerConnections.values());
15053
+ return Promise.all(peerConnections.map(function (peerConnection) { return peerConnection.getRemoteTrackStats(mediaStreamTrack).then(function (stats) { return [
15054
+ peerConnection.id,
15055
+ stats
15056
+ ]; }); })).then(function (reports) { return new Map(reports); });
15057
+ };
15033
15058
  /**
15034
15059
  * Get the {@link PeerConnectionManager}'s media statistics.
15035
15060
  * @returns {Promise.<Map<PeerConnectionV2#id, StandardizedStatsResponse>>}
@@ -15422,6 +15447,9 @@ var RemoteParticipantV2 = /** @class */ (function (_super) {
15422
15447
  _getPendingTrackReceiver: {
15423
15448
  value: options.getPendingTrackReceiver
15424
15449
  },
15450
+ _getTrackStats: {
15451
+ value: options.getTrackStats
15452
+ },
15425
15453
  updateSubscriberTrackPriority: {
15426
15454
  value: function (trackSid, priority) { return setPriority(trackSid, priority); }
15427
15455
  },
@@ -15820,9 +15848,6 @@ var RoomV2 = /** @class */ (function (_super) {
15820
15848
  _RemoteParticipantSignaling: {
15821
15849
  value: options.RemoteParticipantSignaling
15822
15850
  },
15823
- _subscribed: {
15824
- value: new Map()
15825
- },
15826
15851
  _subscribedRevision: {
15827
15852
  value: 0,
15828
15853
  writable: true
@@ -15830,6 +15855,9 @@ var RoomV2 = /** @class */ (function (_super) {
15830
15855
  _subscriptionFailures: {
15831
15856
  value: new Map()
15832
15857
  },
15858
+ _trackSidsToTrackIds: {
15859
+ value: new Map()
15860
+ },
15833
15861
  _dominantSpeakerSignaling: {
15834
15862
  value: new options.DominantSpeakerSignaling(getTrackReceiver, { log: log })
15835
15863
  },
@@ -16101,7 +16129,7 @@ var RoomV2 = /** @class */ (function (_super) {
16101
16129
  }
16102
16130
  });
16103
16131
  trackSidsToTrackSignalings.forEach(function (trackSignaling) {
16104
- var trackId = _this._subscribed.get(trackSignaling.sid);
16132
+ var trackId = _this._trackSidsToTrackIds.get(trackSignaling.sid);
16105
16133
  if (!trackId || (trackSignaling.isSubscribed && trackSignaling.trackTransceiver.id !== trackId)) {
16106
16134
  trackSignaling.setTrackTransceiver(null);
16107
16135
  }
@@ -16228,7 +16256,7 @@ var RoomV2 = /** @class */ (function (_super) {
16228
16256
  subscribed.tracks.forEach(function (trackState) {
16229
16257
  if (trackState.id) {
16230
16258
  _this._subscriptionFailures.delete(trackState.sid);
16231
- _this._subscribed.set(trackState.sid, trackState.id);
16259
+ _this._trackSidsToTrackIds.set(trackState.sid, trackState.id);
16232
16260
  }
16233
16261
  else if (trackState.error && !_this._subscriptionFailures.has(trackState.sid)) {
16234
16262
  _this._subscriptionFailures.set(trackState.sid, trackState.error);
@@ -16237,9 +16265,9 @@ var RoomV2 = /** @class */ (function (_super) {
16237
16265
  var subscribedTrackSids = new Set(subscribed.tracks
16238
16266
  .filter(function (trackState) { return !!trackState.id; })
16239
16267
  .map(function (trackState) { return trackState.sid; }));
16240
- this._subscribed.forEach(function (trackId, trackSid) {
16268
+ this._trackSidsToTrackIds.forEach(function (trackId, trackSid) {
16241
16269
  if (!subscribedTrackSids.has(trackSid)) {
16242
- _this._subscribed.delete(trackSid);
16270
+ _this._trackSidsToTrackIds.delete(trackSid);
16243
16271
  }
16244
16272
  });
16245
16273
  };
@@ -16380,7 +16408,7 @@ function filterAndAddLocalTrackSids(roomV2, localTrackStats) {
16380
16408
  * @returns {Array<RemoteTrackStats>}
16381
16409
  */
16382
16410
  function filterAndAddRemoteTrackSids(roomV2, remoteTrackStats) {
16383
- var idToSid = new Map(Array.from(roomV2._subscribed.entries()).map(function (_a) {
16411
+ var idToSid = new Map(Array.from(roomV2._trackSidsToTrackIds.entries()).map(function (_a) {
16384
16412
  var _b = __read(_a, 2), sid = _b[0], id = _b[1];
16385
16413
  return [id, sid];
16386
16414
  }));
@@ -17383,13 +17411,15 @@ var RemoteParticipantV3 = /** @class */ (function (_super) {
17383
17411
  * @param {function(Track.SID, Track.Priority): boolean} setPriority
17384
17412
  * @param {function(Track.SID, ClientRenderHint): Promise<void>} setRenderHint
17385
17413
  * @param {function(Track.SID): void} clearTrackHint
17414
+ * @param {function(MediaStreamTrack): Promise<Map<PeerConnectionV2#id, StandardizedTrackStatsReport>>} getTrackStats
17386
17415
  * @param {object} [options]
17387
17416
  */
17388
- function RemoteParticipantV3(participantState, getPendingTrackReceiver, getInitialTrackSwitchOffState, setPriority, setRenderHint, clearTrackHint, options) {
17417
+ function RemoteParticipantV3(participantState, getPendingTrackReceiver, getInitialTrackSwitchOffState, setPriority, setRenderHint, clearTrackHint, getTrackStats, options) {
17389
17418
  var _this = this;
17390
17419
  options = Object.assign({
17391
17420
  RemoteTrackPublicationSignaling: RemoteTrackPublicationV3,
17392
- getPendingTrackReceiver: getPendingTrackReceiver
17421
+ getPendingTrackReceiver: getPendingTrackReceiver,
17422
+ getTrackStats: getTrackStats
17393
17423
  }, options);
17394
17424
  _this = _super.call(this, participantState, getInitialTrackSwitchOffState, setPriority, setRenderHint, clearTrackHint, options) || this;
17395
17425
  return _this;
@@ -17398,13 +17428,13 @@ var RemoteParticipantV3 = /** @class */ (function (_super) {
17398
17428
  * @private
17399
17429
  */
17400
17430
  RemoteParticipantV3.prototype._getOrCreateTrack = function (trackState) {
17401
- var _a = this, RemoteTrackPublicationV3 = _a._RemoteTrackPublicationSignaling, getPendingTrackReceiver = _a._getPendingTrackReceiver;
17431
+ var _a = this, RemoteTrackPublicationV3 = _a._RemoteTrackPublicationSignaling, getPendingTrackReceiver = _a._getPendingTrackReceiver, getTrackStats = _a._getTrackStats;
17402
17432
  var track = this.tracks.get(trackState.sid);
17403
17433
  if (!track) {
17404
17434
  var _b = this.kind === 'data'
17405
17435
  ? { state: 'ON', switchOffReason: null }
17406
- : this._getInitialTrackSwitchOffState(trackState.sid), state = _b.state, switchOffReason = _b.switchOffReason;
17407
- track = new RemoteTrackPublicationV3(trackState, state === 'OFF', switchOffReason);
17436
+ : this._getInitialTrackSwitchOffState(trackState.sid), state = _b.state, _c = _b.switchOffReason, switchOffReason = _c === void 0 ? null : _c;
17437
+ track = new RemoteTrackPublicationV3(trackState, state === 'OFF', switchOffReason, getTrackStats);
17408
17438
  this.addTrack(track);
17409
17439
  getPendingTrackReceiver(track.sid).then(function (trackReceiver) {
17410
17440
  // NOTE(mmalavalli): DataTracks are subscribed to only if corresponding DataTrackReceivers
@@ -17448,22 +17478,37 @@ var RemoteTrackPublicationV3 = /** @class */ (function (_super) {
17448
17478
  * @param {RemoteTrackPublicationV3#Representation} track
17449
17479
  * @param {boolean} isSwitchedOff
17450
17480
  * @param {?string} switchOffReason
17481
+ * @param {function(MediaStreamTrack): Promise<Map<PeerConnectionV2#id, StandardizedTrackStatsReport>>} getTrackStats
17451
17482
  */
17452
- function RemoteTrackPublicationV3(track, isSwitchedOff, switchOffReason) {
17453
- if (switchOffReason === void 0) { switchOffReason = null; }
17483
+ function RemoteTrackPublicationV3(track, isSwitchedOff, switchOffReason, getTrackStats) {
17454
17484
  var _this = this;
17455
17485
  switchOffReason = isSwitchedOff ? switchOffReason : null;
17456
17486
  var enabled = isEnabled(isSwitchedOff, switchOffReason);
17457
17487
  var kind = track.kind, name = track.name, priority = track.priority, sid = track.sid;
17458
17488
  _this = _super.call(this, sid, name, kind, enabled, priority, isSwitchedOff, 3) || this;
17459
17489
  Object.defineProperties(_this, {
17490
+ _getTrackStats: {
17491
+ value: getTrackStats
17492
+ },
17460
17493
  _isSubscribed: {
17461
17494
  value: false,
17462
17495
  writable: true
17463
17496
  },
17497
+ _pendingGetTrackStatsPromise: {
17498
+ value: Promise.resolve(),
17499
+ writable: true
17500
+ },
17464
17501
  _switchOffReason: {
17465
17502
  value: switchOffReason,
17466
17503
  writable: true
17504
+ },
17505
+ _switchOffStateChangeStats: {
17506
+ value: initialTrackStats(sid, kind),
17507
+ writable: true
17508
+ },
17509
+ _switchOnMediaStreamTrackStats: {
17510
+ value: initialTrackStats(sid, kind),
17511
+ writable: true
17467
17512
  }
17468
17513
  });
17469
17514
  return _this;
@@ -17490,6 +17535,55 @@ var RemoteTrackPublicationV3 = /** @class */ (function (_super) {
17490
17535
  enumerable: false,
17491
17536
  configurable: true
17492
17537
  });
17538
+ /**
17539
+ * Adjust Track statistics based on new stats. Returns the most recent switched
17540
+ * off state change Track statistics if no argument is provided.
17541
+ * @param {StandardizedTrackStatsReport} [newMediaStreamTrackStats]
17542
+ * @returns {StandardizedTrackStatsReport}
17543
+ */
17544
+ RemoteTrackPublicationV3.prototype.adjustTrackStats = function (newMediaStreamTrackStats) {
17545
+ var _this = this;
17546
+ if (newMediaStreamTrackStats === void 0) { newMediaStreamTrackStats = {}; }
17547
+ var cumulativeStatsProps = [
17548
+ 'bytesReceived',
17549
+ 'framesDecoded',
17550
+ 'packetsLost',
17551
+ 'packetsReceived',
17552
+ 'totalDecodeTime'
17553
+ ];
17554
+ var snapshotStatsProps = [
17555
+ 'audioOutputLevel',
17556
+ 'codecName',
17557
+ 'estimatedPlayoutTimestamp',
17558
+ 'frameHeightReceived',
17559
+ 'frameRateReceived',
17560
+ 'frameWidthReceived',
17561
+ 'jitter',
17562
+ 'jitterBufferDelay',
17563
+ 'jitterBufferEmittedCount',
17564
+ 'roundTripTime',
17565
+ 'ssrc',
17566
+ 'timestamp',
17567
+ 'trackId'
17568
+ ];
17569
+ var trackStats = Object.assign({}, this._switchOffStateChangeStats);
17570
+ cumulativeStatsProps.forEach(function (prop) {
17571
+ if (prop in newMediaStreamTrackStats) {
17572
+ trackStats[prop] = _this._switchOffStateChangeStats[prop] + newMediaStreamTrackStats[prop] - _this._switchOnMediaStreamTrackStats[prop];
17573
+ }
17574
+ });
17575
+ snapshotStatsProps.forEach(function (prop) {
17576
+ if (prop in newMediaStreamTrackStats) {
17577
+ trackStats[prop] = newMediaStreamTrackStats[prop];
17578
+ }
17579
+ });
17580
+ if (!this.isSubscribed || this.isSwitchedOff) {
17581
+ trackStats.ssrc = '';
17582
+ trackStats.timestamp = Date.now();
17583
+ trackStats.trackId = '';
17584
+ }
17585
+ return trackStats;
17586
+ };
17493
17587
  /**
17494
17588
  * Updates track switch on/off state.
17495
17589
  * @param {boolean} isSwitchedOff
@@ -17515,8 +17609,22 @@ var RemoteTrackPublicationV3 = /** @class */ (function (_super) {
17515
17609
  * @returns {this}
17516
17610
  */
17517
17611
  RemoteTrackPublicationV3.prototype.setTrackTransceiver = function (trackReceiver, isSubscribed) {
17612
+ var _this = this;
17518
17613
  isSubscribed = !!trackReceiver || isSubscribed;
17519
17614
  var shouldEmitUpdated = trackReceiver !== this.trackTransceiver || isSubscribed !== this.isSubscribed;
17615
+ if (this.kind !== 'data' && trackReceiver !== this.trackTransceiver) {
17616
+ var track_1 = (trackReceiver || this.trackTransceiver).track;
17617
+ this._pendingGetTrackStatsPromise = this._pendingGetTrackStatsPromise.then(function () { return _this._getTrackStats(track_1); }).then(function (report) {
17618
+ // NOTE(mmalavalli): Because RSPv3 is associated with Large Rooms only, the statistics
17619
+ // map will contain an entry associated with only one RTCPeerConnection.
17620
+ var mediaStreamTrackStats = report.values().next().value;
17621
+ if (trackReceiver) {
17622
+ _this._switchOnMediaStreamTrackStats = mediaStreamTrackStats;
17623
+ }
17624
+ _this._switchOffStateChangeStats = _this.adjustTrackStats(mediaStreamTrackStats);
17625
+ _this._pendingGetTrackStatsPromise = Promise.resolve();
17626
+ });
17627
+ }
17520
17628
  this._trackTransceiver = trackReceiver;
17521
17629
  this._isSubscribed = isSubscribed;
17522
17630
  if (shouldEmitUpdated) {
@@ -17547,6 +17655,41 @@ var RemoteTrackPublicationV3 = /** @class */ (function (_super) {
17547
17655
  function isEnabled(isSwitchedOff, switchOffReason) {
17548
17656
  return !(isSwitchedOff && switchOffReason === 'DISABLED_BY_PUBLISHER');
17549
17657
  }
17658
+ /**
17659
+ * @private
17660
+ * @param {Track.SID} sid
17661
+ * @param {Track.Kind} kind
17662
+ * @returns {StandardizedTrackStatsReport}
17663
+ */
17664
+ function initialTrackStats(sid, kind) {
17665
+ return Object.assign({
17666
+ bytesReceived: 0,
17667
+ codecName: '',
17668
+ estimatedPlayoutTimestamp: 0,
17669
+ jitter: 0,
17670
+ jitterBufferDelay: 0,
17671
+ jitterBufferEmittedCount: 0,
17672
+ packetsLost: 0,
17673
+ packetsReceived: 0,
17674
+ roundTripTime: 0,
17675
+ ssrc: '',
17676
+ timestamp: 0,
17677
+ trackId: '',
17678
+ trackSid: sid
17679
+ }, {
17680
+ audio: {
17681
+ audioOutputLevel: 0
17682
+ },
17683
+ data: {},
17684
+ video: {
17685
+ frameHeightReceived: 0,
17686
+ frameRateReceived: 0,
17687
+ framesDecoded: 0,
17688
+ frameWidthReceived: 0,
17689
+ totalDecodeTime: 0
17690
+ }
17691
+ }[kind]);
17692
+ }
17550
17693
  /**
17551
17694
  * The Room Signaling Protocol (RSP) representation of a {@link RemoteTrackPublicationV3}.
17552
17695
  * @typedef {object} RemoteTrackPublicationV3#Representation
@@ -17609,7 +17752,7 @@ var RoomV3 = /** @class */ (function (_super) {
17609
17752
  RoomV3.prototype._createRemoteParticipant = function (participantState) {
17610
17753
  var _this = this;
17611
17754
  var RemoteParticipantV3 = this._RemoteParticipantSignaling;
17612
- return new RemoteParticipantV3(participantState, function (trackSid) { return _this._getPendingTrackReceiver(trackSid); }, function (trackSid) { return _this._getInitialTrackSwitchOffState(trackSid); }, function (trackSid, priority) { return _this._trackPrioritySignaling.sendTrackPriorityUpdate(trackSid, 'subscribe', priority); }, function (trackSid, hint) { return _this._renderHintsSignaling.setTrackHint(trackSid, hint); }, function (trackSid) { return _this._renderHintsSignaling.clearTrackHint(trackSid); });
17755
+ return new RemoteParticipantV3(participantState, function (trackSid) { return _this._getPendingTrackReceiver(trackSid); }, function (trackSid) { return _this._getInitialTrackSwitchOffState(trackSid); }, function (trackSid, priority) { return _this._trackPrioritySignaling.sendTrackPriorityUpdate(trackSid, 'subscribe', priority); }, function (trackSid, hint) { return _this._renderHintsSignaling.setTrackHint(trackSid, hint); }, function (trackSid) { return _this._renderHintsSignaling.clearTrackHint(trackSid); }, function (track) { return _this._peerConnectionManager.getRemoteTrackStats(track); });
17613
17756
  };
17614
17757
  /**
17615
17758
  * @private
@@ -17693,10 +17836,12 @@ var RoomV3 = /** @class */ (function (_super) {
17693
17836
  // MID. If a RemoteTrackPublicationV3's RemoteTrack is switched off, then we should still be subscribed
17694
17837
  // to it, even though it no longer has an MID associated with it.
17695
17838
  trackSignaling.setTrackTransceiver(null, isSwitchedOff);
17839
+ _this._trackSidsToTrackIds.delete(trackSignaling.sid);
17696
17840
  }
17697
17841
  if (!isSwitchedOff) {
17698
17842
  _this._getTrackReceiver(mid, 'mid').then(function (trackReceiver) {
17699
17843
  trackSignaling.setTrackTransceiver(trackReceiver, true);
17844
+ _this._trackSidsToTrackIds.set(trackSignaling.sid, trackReceiver.id);
17700
17845
  // NOTE(mpatwardhan): when track is switched on, send the switchOn message
17701
17846
  // only after track receiver is set so that application can access (new) mediaStreamTrack
17702
17847
  trackSignaling.setSwitchedOff(isSwitchedOff, switchOffReason);
@@ -17728,6 +17873,7 @@ var RoomV3 = /** @class */ (function (_super) {
17728
17873
  _this._pendingSwitchOffStates.delete(sid);
17729
17874
  _this._pendingTrackMids.delete(sid);
17730
17875
  trackSignaling.setTrackTransceiver(null, false);
17876
+ _this._trackSidsToTrackIds.delete(trackSignaling.sid);
17731
17877
  }
17732
17878
  });
17733
17879
  });
@@ -17739,6 +17885,55 @@ var RoomV3 = /** @class */ (function (_super) {
17739
17885
  RoomV3.prototype._updateSubscribed = function (roomState) {
17740
17886
  /* Do nothing since RSP v3 messages will not contain the "subscribed" property. */
17741
17887
  };
17888
+ /**
17889
+ * Get the {@link RoomV3}'s media statistics. Note that the values reported
17890
+ * are best-effort approximations based off of the raw WebRTC statistics.
17891
+ * @returns {Promise.<Map<PeerConnectionV2#id, StandardizedStatsResponse>>}
17892
+ */
17893
+ RoomV3.prototype.getStats = function () {
17894
+ var _this = this;
17895
+ return _super.prototype.getStats.call(this).then(function (responses) {
17896
+ var trackSidsToTrackSignalings = _this._getTrackSidsToTrackSignalings();
17897
+ var trackSignalings = Array.from(trackSidsToTrackSignalings.values());
17898
+ var switchedOffMediaTrackSignalings = trackSignalings.filter(function (_a) {
17899
+ var isSubscribed = _a.isSubscribed, isSwitchedOff = _a.isSwitchedOff, kind = _a.kind;
17900
+ return kind !== 'data' && isSubscribed && isSwitchedOff;
17901
+ });
17902
+ var switchedOffMediaTrackSidsToTrackStats = new Map(switchedOffMediaTrackSignalings.map(function (trackSignaling) { return [trackSignaling.sid, trackSignaling.adjustTrackStats()]; }));
17903
+ responses.forEach(function (response) {
17904
+ var remoteAudioTrackStats = response.remoteAudioTrackStats, remoteVideoTrackStats = response.remoteVideoTrackStats;
17905
+ // NOTE(mmalavalli): Adjust stats for switched on RemoteAudioTracks with respect
17906
+ // to its associated MediaStreamTrack.
17907
+ remoteAudioTrackStats.forEach(function (stats, i) {
17908
+ var trackSignaling = trackSidsToTrackSignalings.get(stats.trackSid);
17909
+ if (trackSignaling) {
17910
+ remoteAudioTrackStats[i] = trackSignaling.adjustTrackStats(stats);
17911
+ }
17912
+ });
17913
+ // NOTE(mmalavalli): Adjust stats for switched on RemoteVideoTracks with respect
17914
+ // to its associated MediaStreamTrack.
17915
+ remoteVideoTrackStats.forEach(function (stats, i) {
17916
+ var trackSignaling = trackSidsToTrackSignalings.get(stats.trackSid);
17917
+ if (trackSignaling) {
17918
+ remoteVideoTrackStats[i] = trackSignaling.adjustTrackStats(stats);
17919
+ }
17920
+ });
17921
+ // NOTE(mmalavalli): Add stats for switched off media RemoteTracks in
17922
+ // remoteAudioTrackStats and remoteVideoTrackStats respectively.
17923
+ switchedOffMediaTrackSidsToTrackStats.forEach(function (trackStats, trackSid) {
17924
+ var trackSignaling = trackSidsToTrackSignalings.get(trackSid) || {};
17925
+ var trackStatsWithTrackSid = Object.assign({ trackSid: trackSid }, trackStats);
17926
+ if (trackSignaling.kind === 'audio') {
17927
+ remoteAudioTrackStats.push(trackStatsWithTrackSid);
17928
+ }
17929
+ else if (trackSignaling.kind === 'video') {
17930
+ remoteVideoTrackStats.push(trackStatsWithTrackSid);
17931
+ }
17932
+ });
17933
+ });
17934
+ return responses;
17935
+ });
17936
+ };
17742
17937
  return RoomV3;
17743
17938
  }(RoomV2));
17744
17939
  module.exports = RoomV3;
@@ -26618,7 +26813,6 @@ function _getStats(peerConnection, options) {
26618
26813
  isRemote: isRemote
26619
26814
  }, options)).then(function (trackStatsArray) {
26620
26815
  trackStatsArray.forEach(function (trackStats) {
26621
- trackStats.trackId = track.id;
26622
26816
  statsResponse[statsArrayName].push(trackStats);
26623
26817
  });
26624
26818
  });
@@ -26879,7 +27073,7 @@ function chromeOrSafariGetTrackStats(peerConnection, track) {
26879
27073
  return;
26880
27074
  }
26881
27075
  peerConnection.getStats(track).then(function (response) {
26882
- resolve(standardizeChromeOrSafariStats(response));
27076
+ resolve(standardizeChromeOrSafariStats(response, track));
26883
27077
  }, reject);
26884
27078
  });
26885
27079
  }
@@ -26893,7 +27087,7 @@ function chromeOrSafariGetTrackStats(peerConnection, track) {
26893
27087
  function firefoxGetTrackStats(peerConnection, track, isRemote) {
26894
27088
  return new Promise(function (resolve, reject) {
26895
27089
  peerConnection.getStats(track).then(function (response) {
26896
- resolve([standardizeFirefoxStats(response, isRemote)]);
27090
+ resolve([standardizeFirefoxStats(response, track, isRemote)]);
26897
27091
  }, reject);
26898
27092
  });
26899
27093
  }
@@ -26907,7 +27101,7 @@ function standardizeChromeLegacyStats(response, track) {
26907
27101
  var ssrcReport = response.result().find(function (report) {
26908
27102
  return report.type === 'ssrc' && report.stat('googTrackId') === track.id;
26909
27103
  });
26910
- var standardizedStats = {};
27104
+ var standardizedStats = { trackId: track.id };
26911
27105
  if (ssrcReport) {
26912
27106
  standardizedStats.timestamp = Math.round(Number(ssrcReport.timestamp));
26913
27107
  standardizedStats = ssrcReport.names().reduce(function (stats, name) {
@@ -26969,9 +27163,10 @@ function standardizeChromeLegacyStats(response, track) {
26969
27163
  /**
26970
27164
  * Standardize the MediaStreamTrack's statistics in Chrome or Safari.
26971
27165
  * @param {RTCStatsResponse} response
27166
+ * @param {MediaStreamTrack} track
26972
27167
  * @returns {Array<StandardizedTrackStatsReport>}
26973
27168
  */
26974
- function standardizeChromeOrSafariStats(response) {
27169
+ function standardizeChromeOrSafariStats(response, mediaStreamTrack) {
26975
27170
  var inbound = null;
26976
27171
  // NOTE(mpatwardhan): We should expect more than one "outbound-rtp" stats for a
26977
27172
  // VP8 simulcast MediaStreamTrack.
@@ -27011,7 +27206,7 @@ function standardizeChromeOrSafariStats(response) {
27011
27206
  var stats = [];
27012
27207
  var remoteSource = isRemote ? remoteOutbound : remoteInbound; // remote rtp stats
27013
27208
  mainSources.forEach(function (source) {
27014
- var standardizedStats = {};
27209
+ var standardizedStats = { trackId: mediaStreamTrack.id };
27015
27210
  var statSources = [
27016
27211
  source,
27017
27212
  localMedia,
@@ -27137,10 +27332,11 @@ function standardizeChromeOrSafariStats(response) {
27137
27332
  /**
27138
27333
  * Standardize the MediaStreamTrack's statistics in Firefox.
27139
27334
  * @param {RTCStatsReport} response
27335
+ * @param {MediaStreamTrack} track
27140
27336
  * @param {boolean} isRemote
27141
27337
  * @returns {StandardizedTrackStatsReport}
27142
27338
  */
27143
- function standardizeFirefoxStats(response, isRemote) {
27339
+ function standardizeFirefoxStats(response, track, isRemote) {
27144
27340
  // NOTE(mroberts): If getStats is called on a closed RTCPeerConnection,
27145
27341
  // Firefox returns undefined instead of an RTCStatsReport. We workaround this
27146
27342
  // here. See the following bug for more details:
@@ -27185,7 +27381,7 @@ function standardizeFirefoxStats(response, isRemote) {
27185
27381
  }
27186
27382
  return null;
27187
27383
  }
27188
- var standardizedStats = {};
27384
+ var standardizedStats = { trackId: track.id };
27189
27385
  var timestamp = getStatValue('timestamp');
27190
27386
  standardizedStats.timestamp = Math.round(timestamp);
27191
27387
  var ssrc = getStatValue('ssrc');
@@ -27353,7 +27549,8 @@ function standardizeFirefoxStats(response, isRemote) {
27353
27549
  * @property {AudioLevel} [audioInputLevel] - The {@link AudioLevel} of the local audio MediaStreamTrack
27354
27550
  * @property {AudioLevel} [audioOutputLevel] - The {@link AudioLevel} of the remote video MediaStreamTrack
27355
27551
  */
27356
- module.exports = getStats;
27552
+ exports.getStats = getStats;
27553
+ exports.getTrackStats = getTrackStats;
27357
27554
 
27358
27555
  },{"./util":171,"./util/sdp":173}],157:[function(require,module,exports){
27359
27556
  /* globals navigator */
@@ -27381,11 +27578,16 @@ module.exports = getUserMedia;
27381
27578
 
27382
27579
  },{}],158:[function(require,module,exports){
27383
27580
  'use strict';
27581
+ var stats = require('./getstats');
27384
27582
  var WebRTC = {};
27385
27583
  Object.defineProperties(WebRTC, {
27386
27584
  getStats: {
27387
27585
  enumerable: true,
27388
- value: require('./getstats')
27586
+ value: stats.getStats
27587
+ },
27588
+ getTrackStats: {
27589
+ enumerable: true,
27590
+ value: stats.getTrackStats
27389
27591
  },
27390
27592
  getUserMedia: {
27391
27593
  enumerable: true,
@@ -29981,13 +30183,15 @@ module.exports={
29981
30183
  "name": "twilio-video",
29982
30184
  "title": "Twilio Video",
29983
30185
  "description": "Twilio Video JavaScript Library",
29984
- "version": "3.0.0-preview.1",
30186
+ "version": "3.0.0-preview.2",
29985
30187
  "homepage": "https://twilio.com",
29986
30188
  "author": "Mark Andrus Roberts <mroberts@twilio.com>",
29987
30189
  "contributors": [
29988
30190
  "Ryan Rowland <rrowland@twilio.com>",
29989
30191
  "Manjesh Malavalli <mmalavalli@twilio.com>",
29990
- "Makarand Patwardhan <mpatwardhan@twilio.com>"
30192
+ "Makarand Patwardhan <mpatwardhan@twilio.com>",
30193
+ "Charlemegne Santos <csantos@twilio.com>",
30194
+ "Joyce Ma <joma@twilio.com>"
29991
30195
  ],
29992
30196
  "keywords": [
29993
30197
  "twilio",