cloudinary-video-player 2.4.1-edge.8 → 2.4.1

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.
@@ -9389,7 +9389,7 @@ class CloudinaryAnalytics {
9389
9389
  this.cloudinaryAnalytics.startManualTracking(metadata, {
9390
9390
  ...(lodash_isPlainObject__WEBPACK_IMPORTED_MODULE_1___default()(this.analyticsOptions) ? this.analyticsOptions : {}),
9391
9391
  videoPlayerType: 'cloudinary video player',
9392
- videoPlayerVersion: "2.4.1-edge.8"
9392
+ videoPlayerVersion: "2.4.1"
9393
9393
  });
9394
9394
  } else if (this.currentVideMetadata.cloudName !== metadata.cloudName || this.currentVideMetadata.publicId !== metadata.publicId) {
9395
9395
  this.cloudinaryAnalytics.stopManualTracking();
@@ -9762,7 +9762,7 @@ class CloudinaryContext {
9762
9762
  options.sourceTypes = options.sourceTypes || _this.sourceTypes();
9763
9763
  options.poster = options.poster || posterOptionsForCurrent();
9764
9764
  options.queryParams = Object.assign(options.queryParams || {}, options.usageReport ? {
9765
- _s: `vp-${"2.4.1-edge.8"}`
9765
+ _s: `vp-${"2.4.1"}`
9766
9766
  } : {});
9767
9767
  if (options.sourceTypes.indexOf('audio') > -1) {
9768
9768
  builtSrc = new _models_audio_source_audio_source__WEBPACK_IMPORTED_MODULE_7__["default"](publicId, options);
@@ -11029,7 +11029,7 @@ const contextMenuContent = player => {
11029
11029
  const isFullscreen = player.isFullscreen();
11030
11030
  const aboutMenuItem = {
11031
11031
  class: 'player-version',
11032
- label: 'Cloudinary Player v' + "2.4.1-edge.8"
11032
+ label: 'Cloudinary Player v' + "2.4.1"
11033
11033
  };
11034
11034
  if (!player.controls()) {
11035
11035
  return [aboutMenuItem];
@@ -13812,7 +13812,7 @@ class VideoPlayer extends _utils__WEBPACK_IMPORTED_MODULE_9__["default"].mixin(_
13812
13812
  const analyticsData = (0,_utils_get_analytics_player_options__WEBPACK_IMPORTED_MODULE_18__.getAnalyticsFromPlayerOptions)(options);
13813
13813
  const analyticsParams = new URLSearchParams(analyticsData).toString();
13814
13814
  const baseParams = new URLSearchParams({
13815
- vpVersion: "2.4.1-edge.8",
13815
+ vpVersion: "2.4.1",
13816
13816
  vpInstanceId: this.getVPInstanceId(),
13817
13817
  // #if (process.env.WEBPACK_BUILD_LIGHT)
13818
13818
  // vpLightBuild: true,
@@ -26488,7 +26488,7 @@ __webpack_require__.r(__webpack_exports__);
26488
26488
  /* harmony import */ var mux_js_lib_utils_clock__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(mux_js_lib_utils_clock__WEBPACK_IMPORTED_MODULE_14__);
26489
26489
  /**
26490
26490
  * @license
26491
- * Video.js 8.21.0 <http://videojs.com/>
26491
+ * Video.js 8.23.3 <http://videojs.com/>
26492
26492
  * Copyright Brightcove, Inc. <https://www.brightcove.com/>
26493
26493
  * Available under Apache License Version 2.0
26494
26494
  * <https://github.com/videojs/video.js/blob/main/LICENSE>
@@ -26514,7 +26514,7 @@ __webpack_require__.r(__webpack_exports__);
26514
26514
 
26515
26515
 
26516
26516
 
26517
- var version$6 = "8.21.0";
26517
+ var version$6 = "8.23.3";
26518
26518
 
26519
26519
  /**
26520
26520
  * An Object that contains lifecycle hooks as keys which point to an array
@@ -31865,10 +31865,14 @@ class Component$1 {
31865
31865
 
31866
31866
  // If we have players that were disposed, then their name will still be
31867
31867
  // in Players.players. So, we must loop through and verify that the value
31868
- // for each item is not null. This allows registration of the Player component
31868
+ // for each item is null. This allows registration of the Player component
31869
31869
  // after all players have been disposed or before any were created.
31870
- if (players && playerNames.length > 0 && playerNames.map(pname => players[pname]).every(Boolean)) {
31871
- throw new Error('Can not register Player component after player has been created.');
31870
+ if (players && playerNames.length > 0) {
31871
+ for (let i = 0; i < playerNames.length; i++) {
31872
+ if (players[playerNames[i]] !== null) {
31873
+ throw new Error('Can not register Player component after player has been created.');
31874
+ }
31875
+ }
31872
31876
  }
31873
31877
  }
31874
31878
  Component$1.components_[name] = ComponentToRegister;
@@ -32447,7 +32451,7 @@ function silencePromise(value) {
32447
32451
  * A serializable javascript representation of the TextTrack.
32448
32452
  * @private
32449
32453
  */
32450
- const trackToJson_ = function (track) {
32454
+ const trackToJson = function (track) {
32451
32455
  const ret = ['kind', 'label', 'language', 'id', 'inBandMetadataTrackDispatchType', 'mode', 'src'].reduce((acc, prop, i) => {
32452
32456
  if (track[prop]) {
32453
32457
  acc[prop] = track[prop];
@@ -32482,7 +32486,7 @@ const textTracksToJson = function (tech) {
32482
32486
  const trackEls = tech.$$('track');
32483
32487
  const trackObjs = Array.prototype.map.call(trackEls, t => t.track);
32484
32488
  const tracks = Array.prototype.map.call(trackEls, function (trackEl) {
32485
- const json = trackToJson_(trackEl.track);
32489
+ const json = trackToJson(trackEl.track);
32486
32490
  if (trackEl.src) {
32487
32491
  json.src = trackEl.src;
32488
32492
  }
@@ -32490,7 +32494,7 @@ const textTracksToJson = function (tech) {
32490
32494
  });
32491
32495
  return tracks.concat(Array.prototype.filter.call(tech.textTracks(), function (track) {
32492
32496
  return trackObjs.indexOf(track) === -1;
32493
- }).map(trackToJson_));
32497
+ }).map(trackToJson));
32494
32498
  };
32495
32499
 
32496
32500
  /**
@@ -32516,7 +32520,7 @@ const jsonToTextTracks = function (json, tech) {
32516
32520
  var textTrackConverter = {
32517
32521
  textTracksToJson,
32518
32522
  jsonToTextTracks,
32519
- trackToJson_
32523
+ trackToJson
32520
32524
  };
32521
32525
 
32522
32526
  /**
@@ -33480,6 +33484,16 @@ class TextTrackList extends TrackList {
33480
33484
  }
33481
33485
  }
33482
33486
  }
33487
+
33488
+ /**
33489
+ * Creates a serializable array of objects that contains serialized copies
33490
+ * of each text track.
33491
+ *
33492
+ * @return {Object[]} A serializable list of objects for the text track list
33493
+ */
33494
+ toJSON() {
33495
+ return this.tracks_.map(track => track.toJSON());
33496
+ }
33483
33497
  }
33484
33498
 
33485
33499
  /**
@@ -33913,11 +33927,9 @@ const getAbsoluteURL = function (url) {
33913
33927
  */
33914
33928
  const getFileExtension = function (path) {
33915
33929
  if (typeof path === 'string') {
33916
- const splitPathRe = /^(\/?)([\s\S]*?)((?:\.{1,2}|[^\/]+?)(\.([^\.\/\?]+)))(?:[\/]*|[\?].*)$/;
33917
- const pathParts = splitPathRe.exec(path);
33918
- if (pathParts) {
33919
- return pathParts.pop().toLowerCase();
33920
- }
33930
+ const cleanPath = path.split('?')[0].replace(/\/+$/, '');
33931
+ const match = cleanPath.match(/\.([^.\/]+)$/);
33932
+ return match ? match[1].toLowerCase() : '';
33921
33933
  }
33922
33934
  return '';
33923
33935
  };
@@ -34308,6 +34320,16 @@ class TextTrack extends Track {
34308
34320
  this.cues.setCues_(this.cues_);
34309
34321
  }
34310
34322
 
34323
+ /**
34324
+ * Creates a copy of the text track and makes it serializable
34325
+ * by removing circular dependencies.
34326
+ *
34327
+ * @return {Object} The track information as a serializable object
34328
+ */
34329
+ toJSON() {
34330
+ return textTrackConverter.trackToJson(this);
34331
+ }
34332
+
34311
34333
  /**
34312
34334
  * Remove a cue from our internal list
34313
34335
  *
@@ -36528,7 +36550,7 @@ const SpatialNavKeyCodes = {
36528
36550
  /** @import Player from './player' */
36529
36551
 
36530
36552
  // The number of seconds the `step*` functions move the timeline.
36531
- const STEP_SECONDS$1 = 5;
36553
+ const STEP_SECONDS = 5;
36532
36554
 
36533
36555
  /**
36534
36556
  * Spatial Navigation in Video.js enhances user experience and accessibility on smartTV devices,
@@ -36662,10 +36684,10 @@ class SpatialNavigation extends EventTarget$2 {
36662
36684
  }
36663
36685
  break;
36664
36686
  case 'ff':
36665
- this.userSeek_(this.player_.currentTime() + STEP_SECONDS$1);
36687
+ this.userSeek_(this.player_.currentTime() + STEP_SECONDS);
36666
36688
  break;
36667
36689
  case 'rw':
36668
- this.userSeek_(this.player_.currentTime() - STEP_SECONDS$1);
36690
+ this.userSeek_(this.player_.currentTime() - STEP_SECONDS);
36669
36691
  break;
36670
36692
  }
36671
36693
  }
@@ -37722,6 +37744,8 @@ class TextTrackDisplay extends Component$1 {
37722
37744
  this.updateDisplay(e);
37723
37745
  };
37724
37746
  player.on('loadstart', e => this.toggleDisplay(e));
37747
+ player.on('useractive', updateDisplayTextHandler);
37748
+ player.on('userinactive', updateDisplayTextHandler);
37725
37749
  player.on('texttrackchange', updateDisplayTextHandler);
37726
37750
  player.on('loadedmetadata', e => {
37727
37751
  this.updateDisplayOverlay();
@@ -37850,11 +37874,14 @@ class TextTrackDisplay extends Component$1 {
37850
37874
  }
37851
37875
 
37852
37876
  /**
37853
- * Update the displayed TextTrack when a either a {@link Player#texttrackchange} or
37854
- * a {@link Player#fullscreenchange} is fired.
37877
+ * Update the displayed {@link TextTrack} when either a {@link Player#texttrackchange},
37878
+ * a {@link Player#fullscreenchange}, a {@link Player#useractive}, or a
37879
+ * {@link Player#userinactive} is fired.
37855
37880
  *
37856
37881
  * @listens Player#texttrackchange
37857
37882
  * @listens Player#fullscreenchange
37883
+ * @listens Player#useractive
37884
+ * @listens Player#userinactive
37858
37885
  */
37859
37886
  updateDisplay() {
37860
37887
  const tracks = this.player_.textTracks();
@@ -38276,8 +38303,8 @@ class BigPlayButton extends Button {
38276
38303
  handleClick(event) {
38277
38304
  const playPromise = this.player_.play();
38278
38305
 
38279
- // exit early if clicked via the mouse
38280
- if (this.mouseused_ && 'clientX' in event && 'clientY' in event) {
38306
+ // exit early if tapped or clicked via the mouse
38307
+ if (event.type === 'tap' || this.mouseused_ && 'clientX' in event && 'clientY' in event) {
38281
38308
  silencePromise(playPromise);
38282
38309
  if (this.player_.tech(true)) {
38283
38310
  this.player_.tech(true).focus();
@@ -38742,6 +38769,8 @@ class CurrentTimeDisplay extends TimeDisplay {
38742
38769
  let time;
38743
38770
  if (this.player_.ended()) {
38744
38771
  time = this.player_.duration();
38772
+ } else if (event && event.target && typeof event.target.pendingSeekTime === 'function') {
38773
+ time = event.target.pendingSeekTime();
38745
38774
  } else {
38746
38775
  time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
38747
38776
  }
@@ -39488,6 +39517,10 @@ class Slider extends Component$1 {
39488
39517
  event.stopPropagation();
39489
39518
  this.stepForward();
39490
39519
  } else {
39520
+ if (this.pendingSeekTime()) {
39521
+ this.pendingSeekTime(null);
39522
+ this.userSeek_(this.player_.currentTime());
39523
+ }
39491
39524
  super.handleKeyDown(event);
39492
39525
  }
39493
39526
 
@@ -39873,13 +39906,18 @@ class PlayProgressBar extends Component$1 {
39873
39906
  * @param {number} seekBarPoint
39874
39907
  * A number from 0 to 1, representing a horizontal reference point
39875
39908
  * from the left edge of the {@link SeekBar}
39909
+ *
39910
+ * @param {Event} [event]
39911
+ * The `timeupdate` event that caused this function to run.
39876
39912
  */
39877
- update(seekBarRect, seekBarPoint) {
39913
+ update(seekBarRect, seekBarPoint, event) {
39878
39914
  const timeTooltip = this.getChild('timeTooltip');
39879
39915
  if (!timeTooltip) {
39880
39916
  return;
39881
39917
  }
39882
- const time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
39918
+
39919
+ // Combined logic: if an event with a valid pendingSeekTime getter exists, use it.
39920
+ const time = event && event.target && typeof event.target.pendingSeekTime === 'function' ? event.target.pendingSeekTime() : this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
39883
39921
  timeTooltip.updateTime(seekBarRect, seekBarPoint, time);
39884
39922
  }
39885
39923
  }
@@ -39973,12 +40011,6 @@ Component$1.registerComponent('MouseTimeDisplay', MouseTimeDisplay);
39973
40011
  * @file seek-bar.js
39974
40012
  */
39975
40013
 
39976
- // The number of seconds the `step*` functions move the timeline.
39977
- const STEP_SECONDS = 5;
39978
-
39979
- // The multiplier of STEP_SECONDS that PgUp/PgDown move the timeline.
39980
- const PAGE_KEY_MULTIPLIER = 12;
39981
-
39982
40014
  /**
39983
40015
  * Seek bar and container for the progress bars. Uses {@link PlayProgressBar}
39984
40016
  * as its `bar`.
@@ -39994,20 +40026,24 @@ class SeekBar extends Slider {
39994
40026
  *
39995
40027
  * @param {Object} [options]
39996
40028
  * The key/value store of player options.
40029
+ * @param {number} [options.stepSeconds=5]
40030
+ * The number of seconds to increment on keyboard control
40031
+ * @param {number} [options.pageMultiplier=12]
40032
+ * The multiplier of stepSeconds that PgUp/PgDown move the timeline.
39997
40033
  */
39998
40034
  constructor(player, options) {
39999
40035
  options = merge$1(SeekBar.prototype.options_, options);
40000
40036
 
40001
40037
  // Avoid mutating the prototype's `children` array by creating a copy
40002
40038
  options.children = [...options.children];
40003
- const shouldDisableSeekWhileScrubbingOnMobile = player.options_.disableSeekWhileScrubbingOnMobile && (IS_IOS || IS_ANDROID);
40039
+ const shouldDisableSeekWhileScrubbing = player.options_.disableSeekWhileScrubbingOnMobile && (IS_IOS || IS_ANDROID) || player.options_.disableSeekWhileScrubbingOnSTV;
40004
40040
 
40005
40041
  // Add the TimeTooltip as a child if we are on desktop, or on mobile with `disableSeekWhileScrubbingOnMobile: true`
40006
- if (!IS_IOS && !IS_ANDROID || shouldDisableSeekWhileScrubbingOnMobile) {
40042
+ if (!IS_IOS && !IS_ANDROID || shouldDisableSeekWhileScrubbing) {
40007
40043
  options.children.splice(1, 0, 'mouseTimeDisplay');
40008
40044
  }
40009
40045
  super(player, options);
40010
- this.shouldDisableSeekWhileScrubbingOnMobile_ = shouldDisableSeekWhileScrubbingOnMobile;
40046
+ this.shouldDisableSeekWhileScrubbing_ = shouldDisableSeekWhileScrubbing;
40011
40047
  this.pendingSeekTime_ = null;
40012
40048
  this.setEventHandlers_();
40013
40049
  }
@@ -40124,7 +40160,7 @@ class SeekBar extends Slider {
40124
40160
 
40125
40161
  // update the progress bar time tooltip with the current time
40126
40162
  if (this.bar) {
40127
- this.bar.update(getBoundingClientRect(this.el()), this.getProgress());
40163
+ this.bar.update(getBoundingClientRect(this.el()), this.getProgress(), event);
40128
40164
  }
40129
40165
  });
40130
40166
  return percent;
@@ -40157,6 +40193,25 @@ class SeekBar extends Slider {
40157
40193
  return this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
40158
40194
  }
40159
40195
 
40196
+ /**
40197
+ * Getter and setter for pendingSeekTime.
40198
+ * Ensures the value is clamped between 0 and duration.
40199
+ *
40200
+ * @param {number|null} [time] - Optional. The new pending seek time, can be a number or null.
40201
+ * @return {number|null} - The current pending seek time.
40202
+ */
40203
+ pendingSeekTime(time) {
40204
+ if (time !== undefined) {
40205
+ if (time !== null) {
40206
+ const duration = this.player_.duration();
40207
+ this.pendingSeekTime_ = Math.max(0, Math.min(time, duration));
40208
+ } else {
40209
+ this.pendingSeekTime_ = null;
40210
+ }
40211
+ }
40212
+ return this.pendingSeekTime_;
40213
+ }
40214
+
40160
40215
  /**
40161
40216
  * Get the percentage of media played so far.
40162
40217
  *
@@ -40166,8 +40221,8 @@ class SeekBar extends Slider {
40166
40221
  getPercent() {
40167
40222
  // If we have a pending seek time, we are scrubbing on mobile and should set the slider percent
40168
40223
  // to reflect the current scrub location.
40169
- if (this.pendingSeekTime_) {
40170
- return this.pendingSeekTime_ / this.player_.duration();
40224
+ if (this.pendingSeekTime() !== null) {
40225
+ return this.pendingSeekTime() / this.player_.duration();
40171
40226
  }
40172
40227
  const currentTime = this.getCurrentTime_();
40173
40228
  let percent;
@@ -40204,7 +40259,7 @@ class SeekBar extends Slider {
40204
40259
 
40205
40260
  // Don't pause if we are on mobile and `disableSeekWhileScrubbingOnMobile: true`.
40206
40261
  // In that case, playback should continue while the player scrubs to a new location.
40207
- if (!this.shouldDisableSeekWhileScrubbingOnMobile_) {
40262
+ if (!this.shouldDisableSeekWhileScrubbing_) {
40208
40263
  this.player_.pause();
40209
40264
  }
40210
40265
  super.handleMouseDown(event);
@@ -40265,8 +40320,8 @@ class SeekBar extends Slider {
40265
40320
  }
40266
40321
 
40267
40322
  // if on mobile and `disableSeekWhileScrubbingOnMobile: true`, keep track of the desired seek point but we won't initiate the seek until 'touchend'
40268
- if (this.shouldDisableSeekWhileScrubbingOnMobile_) {
40269
- this.pendingSeekTime_ = newTime;
40323
+ if (this.shouldDisableSeekWhileScrubbing_) {
40324
+ this.pendingSeekTime(newTime);
40270
40325
  } else {
40271
40326
  this.userSeek_(newTime);
40272
40327
  }
@@ -40309,9 +40364,9 @@ class SeekBar extends Slider {
40309
40364
  this.player_.scrubbing(false);
40310
40365
 
40311
40366
  // If we have a pending seek time, then we have finished scrubbing on mobile and should initiate a seek.
40312
- if (this.pendingSeekTime_) {
40313
- this.userSeek_(this.pendingSeekTime_);
40314
- this.pendingSeekTime_ = null;
40367
+ if (this.pendingSeekTime() !== null) {
40368
+ this.userSeek_(this.pendingSeekTime());
40369
+ this.pendingSeekTime(null);
40315
40370
  }
40316
40371
 
40317
40372
  /**
@@ -40335,18 +40390,46 @@ class SeekBar extends Slider {
40335
40390
  }
40336
40391
  }
40337
40392
 
40393
+ /**
40394
+ * Handles pending seek time when `disableSeekWhileScrubbingOnSTV` is enabled.
40395
+ *
40396
+ * @param {number} stepAmount - The number of seconds to step (positive for forward, negative for backward).
40397
+ */
40398
+ handlePendingSeek_(stepAmount) {
40399
+ if (!this.player_.paused()) {
40400
+ this.player_.pause();
40401
+ }
40402
+ const currentPos = this.pendingSeekTime() !== null ? this.pendingSeekTime() : this.player_.currentTime();
40403
+ this.pendingSeekTime(currentPos + stepAmount);
40404
+ this.player_.trigger({
40405
+ type: 'timeupdate',
40406
+ target: this,
40407
+ manuallyTriggered: true
40408
+ });
40409
+ }
40410
+
40338
40411
  /**
40339
40412
  * Move more quickly fast forward for keyboard-only users
40340
40413
  */
40341
40414
  stepForward() {
40342
- this.userSeek_(this.player_.currentTime() + STEP_SECONDS);
40415
+ // if `disableSeekWhileScrubbingOnSTV: true`, keep track of the desired seek point but we won't initiate the seek
40416
+ if (this.shouldDisableSeekWhileScrubbing_) {
40417
+ this.handlePendingSeek_(this.options().stepSeconds);
40418
+ } else {
40419
+ this.userSeek_(this.player_.currentTime() + this.options().stepSeconds);
40420
+ }
40343
40421
  }
40344
40422
 
40345
40423
  /**
40346
40424
  * Move more quickly rewind for keyboard-only users
40347
40425
  */
40348
40426
  stepBack() {
40349
- this.userSeek_(this.player_.currentTime() - STEP_SECONDS);
40427
+ // if `disableSeekWhileScrubbingOnSTV: true`, keep track of the desired seek point but we won't initiate the seek
40428
+ if (this.shouldDisableSeekWhileScrubbing_) {
40429
+ this.handlePendingSeek_(-this.options().stepSeconds);
40430
+ } else {
40431
+ this.userSeek_(this.player_.currentTime() - this.options().stepSeconds);
40432
+ }
40350
40433
  }
40351
40434
 
40352
40435
  /**
@@ -40358,6 +40441,10 @@ class SeekBar extends Slider {
40358
40441
  *
40359
40442
  */
40360
40443
  handleAction(event) {
40444
+ if (this.pendingSeekTime() !== null) {
40445
+ this.userSeek_(this.pendingSeekTime());
40446
+ this.pendingSeekTime(null);
40447
+ }
40361
40448
  if (this.player_.paused()) {
40362
40449
  this.player_.play();
40363
40450
  } else {
@@ -40411,11 +40498,11 @@ class SeekBar extends Slider {
40411
40498
  } else if (event.key === 'PageDown') {
40412
40499
  event.preventDefault();
40413
40500
  event.stopPropagation();
40414
- this.userSeek_(this.player_.currentTime() - STEP_SECONDS * PAGE_KEY_MULTIPLIER);
40501
+ this.userSeek_(this.player_.currentTime() - this.options().stepSeconds * this.options().pageMultiplier);
40415
40502
  } else if (event.key === 'PageUp') {
40416
40503
  event.preventDefault();
40417
40504
  event.stopPropagation();
40418
- this.userSeek_(this.player_.currentTime() + STEP_SECONDS * PAGE_KEY_MULTIPLIER);
40505
+ this.userSeek_(this.player_.currentTime() + this.options().stepSeconds * this.options().pageMultiplier);
40419
40506
  } else {
40420
40507
  // Pass keydown handling up for unsupported keys
40421
40508
  super.handleKeyDown(event);
@@ -40448,7 +40535,9 @@ class SeekBar extends Slider {
40448
40535
  */
40449
40536
  SeekBar.prototype.options_ = {
40450
40537
  children: ['loadProgressBar', 'playProgressBar'],
40451
- barName: 'playProgressBar'
40538
+ barName: 'playProgressBar',
40539
+ stepSeconds: 5,
40540
+ pageMultiplier: 12
40452
40541
  };
40453
40542
  Component$1.registerComponent('SeekBar', SeekBar);
40454
40543
 
@@ -44735,22 +44824,22 @@ class TrackSettingsControls extends Component$1 {
44735
44824
  super(player, options);
44736
44825
 
44737
44826
  // Create DOM elements
44738
- const defaultsDescription = this.localize('restore all settings to the default values');
44739
44827
  const resetButton = new Button(player, {
44740
- controlText: defaultsDescription,
44828
+ controlText: this.localize('restore all settings to the default values'),
44741
44829
  className: 'vjs-default-button'
44742
44830
  });
44743
44831
  resetButton.el().classList.remove('vjs-control', 'vjs-button');
44744
44832
  resetButton.el().textContent = this.localize('Reset');
44745
44833
  this.addChild(resetButton);
44834
+ const doneText = this.localize('Done');
44746
44835
  const doneButton = new Button(player, {
44747
- controlText: defaultsDescription,
44836
+ controlText: doneText,
44748
44837
  className: 'vjs-done-button'
44749
44838
  });
44750
44839
 
44751
44840
  // Remove unrequired style classes
44752
44841
  doneButton.el().classList.remove('vjs-control', 'vjs-button');
44753
- doneButton.el().textContent = this.localize('Done');
44842
+ doneButton.el().textContent = doneText;
44754
44843
  this.addChild(doneButton);
44755
44844
  }
44756
44845
 
@@ -48088,8 +48177,12 @@ Tech.registerTech('Html5', Html5);
48088
48177
  * @file player.js
48089
48178
  */
48090
48179
 
48091
- /** @import { TimeRange } from './utils/time' */
48180
+ /** @import AudioTrackList from './tracks/audio-track-list' */
48092
48181
  /** @import HtmlTrackElement from './tracks/html-track-element' */
48182
+ /** @import HtmlTrackElementList from './tracks/html-track-element-list' */
48183
+ /** @import TextTrackList from './tracks/text-track-list' */
48184
+ /** @import { TimeRange } from './utils/time' */
48185
+ /** @import VideoTrackList from './tracks/video-track-list' */
48093
48186
 
48094
48187
  /**
48095
48188
  * @callback PlayerReadyCallback
@@ -53079,6 +53172,7 @@ class Player extends Component$1 {
53079
53172
  *
53080
53173
  * @method Player.prototype.videoTracks
53081
53174
  */
53175
+ Player.prototype.videoTracks = () => {};
53082
53176
 
53083
53177
  /**
53084
53178
  * Get the {@link AudioTrackList}
@@ -53090,6 +53184,7 @@ class Player extends Component$1 {
53090
53184
  *
53091
53185
  * @method Player.prototype.audioTracks
53092
53186
  */
53187
+ Player.prototype.audioTracks = () => {};
53093
53188
 
53094
53189
  /**
53095
53190
  * Get the {@link TextTrackList}
@@ -53101,6 +53196,7 @@ class Player extends Component$1 {
53101
53196
  *
53102
53197
  * @method Player.prototype.textTracks
53103
53198
  */
53199
+ Player.prototype.textTracks = () => {};
53104
53200
 
53105
53201
  /**
53106
53202
  * Get the remote {@link TextTrackList}
@@ -53110,6 +53206,7 @@ class Player extends Component$1 {
53110
53206
  *
53111
53207
  * @method Player.prototype.remoteTextTracks
53112
53208
  */
53209
+ Player.prototype.remoteTextTracks = () => {};
53113
53210
 
53114
53211
  /**
53115
53212
  * Get the remote {@link HtmlTrackElementList} tracks.
@@ -53119,7 +53216,7 @@ class Player extends Component$1 {
53119
53216
  *
53120
53217
  * @method Player.prototype.remoteTextTrackEls
53121
53218
  */
53122
-
53219
+ Player.prototype.remoteTextTrackEls = () => {};
53123
53220
  ALL.names.forEach(function (name) {
53124
53221
  const props = ALL[name];
53125
53222
  Player.prototype[props.getterName] = function () {
@@ -53206,7 +53303,8 @@ Player.prototype.options_ = {
53206
53303
  },
53207
53304
  // Default smooth seeking to false
53208
53305
  enableSmoothSeeking: false,
53209
- disableSeekWhileScrubbingOnMobile: false
53306
+ disableSeekWhileScrubbingOnMobile: false,
53307
+ disableSeekWhileScrubbingOnSTV: false
53210
53308
  };
53211
53309
  TECH_EVENTS_RETRIGGER.forEach(function (event) {
53212
53310
  Player.prototype[`handleTech${toTitleCase$1(event)}_`] = function () {
@@ -54298,9 +54396,13 @@ videojs.trigger = trigger;
54298
54396
  * @see https://github.com/Raynos/xhr
54299
54397
  */
54300
54398
  videojs.xhr = (_videojs_xhr__WEBPACK_IMPORTED_MODULE_2___default());
54399
+ videojs.TrackList = TrackList;
54301
54400
  videojs.TextTrack = TextTrack;
54401
+ videojs.TextTrackList = TextTrackList;
54302
54402
  videojs.AudioTrack = AudioTrack;
54403
+ videojs.AudioTrackList = AudioTrackList;
54303
54404
  videojs.VideoTrack = VideoTrack;
54405
+ videojs.VideoTrackList = VideoTrackList;
54304
54406
  ['isEl', 'isTextNode', 'createEl', 'hasClass', 'addClass', 'removeClass', 'toggleClass', 'setAttributes', 'getAttributes', 'emptyEl', 'appendContent', 'insertContent'].forEach(k => {
54305
54407
  videojs[k] = function () {
54306
54408
  log$1.warn(`videojs.${k}() is deprecated; use videojs.dom.${k}() instead`);
@@ -54624,7 +54726,7 @@ videojs.registerPlugin('qualityLevels', qualityLevels);
54624
54726
  // Include the version number.
54625
54727
  qualityLevels.VERSION = version$5;
54626
54728
 
54627
- /*! @name @videojs/http-streaming @version 3.16.2 @license Apache-2.0 */
54729
+ /*! @name @videojs/http-streaming @version 3.17.0 @license Apache-2.0 */
54628
54730
 
54629
54731
  /**
54630
54732
  * @file resolve-url.js - Handling how URLs are resolved and manipulated
@@ -56137,6 +56239,110 @@ const getStreamingNetworkErrorMetadata = ({
56137
56239
  }
56138
56240
  return errorMetadata;
56139
56241
  };
56242
+
56243
+ /**
56244
+ * @file - codecs.js - Handles tasks regarding codec strings such as translating them to
56245
+ * codec strings, or translating codec strings into objects that can be examined.
56246
+ */
56247
+ const logFn$1 = logger('CodecUtils');
56248
+ /**
56249
+ * Returns a set of codec strings parsed from the playlist or the default
56250
+ * codec strings if no codecs were specified in the playlist
56251
+ *
56252
+ * @param {Playlist} media the current media playlist
56253
+ * @return {Object} an object with the video and audio codecs
56254
+ */
56255
+
56256
+ const getCodecs = function (media) {
56257
+ // if the codecs were explicitly specified, use them instead of the
56258
+ // defaults
56259
+ const mediaAttributes = media.attributes || {};
56260
+ if (mediaAttributes.CODECS) {
56261
+ return (0,_videojs_vhs_utils_es_codecs_js__WEBPACK_IMPORTED_MODULE_7__.parseCodecs)(mediaAttributes.CODECS);
56262
+ }
56263
+ };
56264
+ const isMaat = (main, media) => {
56265
+ const mediaAttributes = media.attributes || {};
56266
+ return main && main.mediaGroups && main.mediaGroups.AUDIO && mediaAttributes.AUDIO && main.mediaGroups.AUDIO[mediaAttributes.AUDIO];
56267
+ };
56268
+ const isMuxed = (main, media) => {
56269
+ if (!isMaat(main, media)) {
56270
+ return true;
56271
+ }
56272
+ const mediaAttributes = media.attributes || {};
56273
+ const audioGroup = main.mediaGroups.AUDIO[mediaAttributes.AUDIO];
56274
+ for (const groupId in audioGroup) {
56275
+ // If an audio group has a URI (the case for HLS, as HLS will use external playlists),
56276
+ // or there are listed playlists (the case for DASH, as the manifest will have already
56277
+ // provided all of the details necessary to generate the audio playlist, as opposed to
56278
+ // HLS' externally requested playlists), then the content is demuxed.
56279
+ if (!audioGroup[groupId].uri && !audioGroup[groupId].playlists) {
56280
+ return true;
56281
+ }
56282
+ }
56283
+ return false;
56284
+ };
56285
+ const unwrapCodecList = function (codecList) {
56286
+ const codecs = {};
56287
+ codecList.forEach(({
56288
+ mediaType,
56289
+ type,
56290
+ details
56291
+ }) => {
56292
+ codecs[mediaType] = codecs[mediaType] || [];
56293
+ codecs[mediaType].push((0,_videojs_vhs_utils_es_codecs_js__WEBPACK_IMPORTED_MODULE_7__.translateLegacyCodec)(`${type}${details}`));
56294
+ });
56295
+ Object.keys(codecs).forEach(function (mediaType) {
56296
+ if (codecs[mediaType].length > 1) {
56297
+ logFn$1(`multiple ${mediaType} codecs found as attributes: ${codecs[mediaType].join(', ')}. Setting playlist codecs to null so that we wait for mux.js to probe segments for real codecs.`);
56298
+ codecs[mediaType] = null;
56299
+ return;
56300
+ }
56301
+ codecs[mediaType] = codecs[mediaType][0];
56302
+ });
56303
+ return codecs;
56304
+ };
56305
+ const codecCount = function (codecObj) {
56306
+ let count = 0;
56307
+ if (codecObj.audio) {
56308
+ count++;
56309
+ }
56310
+ if (codecObj.video) {
56311
+ count++;
56312
+ }
56313
+ return count;
56314
+ };
56315
+ /**
56316
+ * Calculates the codec strings for a working configuration of
56317
+ * SourceBuffers to play variant streams in a main playlist. If
56318
+ * there is no possible working configuration, an empty object will be
56319
+ * returned.
56320
+ *
56321
+ * @param main {Object} the m3u8 object for the main playlist
56322
+ * @param media {Object} the m3u8 object for the variant playlist
56323
+ * @return {Object} the codec strings.
56324
+ *
56325
+ * @private
56326
+ */
56327
+
56328
+ const codecsForPlaylist = function (main, media) {
56329
+ const mediaAttributes = media.attributes || {};
56330
+ const codecInfo = unwrapCodecList(getCodecs(media) || []); // HLS with multiple-audio tracks must always get an audio codec.
56331
+ // Put another way, there is no way to have a video-only multiple-audio HLS!
56332
+
56333
+ if (isMaat(main, media) && !codecInfo.audio) {
56334
+ if (!isMuxed(main, media)) {
56335
+ // It is possible for codecs to be specified on the audio media group playlist but
56336
+ // not on the rendition playlist. This is mostly the case for DASH, where audio and
56337
+ // video are always separate (and separately specified).
56338
+ const defaultCodecs = unwrapCodecList((0,_videojs_vhs_utils_es_codecs_js__WEBPACK_IMPORTED_MODULE_7__.codecsFromDefault)(main, mediaAttributes.AUDIO) || []);
56339
+ if (defaultCodecs.audio) {
56340
+ codecInfo.audio = defaultCodecs.audio;
56341
+ }
56342
+ }
56343
+ }
56344
+ return codecInfo;
56345
+ };
56140
56346
  const {
56141
56347
  EventTarget: EventTarget$1
56142
56348
  } = videojs;
@@ -56572,7 +56778,7 @@ class PlaylistLoader extends EventTarget$1 {
56572
56778
  manifestString
56573
56779
  }) {
56574
56780
  try {
56575
- return parseManifest({
56781
+ const parsed = parseManifest({
56576
56782
  onwarn: ({
56577
56783
  message
56578
56784
  }) => this.logger_(`m3u8-parser warn for ${url}: ${message}`),
@@ -56584,6 +56790,16 @@ class PlaylistLoader extends EventTarget$1 {
56584
56790
  customTagMappers: this.customTagMappers,
56585
56791
  llhls: this.llhls
56586
56792
  });
56793
+ /**
56794
+ * VHS does not support switching between variants with and without audio and video
56795
+ * so we want to filter out audio-only variants when variants with video and(or) audio are also detected.
56796
+ */
56797
+
56798
+ if (!parsed.playlists || !parsed.playlists.length) {
56799
+ return parsed;
56800
+ }
56801
+ this.excludeAudioOnlyVariants(parsed.playlists);
56802
+ return parsed;
56587
56803
  } catch (error) {
56588
56804
  this.error = error;
56589
56805
  this.error.metadata = {
@@ -56592,6 +56808,31 @@ class PlaylistLoader extends EventTarget$1 {
56592
56808
  };
56593
56809
  }
56594
56810
  }
56811
+ excludeAudioOnlyVariants(playlists) {
56812
+ // helper function
56813
+ const hasVideo = playlist => {
56814
+ const attributes = playlist.attributes || {};
56815
+ const {
56816
+ width,
56817
+ height
56818
+ } = attributes.RESOLUTION || {};
56819
+ if (width && height) {
56820
+ return true;
56821
+ } // parse codecs string from playlist attributes
56822
+
56823
+ const codecsList = getCodecs(playlist) || []; // unwrap list
56824
+
56825
+ const codecsInfo = unwrapCodecList(codecsList);
56826
+ return Boolean(codecsInfo.video);
56827
+ };
56828
+ if (playlists.some(hasVideo)) {
56829
+ playlists.forEach(playlist => {
56830
+ if (!hasVideo(playlist)) {
56831
+ playlist.excludeUntil = Infinity;
56832
+ }
56833
+ });
56834
+ }
56835
+ }
56595
56836
  /**
56596
56837
  * Update the playlist loader's state in response to a new or updated playlist.
56597
56838
  *
@@ -69827,110 +70068,6 @@ const mediaSegmentRequest = ({
69827
70068
  });
69828
70069
  return () => abortAll(activeXhrs);
69829
70070
  };
69830
-
69831
- /**
69832
- * @file - codecs.js - Handles tasks regarding codec strings such as translating them to
69833
- * codec strings, or translating codec strings into objects that can be examined.
69834
- */
69835
- const logFn$1 = logger('CodecUtils');
69836
- /**
69837
- * Returns a set of codec strings parsed from the playlist or the default
69838
- * codec strings if no codecs were specified in the playlist
69839
- *
69840
- * @param {Playlist} media the current media playlist
69841
- * @return {Object} an object with the video and audio codecs
69842
- */
69843
-
69844
- const getCodecs = function (media) {
69845
- // if the codecs were explicitly specified, use them instead of the
69846
- // defaults
69847
- const mediaAttributes = media.attributes || {};
69848
- if (mediaAttributes.CODECS) {
69849
- return (0,_videojs_vhs_utils_es_codecs_js__WEBPACK_IMPORTED_MODULE_7__.parseCodecs)(mediaAttributes.CODECS);
69850
- }
69851
- };
69852
- const isMaat = (main, media) => {
69853
- const mediaAttributes = media.attributes || {};
69854
- return main && main.mediaGroups && main.mediaGroups.AUDIO && mediaAttributes.AUDIO && main.mediaGroups.AUDIO[mediaAttributes.AUDIO];
69855
- };
69856
- const isMuxed = (main, media) => {
69857
- if (!isMaat(main, media)) {
69858
- return true;
69859
- }
69860
- const mediaAttributes = media.attributes || {};
69861
- const audioGroup = main.mediaGroups.AUDIO[mediaAttributes.AUDIO];
69862
- for (const groupId in audioGroup) {
69863
- // If an audio group has a URI (the case for HLS, as HLS will use external playlists),
69864
- // or there are listed playlists (the case for DASH, as the manifest will have already
69865
- // provided all of the details necessary to generate the audio playlist, as opposed to
69866
- // HLS' externally requested playlists), then the content is demuxed.
69867
- if (!audioGroup[groupId].uri && !audioGroup[groupId].playlists) {
69868
- return true;
69869
- }
69870
- }
69871
- return false;
69872
- };
69873
- const unwrapCodecList = function (codecList) {
69874
- const codecs = {};
69875
- codecList.forEach(({
69876
- mediaType,
69877
- type,
69878
- details
69879
- }) => {
69880
- codecs[mediaType] = codecs[mediaType] || [];
69881
- codecs[mediaType].push((0,_videojs_vhs_utils_es_codecs_js__WEBPACK_IMPORTED_MODULE_7__.translateLegacyCodec)(`${type}${details}`));
69882
- });
69883
- Object.keys(codecs).forEach(function (mediaType) {
69884
- if (codecs[mediaType].length > 1) {
69885
- logFn$1(`multiple ${mediaType} codecs found as attributes: ${codecs[mediaType].join(', ')}. Setting playlist codecs to null so that we wait for mux.js to probe segments for real codecs.`);
69886
- codecs[mediaType] = null;
69887
- return;
69888
- }
69889
- codecs[mediaType] = codecs[mediaType][0];
69890
- });
69891
- return codecs;
69892
- };
69893
- const codecCount = function (codecObj) {
69894
- let count = 0;
69895
- if (codecObj.audio) {
69896
- count++;
69897
- }
69898
- if (codecObj.video) {
69899
- count++;
69900
- }
69901
- return count;
69902
- };
69903
- /**
69904
- * Calculates the codec strings for a working configuration of
69905
- * SourceBuffers to play variant streams in a main playlist. If
69906
- * there is no possible working configuration, an empty object will be
69907
- * returned.
69908
- *
69909
- * @param main {Object} the m3u8 object for the main playlist
69910
- * @param media {Object} the m3u8 object for the variant playlist
69911
- * @return {Object} the codec strings.
69912
- *
69913
- * @private
69914
- */
69915
-
69916
- const codecsForPlaylist = function (main, media) {
69917
- const mediaAttributes = media.attributes || {};
69918
- const codecInfo = unwrapCodecList(getCodecs(media) || []); // HLS with multiple-audio tracks must always get an audio codec.
69919
- // Put another way, there is no way to have a video-only multiple-audio HLS!
69920
-
69921
- if (isMaat(main, media) && !codecInfo.audio) {
69922
- if (!isMuxed(main, media)) {
69923
- // It is possible for codecs to be specified on the audio media group playlist but
69924
- // not on the rendition playlist. This is mostly the case for DASH, where audio and
69925
- // video are always separate (and separately specified).
69926
- const defaultCodecs = unwrapCodecList((0,_videojs_vhs_utils_es_codecs_js__WEBPACK_IMPORTED_MODULE_7__.codecsFromDefault)(main, mediaAttributes.AUDIO) || []);
69927
- if (defaultCodecs.audio) {
69928
- codecInfo.audio = defaultCodecs.audio;
69929
- }
69930
- }
69931
- }
69932
- return codecInfo;
69933
- };
69934
70071
  const logFn = logger('PlaylistSelector');
69935
70072
  const representationToString = function (representation) {
69936
70073
  if (!representation || !representation.playlist) {
@@ -70041,25 +70178,40 @@ const comparePlaylistResolution = function (left, right) {
70041
70178
  /**
70042
70179
  * Chooses the appropriate media playlist based on bandwidth and player size
70043
70180
  *
70044
- * @param {Object} main
70181
+ * @param {Object} settings
70182
+ * Object of information required to use this selector
70183
+ * @param {Object} settings.main
70045
70184
  * Object representation of the main manifest
70046
- * @param {number} playerBandwidth
70185
+ * @param {number} settings.bandwidth
70047
70186
  * Current calculated bandwidth of the player
70048
- * @param {number} playerWidth
70187
+ * @param {number} settings.playerWidth
70049
70188
  * Current width of the player element (should account for the device pixel ratio)
70050
- * @param {number} playerHeight
70189
+ * @param {number} settings.playerHeight
70051
70190
  * Current height of the player element (should account for the device pixel ratio)
70052
- * @param {boolean} limitRenditionByPlayerDimensions
70191
+ * @param {number} settings.playerObjectFit
70192
+ * Current value of the video element's object-fit CSS property. Allows taking into
70193
+ * account that the video might be scaled up to cover the media element when selecting
70194
+ * media playlists based on player size.
70195
+ * @param {boolean} settings.limitRenditionByPlayerDimensions
70053
70196
  * True if the player width and height should be used during the selection, false otherwise
70054
- * @param {Object} playlistController
70197
+ * @param {Object} settings.playlistController
70055
70198
  * the current playlistController object
70056
70199
  * @return {Playlist} the highest bitrate playlist less than the
70057
70200
  * currently detected bandwidth, accounting for some amount of
70058
70201
  * bandwidth variance
70059
70202
  */
70060
70203
 
70061
- let simpleSelector = function (main, playerBandwidth, playerWidth, playerHeight, limitRenditionByPlayerDimensions, playlistController) {
70062
- // If we end up getting called before `main` is available, exit early
70204
+ let simpleSelector = function (settings) {
70205
+ const {
70206
+ main,
70207
+ bandwidth: playerBandwidth,
70208
+ playerWidth,
70209
+ playerHeight,
70210
+ playerObjectFit,
70211
+ limitRenditionByPlayerDimensions,
70212
+ playlistController
70213
+ } = settings; // If we end up getting called before `main` is available, exit early
70214
+
70063
70215
  if (!main) {
70064
70216
  return;
70065
70217
  }
@@ -70143,7 +70295,17 @@ let simpleSelector = function (main, playerBandwidth, playerWidth, playerHeight,
70143
70295
  // if there is no match of exact resolution
70144
70296
 
70145
70297
  if (!resolutionBestRep) {
70146
- resolutionPlusOneList = haveResolution.filter(rep => rep.width > playerWidth || rep.height > playerHeight); // find all the variants have the same smallest resolution
70298
+ resolutionPlusOneList = haveResolution.filter(rep => {
70299
+ if (playerObjectFit === 'cover') {
70300
+ // video will be scaled up to cover the player. We need to
70301
+ // make sure rendition is at least as wide and as high as the
70302
+ // player.
70303
+ return rep.width > playerWidth && rep.height > playerHeight;
70304
+ } // video will be scaled down to fit inside the player soon as
70305
+ // its resolution exceeds player size in at least one dimension.
70306
+
70307
+ return rep.width > playerWidth || rep.height > playerHeight;
70308
+ }); // find all the variants have the same smallest resolution
70147
70309
 
70148
70310
  resolutionPlusOneSmallest = resolutionPlusOneList.filter(rep => rep.width === resolutionPlusOneList[0].width && rep.height === resolutionPlusOneList[0].height); // ensure that we also pick the highest bandwidth variant that
70149
70311
  // is just-larger-than the video player
@@ -70209,7 +70371,15 @@ const lastBandwidthSelector = function () {
70209
70371
  if (!isNaN(this.customPixelRatio)) {
70210
70372
  pixelRatio = this.customPixelRatio;
70211
70373
  }
70212
- return simpleSelector(this.playlists.main, this.systemBandwidth, parseInt(safeGetComputedStyle(this.tech_.el(), 'width'), 10) * pixelRatio, parseInt(safeGetComputedStyle(this.tech_.el(), 'height'), 10) * pixelRatio, this.limitRenditionByPlayerDimensions, this.playlistController_);
70374
+ return simpleSelector({
70375
+ main: this.playlists.main,
70376
+ bandwidth: this.systemBandwidth,
70377
+ playerWidth: parseInt(safeGetComputedStyle(this.tech_.el(), 'width'), 10) * pixelRatio,
70378
+ playerHeight: parseInt(safeGetComputedStyle(this.tech_.el(), 'height'), 10) * pixelRatio,
70379
+ playerObjectFit: this.usePlayerObjectFit ? safeGetComputedStyle(this.tech_.el(), 'objectFit') : '',
70380
+ limitRenditionByPlayerDimensions: this.limitRenditionByPlayerDimensions,
70381
+ playlistController: this.playlistController_
70382
+ });
70213
70383
  };
70214
70384
  /**
70215
70385
  * Chooses the appropriate media playlist based on an
@@ -70250,7 +70420,15 @@ const movingAverageBandwidthSelector = function (decay) {
70250
70420
  average = decay * this.systemBandwidth + (1 - decay) * average;
70251
70421
  lastSystemBandwidth = this.systemBandwidth;
70252
70422
  }
70253
- return simpleSelector(this.playlists.main, average, parseInt(safeGetComputedStyle(this.tech_.el(), 'width'), 10) * pixelRatio, parseInt(safeGetComputedStyle(this.tech_.el(), 'height'), 10) * pixelRatio, this.limitRenditionByPlayerDimensions, this.playlistController_);
70423
+ return simpleSelector({
70424
+ main: this.playlists.main,
70425
+ bandwidth: average,
70426
+ playerWidth: parseInt(safeGetComputedStyle(this.tech_.el(), 'width'), 10) * pixelRatio,
70427
+ playerHeight: parseInt(safeGetComputedStyle(this.tech_.el(), 'height'), 10) * pixelRatio,
70428
+ playerObjectFit: this.usePlayerObjectFit ? safeGetComputedStyle(this.tech_.el(), 'objectFit') : '',
70429
+ limitRenditionByPlayerDimensions: this.limitRenditionByPlayerDimensions,
70430
+ playlistController: this.playlistController_
70431
+ });
70254
70432
  };
70255
70433
  };
70256
70434
  /**
@@ -78307,6 +78485,7 @@ class PlaylistController extends videojs.EventTarget {
78307
78485
  kind: 'metadata',
78308
78486
  label: 'segment-metadata'
78309
78487
  }, false).track;
78488
+ this.segmentMetadataTrack_.mode = 'hidden';
78310
78489
  this.decrypter_ = new Decrypter();
78311
78490
  this.sourceUpdater_ = new SourceUpdater(this.mediaSource);
78312
78491
  this.inbandTextTracks_ = {};
@@ -79544,12 +79723,9 @@ class PlaylistController extends videojs.EventTarget {
79544
79723
  if (!isFinite(start) || !isFinite(end)) {
79545
79724
  return null;
79546
79725
  }
79547
- const liveEdgeDelay = Vhs$1.Playlist.liveEdgeDelay(this.mainPlaylistLoader_.main, media); // Make sure our seekable end is not negative
79726
+ const liveEdgeDelay = Vhs$1.Playlist.liveEdgeDelay(this.mainPlaylistLoader_.main, media); // Make sure our seekable end is not less than the seekable start
79548
79727
 
79549
- const calculatedEnd = Math.max(0, end - liveEdgeDelay);
79550
- if (calculatedEnd < start) {
79551
- return null;
79552
- }
79728
+ const calculatedEnd = Math.max(start, end - liveEdgeDelay);
79553
79729
  return createTimeRanges([[start, calculatedEnd]]);
79554
79730
  }
79555
79731
  const expired = this.syncController_.getExpiredTime(media, this.duration());
@@ -81144,7 +81320,7 @@ const initPlugin = function (player, options) {
81144
81320
  const reloadSourceOnError = function (options) {
81145
81321
  initPlugin(this, options);
81146
81322
  };
81147
- var version$4 = "3.16.2";
81323
+ var version$4 = "3.17.0";
81148
81324
  var version$3 = "7.1.0";
81149
81325
  var version$2 = "1.3.1";
81150
81326
  var version$1 = "7.2.0";
@@ -81703,9 +81879,10 @@ class VhsHandler extends Component {
81703
81879
  this.options_.withCredentials = this.options_.withCredentials || false;
81704
81880
  this.options_.limitRenditionByPlayerDimensions = this.options_.limitRenditionByPlayerDimensions === false ? false : true;
81705
81881
  this.options_.useDevicePixelRatio = this.options_.useDevicePixelRatio || false;
81882
+ this.options_.usePlayerObjectFit = this.options_.usePlayerObjectFit || false;
81706
81883
  this.options_.useBandwidthFromLocalStorage = typeof this.source_.useBandwidthFromLocalStorage !== 'undefined' ? this.source_.useBandwidthFromLocalStorage : this.options_.useBandwidthFromLocalStorage || false;
81707
81884
  this.options_.useForcedSubtitles = this.options_.useForcedSubtitles || false;
81708
- this.options_.useNetworkInformationApi = this.options_.useNetworkInformationApi || false;
81885
+ this.options_.useNetworkInformationApi = typeof this.options_.useNetworkInformationApi !== 'undefined' ? this.options_.useNetworkInformationApi : true;
81709
81886
  this.options_.useDtsForTimestampOffset = this.options_.useDtsForTimestampOffset || false;
81710
81887
  this.options_.customTagParsers = this.options_.customTagParsers || [];
81711
81888
  this.options_.customTagMappers = this.options_.customTagMappers || [];
@@ -81743,13 +81920,14 @@ class VhsHandler extends Component {
81743
81920
 
81744
81921
  this.options_.enableLowInitialPlaylist = this.options_.enableLowInitialPlaylist && this.options_.bandwidth === Config.INITIAL_BANDWIDTH; // grab options passed to player.src
81745
81922
 
81746
- ['withCredentials', 'useDevicePixelRatio', 'customPixelRatio', 'limitRenditionByPlayerDimensions', 'bandwidth', 'customTagParsers', 'customTagMappers', 'cacheEncryptionKeys', 'playlistSelector', 'initialPlaylistSelector', 'bufferBasedABR', 'liveRangeSafeTimeDelta', 'llhls', 'useForcedSubtitles', 'useNetworkInformationApi', 'useDtsForTimestampOffset', 'exactManifestTimings', 'leastPixelDiffSelector'].forEach(option => {
81923
+ ['withCredentials', 'useDevicePixelRatio', 'usePlayerObjectFit', 'customPixelRatio', 'limitRenditionByPlayerDimensions', 'bandwidth', 'customTagParsers', 'customTagMappers', 'cacheEncryptionKeys', 'playlistSelector', 'initialPlaylistSelector', 'bufferBasedABR', 'liveRangeSafeTimeDelta', 'llhls', 'useForcedSubtitles', 'useNetworkInformationApi', 'useDtsForTimestampOffset', 'exactManifestTimings', 'leastPixelDiffSelector'].forEach(option => {
81747
81924
  if (typeof this.source_[option] !== 'undefined') {
81748
81925
  this.options_[option] = this.source_[option];
81749
81926
  }
81750
81927
  });
81751
81928
  this.limitRenditionByPlayerDimensions = this.options_.limitRenditionByPlayerDimensions;
81752
81929
  this.useDevicePixelRatio = this.options_.useDevicePixelRatio;
81930
+ this.usePlayerObjectFit = this.options_.usePlayerObjectFit;
81753
81931
  const customPixelRatio = this.options_.customPixelRatio; // Ensure the custom pixel ratio is a number greater than or equal to 0
81754
81932
 
81755
81933
  if (typeof customPixelRatio === 'number' && customPixelRatio >= 0) {