twilio-video 2.26.1 → 2.26.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.
package/CHANGELOG.md CHANGED
@@ -2,13 +2,29 @@ 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
+ 2.26.2 (February 21, 2023)
6
+ ==========================
7
+
8
+ Changes
9
+ -------
10
+
11
+ - Starting from version 110, Chrome will no longer support the iSAC audio codec. The SDK will now log a warning to the console
12
+ whenever an audio or a video codec that is specified in `ConnectOptions.preferredAudioCodecs` and `ConnectOptions.preferredVideoCodecs`
13
+ is not supported by the browser. (VIDEO-12494)
14
+
15
+ Bug Fixes
16
+ ---------
17
+
18
+ - Fixed a bug on Chrome versions 112+ where `Room.getStats()` did not reject the returned Promise when an exception was
19
+ raised while accessing WebRTC stats that due to a TypeError caused by trying to read from the now-removed `RTCMediaStreamTrackStats`. (VIDEO-12534)
20
+
5
21
  2.26.1 (January 31, 2023)
6
22
  =========================
7
23
 
8
24
  Bug Fixes
9
25
  ---------
10
26
 
11
- - Fixed a bug that manifests on Chrome versions 112+ where `Room.getStats()` rejects the returned Promise due to a
27
+ - Fixed a bug that manifests on Chrome versions 112+ where `Room.getStats()` raises an unhandled exception due to a
12
28
  TypeError caused by trying to read from the now-removed `RTCMediaStreamTrackStats`. Instead, the SDK now reads from
13
29
  the `RTCMediaSourceStats`. (VIDEO-12411)
14
30
  - Fixed an error in the type definition for the `attach()` method of `AudioTrack` and `VideoTrack`. (VIDEO-12242)
package/COMMON_ISSUES.md CHANGED
@@ -200,10 +200,10 @@ transform: scaleX(-1)
200
200
  </p>
201
201
  </details>
202
202
  <details>
203
- <summary>iOS 15: Audio is lost in a video call after an interruption with a phone call</summary>
203
+ <summary>iOS 16: Local Media Tracks are lost in a video call after an interruption with a phone call</summary>
204
204
  <p>
205
205
 
206
- Due to a regression on Safari on iOS 15, an incoming call causes local and sometimes remote media playback to stop. You can find more details in this [WebKit bug](https://bugs.webkit.org/show_bug.cgi?id=230537).
206
+ Due to a bug on Safari on iOS 16, an incoming call causes local and sometimes remote media playback to stop after the **second** incoming call. You can find more details in this [WebKit bug](https://bugs.webkit.org/show_bug.cgi?id=240651). As a workaround, you can call the [Room.refreshInactiveMedia](https://sdk.twilio.com/js/video/releases/2.26.0/docs/Room.html#refreshInactiveMedia__anchor) method in your application in order to restart the muted local media tracks and resume playback of the paused remote media tracks.
207
207
  </p>
208
208
  </details>
209
209
  <details>
@@ -348,7 +348,7 @@ trouble with twilio-video.js, ensure these are not running.
348
348
  <summary>setSinkId method is not implemented in all browsers</summary>
349
349
  <p>
350
350
 
351
- The `audioElement.setSinkId()` method, which is used to change the audio output device for a given HTML audio element, is only implemented in Desktop Chrome and Desktop Edge. Therefore, it is not possible for users to change their audio output device in other browsers. Users will have to use their operating system settings to change their audio output device instead.
351
+ The `audioElement.setSinkId()` method, which is used to change the audio output device for a given HTML audio element, is only implemented in Desktop Chrome and Desktop Edge. Therefore, it is not possible for users to change their audio output device in other browsers. Users will have to use their operating system settings to change their audio output device instead.
352
352
 
353
353
  More information about this method (including browser compatibility) is available [here](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId).
354
354
  </p>
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 &lt;script&gt; tag.
75
75
 
76
76
  ```html
77
- <script src="//sdk.twilio.com/js/video/releases/2.26.1/twilio-video.min.js"></script>
77
+ <script src="//sdk.twilio.com/js/video/releases/2.26.2/twilio-video.min.js"></script>
78
78
  ```
79
79
 
80
80
  Using this method, twilio-video.js will set a browser global:
@@ -1,4 +1,4 @@
1
- /*! twilio-video.js 2.26.1
1
+ /*! twilio-video.js 2.26.2
2
2
 
3
3
  The following license applies to all parts of this software except as
4
4
  documented below.
@@ -86,7 +86,7 @@ module.exports = createCancelableRoomPromise;
86
86
  },{"./util/cancelablepromise":124}],2:[function(require,module,exports){
87
87
  'use strict';
88
88
  var MediaStreamTrack = require('./webrtc').MediaStreamTrack;
89
- var _a = require('./webrtc/util'), guessBrowser = _a.guessBrowser, guessBrowserVersion = _a.guessBrowserVersion;
89
+ var _a = require('./webrtc/util'), guessBrowser = _a.guessBrowser, guessBrowserVersion = _a.guessBrowserVersion, isCodecSupported = _a.isCodecSupported;
90
90
  var createCancelableRoomPromise = require('./cancelableroompromise');
91
91
  var EncodingParametersImpl = require('./encodingparameters');
92
92
  var LocalParticipant = require('./localparticipant');
@@ -407,6 +407,11 @@ function connect(token, options) {
407
407
  video: options.preferredVideoCodecs.map(normalizeCodecSettings)
408
408
  };
409
409
  var networkQualityConfiguration = new NetworkQualityConfigurationImpl(isNonArrayObject(options.networkQuality) ? options.networkQuality : {});
410
+ // Log warnings for any unsupported preferred codecs.
411
+ ['audio', 'video'].forEach(function (kind) { return preferredCodecs[kind].forEach(function (_a) {
412
+ var codec = _a.codec;
413
+ return isCodecSupported(codec, kind).then(function (isSupported) { return !isSupported && log.warn("The preferred " + kind + " codec \"" + codec + "\" will be ignored as it is not supported by the browser."); });
414
+ }); });
410
415
  // Create a CancelableRoomPromise<Room> that resolves after these steps:
411
416
  // 1 - Get the LocalTracks.
412
417
  // 2 - Create the LocalParticipant using options.tracks.
@@ -26761,14 +26766,14 @@ function getTracks(peerConnection, kind, localOrRemote) {
26761
26766
  function getTrackStats(peerConnection, track, options) {
26762
26767
  if (options === void 0) { options = {}; }
26763
26768
  if (typeof options.testForChrome !== 'undefined' || isChrome) {
26764
- return chromeOrSafariGetTrackStats(peerConnection, track);
26769
+ return chromeOrSafariGetTrackStats(peerConnection, track, options);
26765
26770
  }
26766
26771
  if (typeof options.testForFirefox !== 'undefined' || isFirefox) {
26767
- return firefoxGetTrackStats(peerConnection, track, options.isRemote);
26772
+ return firefoxGetTrackStats(peerConnection, track, options);
26768
26773
  }
26769
26774
  if (typeof options.testForSafari !== 'undefined' || isSafari) {
26770
26775
  if (typeof options.testForSafari !== 'undefined' || getSdpFormat() === 'unified') {
26771
- return chromeOrSafariGetTrackStats(peerConnection, track);
26776
+ return chromeOrSafariGetTrackStats(peerConnection, track, options);
26772
26777
  }
26773
26778
  // NOTE(syerrapragada): getStats() is not supported on
26774
26779
  // Safari versions where plan-b is the SDP format
@@ -26784,33 +26789,31 @@ function getTrackStats(peerConnection, track, options) {
26784
26789
  * Get the standardized statistics for a particular MediaStreamTrack in Chrome or Safari.
26785
26790
  * @param {RTCPeerConnection} peerConnection
26786
26791
  * @param {MediaStreamTrack} track
26792
+ * @param {object} options - Used for testing
26787
26793
  * @returns {Promise.<Array<StandardizedTrackStatsReport>>}
26788
26794
  */
26789
- function chromeOrSafariGetTrackStats(peerConnection, track) {
26790
- return new Promise(function (resolve, reject) {
26791
- if (chromeMajorVersion && chromeMajorVersion < 67) {
26795
+ function chromeOrSafariGetTrackStats(peerConnection, track, options) {
26796
+ if (chromeMajorVersion && chromeMajorVersion < 67) {
26797
+ return new Promise(function (resolve, reject) {
26792
26798
  peerConnection.getStats(function (response) {
26793
26799
  resolve([standardizeChromeLegacyStats(response, track)]);
26794
26800
  }, null, reject);
26795
- return;
26796
- }
26797
- peerConnection.getStats(track).then(function (response) {
26798
- resolve(standardizeChromeOrSafariStats(response));
26799
- }, reject);
26801
+ });
26802
+ }
26803
+ return peerConnection.getStats(track).then(function (response) {
26804
+ return standardizeChromeOrSafariStats(response, options);
26800
26805
  });
26801
26806
  }
26802
26807
  /**
26803
26808
  * Get the standardized statistics for a particular MediaStreamTrack in Firefox.
26804
26809
  * @param {RTCPeerConnection} peerConnection
26805
26810
  * @param {MediaStreamTrack} track
26806
- * @param {boolean} isRemote
26811
+ * @param {object} options
26807
26812
  * @returns {Promise.<Array<StandardizedTrackStatsReport>>}
26808
26813
  */
26809
- function firefoxGetTrackStats(peerConnection, track, isRemote) {
26810
- return new Promise(function (resolve, reject) {
26811
- peerConnection.getStats(track).then(function (response) {
26812
- resolve([standardizeFirefoxStats(response, isRemote)]);
26813
- }, reject);
26814
+ function firefoxGetTrackStats(peerConnection, track, options) {
26815
+ return peerConnection.getStats(track).then(function (response) {
26816
+ return [standardizeFirefoxStats(response, options)];
26814
26817
  });
26815
26818
  }
26816
26819
  /**
@@ -26885,9 +26888,14 @@ function standardizeChromeLegacyStats(response, track) {
26885
26888
  /**
26886
26889
  * Standardize the MediaStreamTrack's statistics in Chrome or Safari.
26887
26890
  * @param {RTCStatsResponse} response
26891
+ * @param {object} options - Used for testing
26888
26892
  * @returns {Array<StandardizedTrackStatsReport>}
26889
26893
  */
26890
- function standardizeChromeOrSafariStats(response) {
26894
+ function standardizeChromeOrSafariStats(response, _a) {
26895
+ var _b = _a.simulateExceptionWhileStandardizingStats, simulateExceptionWhileStandardizingStats = _b === void 0 ? false : _b;
26896
+ if (simulateExceptionWhileStandardizingStats) {
26897
+ throw new Error('Error while gathering stats');
26898
+ }
26891
26899
  var inbound = null;
26892
26900
  // NOTE(mpatwardhan): We should expect more than one "outbound-rtp" stats for a
26893
26901
  // VP8 simulcast MediaStreamTrack.
@@ -27054,17 +27062,21 @@ function standardizeChromeOrSafariStats(response) {
27054
27062
  /**
27055
27063
  * Standardize the MediaStreamTrack's statistics in Firefox.
27056
27064
  * @param {RTCStatsReport} response
27057
- * @param {boolean} isRemote
27065
+ * @param {object} options - Used for testing
27058
27066
  * @returns {StandardizedTrackStatsReport}
27059
27067
  */
27060
- function standardizeFirefoxStats(response, isRemote) {
27068
+ function standardizeFirefoxStats(response, _a) {
27069
+ if (response === void 0) { response = new Map(); }
27070
+ var isRemote = _a.isRemote, _b = _a.simulateExceptionWhileStandardizingStats, simulateExceptionWhileStandardizingStats = _b === void 0 ? false : _b;
27071
+ if (simulateExceptionWhileStandardizingStats) {
27072
+ throw new Error('Error while gathering stats');
27073
+ }
27061
27074
  // NOTE(mroberts): If getStats is called on a closed RTCPeerConnection,
27062
27075
  // Firefox returns undefined instead of an RTCStatsReport. We workaround this
27063
27076
  // here. See the following bug for more details:
27064
27077
  //
27065
27078
  // https://bugzilla.mozilla.org/show_bug.cgi?id=1377225
27066
27079
  //
27067
- if (response === void 0) { response = new Map(); }
27068
27080
  var inbound = null;
27069
27081
  var outbound = null;
27070
27082
  // NOTE(mmalavalli): Starting from Firefox 63, RTC{Inbound, Outbound}RTPStreamStats.isRemote
@@ -29093,18 +29105,79 @@ function support() {
29093
29105
  && typeof navigator.mediaDevices.getUserMedia === 'function'
29094
29106
  && typeof RTCPeerConnection === 'function';
29095
29107
  }
29108
+ /**
29109
+ * Create a Set of supported codecs for a certain kind of media.
29110
+ * @param {'audio'|'video'} kind
29111
+ * @returns {Promise<Set<AudioCodec|VideoCodec>>}
29112
+ */
29113
+ function createSupportedCodecsSet(kind) {
29114
+ if (typeof RTCRtpSender !== 'undefined'
29115
+ && typeof RTCRtpSender.getCapabilities === 'function') {
29116
+ return Promise.resolve(new Set(RTCRtpSender
29117
+ .getCapabilities(kind)
29118
+ .codecs
29119
+ .map(function (_a) {
29120
+ var mimeType = _a.mimeType;
29121
+ return mimeType.split('/')[1].toLowerCase();
29122
+ })));
29123
+ }
29124
+ if (typeof RTCPeerConnection === 'undefined'
29125
+ || typeof RTCPeerConnection.prototype === 'undefined'
29126
+ || typeof RTCPeerConnection.prototype.addTransceiver !== 'function'
29127
+ || typeof RTCPeerConnection.prototype.close !== 'function'
29128
+ || typeof RTCPeerConnection.prototype.createOffer !== 'function') {
29129
+ return Promise.resolve(new Set());
29130
+ }
29131
+ var pc = new RTCPeerConnection();
29132
+ pc.addTransceiver(kind);
29133
+ return pc.createOffer().then(function (_a) {
29134
+ var sdp = _a.sdp;
29135
+ pc.close();
29136
+ return new Set((sdp.match(/^a=rtpmap:.+$/gm) || [])
29137
+ .map(function (line) { return line.match(/^a=rtpmap:.+ ([^/]+)/)[1].toLowerCase(); }));
29138
+ }, function () {
29139
+ pc.close();
29140
+ return new Set();
29141
+ });
29142
+ }
29143
+ // NOTE(mmalavalli): Cache the supported audio and video codecs here.
29144
+ var supportedCodecs = new Map();
29145
+ /**
29146
+ * Check whether a given codec for a certain kind of media is supported.
29147
+ * @param {AudioCodec|VideoCodec} codec
29148
+ * @param {'audio'|'video'} kind
29149
+ * @returns {Promise<boolean>}
29150
+ */
29151
+ function isCodecSupported(codec, kind) {
29152
+ var codecs = supportedCodecs.get(kind);
29153
+ if (codecs) {
29154
+ return Promise.resolve(codecs.has(codec.toLowerCase()));
29155
+ }
29156
+ return createSupportedCodecsSet(kind).then(function (codecs) {
29157
+ supportedCodecs.set(kind, codecs);
29158
+ return codecs.has(codec.toLowerCase());
29159
+ });
29160
+ }
29161
+ /**
29162
+ * Clear cached supported codecs (unit tests only).
29163
+ */
29164
+ function clearCachedSupportedCodecs() {
29165
+ supportedCodecs.clear();
29166
+ }
29096
29167
  /**
29097
29168
  * @typedef {object} Deferred
29098
29169
  * @property {Promise} promise
29099
29170
  * @property {function} reject
29100
29171
  * @property {function} resolve
29101
29172
  */
29173
+ exports.clearCachedSupportedCodecs = clearCachedSupportedCodecs;
29102
29174
  exports.defer = defer;
29103
29175
  exports.delegateMethods = delegateMethods;
29104
29176
  exports.difference = difference;
29105
29177
  exports.flatMap = flatMap;
29106
29178
  exports.guessBrowser = guessBrowser;
29107
29179
  exports.guessBrowserVersion = guessBrowserVersion;
29180
+ exports.isCodecSupported = isCodecSupported;
29108
29181
  exports.isIOSChrome = isIOSChrome;
29109
29182
  exports.interceptEvent = interceptEvent;
29110
29183
  exports.legacyPromise = legacyPromise;
@@ -30010,7 +30083,7 @@ module.exports={
30010
30083
  "name": "twilio-video",
30011
30084
  "title": "Twilio Video",
30012
30085
  "description": "Twilio Video JavaScript Library",
30013
- "version": "2.26.1",
30086
+ "version": "2.26.2",
30014
30087
  "homepage": "https://twilio.com",
30015
30088
  "author": "Mark Andrus Roberts <mroberts@twilio.com>",
30016
30089
  "contributors": [