@amazon/vinyl 3.2.1 → 3.2.3-next.20261001143710

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 (109) hide show
  1. package/README.md +2 -2
  2. package/dist/index.cjs +98 -43
  3. package/dist/index.cjs.map +3 -3
  4. package/dist/index.js +126 -68
  5. package/dist/index.js.map +3 -3
  6. package/dist/test/benchmark.es5.js +7 -6
  7. package/dist/test/benchmark.js +35 -30
  8. package/dist/test/benchmark.js.map +3 -3
  9. package/dist/test/integ.es5.js +329 -312
  10. package/dist/test/integ.js +519 -187
  11. package/dist/test/integ.js.map +4 -4
  12. package/dist/types/current/ad/AdControllerImpl.d.ts.map +1 -1
  13. package/dist/types/current/ad/AdControllerImpl.js +15 -1
  14. package/dist/types/current/ad/discoverHlsInterstitials.js +13 -1
  15. package/dist/types/current/drm/DrmControllerImpl.d.ts +6 -0
  16. package/dist/types/current/drm/DrmControllerImpl.d.ts.map +1 -1
  17. package/dist/types/current/drm/DrmControllerImpl.js +11 -1
  18. package/dist/types/current/drm/commonEme/MsCommonEme.d.ts.map +1 -1
  19. package/dist/types/current/drm/commonEme/MsCommonEme.js +2 -2
  20. package/dist/types/current/drm/commonEme/StandardCommonEme.d.ts.map +1 -1
  21. package/dist/types/current/drm/commonEme/StandardCommonEme.js +3 -2
  22. package/dist/types/current/drm/commonEme/WebKitCommonEme.d.ts.map +1 -1
  23. package/dist/types/current/drm/commonEme/WebKitCommonEme.js +2 -2
  24. package/dist/types/current/drm/dom/MSMediaKeys.d.ts +1 -1
  25. package/dist/types/current/drm/dom/MSMediaKeys.d.ts.map +1 -1
  26. package/dist/types/current/drm/dom/WebKitMediaKeys.d.ts +1 -1
  27. package/dist/types/current/drm/dom/WebKitMediaKeys.d.ts.map +1 -1
  28. package/dist/types/current/drm/util/extractContentId.js +2 -2
  29. package/dist/types/current/playback/PlaybackControllerImpl.d.ts +9 -3
  30. package/dist/types/current/playback/PlaybackControllerImpl.d.ts.map +1 -1
  31. package/dist/types/current/playback/PlaybackControllerImpl.js +38 -33
  32. package/dist/types/current/streaming/MediaQualityMetadata.d.ts +3 -1
  33. package/dist/types/current/streaming/MediaQualityMetadata.d.ts.map +1 -1
  34. package/dist/types/current/streaming/SegmentControllerImpl.d.ts +1 -1
  35. package/dist/types/current/streaming/buffering/BufferingController.d.ts +1 -1
  36. package/dist/types/current/streaming/buffering/BufferingController.d.ts.map +1 -1
  37. package/dist/types/current/streaming/buffering/BufferingController.js +14 -5
  38. package/dist/types/current/streaming/buffering/MediaSourceController.d.ts.map +1 -1
  39. package/dist/types/current/streaming/buffering/MediaSourceController.js +4 -0
  40. package/dist/types/current/text/discoverDashTextTracks.d.ts +2 -2
  41. package/dist/types/current/text/discoverDashTextTracks.js +4 -3
  42. package/dist/types/current/text/parseWebVtt.d.ts.map +1 -1
  43. package/dist/types/current/text/parseWebVtt.js +3 -2
  44. package/dist/types/current/track/TrackController.d.ts.map +1 -1
  45. package/dist/types/current/track/TrackController.js +7 -0
  46. package/dist/types/current/track/hls/HlsManifestData.d.ts +14 -1
  47. package/dist/types/current/track/hls/HlsManifestData.d.ts.map +1 -1
  48. package/dist/types/current/track/hls/buildHlsMediaTimeline.d.ts.map +1 -1
  49. package/dist/types/current/track/hls/buildHlsMediaTimeline.js +10 -2
  50. package/dist/types/current/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
  51. package/dist/types/current/track/hls/createUrlHlsManifestProvider.d.ts.map +1 -1
  52. package/dist/types/current/track/hls/createUrlHlsManifestProvider.js +8 -3
  53. package/dist/types/current/track/mse/MseTrack.d.ts +0 -1
  54. package/dist/types/current/track/mse/MseTrack.d.ts.map +1 -1
  55. package/dist/types/current/track/mse/MseTrack.js +5 -6
  56. package/dist/types/current/tsconfig.tsbuildinfo +1 -1
  57. package/dist/types/ts3.7/drm/DrmControllerImpl.d.ts +6 -0
  58. package/dist/types/ts3.7/playback/PlaybackControllerImpl.d.ts +9 -3
  59. package/dist/types/ts3.7/streaming/MediaQualityMetadata.d.ts +3 -1
  60. package/dist/types/ts3.7/streaming/SegmentControllerImpl.d.ts +1 -1
  61. package/dist/types/ts3.7/streaming/buffering/BufferingController.d.ts +1 -1
  62. package/dist/types/ts3.7/text/discoverDashTextTracks.d.ts +2 -2
  63. package/dist/types/ts3.7/track/hls/HlsManifestData.d.ts +14 -1
  64. package/dist/types/ts3.7/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
  65. package/dist/types/ts3.7/track/mse/MseTrack.d.ts +0 -1
  66. package/dist/types/ts4.1/drm/DrmControllerImpl.d.ts +6 -0
  67. package/dist/types/ts4.1/playback/PlaybackControllerImpl.d.ts +9 -3
  68. package/dist/types/ts4.1/streaming/MediaQualityMetadata.d.ts +3 -1
  69. package/dist/types/ts4.1/streaming/SegmentControllerImpl.d.ts +1 -1
  70. package/dist/types/ts4.1/streaming/buffering/BufferingController.d.ts +1 -1
  71. package/dist/types/ts4.1/text/discoverDashTextTracks.d.ts +2 -2
  72. package/dist/types/ts4.1/track/hls/HlsManifestData.d.ts +14 -1
  73. package/dist/types/ts4.1/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
  74. package/dist/types/ts4.1/track/mse/MseTrack.d.ts +0 -1
  75. package/dist/types/ts4.7/drm/DrmControllerImpl.d.ts +6 -0
  76. package/dist/types/ts4.7/playback/PlaybackControllerImpl.d.ts +9 -3
  77. package/dist/types/ts4.7/streaming/MediaQualityMetadata.d.ts +3 -1
  78. package/dist/types/ts4.7/streaming/SegmentControllerImpl.d.ts +1 -1
  79. package/dist/types/ts4.7/streaming/buffering/BufferingController.d.ts +1 -1
  80. package/dist/types/ts4.7/text/discoverDashTextTracks.d.ts +2 -2
  81. package/dist/types/ts4.7/track/hls/HlsManifestData.d.ts +14 -1
  82. package/dist/types/ts4.7/track/hls/createUrlHlsManifestProvider.d.ts +3 -2
  83. package/dist/types/ts4.7/track/mse/MseTrack.d.ts +0 -1
  84. package/dist/unit/types/current/ad/AdControllerImpl.test.js +66 -0
  85. package/dist/unit/types/current/ad/discoverHlsInterstitials.test.js +29 -2
  86. package/dist/unit/types/current/drm/DrmControllerImpl.test.js +19 -1
  87. package/dist/unit/types/current/drm/commonEme/StandardCommonEme.test.js +12 -4
  88. package/dist/unit/types/current/drm/util/extractContentId.test.js +7 -0
  89. package/dist/unit/types/current/index.d.ts +1 -0
  90. package/dist/unit/types/current/index.d.ts.map +1 -1
  91. package/dist/unit/types/current/index.js +1 -0
  92. package/dist/unit/types/current/playback/PlaybackControllerImpl.test.js +15 -0
  93. package/dist/unit/types/current/streaming/MediaQualityMetadata.test.js +8 -0
  94. package/dist/unit/types/current/streaming/MseTrack.test.js +15 -0
  95. package/dist/unit/types/current/streaming/buffering/BufferingController.test.js +26 -0
  96. package/dist/unit/types/current/streaming/buffering/MediaSourceController.test.js +29 -0
  97. package/dist/unit/types/current/text/TextTrack.test.d.ts +2 -0
  98. package/dist/unit/types/current/text/TextTrack.test.d.ts.map +1 -0
  99. package/dist/unit/types/current/text/TextTrack.test.js +12 -0
  100. package/dist/unit/types/current/text/discoverDashTextTracks.test.js +17 -0
  101. package/dist/unit/types/current/text/parseWebVtt.test.js +26 -0
  102. package/dist/unit/types/current/track/TrackController.test.js +15 -60
  103. package/dist/unit/types/current/track/hls/buildHlsMediaTimeline.test.js +22 -0
  104. package/dist/unit/types/current/track/hls/createUrlHlsManifestProvider.test.js +23 -0
  105. package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
  106. package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
  107. package/docs/CUSTOMIZATION_GUIDE.md +310 -0
  108. package/package.json +10 -10
  109. package/docs/DASH_MANIFEST_TRANSFORM_GUIDE.md +0 -236
package/dist/index.js CHANGED
@@ -383,7 +383,11 @@ var AdControllerImpl = class extends EventHostImpl {
383
383
  logVerbose(this, "nextAd");
384
384
  try {
385
385
  const ad = await adBreakState2.nextAd();
386
- if (this.disposed || adBreakState2.completedReason) return;
386
+ if (this.disposed) return;
387
+ if (adBreakState2.completedReason) {
388
+ if (!this.adBreakState) await nextBreak();
389
+ return;
390
+ }
387
391
  if (ad) {
388
392
  this.startAd(ad);
389
393
  } else {
@@ -517,12 +521,18 @@ var AdControllerImpl = class extends EventHostImpl {
517
521
  const currProgress = pC.currentTimePercent;
518
522
  const progressStart = adState.timeStart / pC.duration;
519
523
  if (!adState.quartile.first && currProgress > 0.25 && progressStart < AD_START_TOLERANCE) {
524
+ adState.quartile.first = true;
525
+ logDebug(this, "adFirstQuartile", adState.ad);
520
526
  this.dispatch("adFirstQuartile", createAdProgressEvent(adState));
521
527
  }
522
528
  if (!adState.quartile.midpoint && currProgress > 0.5 && progressStart < 0.25 + AD_START_TOLERANCE) {
529
+ adState.quartile.midpoint = true;
530
+ logDebug(this, "adMidpoint", adState.ad);
523
531
  this.dispatch("adMidpoint", createAdProgressEvent(adState));
524
532
  }
525
533
  if (!adState.quartile.third && currProgress > 0.75 && progressStart < 0.5 + AD_START_TOLERANCE) {
534
+ adState.quartile.third = true;
535
+ logDebug(this, "adThirdQuartile", adState.ad);
526
536
  this.dispatch("adThirdQuartile", createAdProgressEvent(adState));
527
537
  }
528
538
  }
@@ -939,6 +949,7 @@ async function resolveHlsAssetList({
939
949
  const url = resolveUrl(assetListUrl, baseUrl);
940
950
  const response = await requestWithRetry2(url);
941
951
  const json = await readResponseBody(response, "json");
952
+ const assetListBaseUrl = response.url || url;
942
953
  const assets = (_a = json.ASSETS) != null ? _a : [];
943
954
  const ads = assets.map((asset, i) => {
944
955
  var _a2;
@@ -946,7 +957,14 @@ async function resolveHlsAssetList({
946
957
  id: `${rangeId}-${i}`,
947
958
  startTime,
948
959
  duration: (_a2 = asset.DURATION) != null ? _a2 : null,
949
- uri: resolveUrl(asset.URI, baseUrl)
960
+ // Each Asset-Description "URI" MUST be an absolute URI, so the base
961
+ // only applies to non-conforming lists. As a leniency (not a spec
962
+ // rule), resolve against the asset list the URI was read from, as
963
+ // for any relative reference in a retrieved document (RFC 3986
964
+ // §5.1.3): asset lists are commonly served by an ad server rather
965
+ // than alongside the playlist.
966
+ // @see https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-22#appendix-D.2
967
+ uri: resolveUrl(asset.URI, assetListBaseUrl)
950
968
  };
951
969
  });
952
970
  return { ads, skipControl: parseSkipControl(json["SKIP-CONTROL"]) };
@@ -1152,6 +1170,7 @@ var MediaKeySessionErrorType = /* @__PURE__ */ ((MediaKeySessionErrorType2) => {
1152
1170
 
1153
1171
  // src/drm/commonEme/MsCommonEme.ts
1154
1172
  import {
1173
+ bufferToArrayBuffer,
1155
1174
  bufferToByteArray,
1156
1175
  DisposedError,
1157
1176
  ErrorOrigin as ErrorOrigin5,
@@ -1271,7 +1290,7 @@ var MsCommonMediaKeySession = class extends EventHostImpl2 {
1271
1290
  __publicField(this, "_disposed", false);
1272
1291
  __publicField(this, "messageHandler", (event) => {
1273
1292
  this.dispatch("message", {
1274
- message: event.message.buffer
1293
+ message: bufferToArrayBuffer(event.message)
1275
1294
  });
1276
1295
  });
1277
1296
  __publicField(this, "errorHandler", () => {
@@ -1422,11 +1441,7 @@ var StandardCommonMediaKeySession = class extends EventHostImpl3 {
1422
1441
  return "StandardCommonMediaKeySession";
1423
1442
  }
1424
1443
  generateRequest() {
1425
- const initData = this.initData;
1426
- return this.session.generateRequest(
1427
- this.initDataType,
1428
- initData instanceof ArrayBuffer ? initData : initData.buffer
1429
- ).catch(createDrmErrorHandler());
1444
+ return this.session.generateRequest(this.initDataType, this.initData).catch(createDrmErrorHandler());
1430
1445
  }
1431
1446
  update(key) {
1432
1447
  if (this.disposed) throw new DisposedError2();
@@ -1445,6 +1460,7 @@ var StandardCommonMediaKeySession = class extends EventHostImpl3 {
1445
1460
 
1446
1461
  // src/drm/commonEme/WebKitCommonEme.ts
1447
1462
  import {
1463
+ bufferToArrayBuffer as bufferToArrayBuffer2,
1448
1464
  bufferToByteArray as bufferToByteArray2,
1449
1465
  DisposedError as DisposedError3,
1450
1466
  ErrorOrigin as ErrorOrigin7,
@@ -1540,7 +1556,7 @@ var WebKitCommonMediaKeySession = class extends EventHostImpl4 {
1540
1556
  __publicField(this, "_disposed", false);
1541
1557
  __publicField(this, "messageHandler", (event) => {
1542
1558
  this.dispatch("message", {
1543
- message: event.message.buffer
1559
+ message: bufferToArrayBuffer2(event.message)
1544
1560
  });
1545
1561
  });
1546
1562
  __publicField(this, "errorHandler", () => {
@@ -1636,6 +1652,7 @@ import {
1636
1652
  logDebug as logDebug3,
1637
1653
  logError as logError2,
1638
1654
  logVerbose as logVerbose2,
1655
+ logWarn,
1639
1656
  memoize as memoize4,
1640
1657
  noop as noop3,
1641
1658
  normalizeHeadersInit,
@@ -1841,9 +1858,9 @@ var defaultLicenseProvider = async (keySystem, serverOptions, challenge, abort)
1841
1858
  // src/drm/util/extractContentId.ts
1842
1859
  import { ValidationError as ValidationError2 } from "@amazon/vinyl-util";
1843
1860
  import { ErrorOrigin as ErrorOrigin8 } from "@amazon/vinyl-util";
1844
- import { bufferToUtf16 as bufferToUtf162 } from "@amazon/vinyl-util";
1861
+ import { bufferToArrayBuffer as bufferToArrayBuffer3, bufferToUtf16 as bufferToUtf162 } from "@amazon/vinyl-util";
1845
1862
  function extractContentId(initData) {
1846
- const bufferStr = bufferToUtf162(initData.buffer);
1863
+ const bufferStr = bufferToUtf162(bufferToArrayBuffer3(initData));
1847
1864
  const matches = bufferStr.match(/skd:\/\/(.+)$/);
1848
1865
  if (!matches) {
1849
1866
  throw new ValidationError2("No contentId match", ErrorOrigin8.MEDIA);
@@ -1885,6 +1902,7 @@ function createFairPlaySessionInitData(initData, contentId, certificateData) {
1885
1902
  // src/drm/DrmControllerImpl.ts
1886
1903
  var LICENSE_TIMEOUT = 90;
1887
1904
  var LICENSE_TIMEOUT_MESSAGE = "License provider timed out after {time}s";
1905
+ var EXCESSIVE_SESSION_COUNT = 20;
1888
1906
  var DrmControllerImpl = class extends EventHostImpl5 {
1889
1907
  constructor(deps, options) {
1890
1908
  super();
@@ -2101,6 +2119,13 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2101
2119
  trackUri
2102
2120
  });
2103
2121
  this.sessions.push(newSession);
2122
+ logVerbose2(this, `total sessions: ${this.sessions.length}`);
2123
+ if (this.sessions.length === EXCESSIVE_SESSION_COUNT + 1) {
2124
+ logWarn(
2125
+ this,
2126
+ `${this.sessions.length} open key sessions exceeds ${EXCESSIVE_SESSION_COUNT}; sessions may be leaking (not closing on track deactivation)`
2127
+ );
2128
+ }
2104
2129
  this.dispatch("sessionCreate", {
2105
2130
  initDataType: newSession.initDataType,
2106
2131
  mimeType: newSession.mimeType
@@ -2530,7 +2555,7 @@ import {
2530
2555
  globalRef as globalRef3,
2531
2556
  globalTarget,
2532
2557
  IllegalStateError,
2533
- logWarn,
2558
+ logWarn as logWarn2,
2534
2559
  remove as remove2,
2535
2560
  substitute
2536
2561
  } from "@amazon/vinyl-util";
@@ -2552,7 +2577,7 @@ var PlayerRegistryImpl = class {
2552
2577
  const n = this._players.length;
2553
2578
  if (n > this.maxPlayersWarning && !this.gaveMaxPlayersWarning) {
2554
2579
  this.gaveMaxPlayersWarning = true;
2555
- logWarn(
2580
+ logWarn2(
2556
2581
  globalTarget,
2557
2582
  substitute(locale.maxPlayersWarning, { count: n })
2558
2583
  );
@@ -2628,7 +2653,7 @@ function configureVinylGlobal(options) {
2628
2653
  import { parseVersion } from "@amazon/vinyl-util";
2629
2654
  var vinylVersion = /* @__PURE__ */ parseVersion(
2630
2655
  /* istanbul ignore next */
2631
- "3.2.1"
2656
+ "3.2.2"
2632
2657
  );
2633
2658
 
2634
2659
  // src/global/globalRef.ts
@@ -3176,6 +3201,7 @@ var LIVE_DURATION = 4294967296;
3176
3201
  import {
3177
3202
  Abort,
3178
3203
  AbortError as AbortError2,
3204
+ createAbortSlot,
3179
3205
  Browser,
3180
3206
  clamp,
3181
3207
  closeTo as closeTo2,
@@ -3188,7 +3214,7 @@ import {
3188
3214
  hasBrowser,
3189
3215
  logDebug as logDebug6,
3190
3216
  logInfo,
3191
- logWarn as logWarn2,
3217
+ logWarn as logWarn3,
3192
3218
  nextEventAsPromise as nextEventAsPromise2,
3193
3219
  noop as noop4,
3194
3220
  onAny,
@@ -3222,15 +3248,13 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3222
3248
  __publicField(this, "_playing", false);
3223
3249
  __publicField(this, "_seeking", false);
3224
3250
  __publicField(this, "_waiting", false);
3225
- // Monotonic counter identifying the most recent seekTo call.
3226
- __publicField(this, "_seekId", 0);
3251
+ __publicField(this, "seekAbortSlot", /* @__PURE__ */ createAbortSlot());
3227
3252
  // Stops the stall detector started after the last seek, if any.
3228
3253
  __publicField(this, "stopStallDetection", null);
3229
3254
  // default user volume (0.0 to 1.0 scale)
3230
3255
  __publicField(this, "userVolume", 1);
3231
3256
  __publicField(this, "_pendingPlay", null);
3232
3257
  __publicField(this, "playAbort", null);
3233
- __publicField(this, "disposeAbort", /* @__PURE__ */ new Abort());
3234
3258
  __publicField(this, "options");
3235
3259
  this.options = __spreadValues(__spreadProps(__spreadValues({}, defaultPlaybackControllerImplOptions), {
3236
3260
  minSeekableBuffer: getMinSeekableBufferDefault()
@@ -3241,8 +3265,7 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3241
3265
  const { add } = this.disposer;
3242
3266
  add(() => {
3243
3267
  var _a;
3244
- this.disposeAbort.abort();
3245
- this.disposeAbort.dispose();
3268
+ this.seekAbortSlot.abort();
3246
3269
  (_a = this.stopStallDetection) == null ? void 0 : _a.call(this);
3247
3270
  });
3248
3271
  this.domEvents = add(
@@ -3655,14 +3678,10 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3655
3678
  async seekTo(time, tolerance = 0.5) {
3656
3679
  var _a;
3657
3680
  logDebug6(this, `seekTo: ${time}`);
3658
- const seekId = ++this._seekId;
3659
3681
  (_a = this.stopStallDetection) == null ? void 0 : _a.call(this);
3660
3682
  this.stopStallDetection = null;
3661
- const superseded = () => {
3662
- if (this._seekId === seekId) return false;
3663
- logDebug6(this, `seekTo: ${time} superseded by a newer seek`);
3664
- return true;
3665
- };
3683
+ this.seekAbortSlot.abort();
3684
+ const seekAbort = this.seekAbortSlot.value;
3666
3685
  const nextEvent = (type, options) => {
3667
3686
  var _a2;
3668
3687
  return nextEventAsPromise2(this, type, {
@@ -3670,12 +3689,25 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3670
3689
  timeoutMessage: `seek timed out on ${type} event after {time}s`,
3671
3690
  timeoutOrigin: ErrorOrigin12.INTERNAL,
3672
3691
  timeoutLevel: ErrorLevel7.WARN,
3673
- abort: this.disposeAbort
3692
+ abort: seekAbort
3674
3693
  });
3675
3694
  };
3695
+ try {
3696
+ await this.doSeek(time, tolerance, seekAbort, nextEvent);
3697
+ } catch (error) {
3698
+ if (seekAbort.aborted() && !this.disposed) return;
3699
+ throw error;
3700
+ }
3701
+ }
3702
+ /**
3703
+ * The body of a single {@link seekTo} attempt. Extracted so {@link seekTo}
3704
+ * can wrap it with per-seek abort/supersession handling. `seekAbort` is
3705
+ * aborted when a newer seek supersedes this one (or on dispose).
3706
+ * @private
3707
+ */
3708
+ async doSeek(time, tolerance, seekAbort, nextEvent) {
3676
3709
  if (!this.hasMetadata) {
3677
3710
  await nextEvent("loadedMetadata");
3678
- if (superseded()) return;
3679
3711
  }
3680
3712
  const seekable = this.seekable;
3681
3713
  const range = seekable.getRangeAt(
@@ -3683,7 +3715,7 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3683
3715
  tolerance
3684
3716
  );
3685
3717
  if (range == null) {
3686
- logWarn2(
3718
+ logWarn3(
3687
3719
  this,
3688
3720
  `seekTo: seek outside of seekable ranges, seek ignored`,
3689
3721
  seekable.ranges
@@ -3706,7 +3738,7 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3706
3738
  );
3707
3739
  } else {
3708
3740
  const nullIfStuck = (error) => {
3709
- if (this.disposeAbort.aborted()) throw error;
3741
+ if (this.disposed) throw error;
3710
3742
  return null;
3711
3743
  };
3712
3744
  const seekOnce = async (reSeeking) => {
@@ -3720,7 +3752,7 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3720
3752
  }).catch(nullIfStuck);
3721
3753
  };
3722
3754
  let seekedEvent = await seekOnce(false);
3723
- for (let attempt = 0; !superseded() && attempt < SEEK_RETRY_LIMIT && (seekedEvent === null || seekedEvent.reason === "seeked" && !closeTo2(clampedTime, this.currentTime, tolerance)); attempt++) {
3755
+ for (let attempt = 0; !seekAbort.aborted() && attempt < SEEK_RETRY_LIMIT && (seekedEvent === null || seekedEvent.reason === "seeked" && !closeTo2(clampedTime, this.currentTime, tolerance)); attempt++) {
3724
3756
  if (seekedEvent === null) void this.media.play().catch(noop4);
3725
3757
  logDebug6(this, `seekTo: re-seeking to ${clampedTime}`);
3726
3758
  seekedEvent = await seekOnce(true);
@@ -3728,7 +3760,7 @@ var PlaybackControllerImpl = class extends EventHostImpl7 {
3728
3760
  if ((seekedEvent == null ? void 0 : seekedEvent.reason) === "emptied") {
3729
3761
  throw new AbortError2();
3730
3762
  }
3731
- if (!this.paused) this.startStallDetection();
3763
+ if (!this.paused && !seekAbort.aborted()) this.startStallDetection();
3732
3764
  }
3733
3765
  }
3734
3766
  /**
@@ -3980,7 +4012,7 @@ var audioOptionsValidator = /* @__PURE__ */ object7({
3980
4012
 
3981
4013
  // src/streaming/buffering/BufferingController.ts
3982
4014
  import {
3983
- createAbortSlot,
4015
+ createAbortSlot as createAbortSlot2,
3984
4016
  createDisposer as createDisposer8,
3985
4017
  createLogPrefix as createLogPrefix5,
3986
4018
  createTaskQueue,
@@ -3991,7 +4023,7 @@ import {
3991
4023
  logDebug as logDebug7,
3992
4024
  LogLevel as LogLevel2,
3993
4025
  logVerbose as logVerbose3,
3994
- logWarn as logWarn3,
4026
+ logWarn as logWarn4,
3995
4027
  throttle as throttle2
3996
4028
  } from "@amazon/vinyl-util";
3997
4029
 
@@ -4100,7 +4132,7 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4100
4132
  __publicField(this, "disposer", /* @__PURE__ */ createDisposer8());
4101
4133
  __publicField(this, "_active", false);
4102
4134
  __publicField(this, "activateDisposer", null);
4103
- __publicField(this, "segmentAbort", /* @__PURE__ */ createAbortSlot());
4135
+ __publicField(this, "segmentAbort", /* @__PURE__ */ createAbortSlot2());
4104
4136
  /**
4105
4137
  * Resets the throttle and polls the buffer on the next frame.
4106
4138
  */
@@ -4151,7 +4183,7 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4151
4183
  const newAppendSize = this.getMaxAppendSize(contentType2) * QUOTA_REACHED_SCALE;
4152
4184
  if (newAppendSize >= MIN_APPEND_SIZE) {
4153
4185
  sourceBufferQuotas.set(contentType2, newAppendSize);
4154
- logWarn3(
4186
+ logWarn4(
4155
4187
  this,
4156
4188
  "QuotaExceededError, new source buffer limit:",
4157
4189
  (newAppendSize / 1024 / 1024).toFixed(1) + " MiB"
@@ -4323,14 +4355,16 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4323
4355
  return;
4324
4356
  }
4325
4357
  const byteLength = streamingSegment.data.byteLength;
4326
- if (byteLength > appendSize) {
4358
+ const remaining = byteLength - this.appendOffset;
4359
+ const firstAppend = this.appendOffset === 0;
4360
+ if (remaining > appendSize) {
4327
4361
  const newOffset = this.appendOffset + appendSize;
4328
4362
  const chunk = streamingSegment.data.slice(
4329
4363
  this.appendOffset,
4330
4364
  newOffset
4331
4365
  );
4332
4366
  await sourceBufferController.append(chunk);
4333
- if (this.appendOffset === 0) {
4367
+ if (firstAppend) {
4334
4368
  this.buffered.push(streamingSegment);
4335
4369
  }
4336
4370
  this.appendOffset = newOffset;
@@ -4339,9 +4373,13 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4339
4373
  `appended chunk, this.appendOffset: ${this.appendOffset}`
4340
4374
  );
4341
4375
  } else {
4342
- await sourceBufferController.append(streamingSegment.data);
4343
- this.appendOffset = streamingSegment.data.byteLength;
4344
- this.buffered.push(streamingSegment);
4376
+ await sourceBufferController.append(
4377
+ firstAppend ? streamingSegment.data : streamingSegment.data.slice(this.appendOffset)
4378
+ );
4379
+ this.appendOffset = byteLength;
4380
+ if (firstAppend) {
4381
+ this.buffered.push(streamingSegment);
4382
+ }
4345
4383
  }
4346
4384
  if (!tail) this.refreshHead();
4347
4385
  }
@@ -4447,7 +4485,7 @@ var BufferingControllerImpl = class extends EventHostImpl8 {
4447
4485
  const contentType2 = quality == null ? void 0 : quality.contentType;
4448
4486
  if (!mimeType || !contentType2) return false;
4449
4487
  if (!denylistCodecsFromMimeType(mimeType)) return false;
4450
- logWarn3(
4488
+ logWarn4(
4451
4489
  this,
4452
4490
  "SourceBuffer append failed; denylisting codec and requesting reload:",
4453
4491
  mimeType
@@ -4523,7 +4561,7 @@ import {
4523
4561
  IllegalStateError as IllegalStateError2,
4524
4562
  isSilentError as isSilentError3,
4525
4563
  logDebug as logDebug8,
4526
- logWarn as logWarn4,
4564
+ logWarn as logWarn5,
4527
4565
  ReportableError as ReportableError8,
4528
4566
  toJson as toJson2,
4529
4567
  toLowerCase as toLowerCase2
@@ -4643,10 +4681,11 @@ var MediaSourceControllerImpl = class extends EventHostImpl9 {
4643
4681
  this.activateDisposer.dispose();
4644
4682
  this.activateDisposer = null;
4645
4683
  ++this.durationToken;
4684
+ this.durationSet = false;
4646
4685
  try {
4647
4686
  URL.revokeObjectURL(this.objectUrl);
4648
4687
  } catch (error) {
4649
- logWarn4(this, "error revoking object url", error);
4688
+ logWarn5(this, "error revoking object url", error);
4650
4689
  }
4651
4690
  }
4652
4691
  get sourceBufferCount() {
@@ -5684,7 +5723,7 @@ function createDefaultMediaTimelineTransformer(deps) {
5684
5723
  // src/streaming/ManifestControllerImpl.ts
5685
5724
  import { data } from "@amazon/vinyl-observable";
5686
5725
  import {
5687
- createAbortSlot as createAbortSlot2,
5726
+ createAbortSlot as createAbortSlot3,
5688
5727
  createDisposer as createDisposer11,
5689
5728
  EventHostImpl as EventHostImpl11,
5690
5729
  logDebug as logDebug11
@@ -5694,7 +5733,7 @@ var ManifestControllerImpl = class {
5694
5733
  __publicField(this, "deps", deps);
5695
5734
  __publicField(this, "_data");
5696
5735
  __publicField(this, "_error", null);
5697
- __publicField(this, "abortSlot", /* @__PURE__ */ createAbortSlot2());
5736
+ __publicField(this, "abortSlot", /* @__PURE__ */ createAbortSlot3());
5698
5737
  __publicField(this, "disposer", /* @__PURE__ */ createDisposer11());
5699
5738
  __publicField(this, "events", /* @__PURE__ */ new EventHostImpl11());
5700
5739
  __publicField(this, "manifestSpanArmed", true);
@@ -5820,7 +5859,7 @@ import {
5820
5859
 
5821
5860
  // src/streaming/SegmentDataSlot.ts
5822
5861
  import {
5823
- createAbortSlot as createAbortSlot3,
5862
+ createAbortSlot as createAbortSlot4,
5824
5863
  isSilentError as isSilentError4
5825
5864
  } from "@amazon/vinyl-util";
5826
5865
  var SegmentStatus = /* @__PURE__ */ ((SegmentStatus2) => {
@@ -5838,7 +5877,7 @@ var SegmentDataSlot = class {
5838
5877
  */
5839
5878
  __publicField(this, "onStatusChange", null);
5840
5879
  __publicField(this, "_status", "inactive" /* INACTIVE */);
5841
- __publicField(this, "abortSlot", /* @__PURE__ */ createAbortSlot3());
5880
+ __publicField(this, "abortSlot", /* @__PURE__ */ createAbortSlot4());
5842
5881
  __publicField(this, "bufferPromise", null);
5843
5882
  }
5844
5883
  /**
@@ -6539,10 +6578,16 @@ function discoverDashTextTracks(manifest, baseUrl) {
6539
6578
  return out;
6540
6579
  }
6541
6580
  function isTextAdaptationSet(adaptationSet) {
6581
+ var _a;
6542
6582
  if (adaptationSet.contentType === "text") return true;
6543
6583
  const mt = adaptationSet.mimeType;
6544
6584
  if (mt && mt.startsWith("text/")) return true;
6545
- return false;
6585
+ return ((_a = adaptationSet.Representation) != null ? _a : []).some(
6586
+ (representation) => {
6587
+ var _a2;
6588
+ return (_a2 = representation.mimeType) == null ? void 0 : _a2.startsWith("text/");
6589
+ }
6590
+ );
6546
6591
  }
6547
6592
  function isSidecarTextMime(mimeType) {
6548
6593
  if (mimeType == null) return true;
@@ -6802,7 +6847,7 @@ function parseWebVtt(input) {
6802
6847
  const cues = [];
6803
6848
  const styles = [];
6804
6849
  let i = 1;
6805
- while (i < lines.length && lines[i] !== "") i++;
6850
+ while (i < lines.length && lines[i] !== "" && !lines[i].includes("-->")) i++;
6806
6851
  while (i < lines.length) {
6807
6852
  if (lines[i] === "") {
6808
6853
  i++;
@@ -6987,7 +7032,7 @@ function scoreTextTrack(track, prefs) {
6987
7032
 
6988
7033
  // src/text/SidecarTextTrackController.ts
6989
7034
  import {
6990
- createAbortSlot as createAbortSlot4,
7035
+ createAbortSlot as createAbortSlot5,
6991
7036
  createDisposer as createDisposer13,
6992
7037
  equalDeep,
6993
7038
  EventHostImpl as EventHostImpl13,
@@ -7168,7 +7213,7 @@ var SidecarTextTrackController = class extends EventHostImpl13 {
7168
7213
  // The DOM text track currently rendering cues, or null when hidden. Owned by
7169
7214
  // the provider (never created/removed here).
7170
7215
  __publicField(this, "_ref", null);
7171
- __publicField(this, "loadAbort", /* @__PURE__ */ createAbortSlot4());
7216
+ __publicField(this, "loadAbort", /* @__PURE__ */ createAbortSlot5());
7172
7217
  __publicField(this, "disposer", /* @__PURE__ */ createDisposer13());
7173
7218
  const { add } = this.disposer;
7174
7219
  add(deps.options.onData(() => this.refreshSelection()));
@@ -7562,7 +7607,7 @@ import { func as func2, isOneOf as isOneOf7 } from "@amazon/vinyl-validation";
7562
7607
 
7563
7608
  // src/track/TrackBase.ts
7564
7609
  import {
7565
- createAbortSlot as createAbortSlot5,
7610
+ createAbortSlot as createAbortSlot6,
7566
7611
  createDisposer as createDisposer15,
7567
7612
  emptyRanges as emptyRanges2,
7568
7613
  equalDeep as equalDeep2,
@@ -7592,7 +7637,7 @@ var TrackBase = class extends EventHostImpl15 {
7592
7637
  }
7593
7638
  });
7594
7639
  __publicField(this, "disposer", /* @__PURE__ */ createDisposer15());
7595
- __publicField(this, "drmSessionAbort", /* @__PURE__ */ createAbortSlot5());
7640
+ __publicField(this, "drmSessionAbort", /* @__PURE__ */ createAbortSlot6());
7596
7641
  /**
7597
7642
  * Sets on handleError, cleared on 'reset'.
7598
7643
  */
@@ -8001,7 +8046,6 @@ import {
8001
8046
 
8002
8047
  // src/track/mse/MseTrack.ts
8003
8048
  import {
8004
- Abort as Abort3,
8005
8049
  equalDeep as equalDeep3,
8006
8050
  first as first2,
8007
8051
  IntersectionRanges,
@@ -8015,7 +8059,6 @@ var MseTrack = class extends TrackBase {
8015
8059
  const deps = depsContainer.dependencies;
8016
8060
  super(uri, type, deps);
8017
8061
  __publicField(this, "streams", []);
8018
- __publicField(this, "disposeAbort", /* @__PURE__ */ new Abort3());
8019
8062
  __publicField(this, "lastPreloadOptions", null);
8020
8063
  __publicField(this, "allFetchedRanges", []);
8021
8064
  __publicField(this, "_fetchedRanges", /* @__PURE__ */ new IntersectionRanges(
@@ -8040,7 +8083,7 @@ var MseTrack = class extends TrackBase {
8040
8083
  if (this.active) {
8041
8084
  this.deps.drmController.initializeForPlayback(event.current, {
8042
8085
  trackUri: this.uri,
8043
- abort: this.disposeAbort
8086
+ abort: this.drmSessionAbort.value
8044
8087
  });
8045
8088
  }
8046
8089
  });
@@ -8048,7 +8091,7 @@ var MseTrack = class extends TrackBase {
8048
8091
  if (event.current == null) return;
8049
8092
  this.deps.drmController.setBufferingDrmInfo(event.current, {
8050
8093
  trackUri: this.uri,
8051
- abort: this.disposeAbort
8094
+ abort: this.drmSessionAbort.value
8052
8095
  });
8053
8096
  });
8054
8097
  add(
@@ -8286,7 +8329,7 @@ var MseTrack = class extends TrackBase {
8286
8329
  this.streams.forEach((stream) => {
8287
8330
  this.deps.drmController.initializeForPlayback(
8288
8331
  stream.streamingQuality,
8289
- { trackUri: this.uri, abort: this.disposeAbort }
8332
+ { trackUri: this.uri, abort: this.drmSessionAbort.value }
8290
8333
  );
8291
8334
  });
8292
8335
  this.deps.playbackSource.src = this.deps.mediaSourceController.activate();
@@ -8312,7 +8355,7 @@ var MseTrack = class extends TrackBase {
8312
8355
  this.callOnStreams("deactivate");
8313
8356
  this.deps.drmController.setBufferingDrmInfo(null, {
8314
8357
  trackUri: this.uri,
8315
- abort: this.disposeAbort
8358
+ abort: this.drmSessionAbort.value
8316
8359
  });
8317
8360
  (_b = this.deps.textTrackController) == null ? void 0 : _b.deactivate();
8318
8361
  this.deps.playbackSource.src = null;
@@ -9635,7 +9678,11 @@ function createHlsQualityData(deps, data3, baseUrl, playlistUri, metadata) {
9635
9678
  async getSegment(time, affordance = 0) {
9636
9679
  var _a;
9637
9680
  const playlist = await data3.getMediaPlaylist(playlistUri);
9638
- const playlistBaseUrl = resolveUrl8(playlistUri, baseUrl);
9681
+ const playlistBaseUrl = getPlaylistBaseUrl(
9682
+ playlist,
9683
+ playlistUri,
9684
+ baseUrl
9685
+ );
9639
9686
  const segments = buildSegmentTimeline(
9640
9687
  deps,
9641
9688
  playlistBaseUrl,
@@ -9682,9 +9729,13 @@ async function discoverAdsFromManifest(data3) {
9682
9729
  const variant = data3.mainPlaylist.variants[0];
9683
9730
  const media = await data3.getMediaPlaylist(variant.uri);
9684
9731
  const contentDuration = media.ended ? media.segments.reduce((sum, s) => sum + s.duration, 0) : null;
9685
- const playlistBaseUrl = resolveUrl8(variant.uri, data3.baseUrl);
9732
+ const playlistBaseUrl = getPlaylistBaseUrl(media, variant.uri, data3.baseUrl);
9686
9733
  return discoverHlsInterstitials(media, playlistBaseUrl, contentDuration);
9687
9734
  }
9735
+ function getPlaylistBaseUrl(playlist, playlistUri, mainBaseUrl) {
9736
+ var _a;
9737
+ return (_a = playlist.baseUrl) != null ? _a : resolveUrl8(playlistUri, mainBaseUrl);
9738
+ }
9688
9739
 
9689
9740
  // src/track/hls/createDefaultHlsManifestTransformer.ts
9690
9741
  function createDefaultHlsManifestTransformer(deps) {
@@ -9835,8 +9886,11 @@ async function fetchMediaPlaylist(options) {
9835
9886
  const variantUrl = resolveUrl9(uri, baseUrl);
9836
9887
  const response = await requestWithRetry7(variantUrl, requestInit, { abort });
9837
9888
  const text = await readResponseBody6(response, "text");
9838
- const queryParams = parseQueryParams(response.url || variantUrl);
9839
- return parseMediaPlaylist2(text, defines, queryParams);
9889
+ const playlistUrl = response.url || variantUrl;
9890
+ const queryParams = parseQueryParams(playlistUrl);
9891
+ return __spreadProps(__spreadValues({}, parseMediaPlaylist2(text, defines, queryParams)), {
9892
+ baseUrl: playlistUrl
9893
+ });
9840
9894
  }
9841
9895
  function parseQueryParams(url) {
9842
9896
  const queryStart = url.indexOf("?");
@@ -9919,7 +9973,7 @@ import {
9919
9973
  logError as logError5,
9920
9974
  logInfo as logInfo2,
9921
9975
  logVerbose as logVerbose4,
9922
- logWarn as logWarn5,
9976
+ logWarn as logWarn6,
9923
9977
  LruCache,
9924
9978
  noop as noop8,
9925
9979
  resolveValueProvider as resolveValueProvider3
@@ -9971,7 +10025,7 @@ var TrackControllerImpl = class extends EventHostImpl17 {
9971
10025
  if (this.currentTrackIsAdTrack) return;
9972
10026
  const track = this._current;
9973
10027
  if (!track) {
9974
- logWarn5(this, "an ended event was received with no current track");
10028
+ logWarn6(this, "an ended event was received with no current track");
9975
10029
  return;
9976
10030
  }
9977
10031
  const interrupted = this.getQueueInterrupted();
@@ -10304,6 +10358,9 @@ var TrackControllerImpl = class extends EventHostImpl17 {
10304
10358
  for (const cachedTrack of this.trackCache.values()) {
10305
10359
  cachedTrack.clearPrefetch();
10306
10360
  }
10361
+ for (const adTracks of this.adTracksByParent.values()) {
10362
+ for (const adTrack of adTracks.values()) adTrack.clearPrefetch();
10363
+ }
10307
10364
  }
10308
10365
  clearQueue() {
10309
10366
  this.setQueue(this._current, []);
@@ -10580,7 +10637,7 @@ import {
10580
10637
  logInfo as logInfo3,
10581
10638
  LogLevel as LogLevel3,
10582
10639
  logVerbose as logVerbose5,
10583
- logWarn as logWarn6,
10640
+ logWarn as logWarn7,
10584
10641
  redispatchEvents as redispatchEvents4
10585
10642
  } from "@amazon/vinyl-util";
10586
10643
  import {
@@ -10682,7 +10739,7 @@ var VinylPlayer = class extends EventHostImpl18 {
10682
10739
  add(
10683
10740
  this.on("codecUnsupported", (event) => {
10684
10741
  if (this.deps.adController.currentAdBreak) return;
10685
- logWarn6(
10742
+ logWarn7(
10686
10743
  this,
10687
10744
  "codec unsupported, reloading track:",
10688
10745
  event.mimeType
@@ -11253,6 +11310,7 @@ export {
11253
11310
  DrmError,
11254
11311
  DrmKeySystem,
11255
11312
  DrmRobustness,
11313
+ EXCESSIVE_SESSION_COUNT,
11256
11314
  FAIR_PLAY_KEY_SYSTEMS,
11257
11315
  FixedPlaybackQuality,
11258
11316
  HtmlTextTrackRenderer,