twilio-video 2.26.0 → 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,6 +2,34 @@ 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
+
21
+ 2.26.1 (January 31, 2023)
22
+ =========================
23
+
24
+ Bug Fixes
25
+ ---------
26
+
27
+ - Fixed a bug that manifests on Chrome versions 112+ where `Room.getStats()` raises an unhandled exception due to a
28
+ TypeError caused by trying to read from the now-removed `RTCMediaStreamTrackStats`. Instead, the SDK now reads from
29
+ the `RTCMediaSourceStats`. (VIDEO-12411)
30
+ - Fixed an error in the type definition for the `attach()` method of `AudioTrack` and `VideoTrack`. (VIDEO-12242)
31
+ - Fixed an error in the type definition for `createLocalAudioTrack()`. (VIDEO-12383)
32
+
5
33
  2.26.0 (December 14, 2022)
6
34
  ==========================
7
35
 
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.0/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.0
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.
@@ -20258,6 +20263,9 @@ var WS_CLOSE_NETWORK_CHANGED = 3004;
20258
20263
  var WS_CLOSE_BUSY_WAIT = 3005;
20259
20264
  var WS_CLOSE_SERVER_BUSY = 3006;
20260
20265
  var WS_CLOSE_OPEN_TIMEOUT = 3007;
20266
+ // NOTE(joma): If you want to use close code 3008, please increment
20267
+ // the close code in test/integration/spec/docker/reconnection.js
20268
+ // line number 492.
20261
20269
  var toplevel = globalThis;
20262
20270
  var WebSocket = toplevel.WebSocket ? toplevel.WebSocket : require('ws');
20263
20271
  var CloseReason = {
@@ -26526,9 +26534,7 @@ function _getStats(peerConnection, options) {
26526
26534
  ], function (_a) {
26527
26535
  var _b = __read(_a, 3), tracks = _b[0], statsArrayName = _b[1], isRemote = _b[2];
26528
26536
  return tracks.map(function (track) {
26529
- return getTrackStats(peerConnection, track, Object.assign({
26530
- isRemote: isRemote
26531
- }, options)).then(function (trackStatsArray) {
26537
+ return getTrackStats(peerConnection, track, Object.assign({ isRemote: isRemote }, options)).then(function (trackStatsArray) {
26532
26538
  trackStatsArray.forEach(function (trackStats) {
26533
26539
  trackStats.trackId = track.id;
26534
26540
  statsResponse[statsArrayName].push(trackStats);
@@ -26760,14 +26766,14 @@ function getTracks(peerConnection, kind, localOrRemote) {
26760
26766
  function getTrackStats(peerConnection, track, options) {
26761
26767
  if (options === void 0) { options = {}; }
26762
26768
  if (typeof options.testForChrome !== 'undefined' || isChrome) {
26763
- return chromeOrSafariGetTrackStats(peerConnection, track);
26769
+ return chromeOrSafariGetTrackStats(peerConnection, track, options);
26764
26770
  }
26765
26771
  if (typeof options.testForFirefox !== 'undefined' || isFirefox) {
26766
- return firefoxGetTrackStats(peerConnection, track, options.isRemote);
26772
+ return firefoxGetTrackStats(peerConnection, track, options);
26767
26773
  }
26768
26774
  if (typeof options.testForSafari !== 'undefined' || isSafari) {
26769
26775
  if (typeof options.testForSafari !== 'undefined' || getSdpFormat() === 'unified') {
26770
- return chromeOrSafariGetTrackStats(peerConnection, track);
26776
+ return chromeOrSafariGetTrackStats(peerConnection, track, options);
26771
26777
  }
26772
26778
  // NOTE(syerrapragada): getStats() is not supported on
26773
26779
  // Safari versions where plan-b is the SDP format
@@ -26783,33 +26789,31 @@ function getTrackStats(peerConnection, track, options) {
26783
26789
  * Get the standardized statistics for a particular MediaStreamTrack in Chrome or Safari.
26784
26790
  * @param {RTCPeerConnection} peerConnection
26785
26791
  * @param {MediaStreamTrack} track
26792
+ * @param {object} options - Used for testing
26786
26793
  * @returns {Promise.<Array<StandardizedTrackStatsReport>>}
26787
26794
  */
26788
- function chromeOrSafariGetTrackStats(peerConnection, track) {
26789
- return new Promise(function (resolve, reject) {
26790
- if (chromeMajorVersion && chromeMajorVersion < 67) {
26795
+ function chromeOrSafariGetTrackStats(peerConnection, track, options) {
26796
+ if (chromeMajorVersion && chromeMajorVersion < 67) {
26797
+ return new Promise(function (resolve, reject) {
26791
26798
  peerConnection.getStats(function (response) {
26792
26799
  resolve([standardizeChromeLegacyStats(response, track)]);
26793
26800
  }, null, reject);
26794
- return;
26795
- }
26796
- peerConnection.getStats(track).then(function (response) {
26797
- resolve(standardizeChromeOrSafariStats(response));
26798
- }, reject);
26801
+ });
26802
+ }
26803
+ return peerConnection.getStats(track).then(function (response) {
26804
+ return standardizeChromeOrSafariStats(response, options);
26799
26805
  });
26800
26806
  }
26801
26807
  /**
26802
26808
  * Get the standardized statistics for a particular MediaStreamTrack in Firefox.
26803
26809
  * @param {RTCPeerConnection} peerConnection
26804
26810
  * @param {MediaStreamTrack} track
26805
- * @param {boolean} isRemote
26811
+ * @param {object} options
26806
26812
  * @returns {Promise.<Array<StandardizedTrackStatsReport>>}
26807
26813
  */
26808
- function firefoxGetTrackStats(peerConnection, track, isRemote) {
26809
- return new Promise(function (resolve, reject) {
26810
- peerConnection.getStats(track).then(function (response) {
26811
- resolve([standardizeFirefoxStats(response, isRemote)]);
26812
- }, reject);
26814
+ function firefoxGetTrackStats(peerConnection, track, options) {
26815
+ return peerConnection.getStats(track).then(function (response) {
26816
+ return [standardizeFirefoxStats(response, options)];
26813
26817
  });
26814
26818
  }
26815
26819
  /**
@@ -26884,9 +26888,14 @@ function standardizeChromeLegacyStats(response, track) {
26884
26888
  /**
26885
26889
  * Standardize the MediaStreamTrack's statistics in Chrome or Safari.
26886
26890
  * @param {RTCStatsResponse} response
26891
+ * @param {object} options - Used for testing
26887
26892
  * @returns {Array<StandardizedTrackStatsReport>}
26888
26893
  */
26889
- 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
+ }
26890
26899
  var inbound = null;
26891
26900
  // NOTE(mpatwardhan): We should expect more than one "outbound-rtp" stats for a
26892
26901
  // VP8 simulcast MediaStreamTrack.
@@ -26922,7 +26931,7 @@ function standardizeChromeOrSafariStats(response) {
26922
26931
  break;
26923
26932
  }
26924
26933
  });
26925
- var isRemote = track && track.remoteSource;
26934
+ var isRemote = track ? track.remoteSource : !localMedia;
26926
26935
  var mainSources = isRemote ? [inbound] : outbound;
26927
26936
  var stats = [];
26928
26937
  var remoteSource = isRemote ? remoteOutbound : remoteInbound; // remote rtp stats
@@ -26967,7 +26976,7 @@ function standardizeChromeOrSafariStats(response) {
26967
26976
  }
26968
26977
  else {
26969
26978
  standardizedStats.frameWidthSent = frameWidth;
26970
- standardizedStats.frameWidthInput = track.frameWidth;
26979
+ standardizedStats.frameWidthInput = track ? track.frameWidth : localMedia.width;
26971
26980
  }
26972
26981
  }
26973
26982
  var frameHeight = getStatValue('frameHeight');
@@ -26977,7 +26986,7 @@ function standardizeChromeOrSafariStats(response) {
26977
26986
  }
26978
26987
  else {
26979
26988
  standardizedStats.frameHeightSent = frameHeight;
26980
- standardizedStats.frameHeightInput = track.frameHeight;
26989
+ standardizedStats.frameHeightInput = track ? track.frameHeight : localMedia.height;
26981
26990
  }
26982
26991
  }
26983
26992
  var framesPerSecond = getStatValue('framesPerSecond');
@@ -27053,17 +27062,21 @@ function standardizeChromeOrSafariStats(response) {
27053
27062
  /**
27054
27063
  * Standardize the MediaStreamTrack's statistics in Firefox.
27055
27064
  * @param {RTCStatsReport} response
27056
- * @param {boolean} isRemote
27065
+ * @param {object} options - Used for testing
27057
27066
  * @returns {StandardizedTrackStatsReport}
27058
27067
  */
27059
- 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
+ }
27060
27074
  // NOTE(mroberts): If getStats is called on a closed RTCPeerConnection,
27061
27075
  // Firefox returns undefined instead of an RTCStatsReport. We workaround this
27062
27076
  // here. See the following bug for more details:
27063
27077
  //
27064
27078
  // https://bugzilla.mozilla.org/show_bug.cgi?id=1377225
27065
27079
  //
27066
- if (response === void 0) { response = new Map(); }
27067
27080
  var inbound = null;
27068
27081
  var outbound = null;
27069
27082
  // NOTE(mmalavalli): Starting from Firefox 63, RTC{Inbound, Outbound}RTPStreamStats.isRemote
@@ -29092,18 +29105,79 @@ function support() {
29092
29105
  && typeof navigator.mediaDevices.getUserMedia === 'function'
29093
29106
  && typeof RTCPeerConnection === 'function';
29094
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
+ }
29095
29167
  /**
29096
29168
  * @typedef {object} Deferred
29097
29169
  * @property {Promise} promise
29098
29170
  * @property {function} reject
29099
29171
  * @property {function} resolve
29100
29172
  */
29173
+ exports.clearCachedSupportedCodecs = clearCachedSupportedCodecs;
29101
29174
  exports.defer = defer;
29102
29175
  exports.delegateMethods = delegateMethods;
29103
29176
  exports.difference = difference;
29104
29177
  exports.flatMap = flatMap;
29105
29178
  exports.guessBrowser = guessBrowser;
29106
29179
  exports.guessBrowserVersion = guessBrowserVersion;
29180
+ exports.isCodecSupported = isCodecSupported;
29107
29181
  exports.isIOSChrome = isIOSChrome;
29108
29182
  exports.interceptEvent = interceptEvent;
29109
29183
  exports.legacyPromise = legacyPromise;
@@ -30009,7 +30083,7 @@ module.exports={
30009
30083
  "name": "twilio-video",
30010
30084
  "title": "Twilio Video",
30011
30085
  "description": "Twilio Video JavaScript Library",
30012
- "version": "2.26.0",
30086
+ "version": "2.26.2",
30013
30087
  "homepage": "https://twilio.com",
30014
30088
  "author": "Mark Andrus Roberts <mroberts@twilio.com>",
30015
30089
  "contributors": [