@scarlett-player/embed 0.5.3 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -43,6 +43,18 @@ function mapLevels(levels, _currentLevel) {
43
43
  codec: level.codecSet
44
44
  }));
45
45
  }
46
+ function getInitialBandwidthEstimate(overrideBps) {
47
+ const HLS_DEFAULT_ESTIMATE = 5e5;
48
+ if (overrideBps !== void 0 && overrideBps > 0) {
49
+ return overrideBps;
50
+ }
51
+ const connection = navigator.connection;
52
+ if (connection?.downlink && connection.downlink > 0) {
53
+ const bps = connection.downlink * 1e6;
54
+ return Math.round(bps * 0.85);
55
+ }
56
+ return HLS_DEFAULT_ESTIMATE;
57
+ }
46
58
  var HLS_ERROR_TYPES = {
47
59
  NETWORK_ERROR: "networkError",
48
60
  MEDIA_ERROR: "mediaError",
@@ -113,6 +125,14 @@ function setupHlsEventHandlers(hls, api, callbacks) {
113
125
  });
114
126
  callbacks.onLevelSwitched?.(data.level);
115
127
  });
128
+ let lastBandwidthUpdate = 0;
129
+ addHandler("hlsFragLoaded", () => {
130
+ const now = Date.now();
131
+ if (now - lastBandwidthUpdate >= 2e3 && hls.bandwidthEstimate) {
132
+ lastBandwidthUpdate = now;
133
+ api.setState("bandwidth", Math.round(hls.bandwidthEstimate));
134
+ }
135
+ });
116
136
  addHandler("hlsFragBuffered", () => {
117
137
  api.setState("buffering", false);
118
138
  callbacks.onBufferUpdate?.();
@@ -355,6 +375,7 @@ var DEFAULT_CONFIG$3 = {
355
375
  maxMaxBufferLength: 600,
356
376
  backBufferLength: 30,
357
377
  enableWorker: true,
378
+ capLevelToPlayerSize: true,
358
379
  // Error recovery settings
359
380
  maxNetworkRetries: 3,
360
381
  maxMediaRetries: 2,
@@ -424,11 +445,13 @@ function createHLSPlugin(config) {
424
445
  startPosition: mergedConfig.startPosition,
425
446
  startLevel: -1,
426
447
  // Auto quality selection (ABR)
448
+ abrEwmaDefaultEstimate: getInitialBandwidthEstimate(mergedConfig.initialBandwidthEstimate),
427
449
  lowLatencyMode: mergedConfig.lowLatencyMode,
428
450
  maxBufferLength: mergedConfig.maxBufferLength,
429
451
  maxMaxBufferLength: mergedConfig.maxMaxBufferLength,
430
452
  backBufferLength: mergedConfig.backBufferLength,
431
453
  enableWorker: mergedConfig.enableWorker,
454
+ capLevelToPlayerSize: mergedConfig.capLevelToPlayerSize,
432
455
  // Minimize hls.js internal retries - we handle retries ourselves
433
456
  fragLoadingMaxRetry: 1,
434
457
  manifestLoadingMaxRetry: 1,
@@ -699,7 +722,10 @@ function createHLSPlugin(config) {
699
722
  currentSrc = src;
700
723
  api.setState("playbackState", "loading");
701
724
  api.setState("buffering", true);
702
- if (isHlsJsSupported()) {
725
+ if (api.getState("airplayActive") && supportsNativeHLS()) {
726
+ api.logger.info("Using native HLS (AirPlay active)");
727
+ await loadNative(src);
728
+ } else if (isHlsJsSupported()) {
703
729
  api.logger.info("Using hls.js for HLS playback");
704
730
  await loadWithHlsJs(src);
705
731
  } else if (supportsNativeHLS()) {
@@ -1561,7 +1587,9 @@ var DEFAULT_CONFIG$1 = {
1561
1587
  persist: false,
1562
1588
  persistKey: "scarlett-playlist",
1563
1589
  shuffle: false,
1564
- repeat: "none"
1590
+ repeat: "none",
1591
+ autoLoad: true,
1592
+ advanceDelay: 0
1565
1593
  };
1566
1594
  function generateId() {
1567
1595
  return `track-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
@@ -1578,7 +1606,10 @@ function createPlaylistPlugin(config) {
1578
1606
  const mergedConfig = { ...DEFAULT_CONFIG$1, ...config };
1579
1607
  let api = null;
1580
1608
  let tracks = mergedConfig.tracks || [];
1581
- let currentIndex = -1;
1609
+ let currentIndex = mergedConfig.initialIndex ?? -1;
1610
+ if (currentIndex < -1 || currentIndex >= tracks.length) {
1611
+ currentIndex = -1;
1612
+ }
1582
1613
  let shuffle = mergedConfig.shuffle || false;
1583
1614
  let repeat = mergedConfig.repeat || "none";
1584
1615
  let shuffleOrder = [];
@@ -1705,6 +1736,9 @@ function createPlaylistPlugin(config) {
1705
1736
  }
1706
1737
  api?.setState("mediaType", track.type || "audio");
1707
1738
  emitChange();
1739
+ if (mergedConfig.autoLoad !== false && track.src) {
1740
+ api?.emit("media:load-request", { src: track.src, autoplay: true });
1741
+ }
1708
1742
  };
1709
1743
  const plugin = {
1710
1744
  id: "playlist",
@@ -1719,12 +1753,20 @@ function createPlaylistPlugin(config) {
1719
1753
  if (shuffle && tracks.length > 0) {
1720
1754
  generateShuffleOrder();
1721
1755
  }
1756
+ let advanceTimeout = null;
1722
1757
  const unsubEnded = api.on("playback:ended", () => {
1723
1758
  if (!mergedConfig.autoAdvance) return;
1724
1759
  const nextIdx = getNextIndex();
1725
1760
  if (nextIdx >= 0) {
1726
- api?.logger.debug("Auto-advancing to next track", { nextIdx });
1727
- setCurrentTrack(nextIdx);
1761
+ const advance = () => {
1762
+ api?.logger.debug("Auto-advancing to next track", { nextIdx });
1763
+ setCurrentTrack(nextIdx);
1764
+ };
1765
+ if (mergedConfig.advanceDelay) {
1766
+ advanceTimeout = setTimeout(advance, mergedConfig.advanceDelay);
1767
+ } else {
1768
+ advance();
1769
+ }
1728
1770
  } else {
1729
1771
  api?.logger.info("Playlist ended");
1730
1772
  api?.emit("playlist:ended", void 0);
@@ -1732,6 +1774,10 @@ function createPlaylistPlugin(config) {
1732
1774
  });
1733
1775
  api.onDestroy(() => {
1734
1776
  unsubEnded();
1777
+ if (advanceTimeout) {
1778
+ clearTimeout(advanceTimeout);
1779
+ advanceTimeout = null;
1780
+ }
1735
1781
  persistPlaylist();
1736
1782
  });
1737
1783
  },
@@ -3716,6 +3762,13 @@ class ScarlettPlayer {
3716
3762
  await this.pluginManager.initPlugin(id);
3717
3763
  }
3718
3764
  }
3765
+ this.eventBus.on("media:load-request", async ({ src, autoplay }) => {
3766
+ if (this.stateManager.getValue("chromecastActive")) return;
3767
+ await this.load(src);
3768
+ if (autoplay !== false) {
3769
+ await this.play();
3770
+ }
3771
+ });
3719
3772
  if (this.initialSrc) {
3720
3773
  await this.load(this.initialSrc);
3721
3774
  }
@@ -4543,6 +4596,12 @@ async function createEmbedPlayer(container, config, pluginCreators2, availableTy
4543
4596
  artwork: config.artwork || config.poster || config.playlist?.[0]?.artwork
4544
4597
  }));
4545
4598
  }
4599
+ if (pluginCreators2.watermark && config.watermark) {
4600
+ plugins.push(pluginCreators2.watermark(config.watermark));
4601
+ }
4602
+ if (pluginCreators2.captions) {
4603
+ plugins.push(pluginCreators2.captions(config.captions || {}));
4604
+ }
4546
4605
  if (pluginCreators2.analytics && config.analytics?.beaconUrl) {
4547
4606
  plugins.push(pluginCreators2.analytics({
4548
4607
  beaconUrl: config.analytics.beaconUrl,
@@ -4660,7 +4719,7 @@ function setupAutoInit(pluginCreators2, availableTypes) {
4660
4719
  }
4661
4720
  }
4662
4721
  }
4663
- const VERSION = "0.3.0-audio";
4722
+ const VERSION = "0.5.3-audio";
4664
4723
  const AVAILABLE_TYPES = ["audio", "audio-mini"];
4665
4724
  const pluginCreators = {
4666
4725
  hls: createHLSPlugin,