twilio-video 2.24.2 → 2.25.0

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 (41) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/COMMON_ISSUES.md +4 -48
  3. package/README.md +1 -2
  4. package/dist/twilio-video.js +188 -71
  5. package/dist/twilio-video.min.js +21 -21
  6. package/es5/createlocaltrack.js +10 -2
  7. package/es5/createlocaltrack.js.map +1 -1
  8. package/es5/createlocaltracks.js +20 -8
  9. package/es5/createlocaltracks.js.map +1 -1
  10. package/es5/media/track/audiotrack.js +0 -11
  11. package/es5/media/track/audiotrack.js.map +1 -1
  12. package/es5/media/track/localaudiotrack.js +112 -0
  13. package/es5/media/track/localaudiotrack.js.map +1 -1
  14. package/es5/media/track/localmediatrack.js +3 -6
  15. package/es5/media/track/localmediatrack.js.map +1 -1
  16. package/es5/media/track/localvideotrack.js +2 -2
  17. package/es5/media/track/localvideotrack.js.map +1 -1
  18. package/es5/media/track/mediatrack.js +3 -3
  19. package/es5/media/track/mediatrack.js.map +1 -1
  20. package/es5/media/track/remoteaudiotrack.js +12 -0
  21. package/es5/media/track/remoteaudiotrack.js.map +1 -1
  22. package/es5/media/track/remotemediatrack.js +2 -2
  23. package/es5/media/track/remotemediatrack.js.map +1 -1
  24. package/es5/util/browserdetection.js +16 -15
  25. package/es5/util/browserdetection.js.map +1 -1
  26. package/es5/webrtc/rtcpeerconnection/firefox.js +0 -14
  27. package/es5/webrtc/rtcpeerconnection/firefox.js.map +1 -1
  28. package/lib/createlocaltrack.js +10 -2
  29. package/lib/createlocaltracks.ts +32 -11
  30. package/lib/media/track/audiotrack.js +0 -12
  31. package/lib/media/track/localaudiotrack.js +112 -0
  32. package/lib/media/track/localmediatrack.js +2 -5
  33. package/lib/media/track/localvideotrack.js +2 -3
  34. package/lib/media/track/mediatrack.js +2 -2
  35. package/lib/media/track/remoteaudiotrack.js +13 -0
  36. package/lib/media/track/remotemediatrack.js +2 -2
  37. package/lib/util/browserdetection.js +16 -15
  38. package/lib/webrtc/rtcpeerconnection/firefox.js +0 -16
  39. package/package.json +2 -2
  40. package/tsdef/index.d.ts +1 -0
  41. package/tsdef/types.d.ts +2 -0
@@ -1,4 +1,4 @@
1
- /*! twilio-video.js 2.24.2
1
+ /*! twilio-video.js 2.25.0
2
2
 
3
3
  The following license applies to all parts of this software except as
4
4
  documented below.
@@ -1116,8 +1116,16 @@ var NoiseCancellationVendor = {
1116
1116
  * @property {boolean} [workaroundWebKitBug180748=false] - setting this
1117
1117
  * attempts to workaround WebKit Bug 180748, where, in Safari, getUserMedia may return a silent audio
1118
1118
  * MediaStreamTrack.
1119
- * @property {NoiseCancellationOptions} [noiseCancellationOptions] - This property enables using 3rd party plugins
1120
- * for noise cancellation. This is a beta feature.
1119
+ * @property {DefaultDeviceCaptureMode} [defaultDeviceCaptureMode="auto"] - This optional property only applies if the
1120
+ * {@link LocalAudioTrack} is capturing from the default audio input device connected to a desktop or laptop. When the
1121
+ * property is set to "auto", the LocalAudioTrack restarts whenever the default audio input device changes, in order to
1122
+ * capture audio from the new default audio input device. For example, when a bluetooth audio headset is connected to a
1123
+ * Macbook, the LocalAudioTrack will start capturing audio from the headset microphone. When the headset is disconnected,
1124
+ * the LocalAudioTrack will start capturing audio from the Macbook microphone. When the property is set to "manual", the
1125
+ * LocalAudioTrack continues to capture from the same audio input device even after the default audio input device changes.
1126
+ * When the property is not specified, it defaults to "auto".
1127
+ * @property {NoiseCancellationOptions} [noiseCancellationOptions] - This optional property enables using 3rd party plugins
1128
+ * for noise cancellation.
1121
1129
  */
1122
1130
  /**
1123
1131
  * Create {@link LocalTrack} options. Apart from the properties listed here, you can
@@ -1218,7 +1226,7 @@ var buildLogLevels = require('./util').buildLogLevels;
1218
1226
  var _a = require('./webrtc'), getUserMedia = _a.getUserMedia, MediaStreamTrack = _a.MediaStreamTrack;
1219
1227
  var _b = require('./media/track/es5'), LocalAudioTrack = _b.LocalAudioTrack, LocalDataTrack = _b.LocalDataTrack, LocalVideoTrack = _b.LocalVideoTrack;
1220
1228
  var Log = require('./util/log');
1221
- var _c = require('./util/constants'), DEFAULT_LOG_LEVEL = _c.DEFAULT_LOG_LEVEL, DEFAULT_LOGGER_NAME = _c.DEFAULT_LOGGER_NAME;
1229
+ var _c = require('./util/constants'), DEFAULT_LOG_LEVEL = _c.DEFAULT_LOG_LEVEL, DEFAULT_LOGGER_NAME = _c.DEFAULT_LOGGER_NAME, INVALID_VALUE = _c.typeErrors.INVALID_VALUE;
1222
1230
  var workaround180748 = require('./webaudio/workaround180748');
1223
1231
  // This is used to make out which createLocalTracks() call a particular Log
1224
1232
  // statement belongs to. Each call to createLocalTracks() increments this
@@ -1317,19 +1325,31 @@ function createLocalTracks(options) {
1317
1325
  extraLocalTrackOptions = {
1318
1326
  audio: typeof fullOptions.audio === 'object' && fullOptions.audio.name
1319
1327
  ? { name: fullOptions.audio.name }
1320
- : {},
1328
+ : { defaultDeviceCaptureMode: 'auto' },
1321
1329
  video: typeof fullOptions.video === 'object' && fullOptions.video.name
1322
1330
  ? { name: fullOptions.video.name }
1323
1331
  : {}
1324
1332
  };
1325
1333
  extraLocalTrackOptions.audio.isCreatedByCreateLocalTracks = true;
1326
1334
  extraLocalTrackOptions.video.isCreatedByCreateLocalTracks = true;
1327
- if (typeof fullOptions.audio === 'object' && typeof fullOptions.audio.workaroundWebKitBug1208516 === 'boolean') {
1328
- extraLocalTrackOptions.audio.workaroundWebKitBug1208516 = fullOptions.audio.workaroundWebKitBug1208516;
1329
- }
1330
- if (typeof fullOptions.audio === 'object' && 'noiseCancellationOptions' in fullOptions.audio) {
1331
- noiseCancellationOptions = fullOptions.audio.noiseCancellationOptions;
1332
- delete fullOptions.audio.noiseCancellationOptions;
1335
+ if (typeof fullOptions.audio === 'object') {
1336
+ if (typeof fullOptions.audio.workaroundWebKitBug1208516 === 'boolean') {
1337
+ extraLocalTrackOptions.audio.workaroundWebKitBug1208516 = fullOptions.audio.workaroundWebKitBug1208516;
1338
+ }
1339
+ if ('noiseCancellationOptions' in fullOptions.audio) {
1340
+ noiseCancellationOptions = fullOptions.audio.noiseCancellationOptions;
1341
+ delete fullOptions.audio.noiseCancellationOptions;
1342
+ }
1343
+ if (!('defaultDeviceCaptureMode' in fullOptions.audio)) {
1344
+ extraLocalTrackOptions.audio.defaultDeviceCaptureMode = 'auto';
1345
+ }
1346
+ else if (['auto', 'manual'].every(function (mode) { return mode !== fullOptions.audio.defaultDeviceCaptureMode; })) {
1347
+ // eslint-disable-next-line new-cap
1348
+ throw INVALID_VALUE('CreateLocalAudioTrackOptions.defaultDeviceCaptureMode', ['auto', 'manual']);
1349
+ }
1350
+ else {
1351
+ extraLocalTrackOptions.audio.defaultDeviceCaptureMode = fullOptions.audio.defaultDeviceCaptureMode;
1352
+ }
1333
1353
  }
1334
1354
  if (typeof fullOptions.video === 'object' && typeof fullOptions.video.workaroundWebKitBug1208516 === 'boolean') {
1335
1355
  extraLocalTrackOptions.video.workaroundWebKitBug1208516 = fullOptions.video.workaroundWebKitBug1208516;
@@ -2676,17 +2696,6 @@ var AudioTrack = /** @class */ (function (_super) {
2676
2696
  function AudioTrack(mediaTrackTransceiver, options) {
2677
2697
  return _super.call(this, mediaTrackTransceiver, options) || this;
2678
2698
  }
2679
- /**
2680
- * @private
2681
- */
2682
- AudioTrack.prototype._start = function () {
2683
- _super.prototype._start.call(this);
2684
- if (this._dummyEl) {
2685
- // once started let go of dummy element
2686
- this._dummyEl.srcObject = null;
2687
- this._dummyEl = null;
2688
- }
2689
- };
2690
2699
  /**
2691
2700
  * Create an HTMLAudioElement and attach the {@link AudioTrack} to it.
2692
2701
  *
@@ -2980,6 +2989,7 @@ var __extends = (this && this.__extends) || (function () {
2980
2989
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
2981
2990
  };
2982
2991
  })();
2992
+ var isIOS = require('../../util/browserdetection').isIOS;
2983
2993
  var AudioTrack = require('./audiotrack');
2984
2994
  var mixinLocalMediaTrack = require('./localmediatrack');
2985
2995
  var LocalMediaAudioTrack = mixinLocalMediaTrack(AudioTrack);
@@ -3012,13 +3022,61 @@ var LocalAudioTrack = /** @class */ (function (_super) {
3012
3022
  var _this = this;
3013
3023
  var noiseCancellation = (options === null || options === void 0 ? void 0 : options.noiseCancellation) || null;
3014
3024
  _this = _super.call(this, mediaStreamTrack, options) || this;
3025
+ var log = _this._log;
3026
+ var _a = mediaStreamTrack.label, defaultDeviceLabel = _a === void 0 ? '' : _a;
3027
+ var _b = mediaStreamTrack.getSettings(), _c = _b.deviceId, defaultDeviceId = _c === void 0 ? '' : _c, _d = _b.groupId, defaultGroupId = _d === void 0 ? '' : _d;
3015
3028
  Object.defineProperties(_this, {
3029
+ _currentDefaultDeviceInfo: {
3030
+ value: { deviceId: defaultDeviceId, groupId: defaultGroupId, label: defaultDeviceLabel },
3031
+ writable: true
3032
+ },
3033
+ _defaultDeviceCaptureMode: {
3034
+ value: !isIOS()
3035
+ && _this._isCreatedByCreateLocalTracks
3036
+ && typeof navigator === 'object'
3037
+ && typeof navigator.mediaDevices === 'object'
3038
+ && typeof navigator.mediaDevices.addEventListener === 'function'
3039
+ && typeof navigator.mediaDevices.enumerateDevices === 'function'
3040
+ ? (options === null || options === void 0 ? void 0 : options.defaultDeviceCaptureMode) || 'auto'
3041
+ : 'manual'
3042
+ },
3043
+ _onDeviceChange: {
3044
+ value: function () {
3045
+ navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) {
3046
+ // NOTE(mmalavalli): In Chrome, when the default device changes, and we restart the LocalAudioTrack with
3047
+ // device ID "default", it will not switch to the new default device unless all LocalAudioTracks capturing
3048
+ // from the old default device are stopped. So, we restart the LocalAudioTrack with the actual device ID of
3049
+ // the new default device instead.
3050
+ var defaultDeviceInfo = deviceInfos.find(function (_a) {
3051
+ var deviceId = _a.deviceId, kind = _a.kind;
3052
+ return kind === 'audioinput' && deviceId !== 'default';
3053
+ });
3054
+ if (defaultDeviceInfo && ['deviceId', 'groupId'].some(function (prop) {
3055
+ return defaultDeviceInfo[prop] !== _this._currentDefaultDeviceInfo[prop];
3056
+ })) {
3057
+ log.info('Default device changed, restarting the LocalAudioTrack');
3058
+ log.debug("Old default device: \"" + _this._currentDefaultDeviceInfo.deviceId + "\" => \"" + _this._currentDefaultDeviceInfo.label + "\"");
3059
+ log.debug("New default device: \"" + defaultDeviceInfo.deviceId + "\" => \"" + defaultDeviceInfo.label + "\"");
3060
+ _this._currentDefaultDeviceInfo = defaultDeviceInfo;
3061
+ _this._restartDefaultDevice().catch(function (error) { return log.warn("Failed to restart: " + error.message); });
3062
+ }
3063
+ }, function (error) {
3064
+ log.warn("Failed to run enumerateDevices(): " + error.message);
3065
+ });
3066
+ }
3067
+ },
3068
+ _restartOnDefaultDeviceChangeCleanup: {
3069
+ value: null,
3070
+ writable: true
3071
+ },
3016
3072
  noiseCancellation: {
3017
3073
  enumerable: true,
3018
3074
  value: noiseCancellation,
3019
3075
  writable: false
3020
3076
  },
3021
3077
  });
3078
+ log.debug('defaultDeviceCaptureMode:', _this._defaultDeviceCaptureMode);
3079
+ _this._maybeRestartOnDefaultDeviceChange();
3022
3080
  return _this;
3023
3081
  }
3024
3082
  LocalAudioTrack.prototype.toString = function () {
@@ -3035,6 +3093,51 @@ var LocalAudioTrack = /** @class */ (function (_super) {
3035
3093
  LocalAudioTrack.prototype._end = function () {
3036
3094
  return _super.prototype._end.apply(this, arguments);
3037
3095
  };
3096
+ /**
3097
+ * @private
3098
+ */
3099
+ LocalAudioTrack.prototype._maybeRestartOnDefaultDeviceChange = function () {
3100
+ var _this = this;
3101
+ var _a = this, constraints = _a._constraints, defaultDeviceCaptureMode = _a._defaultDeviceCaptureMode, log = _a._log;
3102
+ var mediaStreamTrack = this.noiseCancellation ? this.noiseCancellation.sourceTrack : this.mediaStreamTrack;
3103
+ var deviceId = mediaStreamTrack.getSettings().deviceId;
3104
+ var isNotEqualToCapturedDeviceIdOrEqualToDefault = function (requestedDeviceId) {
3105
+ return requestedDeviceId !== deviceId || requestedDeviceId === 'default';
3106
+ };
3107
+ var isCapturingFromDefaultDevice = (function checkIfCapturingFromDefaultDevice(deviceIdConstraint) {
3108
+ if (deviceIdConstraint === void 0) { deviceIdConstraint = {}; }
3109
+ if (typeof deviceIdConstraint === 'string') {
3110
+ return isNotEqualToCapturedDeviceIdOrEqualToDefault(deviceIdConstraint);
3111
+ }
3112
+ else if (Array.isArray(deviceIdConstraint)) {
3113
+ return deviceIdConstraint.every(isNotEqualToCapturedDeviceIdOrEqualToDefault);
3114
+ }
3115
+ else if (deviceIdConstraint.exact) {
3116
+ return checkIfCapturingFromDefaultDevice(deviceIdConstraint.exact);
3117
+ }
3118
+ else if (deviceIdConstraint.ideal) {
3119
+ return checkIfCapturingFromDefaultDevice(deviceIdConstraint.ideal);
3120
+ }
3121
+ return true;
3122
+ }(constraints.deviceId));
3123
+ if (defaultDeviceCaptureMode === 'auto' && isCapturingFromDefaultDevice) {
3124
+ if (!this._restartOnDefaultDeviceChangeCleanup) {
3125
+ log.info('LocalAudioTrack will be restarted if the default device changes');
3126
+ navigator.mediaDevices.addEventListener('devicechange', this._onDeviceChange);
3127
+ this._restartOnDefaultDeviceChangeCleanup = function () {
3128
+ log.info('Cleaning up the listener to restart the LocalAudioTrack if the default device changes');
3129
+ navigator.mediaDevices.removeEventListener('devicechange', _this._onDeviceChange);
3130
+ _this._restartOnDefaultDeviceChangeCleanup = null;
3131
+ };
3132
+ }
3133
+ }
3134
+ else {
3135
+ log.info('LocalAudioTrack will NOT be restarted if the default device changes');
3136
+ if (this._restartOnDefaultDeviceChangeCleanup) {
3137
+ this._restartOnDefaultDeviceChangeCleanup();
3138
+ }
3139
+ }
3140
+ };
3038
3141
  /**
3039
3142
  * @private
3040
3143
  */
@@ -3048,6 +3151,21 @@ var LocalAudioTrack = /** @class */ (function (_super) {
3048
3151
  }
3049
3152
  return _super.prototype._reacquireTrack.call(this, constraints);
3050
3153
  };
3154
+ /**
3155
+ * @private
3156
+ */
3157
+ LocalAudioTrack.prototype._restartDefaultDevice = function () {
3158
+ var _this = this;
3159
+ var constraints = Object.assign({}, this._constraints);
3160
+ var restartConstraints = Object.assign({}, constraints, { deviceId: this._currentDefaultDeviceInfo.deviceId });
3161
+ return this.restart(restartConstraints).then(function () {
3162
+ // NOTE(mmalavalli): Since we used the new default device's ID while restarting the LocalAudioTrack,
3163
+ // we reset the constraints to the original constraints so that the default device detection logic in
3164
+ // _maybeRestartOnDefaultDeviceChange() still works.
3165
+ _this._constraints = constraints;
3166
+ _this._maybeRestartOnDefaultDeviceChange();
3167
+ });
3168
+ };
3051
3169
  /**
3052
3170
  * Disable the {@link LocalAudioTrack}. This is effectively "mute".
3053
3171
  * @returns {this}
@@ -3119,6 +3237,9 @@ var LocalAudioTrack = /** @class */ (function (_super) {
3119
3237
  if (this.noiseCancellation) {
3120
3238
  this.noiseCancellation.stop();
3121
3239
  }
3240
+ if (this._restartOnDefaultDeviceChangeCleanup) {
3241
+ this._restartOnDefaultDeviceChangeCleanup();
3242
+ }
3122
3243
  return _super.prototype.stop.apply(this, arguments);
3123
3244
  };
3124
3245
  return LocalAudioTrack;
@@ -3149,7 +3270,7 @@ var LocalAudioTrack = /** @class */ (function (_super) {
3149
3270
  */
3150
3271
  module.exports = LocalAudioTrack;
3151
3272
 
3152
- },{"./audiotrack":13,"./localmediatrack":23}],20:[function(require,module,exports){
3273
+ },{"../../util/browserdetection":122,"./audiotrack":13,"./localmediatrack":23}],20:[function(require,module,exports){
3153
3274
  'use strict';
3154
3275
  var __extends = (this && this.__extends) || (function () {
3155
3276
  var extendStatics = function (d, b) {
@@ -3398,8 +3519,8 @@ var __extends = (this && this.__extends) || (function () {
3398
3519
  };
3399
3520
  })();
3400
3521
  var getUserMedia = require('../../webrtc').getUserMedia;
3401
- var _a = require('../../webrtc/util'), guessBrowser = _a.guessBrowser, isIOSChrome = _a.isIOSChrome;
3402
- var _b = require('../../util'), capitalize = _b.capitalize, defer = _b.defer, isUserMediaTrack = _b.isUserMediaTrack, waitForSometime = _b.waitForSometime, waitForEvent = _b.waitForEvent;
3522
+ var isIOS = require('../../util/browserdetection').isIOS;
3523
+ var _a = require('../../util'), capitalize = _a.capitalize, defer = _a.defer, isUserMediaTrack = _a.isUserMediaTrack, waitForSometime = _a.waitForSometime, waitForEvent = _a.waitForEvent;
3403
3524
  var ILLEGAL_INVOKE = require('../../util/constants').typeErrors.ILLEGAL_INVOKE;
3404
3525
  var detectSilentAudio = require('../../util/detectsilentaudio');
3405
3526
  var detectSilentVideo = require('../../util/detectsilentvideo');
@@ -3425,10 +3546,7 @@ function mixinLocalMediaTrack(AudioOrVideoTrack) {
3425
3546
  */
3426
3547
  function LocalMediaTrack(mediaStreamTrack, options) {
3427
3548
  var _this = this;
3428
- // NOTE(mpatwardhan): by default workaround for WebKitBug1208516 will be enabled on Safari browsers
3429
- // although the bug is seen mainly on iOS devices, we do not have a reliable way to tell iOS from MacOs
3430
- // userAgent on iOS pretends its macOs if Safari is set to request desktop pages.
3431
- var workaroundWebKitBug1208516 = (guessBrowser() === 'safari' || isIOSChrome())
3549
+ var workaroundWebKitBug1208516 = isIOS()
3432
3550
  && isUserMediaTrack(mediaStreamTrack)
3433
3551
  && typeof document === 'object'
3434
3552
  && typeof document.addEventListener === 'function'
@@ -3737,7 +3855,7 @@ function restartWhenInadvertentlyStopped(localMediaTrack) {
3737
3855
  }
3738
3856
  module.exports = mixinLocalMediaTrack;
3739
3857
 
3740
- },{"../../util":131,"../../util/constants":124,"../../util/detectsilentaudio":125,"../../util/detectsilentvideo":126,"../../util/documentvisibilitymonitor.js":127,"../../util/localmediarestartdeferreds":134,"../../webaudio/workaround180748":154,"../../webrtc":157,"../../webrtc/util":170,"./sender":38}],24:[function(require,module,exports){
3858
+ },{"../../util":131,"../../util/browserdetection":122,"../../util/constants":124,"../../util/detectsilentaudio":125,"../../util/detectsilentvideo":126,"../../util/documentvisibilitymonitor.js":127,"../../util/localmediarestartdeferreds":134,"../../webaudio/workaround180748":154,"../../webrtc":157,"./sender":38}],24:[function(require,module,exports){
3741
3859
  /* eslint new-cap:0 */
3742
3860
  'use strict';
3743
3861
  var __extends = (this && this.__extends) || (function () {
@@ -3920,7 +4038,7 @@ var __extends = (this && this.__extends) || (function () {
3920
4038
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
3921
4039
  };
3922
4040
  })();
3923
- var _a = require('../../webrtc/util'), guessBrowser = _a.guessBrowser, isIOSChrome = _a.isIOSChrome;
4041
+ var isIOS = require('../../util/browserdetection').isIOS;
3924
4042
  var detectSilentVideo = require('../../util/detectsilentvideo');
3925
4043
  var mixinLocalMediaTrack = require('./localmediatrack');
3926
4044
  var VideoTrack = require('./videotrack');
@@ -3951,7 +4069,7 @@ var LocalVideoTrack = /** @class */ (function (_super) {
3951
4069
  function LocalVideoTrack(mediaStreamTrack, options) {
3952
4070
  var _this = this;
3953
4071
  options = Object.assign({
3954
- workaroundSilentLocalVideo: (guessBrowser() === 'safari' || isIOSChrome())
4072
+ workaroundSilentLocalVideo: isIOS()
3955
4073
  && isUserMediaTrack(mediaStreamTrack)
3956
4074
  && typeof document !== 'undefined'
3957
4075
  && typeof document.createElement === 'function'
@@ -4250,7 +4368,7 @@ function workaroundSilentLocalVideo(localVideoTrack, doc) {
4250
4368
  */
4251
4369
  module.exports = LocalVideoTrack;
4252
4370
 
4253
- },{"../../util":131,"../../util/detectsilentvideo":126,"../../webrtc/util":170,"./localmediatrack":23,"./videotrack":42}],26:[function(require,module,exports){
4371
+ },{"../../util":131,"../../util/browserdetection":122,"../../util/detectsilentvideo":126,"./localmediatrack":23,"./videotrack":42}],26:[function(require,module,exports){
4254
4372
  'use strict';
4255
4373
  var __extends = (this && this.__extends) || (function () {
4256
4374
  var extendStatics = function (d, b) {
@@ -4313,9 +4431,9 @@ var __extends = (this && this.__extends) || (function () {
4313
4431
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4314
4432
  };
4315
4433
  })();
4316
- var _a = require('../../webrtc/util'), guessBrowser = _a.guessBrowser, isIOSChrome = _a.isIOSChrome;
4434
+ var isIOS = require('../../util/browserdetection').isIOS;
4317
4435
  var MediaStream = require('../../webrtc').MediaStream;
4318
- var _b = require('../../util'), waitForEvent = _b.waitForEvent, waitForSometime = _b.waitForSometime;
4436
+ var _a = require('../../util'), waitForEvent = _a.waitForEvent, waitForSometime = _a.waitForSometime;
4319
4437
  var localMediaRestartDeferreds = require('../../util/localmediarestartdeferreds');
4320
4438
  var Track = require('./');
4321
4439
  /**
@@ -4345,7 +4463,7 @@ var MediaTrack = /** @class */ (function (_super) {
4345
4463
  function MediaTrack(mediaTrackTransceiver, options) {
4346
4464
  var _this = this;
4347
4465
  options = Object.assign({
4348
- playPausedElementsIfNotBackgrounded: (guessBrowser() === 'safari' || isIOSChrome())
4466
+ playPausedElementsIfNotBackgrounded: isIOS()
4349
4467
  && typeof document === 'object'
4350
4468
  && typeof document.addEventListener === 'function'
4351
4469
  && typeof document.visibilityState === 'string'
@@ -4660,7 +4778,7 @@ function shimMediaElement(el, onUnintentionallyPaused) {
4660
4778
  }
4661
4779
  module.exports = MediaTrack;
4662
4780
 
4663
- },{"../../util":131,"../../util/localmediarestartdeferreds":134,"../../webrtc":157,"../../webrtc/util":170,"./":18}],28:[function(require,module,exports){
4781
+ },{"../../util":131,"../../util/browserdetection":122,"../../util/localmediarestartdeferreds":134,"../../webrtc":157,"./":18}],28:[function(require,module,exports){
4664
4782
  'use strict';
4665
4783
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4666
4784
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@@ -4978,6 +5096,18 @@ var RemoteAudioTrack = /** @class */ (function (_super) {
4978
5096
  RemoteAudioTrack.prototype.toString = function () {
4979
5097
  return "[RemoteAudioTrack #" + this._instanceId + ": " + this.sid + "]";
4980
5098
  };
5099
+ /**
5100
+ * @private
5101
+ */
5102
+ RemoteAudioTrack.prototype._start = function () {
5103
+ _super.prototype._start.call(this);
5104
+ if (this._dummyEl) {
5105
+ // NOTE(mpatwardhan): To fix VIDEO-6336, clear dummy element after the
5106
+ // RemoteAudioTrack has started.
5107
+ this._dummyEl.srcObject = null;
5108
+ this._dummyEl = null;
5109
+ }
5110
+ };
4981
5111
  /**
4982
5112
  * Update the subscribe {@link Track.Priority} of the {@link RemoteAudioTrack}.
4983
5113
  * @param {?Track.Priority} priority - the new subscribe {@link Track.Priority};
@@ -5382,7 +5512,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from) {
5382
5512
  return to;
5383
5513
  };
5384
5514
  var _a = require('../../util/constants'), E = _a.typeErrors, trackPriority = _a.trackPriority;
5385
- var _b = require('../../webrtc/util'), guessBrowser = _b.guessBrowser, isIOSChrome = _b.isIOSChrome;
5515
+ var isIOS = require('../../util/browserdetection').isIOS;
5386
5516
  var documentVisibilityMonitor = require('../../util/documentvisibilitymonitor.js');
5387
5517
  function mixinRemoteMediaTrack(AudioOrVideoTrack) {
5388
5518
  /**
@@ -5416,7 +5546,7 @@ function mixinRemoteMediaTrack(AudioOrVideoTrack) {
5416
5546
  // NOTE(mpatwardhan): WebKit bug: 212780 sometimes causes the audio/video elements to stay paused when safari
5417
5547
  // regains foreground. To workaround it, when safari gains foreground - we will play any elements that were
5418
5548
  // playing before safari lost foreground.
5419
- workaroundWebKitBug212780: (guessBrowser() === 'safari' || isIOSChrome())
5549
+ workaroundWebKitBug212780: isIOS()
5420
5550
  && typeof document === 'object'
5421
5551
  && typeof document.addEventListener === 'function'
5422
5552
  && typeof document.visibilityState === 'string'
@@ -5629,7 +5759,7 @@ function playIfPausedWhileInBackground(remoteMediaTrack) {
5629
5759
  */
5630
5760
  module.exports = mixinRemoteMediaTrack;
5631
5761
 
5632
- },{"../../util/constants":124,"../../util/documentvisibilitymonitor.js":127,"../../webrtc/util":170}],35:[function(require,module,exports){
5762
+ },{"../../util/browserdetection":122,"../../util/constants":124,"../../util/documentvisibilitymonitor.js":127}],35:[function(require,module,exports){
5633
5763
  'use strict';
5634
5764
  var __extends = (this && this.__extends) || (function () {
5635
5765
  var extendStatics = function (d, b) {
@@ -20660,36 +20790,37 @@ var __read = (this && this.__read) || function (o, n) {
20660
20790
  function isAndroid() {
20661
20791
  return /Android/.test(navigator.userAgent);
20662
20792
  }
20663
- /**
20664
- * Check whether the current browser is an iOS device.
20665
- * @returns {boolean}
20666
- */
20667
- function isIOS() {
20668
- return /iPad|iPhone|iPod/.test(navigator.userAgent);
20669
- }
20670
20793
  /**
20671
20794
  * Detects whether or not a device is an Apple touch screen device.
20672
20795
  * @returns {boolean}
20673
20796
  */
20674
20797
  function hasTouchScreen() {
20675
- return navigator && navigator.maxTouchPoints &&
20676
- navigator.maxTouchPoints > 2;
20798
+ return !!(navigator && navigator.maxTouchPoints && navigator.maxTouchPoints > 2);
20677
20799
  }
20678
20800
  /**
20679
- * Detects whether or not a device is an iPad
20801
+ * Detects whether or not a device is an iPad.
20680
20802
  * @returns {boolean}
20681
20803
  */
20682
20804
  function isIpad() {
20683
- return hasTouchScreen() && window.screen.width >= 744 &&
20684
- (/Macintosh/i.test(navigator.userAgent) || /iPad/.test(navigator.userAgent) || /iPad/.test(navigator.platform));
20805
+ return hasTouchScreen() && window.screen.width >= 744 && (/Macintosh/i.test(navigator.userAgent)
20806
+ || /iPad/.test(navigator.userAgent)
20807
+ || /iPad/.test(navigator.platform));
20685
20808
  }
20686
20809
  /**
20687
- * Detects whether or not a device is an iPhone
20810
+ * Detects whether or not a device is an iPhone.
20688
20811
  * @returns {boolean}
20689
20812
  */
20690
20813
  function isIphone() {
20691
- return hasTouchScreen() && window.screen.width <= 476 &&
20692
- (/Macintosh/i.test(navigator.userAgent) || /iPhone/.test(navigator.userAgent) || /iPhone/.test(navigator.platform));
20814
+ return hasTouchScreen() && window.screen.width <= 476 && (/Macintosh/i.test(navigator.userAgent)
20815
+ || /iPhone/.test(navigator.userAgent)
20816
+ || /iPhone/.test(navigator.platform));
20817
+ }
20818
+ /**
20819
+ * Check whether the current device is an iOS device.
20820
+ * @returns {boolean}
20821
+ */
20822
+ function isIOS() {
20823
+ return isIpad() || isIphone();
20693
20824
  }
20694
20825
  /**
20695
20826
  * Check whether the current browser is a mobile browser
@@ -27533,12 +27664,6 @@ var FirefoxRTCSessionDescription = require('../rtcsessiondescription/firefox');
27533
27664
  var inherits = require('../../vendor/inherits');
27534
27665
  var updateTracksToSSRCs = require('../util/sdp').updateUnifiedPlanTrackIdsToSSRCs;
27535
27666
  var util = require('../util');
27536
- // NOTE(mroberts): This is a short-lived workaround. Checking the user agent
27537
- // string might not fix every affected Firefox instance, but it should be good
27538
- // enough for this bug.
27539
- var needsWorkaroundForBug1480277 = typeof navigator === 'object'
27540
- && navigator.userAgent
27541
- && (navigator.userAgent.match(/Firefox\/61/) || navigator.userAgent.match(/Firefox\/62/));
27542
27667
  // NOTE(mroberts): This class wraps Firefox's RTCPeerConnection implementation.
27543
27668
  // It provides some functionality not currently present in Firefox, namely the
27544
27669
  // abilities to
@@ -27637,14 +27762,6 @@ Object.defineProperty(FirefoxRTCPeerConnection.prototype, 'peerIdentity', {
27637
27762
  name: ''
27638
27763
  })
27639
27764
  });
27640
- if (needsWorkaroundForBug1480277) {
27641
- FirefoxRTCPeerConnection.prototype.addTrack = function addTrack() {
27642
- var track = arguments[0];
27643
- var sender = this._peerConnection.addTrack.apply(this._peerConnection, arguments);
27644
- sender.replaceTrack(track);
27645
- return sender;
27646
- };
27647
- }
27648
27765
  FirefoxRTCPeerConnection.prototype.createAnswer = function createAnswer() {
27649
27766
  var args = [].slice.call(arguments);
27650
27767
  var promise;
@@ -29545,7 +29662,7 @@ module.exports={
29545
29662
  "name": "twilio-video",
29546
29663
  "title": "Twilio Video",
29547
29664
  "description": "Twilio Video JavaScript Library",
29548
- "version": "2.24.2",
29665
+ "version": "2.25.0",
29549
29666
  "homepage": "https://twilio.com",
29550
29667
  "author": "Mark Andrus Roberts <mroberts@twilio.com>",
29551
29668
  "contributors": [
@@ -29646,7 +29763,7 @@ module.exports={
29646
29763
  "test:serversiderender": "mocha ./test/serversiderender/index.js",
29647
29764
  "test:integration:adapter": "node ./scripts/karma.js karma/integration.adapter.conf.js",
29648
29765
  "test:integration": "npm run build:es5 && node ./scripts/karma.js karma/integration.conf.js",
29649
- "test:umd:install": "npm install puppeteer@5.5.0",
29766
+ "test:umd:install": "npm install puppeteer@19.2.2",
29650
29767
  "test:umd": "mocha ./test/umd/index.js",
29651
29768
  "test:crossbrowser:build:clean": "rimraf ./test/crossbrowser/lib ./test/crossbrowser/src/browser/index.js",
29652
29769
  "test:crossbrowser:build:lint": "cd ./test/crossbrowser && tslint --project tsconfig.json",