hls.js 1.5.12-0.canary.10366 → 1.5.12-0.canary.10367

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/dist/hls.light.js CHANGED
@@ -493,7 +493,7 @@
493
493
  // Some browsers don't allow to use bind on console object anyway
494
494
  // fallback to default if needed
495
495
  try {
496
- newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.12-0.canary.10366");
496
+ newLogger.log("Debug logs enabled for \"" + context + "\" in hls.js version " + "1.5.12-0.canary.10367");
497
497
  } catch (e) {
498
498
  /* log fn threw an exception. All logger methods are no-ops. */
499
499
  return createLogger();
@@ -3713,10 +3713,9 @@
3713
3713
  level = context.level,
3714
3714
  type = context.type;
3715
3715
  var url = getResponseUrl(response, context);
3716
- var levelUrlId = 0;
3717
3716
  var levelId = isFiniteNumber(level) ? level : isFiniteNumber(id) ? id : 0;
3718
3717
  var levelType = mapContextToLevelType(context);
3719
- var levelDetails = M3U8Parser.parseLevelPlaylist(response.data, url, levelId, levelType, levelUrlId, this.variableList);
3718
+ var levelDetails = M3U8Parser.parseLevelPlaylist(response.data, url, levelId, levelType, 0, this.variableList);
3720
3719
 
3721
3720
  // We have done our first request (Manifest-type) and receive
3722
3721
  // not a master playlist but a chunk-list (track/level)
@@ -5504,8 +5503,7 @@
5504
5503
  }
5505
5504
  return Math.round(reloadInterval);
5506
5505
  }
5507
- function getFragmentWithSN(level, sn, fragCurrent) {
5508
- var details = level == null ? void 0 : level.details;
5506
+ function getFragmentWithSN(details, sn, fragCurrent) {
5509
5507
  if (!details) {
5510
5508
  return null;
5511
5509
  }
@@ -5522,12 +5520,11 @@
5522
5520
  }
5523
5521
  return null;
5524
5522
  }
5525
- function getPartWith(level, sn, partIndex) {
5526
- var _level$details;
5527
- if (!(level != null && level.details)) {
5523
+ function getPartWith(details, sn, partIndex) {
5524
+ if (!details) {
5528
5525
  return null;
5529
5526
  }
5530
- return findPart((_level$details = level.details) == null ? void 0 : _level$details.partList, sn, partIndex);
5527
+ return findPart(details.partList, sn, partIndex);
5531
5528
  }
5532
5529
  function findPart(partList, sn, partIndex) {
5533
5530
  if (partList) {
@@ -5678,12 +5675,15 @@
5678
5675
  }
5679
5676
  var fragNext = null;
5680
5677
  if (fragPrevious) {
5681
- fragNext = fragments[fragPrevious.sn - fragments[0].sn + 1] || null;
5678
+ fragNext = fragments[1 + fragPrevious.sn - fragments[0].sn] || null;
5682
5679
  // check for buffer-end rounding error
5683
5680
  var bufferEdgeError = fragPrevious.endDTS - bufferEnd;
5684
5681
  if (bufferEdgeError > 0 && bufferEdgeError < 0.0000015) {
5685
5682
  bufferEnd += 0.0000015;
5686
5683
  }
5684
+ if (fragNext && fragPrevious.level !== fragNext.level && fragNext.end <= fragPrevious.end) {
5685
+ fragNext = fragments[2 + fragPrevious.sn - fragments[0].sn] || null;
5686
+ }
5687
5687
  } else if (bufferEnd === 0 && fragments[0].start === 0) {
5688
5688
  fragNext = fragments[0];
5689
5689
  }
@@ -5845,7 +5845,7 @@
5845
5845
  this.playlistError = 0;
5846
5846
  };
5847
5847
  _proto.onError = function onError(event, data) {
5848
- var _data$frag, _data$level;
5848
+ var _data$frag;
5849
5849
  if (data.fatal) {
5850
5850
  return;
5851
5851
  }
@@ -5861,10 +5861,7 @@
5861
5861
  case ErrorDetails.FRAG_PARSING_ERROR:
5862
5862
  // ignore empty segment errors marked as gap
5863
5863
  if ((_data$frag = data.frag) != null && _data$frag.gap) {
5864
- data.errorAction = {
5865
- action: NetworkErrorAction.DoNothing,
5866
- flags: ErrorActionFlags.None
5867
- };
5864
+ data.errorAction = createDoNothingErrorAction();
5868
5865
  return;
5869
5866
  }
5870
5867
  // falls through
@@ -5931,7 +5928,11 @@
5931
5928
  case ErrorDetails.BUFFER_ADD_CODEC_ERROR:
5932
5929
  case ErrorDetails.REMUX_ALLOC_ERROR:
5933
5930
  case ErrorDetails.BUFFER_APPEND_ERROR:
5934
- data.errorAction = this.getLevelSwitchAction(data, (_data$level = data.level) != null ? _data$level : hls.loadLevel);
5931
+ // Buffer-controller can set errorAction when append errors can be ignored or resolved locally
5932
+ if (!data.errorAction) {
5933
+ var _data$level;
5934
+ data.errorAction = this.getLevelSwitchAction(data, (_data$level = data.level) != null ? _data$level : hls.loadLevel);
5935
+ }
5935
5936
  return;
5936
5937
  case ErrorDetails.INTERNAL_EXCEPTION:
5937
5938
  case ErrorDetails.BUFFER_APPENDING_ERROR:
@@ -5940,10 +5941,7 @@
5940
5941
  case ErrorDetails.BUFFER_STALLED_ERROR:
5941
5942
  case ErrorDetails.BUFFER_SEEK_OVER_HOLE:
5942
5943
  case ErrorDetails.BUFFER_NUDGE_ON_STALL:
5943
- data.errorAction = {
5944
- action: NetworkErrorAction.DoNothing,
5945
- flags: ErrorActionFlags.None
5946
- };
5944
+ data.errorAction = createDoNothingErrorAction();
5947
5945
  return;
5948
5946
  }
5949
5947
  if (data.type === ErrorTypes.KEY_SYSTEM_ERROR) {
@@ -6162,6 +6160,13 @@
6162
6160
  };
6163
6161
  return ErrorController;
6164
6162
  }(Logger);
6163
+ function createDoNothingErrorAction(resolved) {
6164
+ var errorAction = {
6165
+ action: NetworkErrorAction.DoNothing,
6166
+ flags: ErrorActionFlags.None
6167
+ };
6168
+ return errorAction;
6169
+ }
6165
6170
 
6166
6171
  var BasePlaylistController = /*#__PURE__*/function (_Logger) {
6167
6172
  function BasePlaylistController(hls, logPrefix) {
@@ -6637,6 +6642,7 @@
6637
6642
  if (!hasCurrentVideoRange) {
6638
6643
  currentVideoRange = undefined;
6639
6644
  }
6645
+ var hasMultipleSets = codecSets.length > 1;
6640
6646
  var codecSet = codecSets.reduce(function (selected, candidate) {
6641
6647
  // Remove candiates which do not meet bitrate, default audio, stereo or channels preference, 1080p or lower, 30fps or lower, or SDR/HDR selection if present
6642
6648
  var candidateTier = codecTiers[candidate];
@@ -6646,48 +6652,50 @@
6646
6652
  videoRanges = hasCurrentVideoRange ? allowedVideoRanges.filter(function (range) {
6647
6653
  return candidateTier.videoRanges[range] > 0;
6648
6654
  }) : [];
6649
- if (candidateTier.minBitrate > currentBw) {
6650
- logStartCodecCandidateIgnored(candidate, "min bitrate of " + candidateTier.minBitrate + " > current estimate of " + currentBw);
6651
- return selected;
6652
- }
6653
- if (!candidateTier.hasDefaultAudio) {
6654
- logStartCodecCandidateIgnored(candidate, "no renditions with default or auto-select sound found");
6655
- return selected;
6656
- }
6657
- if (audioCodecPreference && candidate.indexOf(audioCodecPreference.substring(0, 4)) % 5 !== 0) {
6658
- logStartCodecCandidateIgnored(candidate, "audio codec preference \"" + audioCodecPreference + "\" not found");
6659
- return selected;
6660
- }
6661
- if (channelsPreference && !preferStereo) {
6662
- if (!candidateTier.channels[channelsPreference]) {
6663
- logStartCodecCandidateIgnored(candidate, "no renditions with " + channelsPreference + " channel sound found (channels options: " + Object.keys(candidateTier.channels) + ")");
6655
+ if (hasMultipleSets) {
6656
+ if (candidateTier.minBitrate > currentBw) {
6657
+ logStartCodecCandidateIgnored(candidate, "min bitrate of " + candidateTier.minBitrate + " > current estimate of " + currentBw);
6658
+ return selected;
6659
+ }
6660
+ if (!candidateTier.hasDefaultAudio) {
6661
+ logStartCodecCandidateIgnored(candidate, "no renditions with default or auto-select sound found");
6662
+ return selected;
6663
+ }
6664
+ if (audioCodecPreference && candidate.indexOf(audioCodecPreference.substring(0, 4)) % 5 !== 0) {
6665
+ logStartCodecCandidateIgnored(candidate, "audio codec preference \"" + audioCodecPreference + "\" not found");
6666
+ return selected;
6667
+ }
6668
+ if (channelsPreference && !preferStereo) {
6669
+ if (!candidateTier.channels[channelsPreference]) {
6670
+ logStartCodecCandidateIgnored(candidate, "no renditions with " + channelsPreference + " channel sound found (channels options: " + Object.keys(candidateTier.channels) + ")");
6671
+ return selected;
6672
+ }
6673
+ } else if ((!audioCodecPreference || preferStereo) && hasStereo && candidateTier.channels['2'] === 0) {
6674
+ logStartCodecCandidateIgnored(candidate, "no renditions with stereo sound found");
6675
+ return selected;
6676
+ }
6677
+ if (candidateTier.minHeight > maxHeight) {
6678
+ logStartCodecCandidateIgnored(candidate, "min resolution of " + candidateTier.minHeight + " > maximum of " + maxHeight);
6679
+ return selected;
6680
+ }
6681
+ if (candidateTier.minFramerate > maxFramerate) {
6682
+ logStartCodecCandidateIgnored(candidate, "min framerate of " + candidateTier.minFramerate + " > maximum of " + maxFramerate);
6683
+ return selected;
6684
+ }
6685
+ if (!videoRanges.some(function (range) {
6686
+ return candidateTier.videoRanges[range] > 0;
6687
+ })) {
6688
+ logStartCodecCandidateIgnored(candidate, "no variants with VIDEO-RANGE of " + JSON.stringify(videoRanges) + " found");
6689
+ return selected;
6690
+ }
6691
+ if (videoCodecPreference && candidate.indexOf(videoCodecPreference.substring(0, 4)) % 5 !== 0) {
6692
+ logStartCodecCandidateIgnored(candidate, "video codec preference \"" + videoCodecPreference + "\" not found");
6693
+ return selected;
6694
+ }
6695
+ if (candidateTier.maxScore < selectedScore) {
6696
+ logStartCodecCandidateIgnored(candidate, "max score of " + candidateTier.maxScore + " < selected max of " + selectedScore);
6664
6697
  return selected;
6665
6698
  }
6666
- } else if ((!audioCodecPreference || preferStereo) && hasStereo && candidateTier.channels['2'] === 0) {
6667
- logStartCodecCandidateIgnored(candidate, "no renditions with stereo sound found");
6668
- return selected;
6669
- }
6670
- if (candidateTier.minHeight > maxHeight) {
6671
- logStartCodecCandidateIgnored(candidate, "min resolution of " + candidateTier.minHeight + " > maximum of " + maxHeight);
6672
- return selected;
6673
- }
6674
- if (candidateTier.minFramerate > maxFramerate) {
6675
- logStartCodecCandidateIgnored(candidate, "min framerate of " + candidateTier.minFramerate + " > maximum of " + maxFramerate);
6676
- return selected;
6677
- }
6678
- if (!videoRanges.some(function (range) {
6679
- return candidateTier.videoRanges[range] > 0;
6680
- })) {
6681
- logStartCodecCandidateIgnored(candidate, "no variants with VIDEO-RANGE of " + JSON.stringify(videoRanges) + " found");
6682
- return selected;
6683
- }
6684
- if (videoCodecPreference && candidate.indexOf(videoCodecPreference.substring(0, 4)) % 5 !== 0) {
6685
- logStartCodecCandidateIgnored(candidate, "video codec preference \"" + videoCodecPreference + "\" not found");
6686
- return selected;
6687
- }
6688
- if (candidateTier.maxScore < selectedScore) {
6689
- logStartCodecCandidateIgnored(candidate, "max score of " + candidateTier.maxScore + " < selected max of " + selectedScore);
6690
- return selected;
6691
6699
  }
6692
6700
  // Remove candiates with less preferred codecs or more errors
6693
6701
  if (selected && (codecsSetSelectionPreferenceValue(candidate) >= codecsSetSelectionPreferenceValue(selected) || candidateTier.fragmentError > codecTiers[selected].fragmentError)) {
@@ -7288,7 +7296,7 @@
7288
7296
  if (levelsSkipped.length) {
7289
7297
  _this3.trace("Skipped level(s) " + levelsSkipped.join(',') + " of " + maxAutoLevel + " max with CODECS and VIDEO-RANGE:\"" + levels[levelsSkipped[0]].codecs + "\" " + levels[levelsSkipped[0]].videoRange + "; not compatible with \"" + level.codecs + "\" " + currentVideoRange);
7290
7298
  }
7291
- _this3.info("switch candidate:" + selectionBaseLevel + "->" + i + " adjustedbw(" + Math.round(adjustedbw) + ")-bitrate=" + Math.round(adjustedbw - bitrate) + " ttfb:" + ttfbEstimateSec.toFixed(1) + " avgDuration:" + avgDuration.toFixed(1) + " maxFetchDuration:" + maxFetchDuration.toFixed(1) + " fetchDuration:" + fetchDuration.toFixed(1) + " firstSelection:" + firstSelection + " codecSet:" + level.codecSet + " videoRange:" + level.videoRange + " hls.loadLevel:" + loadLevel);
7299
+ _this3.info("switch candidate:" + selectionBaseLevel + "->" + i + " adjustedbw(" + Math.round(adjustedbw) + ")-bitrate=" + Math.round(adjustedbw - bitrate) + " ttfb:" + ttfbEstimateSec.toFixed(1) + " avgDuration:" + avgDuration.toFixed(1) + " maxFetchDuration:" + maxFetchDuration.toFixed(1) + " fetchDuration:" + fetchDuration.toFixed(1) + " firstSelection:" + firstSelection + " codecSet:" + levelInfo.codecSet + " videoRange:" + levelInfo.videoRange + " hls.loadLevel:" + loadLevel);
7292
7300
  }
7293
7301
  if (firstSelection) {
7294
7302
  _this3.firstSelection = i;
@@ -7704,6 +7712,7 @@
7704
7712
  hls.on(Events.LEVEL_UPDATED, this.onLevelUpdated, this);
7705
7713
  hls.on(Events.FRAG_PARSED, this.onFragParsed, this);
7706
7714
  hls.on(Events.FRAG_CHANGED, this.onFragChanged, this);
7715
+ hls.on(Events.ERROR, this.onError, this);
7707
7716
  };
7708
7717
  _proto.unregisterListeners = function unregisterListeners() {
7709
7718
  var hls = this.hls;
@@ -7719,6 +7728,7 @@
7719
7728
  hls.off(Events.LEVEL_UPDATED, this.onLevelUpdated, this);
7720
7729
  hls.off(Events.FRAG_PARSED, this.onFragParsed, this);
7721
7730
  hls.off(Events.FRAG_CHANGED, this.onFragChanged, this);
7731
+ hls.off(Events.ERROR, this.onError, this);
7722
7732
  };
7723
7733
  _proto._initSourceBuffer = function _initSourceBuffer() {
7724
7734
  this.sourceBuffer = {};
@@ -7728,11 +7738,7 @@
7728
7738
  video: [],
7729
7739
  audiovideo: []
7730
7740
  };
7731
- this.appendErrors = {
7732
- audio: 0,
7733
- video: 0,
7734
- audiovideo: 0
7735
- };
7741
+ this.resetAppendErrors();
7736
7742
  this.lastMpegAudioChunk = null;
7737
7743
  this.blockedAudioAppend = null;
7738
7744
  this.lastVideoAppendEnd = 0;
@@ -8262,6 +8268,22 @@
8262
8268
  this.updateMediaSource(durationAndRange);
8263
8269
  }
8264
8270
  };
8271
+ _proto.onError = function onError(event, data) {
8272
+ if (data.details === ErrorDetails.BUFFER_APPEND_ERROR && data.frag) {
8273
+ var _data$errorAction;
8274
+ var nextAutoLevel = (_data$errorAction = data.errorAction) == null ? void 0 : _data$errorAction.nextAutoLevel;
8275
+ if (isFiniteNumber(nextAutoLevel) && nextAutoLevel !== data.frag.level) {
8276
+ this.resetAppendErrors();
8277
+ }
8278
+ }
8279
+ };
8280
+ _proto.resetAppendErrors = function resetAppendErrors() {
8281
+ this.appendErrors = {
8282
+ audio: 0,
8283
+ video: 0,
8284
+ audiovideo: 0
8285
+ };
8286
+ };
8265
8287
  _proto.trimBuffers = function trimBuffers() {
8266
8288
  var hls = this.hls,
8267
8289
  details = this.details,
@@ -10963,12 +10985,14 @@
10963
10985
  var _proto = FragmentTracker.prototype;
10964
10986
  _proto._registerListeners = function _registerListeners() {
10965
10987
  var hls = this.hls;
10988
+ hls.on(Events.MANIFEST_LOADING, this.onManifestLoading, this);
10966
10989
  hls.on(Events.BUFFER_APPENDED, this.onBufferAppended, this);
10967
10990
  hls.on(Events.FRAG_BUFFERED, this.onFragBuffered, this);
10968
10991
  hls.on(Events.FRAG_LOADED, this.onFragLoaded, this);
10969
10992
  };
10970
10993
  _proto._unregisterListeners = function _unregisterListeners() {
10971
10994
  var hls = this.hls;
10995
+ hls.off(Events.MANIFEST_LOADING, this.onManifestLoading, this);
10972
10996
  hls.off(Events.BUFFER_APPENDED, this.onBufferAppended, this);
10973
10997
  hls.off(Events.FRAG_BUFFERED, this.onFragBuffered, this);
10974
10998
  hls.off(Events.FRAG_LOADED, this.onFragLoaded, this);
@@ -11032,7 +11056,7 @@
11032
11056
  * The browser will unload parts of the buffer to free up memory for new buffer data
11033
11057
  * Fragments will need to be reloaded when the buffer is freed up, removing partial fragments will allow them to reload(since there might be parts that are still playable)
11034
11058
  */;
11035
- _proto.detectEvictedFragments = function detectEvictedFragments(elementaryStream, timeRange, playlistType, appendedPart) {
11059
+ _proto.detectEvictedFragments = function detectEvictedFragments(elementaryStream, timeRange, playlistType, appendedPart, removeAppending) {
11036
11060
  var _this = this;
11037
11061
  if (this.timeRanges) {
11038
11062
  this.timeRanges[elementaryStream] = timeRange;
@@ -11048,7 +11072,7 @@
11048
11072
  if (appendedPartSn >= fragmentEntity.body.sn) {
11049
11073
  return;
11050
11074
  }
11051
- if (!fragmentEntity.buffered && !fragmentEntity.loaded) {
11075
+ if (!fragmentEntity.buffered && (!fragmentEntity.loaded || removeAppending)) {
11052
11076
  if (fragmentEntity.body.type === playlistType) {
11053
11077
  _this.removeFragment(fragmentEntity.body);
11054
11078
  }
@@ -11058,6 +11082,10 @@
11058
11082
  if (!esData) {
11059
11083
  return;
11060
11084
  }
11085
+ if (esData.time.length === 0) {
11086
+ _this.removeFragment(fragmentEntity.body);
11087
+ return;
11088
+ }
11061
11089
  esData.time.some(function (time) {
11062
11090
  var isNotBuffered = !_this.isTimeBuffered(time.startPTS, time.endPTS, timeRange);
11063
11091
  if (isNotBuffered) {
@@ -11245,6 +11273,9 @@
11245
11273
  }
11246
11274
  return false;
11247
11275
  };
11276
+ _proto.onManifestLoading = function onManifestLoading() {
11277
+ this.removeAllFragments();
11278
+ };
11248
11279
  _proto.onFragLoaded = function onFragLoaded(event, data) {
11249
11280
  // don't track initsegment (for which sn is not a number)
11250
11281
  // don't track frags used for bitrateTest, they're irrelevant.
@@ -11291,6 +11322,20 @@
11291
11322
  var fragKey = getFragmentKey(fragment);
11292
11323
  return !!this.fragments[fragKey];
11293
11324
  };
11325
+ _proto.hasFragments = function hasFragments(type) {
11326
+ var fragments = this.fragments;
11327
+ var keys = Object.keys(fragments);
11328
+ if (!type) {
11329
+ return keys.length > 0;
11330
+ }
11331
+ for (var i = keys.length; i--;) {
11332
+ var fragmentEntity = fragments[keys[i]];
11333
+ if ((fragmentEntity == null ? void 0 : fragmentEntity.body.type) === type) {
11334
+ return true;
11335
+ }
11336
+ }
11337
+ return false;
11338
+ };
11294
11339
  _proto.hasParts = function hasParts(type) {
11295
11340
  var _this$activePartLists;
11296
11341
  return !!((_this$activePartLists = this.activePartLists[type]) != null && _this$activePartLists.length);
@@ -11399,8 +11444,9 @@
11399
11444
  frag.gap = false;
11400
11445
  }
11401
11446
  }
11402
- var loader = _this.loader = frag.loader = FragmentILoader ? new FragmentILoader(config) : new DefaultILoader(config);
11447
+ var loader = _this.loader = FragmentILoader ? new FragmentILoader(config) : new DefaultILoader(config);
11403
11448
  var loaderContext = createLoaderContext(frag);
11449
+ frag.loader = loader;
11404
11450
  var loadPolicy = getLoaderConfigWithoutReties(config.fragLoadPolicy.default);
11405
11451
  var loaderConfig = {
11406
11452
  loadPolicy: loadPolicy,
@@ -11494,8 +11540,9 @@
11494
11540
  reject(createGapLoadError(frag, part));
11495
11541
  return;
11496
11542
  }
11497
- var loader = _this2.loader = frag.loader = FragmentILoader ? new FragmentILoader(config) : new DefaultILoader(config);
11543
+ var loader = _this2.loader = FragmentILoader ? new FragmentILoader(config) : new DefaultILoader(config);
11498
11544
  var loaderContext = createLoaderContext(frag, part);
11545
+ frag.loader = loader;
11499
11546
  // Should we define another load policy for parts?
11500
11547
  var loadPolicy = getLoaderConfigWithoutReties(config.fragLoadPolicy.default);
11501
11548
  var loaderConfig = {
@@ -12767,6 +12814,7 @@
12767
12814
  _this.initPTS = [];
12768
12815
  _this.buffering = true;
12769
12816
  _this.loadingParts = false;
12817
+ _this.loopSn = void 0;
12770
12818
  _this.onMediaSeeking = function () {
12771
12819
  var _this2 = _this,
12772
12820
  config = _this2.config,
@@ -12865,6 +12913,9 @@
12865
12913
  ;
12866
12914
  _proto.startLoad = function startLoad(startPosition) {};
12867
12915
  _proto.stopLoad = function stopLoad() {
12916
+ if (this.state === State.STOPPED) {
12917
+ return;
12918
+ }
12868
12919
  this.fragmentLoader.abort();
12869
12920
  this.keyLoader.abort(this.playlistType);
12870
12921
  var frag = this.fragCurrent;
@@ -12938,15 +12989,20 @@
12938
12989
  this.keyLoader.detach();
12939
12990
  }
12940
12991
  this.media = this.mediaBuffer = null;
12941
- this.loadedmetadata = false;
12992
+ this.loopSn = undefined;
12993
+ this.startFragRequested = this.loadedmetadata = this.loadingParts = false;
12942
12994
  this.fragmentTracker.removeAllFragments();
12943
12995
  this.stopLoad();
12944
12996
  };
12945
- _proto.onManifestLoading = function onManifestLoading() {};
12997
+ _proto.onManifestLoading = function onManifestLoading() {
12998
+ this.initPTS = [];
12999
+ this.levels = this.levelLastLoaded = this.fragCurrent = null;
13000
+ this.lastCurrentTime = this.startPosition = 0;
13001
+ this.startFragRequested = false;
13002
+ };
12946
13003
  _proto.onError = function onError(event, data) {};
12947
13004
  _proto.onManifestLoaded = function onManifestLoaded(event, data) {
12948
13005
  this.startTimeOffset = data.startTimeOffset;
12949
- this.initPTS = [];
12950
13006
  };
12951
13007
  _proto.onHandlerDestroying = function onHandlerDestroying() {
12952
13008
  this.stopLoad();
@@ -12969,6 +13025,7 @@
12969
13025
  _TaskLoop.prototype.onHandlerDestroyed.call(this);
12970
13026
  };
12971
13027
  _proto.loadFragment = function loadFragment(frag, level, targetBufferTime) {
13028
+ this.startFragRequested = true;
12972
13029
  this._loadFragForPlayback(frag, level, targetBufferTime);
12973
13030
  };
12974
13031
  _proto._loadFragForPlayback = function _loadFragForPlayback(frag, level, targetBufferTime) {
@@ -13197,6 +13254,7 @@
13197
13254
  if (targetBufferTime === void 0) {
13198
13255
  targetBufferTime = null;
13199
13256
  }
13257
+ this.fragCurrent = frag;
13200
13258
  var details = level == null ? void 0 : level.details;
13201
13259
  if (!this.levels || !details) {
13202
13260
  throw new Error("frag load aborted, missing level" + (details ? '' : ' detail') + "s");
@@ -13334,7 +13392,7 @@
13334
13392
  partsLoaded[part.index] = partLoadedData;
13335
13393
  var loadedPart = partLoadedData.part;
13336
13394
  _this6.hls.trigger(Events.FRAG_LOADED, partLoadedData);
13337
- var nextPart = getPartWith(level, frag.sn, part.index + 1) || findPart(initialPartList, frag.sn, part.index + 1);
13395
+ var nextPart = getPartWith(level.details, frag.sn, part.index + 1) || findPart(initialPartList, frag.sn, part.index + 1);
13338
13396
  if (nextPart) {
13339
13397
  loadPart(nextPart);
13340
13398
  } else {
@@ -13423,8 +13481,9 @@
13423
13481
  return null;
13424
13482
  }
13425
13483
  var level = levels[levelIndex];
13426
- var part = partIndex > -1 ? getPartWith(level, sn, partIndex) : null;
13427
- var frag = part ? part.fragment : getFragmentWithSN(level, sn, fragCurrent);
13484
+ var levelDetails = level.details;
13485
+ var part = partIndex > -1 ? getPartWith(levelDetails, sn, partIndex) : null;
13486
+ var frag = part ? part.fragment : getFragmentWithSN(levelDetails, sn, fragCurrent);
13428
13487
  if (!frag) {
13429
13488
  return null;
13430
13489
  }
@@ -13531,7 +13590,11 @@
13531
13590
  return false;
13532
13591
  };
13533
13592
  _proto.getAppendedFrag = function getAppendedFrag(position, playlistType) {
13534
- var fragOrPart = this.fragmentTracker.getAppendedFrag(position, PlaylistLevelType.MAIN);
13593
+ var _this$fragmentTracker;
13594
+ if (playlistType === void 0) {
13595
+ playlistType = PlaylistLevelType.MAIN;
13596
+ }
13597
+ var fragOrPart = (_this$fragmentTracker = this.fragmentTracker) == null ? void 0 : _this$fragmentTracker.getAppendedFrag(position, playlistType);
13535
13598
  if (fragOrPart && 'fragment' in fragOrPart) {
13536
13599
  return fragOrPart.fragment;
13537
13600
  }
@@ -13584,22 +13647,25 @@
13584
13647
  return (trackerState === FragmentState.OK || trackerState === FragmentState.PARTIAL && !!frag.gap) && this.nextLoadPosition > targetBufferTime;
13585
13648
  };
13586
13649
  _proto.getNextFragmentLoopLoading = function getNextFragmentLoopLoading(frag, levelDetails, bufferInfo, playlistType, maxBufLen) {
13587
- var gapStart = frag.gap;
13588
- var nextFragment = this.getNextFragment(this.nextLoadPosition, levelDetails);
13589
- if (nextFragment === null) {
13590
- return nextFragment;
13591
- }
13592
- frag = nextFragment;
13593
- if (gapStart && frag && !frag.gap && bufferInfo.nextStart) {
13594
- // Media buffered after GAP tags should not make the next buffer timerange exceed forward buffer length
13595
- var nextbufferInfo = this.getFwdBufferInfoAtPos(this.mediaBuffer ? this.mediaBuffer : this.media, bufferInfo.nextStart, playlistType);
13596
- if (nextbufferInfo !== null && bufferInfo.len + nextbufferInfo.len >= maxBufLen) {
13597
- // Returning here might result in not finding an audio and video candiate to skip to
13598
- this.log("buffer full after gaps in \"" + playlistType + "\" playlist starting at sn: " + frag.sn);
13599
- return null;
13650
+ var nextFragment = null;
13651
+ if (frag.gap) {
13652
+ nextFragment = this.getNextFragment(this.nextLoadPosition, levelDetails);
13653
+ if (nextFragment && !nextFragment.gap && bufferInfo.nextStart) {
13654
+ // Media buffered after GAP tags should not make the next buffer timerange exceed forward buffer length
13655
+ var nextbufferInfo = this.getFwdBufferInfoAtPos(this.mediaBuffer ? this.mediaBuffer : this.media, bufferInfo.nextStart, playlistType);
13656
+ if (nextbufferInfo !== null && bufferInfo.len + nextbufferInfo.len >= maxBufLen) {
13657
+ // Returning here might result in not finding an audio and video candiate to skip to
13658
+ var sn = nextFragment.sn;
13659
+ if (this.loopSn !== sn) {
13660
+ this.log("buffer full after gaps in \"" + playlistType + "\" playlist starting at sn: " + sn);
13661
+ this.loopSn = sn;
13662
+ }
13663
+ return null;
13664
+ }
13600
13665
  }
13601
13666
  }
13602
- return frag;
13667
+ this.loopSn = undefined;
13668
+ return nextFragment;
13603
13669
  };
13604
13670
  _proto.mapToInitFragWhenRequired = function mapToInitFragWhenRequired(frag) {
13605
13671
  // If an initSegment is present, it must be buffered first
@@ -13794,7 +13860,7 @@
13794
13860
  if (startTimeOffset !== null && isFiniteNumber(startTimeOffset)) {
13795
13861
  startPosition = sliding + startTimeOffset;
13796
13862
  if (startTimeOffset < 0) {
13797
- startPosition += details.totalduration;
13863
+ startPosition += details.edge;
13798
13864
  }
13799
13865
  startPosition = Math.min(Math.max(sliding, startPosition), sliding + details.totalduration);
13800
13866
  this.log("Start time offset " + startTimeOffset + " found in " + (offsetInMultivariantPlaylist ? 'multivariant' : 'media') + " playlist, adjust startPosition to " + startPosition);
@@ -17395,10 +17461,11 @@
17395
17461
  if (this.ISGenerated) {
17396
17462
  var _videoTrack$pixelRati, _config$pixelRatio, _videoTrack$pixelRati2, _config$pixelRatio2;
17397
17463
  var config = this.videoTrackConfig;
17398
- if (config && (videoTrack.width !== config.width || videoTrack.height !== config.height || ((_videoTrack$pixelRati = videoTrack.pixelRatio) == null ? void 0 : _videoTrack$pixelRati[0]) !== ((_config$pixelRatio = config.pixelRatio) == null ? void 0 : _config$pixelRatio[0]) || ((_videoTrack$pixelRati2 = videoTrack.pixelRatio) == null ? void 0 : _videoTrack$pixelRati2[1]) !== ((_config$pixelRatio2 = config.pixelRatio) == null ? void 0 : _config$pixelRatio2[1]))) {
17464
+ if (config && (videoTrack.width !== config.width || videoTrack.height !== config.height || ((_videoTrack$pixelRati = videoTrack.pixelRatio) == null ? void 0 : _videoTrack$pixelRati[0]) !== ((_config$pixelRatio = config.pixelRatio) == null ? void 0 : _config$pixelRatio[0]) || ((_videoTrack$pixelRati2 = videoTrack.pixelRatio) == null ? void 0 : _videoTrack$pixelRati2[1]) !== ((_config$pixelRatio2 = config.pixelRatio) == null ? void 0 : _config$pixelRatio2[1])) || !config && enoughVideoSamples || this.nextAudioPts === null && enoughAudioSamples) {
17399
17465
  this.resetInitSegment();
17400
17466
  }
17401
- } else {
17467
+ }
17468
+ if (!this.ISGenerated) {
17402
17469
  initSegment = this.generateIS(audioTrack, videoTrack, timeOffset, accurateTimeOffset);
17403
17470
  }
17404
17471
  var isVideoContiguous = this.isVideoContiguous;
@@ -18316,7 +18383,7 @@
18316
18383
  if (isInvalidInitPts(initPTS, decodeTime, timeOffset, duration) || initSegment.timescale !== initPTS.timescale && accurateTimeOffset) {
18317
18384
  initSegment.initPTS = decodeTime - timeOffset;
18318
18385
  if (initPTS && initPTS.timescale === 1) {
18319
- logger.warn("Adjusting initPTS by " + (initSegment.initPTS - initPTS.baseTime));
18386
+ logger.warn("Adjusting initPTS @" + timeOffset + " from " + initPTS.baseTime / initPTS.timescale + " to " + initSegment.initPTS);
18320
18387
  }
18321
18388
  this.initPTS = initPTS = {
18322
18389
  baseTime: initSegment.initPTS,
@@ -20171,7 +20238,6 @@
20171
20238
  _proto.loadFragment = function loadFragment(frag, level, targetBufferTime) {
20172
20239
  // Check if fragment is not loaded
20173
20240
  var fragState = this.fragmentTracker.getState(frag);
20174
- this.fragCurrent = frag;
20175
20241
  if (fragState === FragmentState.NOT_LOADED || fragState === FragmentState.PARTIAL) {
20176
20242
  if (frag.sn === 'initSegment') {
20177
20243
  this._loadInitSegment(frag, level);
@@ -20179,7 +20245,6 @@
20179
20245
  this.log("Fragment " + frag.sn + " of level " + frag.level + " is being downloaded to test bitrate and will not be buffered");
20180
20246
  this._loadBitrateTestFrag(frag, level);
20181
20247
  } else {
20182
- this.startFragRequested = true;
20183
20248
  _BaseStreamController.prototype.loadFragment.call(this, frag, level, targetBufferTime);
20184
20249
  }
20185
20250
  } else {
@@ -20309,14 +20374,14 @@
20309
20374
  _BaseStreamController.prototype.onMediaDetaching.call(this);
20310
20375
  };
20311
20376
  _proto.onManifestLoading = function onManifestLoading() {
20377
+ _BaseStreamController.prototype.onManifestLoading.call(this);
20312
20378
  // reset buffer on manifest loading
20313
20379
  this.log('Trigger BUFFER_RESET');
20314
20380
  this.hls.trigger(Events.BUFFER_RESET, undefined);
20315
- this.fragmentTracker.removeAllFragments();
20316
20381
  this.couldBacktrack = false;
20317
- this.startPosition = this.lastCurrentTime = this.fragLastKbps = 0;
20318
- this.levels = this.fragPlaying = this.backtrackFragment = this.levelLastLoaded = null;
20319
- this.altAudio = this.audioOnly = this.startFragRequested = false;
20382
+ this.fragLastKbps = 0;
20383
+ this.fragPlaying = this.backtrackFragment = null;
20384
+ this.altAudio = this.audioOnly = false;
20320
20385
  };
20321
20386
  _proto.onManifestParsed = function onManifestParsed(event, data) {
20322
20387
  // detect if we have different kind of audio codecs used amongst playlists
@@ -20601,7 +20666,7 @@
20601
20666
  // in that case, reset startFragRequested flag
20602
20667
  if (!this.loadedmetadata) {
20603
20668
  this.startFragRequested = false;
20604
- this.nextLoadPosition = this.startPosition;
20669
+ this.nextLoadPosition = this.lastCurrentTime;
20605
20670
  }
20606
20671
  this.tickImmediate();
20607
20672
  };
@@ -20685,7 +20750,7 @@
20685
20750
  };
20686
20751
  _proto._handleTransmuxComplete = function _handleTransmuxComplete(transmuxResult) {
20687
20752
  var _id3$samples;
20688
- var id = 'main';
20753
+ var id = this.playlistType;
20689
20754
  var hls = this.hls;
20690
20755
  var remuxResult = transmuxResult.remuxResult,
20691
20756
  chunkMeta = transmuxResult.chunkMeta;
@@ -20875,31 +20940,38 @@
20875
20940
  audio.levelCodec = audioCodec;
20876
20941
  audio.id = 'main';
20877
20942
  this.log("Init audio buffer, container:" + audio.container + ", codecs[selected/level/parsed]=[" + (audioCodec || '') + "/" + (currentLevel.audioCodec || '') + "/" + audio.codec + "]");
20943
+ delete tracks.audiovideo;
20878
20944
  }
20879
20945
  if (video) {
20880
20946
  video.levelCodec = currentLevel.videoCodec;
20881
20947
  video.id = 'main';
20882
20948
  this.log("Init video buffer, container:" + video.container + ", codecs[level/parsed]=[" + (currentLevel.videoCodec || '') + "/" + video.codec + "]");
20949
+ delete tracks.audiovideo;
20883
20950
  }
20884
20951
  if (audiovideo) {
20885
20952
  this.log("Init audiovideo buffer, container:" + audiovideo.container + ", codecs[level/parsed]=[" + currentLevel.codecs + "/" + audiovideo.codec + "]");
20953
+ delete tracks.video;
20954
+ delete tracks.audio;
20955
+ }
20956
+ var trackTypes = Object.keys(tracks);
20957
+ if (trackTypes.length) {
20958
+ this.hls.trigger(Events.BUFFER_CODECS, tracks);
20959
+ // loop through tracks that are going to be provided to bufferController
20960
+ trackTypes.forEach(function (trackName) {
20961
+ var track = tracks[trackName];
20962
+ var initSegment = track.initSegment;
20963
+ if (initSegment != null && initSegment.byteLength) {
20964
+ _this3.hls.trigger(Events.BUFFER_APPENDING, {
20965
+ type: trackName,
20966
+ data: initSegment,
20967
+ frag: frag,
20968
+ part: null,
20969
+ chunkMeta: chunkMeta,
20970
+ parent: frag.type
20971
+ });
20972
+ }
20973
+ });
20886
20974
  }
20887
- this.hls.trigger(Events.BUFFER_CODECS, tracks);
20888
- // loop through tracks that are going to be provided to bufferController
20889
- Object.keys(tracks).forEach(function (trackName) {
20890
- var track = tracks[trackName];
20891
- var initSegment = track.initSegment;
20892
- if (initSegment != null && initSegment.byteLength) {
20893
- _this3.hls.trigger(Events.BUFFER_APPENDING, {
20894
- type: trackName,
20895
- data: initSegment,
20896
- frag: frag,
20897
- part: null,
20898
- chunkMeta: chunkMeta,
20899
- parent: frag.type
20900
- });
20901
- }
20902
- });
20903
20975
  // trigger handler right now
20904
20976
  this.tickImmediate();
20905
20977
  };
@@ -20980,22 +21052,30 @@
20980
21052
  }, {
20981
21053
  key: "currentFrag",
20982
21054
  get: function get() {
20983
- var media = this.media;
20984
- if (media) {
20985
- return this.fragPlaying || this.getAppendedFrag(media.currentTime);
21055
+ var _this$media2;
21056
+ if (this.fragPlaying) {
21057
+ return this.fragPlaying;
21058
+ }
21059
+ var currentTime = ((_this$media2 = this.media) == null ? void 0 : _this$media2.currentTime) || this.lastCurrentTime;
21060
+ if (isFiniteNumber(currentTime)) {
21061
+ return this.getAppendedFrag(currentTime);
20986
21062
  }
20987
21063
  return null;
20988
21064
  }
20989
21065
  }, {
20990
21066
  key: "currentProgramDateTime",
20991
21067
  get: function get() {
20992
- var media = this.media;
20993
- if (media) {
20994
- var currentTime = media.currentTime;
20995
- var frag = this.currentFrag;
20996
- if (frag && isFiniteNumber(currentTime) && isFiniteNumber(frag.programDateTime)) {
20997
- var epocMs = frag.programDateTime + (currentTime - frag.start) * 1000;
20998
- return new Date(epocMs);
21068
+ var _this$media3;
21069
+ var currentTime = ((_this$media3 = this.media) == null ? void 0 : _this$media3.currentTime) || this.lastCurrentTime;
21070
+ if (isFiniteNumber(currentTime)) {
21071
+ var details = this.getLevelDetails();
21072
+ var frag = this.currentFrag || (details ? findFragmentByPTS(null, details.fragments, currentTime) : null);
21073
+ if (frag) {
21074
+ var programDateTime = frag.programDateTime;
21075
+ if (programDateTime !== null) {
21076
+ var epocMs = programDateTime + (currentTime - frag.start) * 1000;
21077
+ return new Date(epocMs);
21078
+ }
20999
21079
  }
21000
21080
  }
21001
21081
  return null;
@@ -21113,7 +21193,7 @@
21113
21193
  if (AudioStreamControllerClass) {
21114
21194
  networkControllers.push(new AudioStreamControllerClass(this, fragmentTracker, keyLoader));
21115
21195
  }
21116
- // subtitleTrackController must be defined before subtitleStreamController because the order of event handling is important
21196
+ // Instantiate subtitleTrackController before SubtitleStreamController to receive level events first
21117
21197
  this.subtitleTrackController = this.createController(config.subtitleTrackController, networkControllers);
21118
21198
  var SubtitleStreamControllerClass = config.subtitleStreamController;
21119
21199
  if (SubtitleStreamControllerClass) {
@@ -21909,7 +21989,7 @@
21909
21989
  * Get the video-dev/hls.js package version.
21910
21990
  */
21911
21991
  function get() {
21912
- return "1.5.12-0.canary.10366";
21992
+ return "1.5.12-0.canary.10367";
21913
21993
  }
21914
21994
  }, {
21915
21995
  key: "Events",