@amazon/vinyl 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/index.cjs +207 -164
  2. package/dist/index.cjs.map +4 -4
  3. package/dist/index.js +195 -151
  4. package/dist/index.js.map +4 -4
  5. package/dist/test/integ.es5.js +201 -199
  6. package/dist/test/integ.js +417 -222
  7. package/dist/test/integ.js.map +4 -4
  8. package/dist/types/current/drm/DrmControllerImpl.d.ts +17 -1
  9. package/dist/types/current/drm/DrmControllerImpl.d.ts.map +1 -1
  10. package/dist/types/current/drm/DrmControllerImpl.js +45 -10
  11. package/dist/types/current/streaming/LoadMetric.d.ts +15 -1
  12. package/dist/types/current/streaming/LoadMetric.d.ts.map +1 -1
  13. package/dist/types/current/streaming/mediaTimelineFilter.d.ts +4 -2
  14. package/dist/types/current/streaming/mediaTimelineFilter.d.ts.map +1 -1
  15. package/dist/types/current/streaming/mediaTimelineFilter.js +23 -8
  16. package/dist/types/current/track/filters/sampleRateFilter.d.ts +8 -4
  17. package/dist/types/current/track/filters/sampleRateFilter.d.ts.map +1 -1
  18. package/dist/types/current/track/filters/sampleRateFilter.js +31 -21
  19. package/dist/types/current/track/mse/MseTrack.d.ts +0 -9
  20. package/dist/types/current/track/mse/MseTrack.d.ts.map +1 -1
  21. package/dist/types/current/track/mse/MseTrack.js +2 -29
  22. package/dist/types/current/tsconfig.tsbuildinfo +1 -1
  23. package/dist/types/current/vinyl/VinylPlayer.d.ts +5 -0
  24. package/dist/types/current/vinyl/VinylPlayer.d.ts.map +1 -1
  25. package/dist/types/current/vinyl/VinylPlayer.js +23 -1
  26. package/dist/types/ts3.7/drm/DrmControllerImpl.d.ts +17 -1
  27. package/dist/types/ts3.7/streaming/LoadMetric.d.ts +15 -1
  28. package/dist/types/ts3.7/streaming/mediaTimelineFilter.d.ts +4 -2
  29. package/dist/types/ts3.7/track/filters/sampleRateFilter.d.ts +8 -4
  30. package/dist/types/ts3.7/track/mse/MseTrack.d.ts +0 -9
  31. package/dist/types/ts3.7/vinyl/VinylPlayer.d.ts +5 -0
  32. package/dist/types/ts4.1/drm/DrmControllerImpl.d.ts +17 -1
  33. package/dist/types/ts4.1/streaming/LoadMetric.d.ts +15 -1
  34. package/dist/types/ts4.1/streaming/mediaTimelineFilter.d.ts +4 -2
  35. package/dist/types/ts4.1/track/filters/sampleRateFilter.d.ts +8 -4
  36. package/dist/types/ts4.1/track/mse/MseTrack.d.ts +0 -9
  37. package/dist/types/ts4.1/vinyl/VinylPlayer.d.ts +5 -0
  38. package/dist/types/ts4.7/drm/DrmControllerImpl.d.ts +17 -1
  39. package/dist/types/ts4.7/streaming/LoadMetric.d.ts +15 -1
  40. package/dist/types/ts4.7/streaming/mediaTimelineFilter.d.ts +4 -2
  41. package/dist/types/ts4.7/track/filters/sampleRateFilter.d.ts +8 -4
  42. package/dist/types/ts4.7/track/mse/MseTrack.d.ts +0 -9
  43. package/dist/types/ts4.7/vinyl/VinylPlayer.d.ts +5 -0
  44. package/dist/unit/types/current/drm/DrmControllerImpl.test.js +53 -9
  45. package/dist/unit/types/current/streaming/MseTrack.test.js +11 -8
  46. package/dist/unit/types/current/streaming/mediaTimelineFilter.test.js +60 -54
  47. package/dist/unit/types/current/track/filters/sampleRateFilter.test.js +75 -0
  48. package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
  49. package/dist/unit/types/current/vinyl/VinylPlayer.test.js +33 -2
  50. package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
  51. package/package.json +10 -10
package/dist/index.js CHANGED
@@ -1892,6 +1892,10 @@ var DrmControllerImpl = class extends EventHostImpl5 {
1892
1892
  __publicField(this, "bufferingTrackUri", null);
1893
1893
  __publicField(this, "sessionAbort", null);
1894
1894
  __publicField(this, "pendingMessageProps", null);
1895
+ // Armed per track load; latches on the first session so only the
1896
+ // critical-path session's EME/CDM setup is measured.
1897
+ __publicField(this, "keySetupSpanArmed", true);
1898
+ __publicField(this, "keySetupSpanStart", null);
1895
1899
  __publicField(this, "disposer", /* @__PURE__ */ createDisposer2());
1896
1900
  __publicField(this, "checkIsSupportedCached", /* @__PURE__ */ memoize4(
1897
1901
  async (params) => {
@@ -2057,6 +2061,7 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2057
2061
  if (!hasMimeType(drmInfo)) {
2058
2062
  throw new DrmError("Encrypted content must have a mimeType.");
2059
2063
  }
2064
+ this.markKeySetupStart();
2060
2065
  const mediaKeys = await this.attachMediaKeys(drmInfo);
2061
2066
  this.abortIfDisposed();
2062
2067
  const keySystemOptions = (_a = this.options.keySystems[mediaKeys.keySystem]) != null ? _a : this.options.keySystems["*"];
@@ -2101,6 +2106,28 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2101
2106
  });
2102
2107
  return newSession;
2103
2108
  }
2109
+ /**
2110
+ * Captures the key-setup span start at the top of the session-creation path
2111
+ * (before media keys are attached), latching so only the first session of
2112
+ * the current track load is measured.
2113
+ */
2114
+ markKeySetupStart() {
2115
+ if (!this.keySetupSpanArmed) return;
2116
+ this.keySetupSpanArmed = false;
2117
+ this.keySetupSpanStart = Date.now();
2118
+ }
2119
+ dispatchLoadSpan(kind, startTime, endTime, messageProps) {
2120
+ this.dispatch("loadSpanMeasured", __spreadValues(__spreadValues({
2121
+ kind,
2122
+ startTime,
2123
+ endTime,
2124
+ mimeType: messageProps.mimeType
2125
+ }, messageProps.trackUri != null && {
2126
+ trackUri: messageProps.trackUri
2127
+ }), messageProps.contentType != null && {
2128
+ contentType: messageProps.contentType
2129
+ }));
2130
+ }
2104
2131
  initializeForPlayback(drmInfo, options) {
2105
2132
  var _a;
2106
2133
  logDebug3(this, "initializeForPlayback", drmInfo);
@@ -2124,6 +2151,8 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2124
2151
  this.drmInfo = drmInfo;
2125
2152
  this.bufferingTrackUri = (_a = options == null ? void 0 : options.trackUri) != null ? _a : null;
2126
2153
  this.sessionAbort = (_b = options == null ? void 0 : options.abort) != null ? _b : null;
2154
+ this.keySetupSpanArmed = true;
2155
+ this.keySetupSpanStart = null;
2127
2156
  }
2128
2157
  /**
2129
2158
  * If the drm metadata contains initialization data for the current key system, create a new session.
@@ -2135,6 +2164,7 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2135
2164
  this.handleError(new DrmError("DRM not supported."));
2136
2165
  return;
2137
2166
  }
2167
+ this.markKeySetupStart();
2138
2168
  const mediaKeys = await this.attachMediaKeys(drmInfo);
2139
2169
  const drmProtection = (_a = drmInfo.contentProtections.find((cP) => {
2140
2170
  return cP.keySystem === mediaKeys.keySystem;
@@ -2273,7 +2303,9 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2273
2303
  event,
2274
2304
  // Captured per session, so a concurrent preloaded track's
2275
2305
  // license exchange keeps its own attribution.
2276
- trackUri
2306
+ trackUri,
2307
+ mimeType: drmInfo.mimeType,
2308
+ contentType: drmInfo.contentType
2277
2309
  }),
2278
2310
  LICENSE_TIMEOUT,
2279
2311
  { message: LICENSE_TIMEOUT_MESSAGE }
@@ -2295,6 +2327,15 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2295
2327
  this.pendingMessageProps = messageProps;
2296
2328
  const keySystem = mediaKeys.keySystem;
2297
2329
  logDebug3(this, "message", keySystem, event.message.byteLength);
2330
+ if (this.keySetupSpanStart != null) {
2331
+ this.dispatchLoadSpan(
2332
+ "keySetup",
2333
+ this.keySetupSpanStart,
2334
+ Date.now(),
2335
+ messageProps
2336
+ );
2337
+ this.keySetupSpanStart = null;
2338
+ }
2298
2339
  const keySystemOptions = (_a = this.options.keySystems[keySystem]) != null ? _a : this.options.keySystems["*"];
2299
2340
  const licenseServerOptionsProvider = keySystemOptions == null ? void 0 : keySystemOptions.licenseServer;
2300
2341
  const licenseServerOptions = (_b = clone(await resolveValueProvider2(licenseServerOptionsProvider))) != null ? _b : {};
@@ -2316,13 +2357,12 @@ var DrmControllerImpl = class extends EventHostImpl5 {
2316
2357
  challenge
2317
2358
  );
2318
2359
  if (this.disposed) return;
2319
- this.dispatch("loadSpanMeasured", __spreadValues({
2320
- kind: "license",
2321
- startTime: licenseSpanStart,
2322
- endTime: Date.now()
2323
- }, messageProps.trackUri != null && {
2324
- trackUri: messageProps.trackUri
2325
- }));
2360
+ this.dispatchLoadSpan(
2361
+ "license",
2362
+ licenseSpanStart,
2363
+ Date.now(),
2364
+ messageProps
2365
+ );
2326
2366
  this.pendingMessageProps = null;
2327
2367
  if (session.disposed) return;
2328
2368
  logDebug3(this, "update");
@@ -2581,7 +2621,7 @@ function configureVinylGlobal(options) {
2581
2621
  import { parseVersion } from "@amazon/vinyl-util";
2582
2622
  var vinylVersion = /* @__PURE__ */ parseVersion(
2583
2623
  /* istanbul ignore next */
2584
- "3.1.0"
2624
+ "3.2.0"
2585
2625
  );
2586
2626
 
2587
2627
  // src/global/globalRef.ts
@@ -5013,6 +5053,107 @@ function filterContentTypes(contentTypes, allowedContentTypes) {
5013
5053
  // src/streaming/createDefaultMediaTimelineTransformer.ts
5014
5054
  import { combineData as combineData2 } from "@amazon/vinyl-observable";
5015
5055
 
5056
+ // src/streaming/MediaQualityMetadata.ts
5057
+ import {
5058
+ createShortUid
5059
+ } from "@amazon/vinyl-util";
5060
+ import {
5061
+ array as array3,
5062
+ enumOf as enumOf3,
5063
+ isOneOf as isOneOf3,
5064
+ number as number6,
5065
+ object as object9,
5066
+ string as string6,
5067
+ tuple
5068
+ } from "@amazon/vinyl-validation";
5069
+
5070
+ // src/streaming/DescriptorRecord.ts
5071
+ import {
5072
+ array as array2,
5073
+ object as object8,
5074
+ record as record2,
5075
+ string as string5
5076
+ } from "@amazon/vinyl-validation";
5077
+ import { first } from "@amazon/vinyl-util";
5078
+ function getDescriptorValue(record4, uri, id) {
5079
+ var _a, _b;
5080
+ let arr = record4[uri];
5081
+ if (!arr) return null;
5082
+ if (id !== void 0) arr = arr.filter((descriptor) => descriptor.id === id);
5083
+ return (_b = (_a = first(arr)) == null ? void 0 : _a.value) != null ? _b : null;
5084
+ }
5085
+ var descriptorValidator = /* @__PURE__ */ object8({
5086
+ id: /* @__PURE__ */ string5().maybe().optional(),
5087
+ value: /* @__PURE__ */ string5().maybe().optional()
5088
+ });
5089
+ var descriptorRecordValidator = /* @__PURE__ */ record2(/* @__PURE__ */ string5(), /* @__PURE__ */ array2(descriptorValidator).readonly().orUndefined());
5090
+
5091
+ // src/streaming/MediaQualityMetadata.ts
5092
+ var ALL_CONTENT_TYPES = [
5093
+ "video",
5094
+ "audio",
5095
+ "text"
5096
+ ];
5097
+ var RESTRICTABLE_CONTENT_TYPES = [
5098
+ "video",
5099
+ "audio"
5100
+ ];
5101
+ var drmProtectionValidator = /* @__PURE__ */ descriptorValidator.extend({
5102
+ keySystem: /* @__PURE__ */ enumOf3(DrmKeySystem),
5103
+ pro: /* @__PURE__ */ string6().maybe().optional(),
5104
+ pssh: /* @__PURE__ */ string6().maybe().optional()
5105
+ });
5106
+ var mediaFormatMetadataValidator = /* @__PURE__ */ object9({
5107
+ contentProtections: /* @__PURE__ */ array3(drmProtectionValidator).readonly(),
5108
+ contentType: /* @__PURE__ */ isOneOf3("audio", "video", "text").orNull(),
5109
+ initDataType: /* @__PURE__ */ string6().orNull(),
5110
+ encryptionScheme: /* @__PURE__ */ string6().orNull(),
5111
+ mimeType: /* @__PURE__ */ string6().orNull()
5112
+ });
5113
+ function createEmptyMediaFormatMetadata() {
5114
+ return {
5115
+ contentType: null,
5116
+ mimeType: null,
5117
+ initDataType: null,
5118
+ encryptionScheme: null,
5119
+ contentProtections: []
5120
+ };
5121
+ }
5122
+ function createEmptyMediaQualityMetadata() {
5123
+ return __spreadProps(__spreadValues({}, createEmptyMediaFormatMetadata()), {
5124
+ decoderId: createShortUid(),
5125
+ qualityId: createShortUid(),
5126
+ codecs: null,
5127
+ bandwidth: null,
5128
+ bandwidthTotal: null,
5129
+ supplementalProperties: {},
5130
+ audioSamplingRate: null,
5131
+ frameRate: null,
5132
+ height: null,
5133
+ width: null,
5134
+ lang: null,
5135
+ characteristics: [],
5136
+ groupId: createShortUid(),
5137
+ switchingGroupIds: null
5138
+ });
5139
+ }
5140
+ var mediaQualityMetadataValidator = /* @__PURE__ */ mediaFormatMetadataValidator.extend({
5141
+ audioSamplingRate: /* @__PURE__ */ array3(/* @__PURE__ */ number6()).readonly().orNull(),
5142
+ bandwidth: /* @__PURE__ */ number6().orNull(),
5143
+ bandwidthTotal: /* @__PURE__ */ number6().orNull(),
5144
+ codecs: /* @__PURE__ */ string6().orNull(),
5145
+ decoderId: /* @__PURE__ */ string6(),
5146
+ frameRate: /* @__PURE__ */ tuple(/* @__PURE__ */ number6(), /* @__PURE__ */ number6()).readonly().orNull(),
5147
+ height: /* @__PURE__ */ number6().orNull(),
5148
+ qualityId: /* @__PURE__ */ string6(),
5149
+ supplementalProperties: descriptorRecordValidator,
5150
+ width: /* @__PURE__ */ number6().orNull(),
5151
+ lang: /* @__PURE__ */ string6().orNull(),
5152
+ characteristics: /* @__PURE__ */ array3(/* @__PURE__ */ string6()).readonly(),
5153
+ groupId: /* @__PURE__ */ string6(),
5154
+ switchingGroupIds: /* @__PURE__ */ array3(/* @__PURE__ */ string6()).readonly().orNull()
5155
+ });
5156
+
5016
5157
  // src/streaming/mediaTimelineFilter.ts
5017
5158
  import { map, memoize as memoize6 } from "@amazon/vinyl-util";
5018
5159
 
@@ -5301,6 +5442,13 @@ function createLanguageFilter(preferredLanguage, contentType2) {
5301
5442
  }
5302
5443
 
5303
5444
  // src/streaming/mediaTimelineFilter.ts
5445
+ function assertMediaStreamsRetained(original, filtered, throwError) {
5446
+ for (const contentType2 of RESTRICTABLE_CONTENT_TYPES) {
5447
+ if (original.some((q) => q.metadata.contentType === contentType2) && !filtered.some((q) => q.metadata.contentType === contentType2)) {
5448
+ throwError();
5449
+ }
5450
+ }
5451
+ }
5304
5452
  function filterTimelineQualities(filter, throwError, timeline) {
5305
5453
  if (!filter) return timeline;
5306
5454
  const mapMetadataArray = memoize6(
@@ -5312,11 +5460,9 @@ function filterTimelineQualities(filter, throwError, timeline) {
5312
5460
  const filtered = period.qualities.filter(
5313
5461
  (q, index) => filter(q.metadata, index, mapMetadataArray(period.qualities))
5314
5462
  );
5463
+ assertMediaStreamsRetained(period.qualities, filtered, throwError);
5315
5464
  return __spreadProps(__spreadValues({}, period), { qualities: filtered });
5316
5465
  });
5317
- if (periods.some((p) => p.qualities.length === 0)) {
5318
- throwError();
5319
- }
5320
5466
  return __spreadProps(__spreadValues({}, timeline), { periods });
5321
5467
  }
5322
5468
  async function filterTimelineQualitiesAsync(filter, throwError, timeline) {
@@ -5334,11 +5480,9 @@ async function filterTimelineQualitiesAsync(filter, throwError, timeline) {
5334
5480
  filtered.push(period.qualities[i]);
5335
5481
  }
5336
5482
  }
5483
+ assertMediaStreamsRetained(period.qualities, filtered, throwError);
5337
5484
  periods.push(__spreadProps(__spreadValues({}, period), { qualities: filtered }));
5338
5485
  }
5339
- if (periods.some((p) => p.qualities.length === 0)) {
5340
- throwError();
5341
- }
5342
5486
  return __spreadProps(__spreadValues({}, timeline), { periods });
5343
5487
  }
5344
5488
 
@@ -5412,7 +5556,6 @@ import {
5412
5556
  Browser as Browser2,
5413
5557
  last,
5414
5558
  MediaUnsupportedError as MediaUnsupportedError6,
5415
- every,
5416
5559
  map as map2,
5417
5560
  max as max2,
5418
5561
  min
@@ -5425,23 +5568,28 @@ function withinAudioSampleRateRange(options, metadata, _index, array6) {
5425
5568
  if (metadata.contentType !== "audio") return true;
5426
5569
  const samplingRate = last(metadata.audioSamplingRate);
5427
5570
  if (!samplingRate) return true;
5571
+ const { minSampleRate } = options;
5572
+ const maxSampleRate = (_a = options.maxSampleRate) != null ? _a : options.capabilities.sampleRate;
5428
5573
  const audioRates = () => map2(
5429
5574
  array6,
5430
5575
  (item) => item.contentType === "audio" ? last(item.audioSamplingRate) : void 0
5431
5576
  ).filter((rate) => rate != null);
5432
- const { minSampleRate } = options;
5577
+ const outOfBandFallback = () => {
5578
+ const rates = audioRates();
5579
+ const inBand = (rate) => (minSampleRate == null || rate >= minSampleRate) && (!maxSampleRate || rate <= maxSampleRate);
5580
+ if (rates.some(inBand)) return void 0;
5581
+ const decodable = maxSampleRate ? rates.filter((rate) => rate <= maxSampleRate) : rates;
5582
+ return decodable.length ? max2(decodable) : min(rates);
5583
+ };
5433
5584
  if (minSampleRate != null && samplingRate < minSampleRate) {
5434
- const rates2 = audioRates();
5435
- return every(rates2, (rate) => rate < minSampleRate) && samplingRate === max2(rates2);
5585
+ return samplingRate === outOfBandFallback();
5436
5586
  }
5437
- const maxSampleRate = (_a = options.maxSampleRate) != null ? _a : options.capabilities.sampleRate;
5438
5587
  if (!maxSampleRate) return true;
5439
5588
  if (hasBrowser2(Browser2.FIREFOX)) {
5440
5589
  return samplingRate <= 48e3;
5441
5590
  }
5442
5591
  if (samplingRate <= maxSampleRate) return true;
5443
- const rates = audioRates();
5444
- return every(rates, (rate) => rate > maxSampleRate) && samplingRate === min(rates);
5592
+ return samplingRate === outOfBandFallback();
5445
5593
  }
5446
5594
 
5447
5595
  // src/util/media/codecOverrides.ts
@@ -5528,27 +5676,6 @@ function createDefaultMediaTimelineTransformer(deps) {
5528
5676
  });
5529
5677
  }
5530
5678
 
5531
- // src/streaming/DescriptorRecord.ts
5532
- import {
5533
- array as array2,
5534
- object as object8,
5535
- record as record2,
5536
- string as string5
5537
- } from "@amazon/vinyl-validation";
5538
- import { first } from "@amazon/vinyl-util";
5539
- function getDescriptorValue(record4, uri, id) {
5540
- var _a, _b;
5541
- let arr = record4[uri];
5542
- if (!arr) return null;
5543
- if (id !== void 0) arr = arr.filter((descriptor) => descriptor.id === id);
5544
- return (_b = (_a = first(arr)) == null ? void 0 : _a.value) != null ? _b : null;
5545
- }
5546
- var descriptorValidator = /* @__PURE__ */ object8({
5547
- id: /* @__PURE__ */ string5().maybe().optional(),
5548
- value: /* @__PURE__ */ string5().maybe().optional()
5549
- });
5550
- var descriptorRecordValidator = /* @__PURE__ */ record2(/* @__PURE__ */ string5(), /* @__PURE__ */ array2(descriptorValidator).readonly().orUndefined());
5551
-
5552
5679
  // src/streaming/ManifestControllerImpl.ts
5553
5680
  import { data } from "@amazon/vinyl-observable";
5554
5681
  import {
@@ -5655,84 +5782,6 @@ var ManifestControllerImpl = class {
5655
5782
  }
5656
5783
  };
5657
5784
 
5658
- // src/streaming/MediaQualityMetadata.ts
5659
- import {
5660
- createShortUid
5661
- } from "@amazon/vinyl-util";
5662
- import {
5663
- array as array3,
5664
- enumOf as enumOf3,
5665
- isOneOf as isOneOf3,
5666
- number as number6,
5667
- object as object9,
5668
- string as string6,
5669
- tuple
5670
- } from "@amazon/vinyl-validation";
5671
- var ALL_CONTENT_TYPES = [
5672
- "video",
5673
- "audio",
5674
- "text"
5675
- ];
5676
- var RESTRICTABLE_CONTENT_TYPES = [
5677
- "video",
5678
- "audio"
5679
- ];
5680
- var drmProtectionValidator = /* @__PURE__ */ descriptorValidator.extend({
5681
- keySystem: /* @__PURE__ */ enumOf3(DrmKeySystem),
5682
- pro: /* @__PURE__ */ string6().maybe().optional(),
5683
- pssh: /* @__PURE__ */ string6().maybe().optional()
5684
- });
5685
- var mediaFormatMetadataValidator = /* @__PURE__ */ object9({
5686
- contentProtections: /* @__PURE__ */ array3(drmProtectionValidator).readonly(),
5687
- contentType: /* @__PURE__ */ isOneOf3("audio", "video", "text").orNull(),
5688
- initDataType: /* @__PURE__ */ string6().orNull(),
5689
- encryptionScheme: /* @__PURE__ */ string6().orNull(),
5690
- mimeType: /* @__PURE__ */ string6().orNull()
5691
- });
5692
- function createEmptyMediaFormatMetadata() {
5693
- return {
5694
- contentType: null,
5695
- mimeType: null,
5696
- initDataType: null,
5697
- encryptionScheme: null,
5698
- contentProtections: []
5699
- };
5700
- }
5701
- function createEmptyMediaQualityMetadata() {
5702
- return __spreadProps(__spreadValues({}, createEmptyMediaFormatMetadata()), {
5703
- decoderId: createShortUid(),
5704
- qualityId: createShortUid(),
5705
- codecs: null,
5706
- bandwidth: null,
5707
- bandwidthTotal: null,
5708
- supplementalProperties: {},
5709
- audioSamplingRate: null,
5710
- frameRate: null,
5711
- height: null,
5712
- width: null,
5713
- lang: null,
5714
- characteristics: [],
5715
- groupId: createShortUid(),
5716
- switchingGroupIds: null
5717
- });
5718
- }
5719
- var mediaQualityMetadataValidator = /* @__PURE__ */ mediaFormatMetadataValidator.extend({
5720
- audioSamplingRate: /* @__PURE__ */ array3(/* @__PURE__ */ number6()).readonly().orNull(),
5721
- bandwidth: /* @__PURE__ */ number6().orNull(),
5722
- bandwidthTotal: /* @__PURE__ */ number6().orNull(),
5723
- codecs: /* @__PURE__ */ string6().orNull(),
5724
- decoderId: /* @__PURE__ */ string6(),
5725
- frameRate: /* @__PURE__ */ tuple(/* @__PURE__ */ number6(), /* @__PURE__ */ number6()).readonly().orNull(),
5726
- height: /* @__PURE__ */ number6().orNull(),
5727
- qualityId: /* @__PURE__ */ string6(),
5728
- supplementalProperties: descriptorRecordValidator,
5729
- width: /* @__PURE__ */ number6().orNull(),
5730
- lang: /* @__PURE__ */ string6().orNull(),
5731
- characteristics: /* @__PURE__ */ array3(/* @__PURE__ */ string6()).readonly(),
5732
- groupId: /* @__PURE__ */ string6(),
5733
- switchingGroupIds: /* @__PURE__ */ array3(/* @__PURE__ */ string6()).readonly().orNull()
5734
- });
5735
-
5736
5785
  // src/streaming/MediaTimeline.ts
5737
5786
  import { sortedInsertionIndex as sortedInsertionIndex2 } from "@amazon/vinyl-util";
5738
5787
  function getMediaPeriodAtTime(timeline, time) {
@@ -7952,7 +8001,6 @@ import {
7952
8001
  first as first2,
7953
8002
  IntersectionRanges,
7954
8003
  logDebug as logDebug16,
7955
- MediaUnsupportedError as MediaUnsupportedError7,
7956
8004
  redispatchEvents as redispatchEvents3
7957
8005
  } from "@amazon/vinyl-util";
7958
8006
  import { createContainer as createContainer2 } from "@amazon/vinyl-di";
@@ -7980,10 +8028,7 @@ var MseTrack = class extends TrackBase {
7980
8028
  this.deps = deps;
7981
8029
  add(
7982
8030
  deps.contentTypesValue.onData((contentTypesPromise) => {
7983
- contentTypesPromise.then((value) => {
7984
- this.setContentTypes(value);
7985
- this.validateRequiredContentTypesPlayable();
7986
- }).catch(this.errorHandler);
8031
+ contentTypesPromise.then((value) => this.setContentTypes(value)).catch(this.errorHandler);
7987
8032
  })
7988
8033
  );
7989
8034
  this.on("streamingQualityChange", (event) => {
@@ -8084,33 +8129,8 @@ var MseTrack = class extends TrackBase {
8084
8129
  });
8085
8130
  }
8086
8131
  }
8087
- this.validateRequiredContentTypesPlayable();
8088
8132
  });
8089
8133
  }
8090
- /**
8091
- * Fails fast when a media content type the manifest declared (audio/video)
8092
- * has no playable qualities left after timeline filtering. Its stream can
8093
- * never create a source buffer, so without this the track waits forever for
8094
- * a source buffer that never arrives, surfacing only as an opaque
8095
- * `readyToAppend` timeout. Runs once both the required content types and the
8096
- * filtered timeline qualities are known (either order).
8097
- */
8098
- validateRequiredContentTypesPlayable() {
8099
- const qualities = this._qualities;
8100
- if (!qualities) return;
8101
- const present = new Set(qualities.map((q) => q.contentType));
8102
- for (const contentType2 of this._contentTypes) {
8103
- if (!present.has(contentType2)) {
8104
- this.errorHandler(
8105
- new MediaUnsupportedError7(
8106
- `No playable ${contentType2} rendition`,
8107
- `no-playable-${contentType2}`
8108
- )
8109
- );
8110
- return;
8111
- }
8112
- }
8113
- }
8114
8134
  async getAds() {
8115
8135
  const timeline = await this.deps.mediaTimeline.value;
8116
8136
  return {
@@ -10550,8 +10570,11 @@ import {
10550
10570
  emptyRanges as emptyRanges3,
10551
10571
  equalDeep as equalDeep4,
10552
10572
  EventHostImpl as EventHostImpl18,
10573
+ getLogLevel as getLogLevel2,
10553
10574
  logDebug as logDebug18,
10554
10575
  logInfo as logInfo3,
10576
+ LogLevel as LogLevel3,
10577
+ logVerbose as logVerbose5,
10555
10578
  logWarn as logWarn6,
10556
10579
  redispatchEvents as redispatchEvents4
10557
10580
  } from "@amazon/vinyl-util";
@@ -10584,6 +10607,7 @@ var VinylPlayer = class extends EventHostImpl18 {
10584
10607
  playerRegistryRef.value.addPlayer(this);
10585
10608
  this.redispatchSubControllerEvents();
10586
10609
  this.redispatchCurrentTrackEvents();
10610
+ this.initializeLoadSpanLogging();
10587
10611
  this.initializeAutoResetHandling();
10588
10612
  }
10589
10613
  get [Symbol.toStringTag]() {
@@ -10601,6 +10625,26 @@ var VinylPlayer = class extends EventHostImpl18 {
10601
10625
  get autoResetController() {
10602
10626
  return this.deps.autoResetController;
10603
10627
  }
10628
+ /**
10629
+ * Logs each republished load span once at the verbose level, formatting its
10630
+ * bounds as ISO date strings and its duration in milliseconds.
10631
+ */
10632
+ initializeLoadSpanLogging() {
10633
+ this.disposer.add(
10634
+ this.on("loadSpan", (span) => {
10635
+ if (getLogLevel2() > LogLevel3.VERBOSE) return;
10636
+ logVerbose5(this, "loadSpan", {
10637
+ kind: span.kind,
10638
+ trackUri: span.trackUri,
10639
+ mimeType: span.mimeType,
10640
+ contentType: span.contentType,
10641
+ startTime: new Date(span.startTime).toISOString(),
10642
+ endTime: new Date(span.endTime).toISOString(),
10643
+ durationMs: (span.endTime - span.startTime).toFixed(2)
10644
+ });
10645
+ })
10646
+ );
10647
+ }
10604
10648
  redispatchSubControllerEvents() {
10605
10649
  const add = this.disposer.add;
10606
10650
  add(