eb-player 2.0.1 → 2.0.4
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/build/eb-player.css +792 -9
- package/dist/build/ebplayer.bundle.js +215 -60
- package/dist/build/ebplayer.bundle.js.map +1 -1
- package/dist/build/theme-forja.css +1 -1
- package/dist/build/theme-lequipe.css +767 -0
- package/dist/build/theme-modern.css +1 -1
- package/dist/build/theme-v2.css +1 -1
- package/dist/build/types/core/config.d.ts +14 -2
- package/dist/build/types/core/config.d.ts.map +1 -1
- package/dist/build/types/core/i18n.d.ts.map +1 -1
- package/dist/build/types/core/index.d.ts +1 -1
- package/dist/build/types/core/index.d.ts.map +1 -1
- package/dist/build/types/core/lifecycle.d.ts.map +1 -1
- package/dist/build/types/eb-player-standalone.d.ts +14 -3
- package/dist/build/types/eb-player-standalone.d.ts.map +1 -1
- package/dist/build/types/engines/hls.d.ts +1 -0
- package/dist/build/types/engines/hls.d.ts.map +1 -1
- package/dist/build/types/engines/snapshot/hls.d.ts +1 -1
- package/dist/build/types/engines/snapshot/hls.d.ts.map +1 -1
- package/dist/build/types/integrations/p2p-manager.d.ts.map +1 -1
- package/dist/build/types/skin/controls/seekbar.d.ts.map +1 -1
- package/dist/build/types/skin/controls/settings-panel.d.ts +8 -0
- package/dist/build/types/skin/controls/settings-panel.d.ts.map +1 -1
- package/dist/dev/default.js +734 -508
- package/dist/dev/default.js.map +1 -1
- package/dist/dev/easybroadcast.js +266 -88
- package/dist/dev/easybroadcast.js.map +1 -1
- package/dist/dev/equipe.js +6683 -0
- package/dist/dev/equipe.js.map +1 -0
- package/dist/eb-player.css +792 -9
- package/dist/players/easybroadcast/easybroadcast.js +397 -0
- package/dist/players/easybroadcast/index.html +1 -0
- package/dist/players/equipe/EB_lequipe-preprod.js +385 -0
- package/dist/players/equipe/equipe.js +385 -0
- package/dist/players/equipe/index.html +1 -0
- package/dist/players/forja/forja.js +198 -111
- package/dist/players/forja/index.html +1 -1
- package/dist/theme-forja.css +1 -1
- package/dist/theme-lequipe.css +767 -0
- package/dist/theme-modern.css +1 -1
- package/dist/theme-v2.css +1 -1
- package/package.json +8 -73
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.EBPlayer = {}));
|
|
5
5
|
})(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
|
+
var __EB_PLAYER_VERSION__ = "2.0.4";
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* Finite State Machine for player playback state transitions.
|
|
9
11
|
*
|
|
@@ -274,28 +276,61 @@
|
|
|
274
276
|
right: ['forward']
|
|
275
277
|
}
|
|
276
278
|
};
|
|
279
|
+
/**
|
|
280
|
+
* Available themes — single source of truth for all theme names and labels.
|
|
281
|
+
* The test player reads this to populate the skin selector dynamically.
|
|
282
|
+
* Add new entries here when creating a new theme-*.css file.
|
|
283
|
+
*/
|
|
284
|
+
const AVAILABLE_THEMES = [
|
|
285
|
+
{ value: 'default', label: 'Default' },
|
|
286
|
+
{ value: 'forja', label: 'Forja', primaryColor: '#FC013B' },
|
|
287
|
+
{ value: 'radio', label: 'Radio', primaryColor: '#F4A261' },
|
|
288
|
+
{ value: 'snrt', label: 'SNRT', primaryColor: '#006633' },
|
|
289
|
+
{ value: 'modern', label: 'Modern', primaryColor: '#7c3aed' },
|
|
290
|
+
{ value: 'v2', label: 'V2', primaryColor: '#ff841f' },
|
|
291
|
+
{ value: 'lequipe', label: "L'Equipe", primaryColor: '#d61e00' },
|
|
292
|
+
];
|
|
277
293
|
/**
|
|
278
294
|
* Theme-specific default layouts.
|
|
279
295
|
* Used when config.layout is not explicitly provided but a theme is set.
|
|
280
296
|
*/
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
+
const V2_LAYOUT = {
|
|
298
|
+
topBar: {
|
|
299
|
+
left: [],
|
|
300
|
+
right: ['settings', 'pip', 'cast']
|
|
301
|
+
},
|
|
302
|
+
bottomBar: {
|
|
303
|
+
left: ['play-pause', 'live-sync', 'time'],
|
|
304
|
+
center: ['seekbar'],
|
|
305
|
+
right: ['volume', 'fullscreen']
|
|
306
|
+
},
|
|
307
|
+
middleBar: {
|
|
308
|
+
left: ['rewind'],
|
|
309
|
+
center: [],
|
|
310
|
+
right: ['forward']
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
const LEQUIPE_LAYOUT = {
|
|
314
|
+
topBar: {
|
|
315
|
+
left: [],
|
|
316
|
+
right: ['pip', 'settings']
|
|
317
|
+
},
|
|
318
|
+
bottomBar: {
|
|
319
|
+
left: ['play-pause', 'live-sync', 'time'],
|
|
320
|
+
center: ['seekbar'],
|
|
321
|
+
right: ['volume', 'fullscreen']
|
|
322
|
+
},
|
|
323
|
+
middleBar: {
|
|
324
|
+
left: ['rewind'],
|
|
325
|
+
center: [],
|
|
326
|
+
right: ['forward']
|
|
297
327
|
}
|
|
298
328
|
};
|
|
329
|
+
const THEME_LAYOUTS = {
|
|
330
|
+
v2: V2_LAYOUT,
|
|
331
|
+
lequipe: LEQUIPE_LAYOUT,
|
|
332
|
+
modern: V2_LAYOUT,
|
|
333
|
+
};
|
|
299
334
|
/**
|
|
300
335
|
* Returns the effective layout for a given config.
|
|
301
336
|
* Priority: explicit config.layout > theme default > DEFAULT_LAYOUT
|
|
@@ -515,6 +550,30 @@
|
|
|
515
550
|
fr: 'La diffusion a échoué. Reprise de la lecture locale.',
|
|
516
551
|
ar: 'Casting failed. Resuming local playback.',
|
|
517
552
|
es: 'Error en la transmisión. Reanudando la reproducción local.'
|
|
553
|
+
},
|
|
554
|
+
'settings.audio': {
|
|
555
|
+
en: 'Audio track', fr: 'Piste audio', ar: 'مسار صوتي', es: 'Pista de audio'
|
|
556
|
+
},
|
|
557
|
+
'settings.subtitles': {
|
|
558
|
+
en: 'Subtitles', fr: 'Sous-titres', ar: 'ترجمات', es: 'Subtítulos'
|
|
559
|
+
},
|
|
560
|
+
'settings.speed': {
|
|
561
|
+
en: 'Playback speed', fr: 'Vitesse de lecture', ar: 'سرعة التشغيل', es: 'Velocidad'
|
|
562
|
+
},
|
|
563
|
+
'settings.quality': {
|
|
564
|
+
en: 'Quality', fr: 'Qualité', ar: 'الجودة', es: 'Calidad'
|
|
565
|
+
},
|
|
566
|
+
'settings.default': {
|
|
567
|
+
en: 'Default', fr: 'Défaut', ar: 'افتراضي', es: 'Predeterminado'
|
|
568
|
+
},
|
|
569
|
+
'settings.off': {
|
|
570
|
+
en: 'Off', fr: 'Désactivés', ar: 'إيقاف', es: 'Desactivado'
|
|
571
|
+
},
|
|
572
|
+
'settings.normal': {
|
|
573
|
+
en: 'Normal', fr: 'Normale', ar: 'عادي', es: 'Normal'
|
|
574
|
+
},
|
|
575
|
+
'settings.auto': {
|
|
576
|
+
en: 'Auto', fr: 'Auto', ar: 'تلقائي', es: 'Auto'
|
|
518
577
|
}
|
|
519
578
|
};
|
|
520
579
|
/**
|
|
@@ -1313,8 +1372,14 @@
|
|
|
1313
1372
|
const trackEl = event.currentTarget;
|
|
1314
1373
|
this.dragValue = this.eventToTime(event, trackEl);
|
|
1315
1374
|
this.scheduleRender();
|
|
1375
|
+
// During drag with pointer capture, only update tooltip when pointer is within track bounds
|
|
1376
|
+
const rect = trackEl.getBoundingClientRect();
|
|
1377
|
+
if (event.clientX >= rect.left && event.clientX <= rect.right) {
|
|
1378
|
+
this.updateTooltip(event);
|
|
1379
|
+
}
|
|
1380
|
+
return;
|
|
1316
1381
|
}
|
|
1317
|
-
// Always update tooltip on pointermove over the track
|
|
1382
|
+
// Always update tooltip on pointermove over the track when not dragging
|
|
1318
1383
|
this.updateTooltip(event);
|
|
1319
1384
|
}
|
|
1320
1385
|
handlePointerUp(event) {
|
|
@@ -1324,6 +1389,11 @@
|
|
|
1324
1389
|
const seekTime = this.eventToTime(event, trackEl);
|
|
1325
1390
|
this.isDragging = false;
|
|
1326
1391
|
this.bus.emit('seek', { time: seekTime });
|
|
1392
|
+
// Hide tooltip if pointer is outside the track bounds after drag ends
|
|
1393
|
+
const rect = trackEl.getBoundingClientRect();
|
|
1394
|
+
if (event.clientX < rect.left || event.clientX > rect.right) {
|
|
1395
|
+
this.tooltipVisible = false;
|
|
1396
|
+
}
|
|
1327
1397
|
this.render();
|
|
1328
1398
|
}
|
|
1329
1399
|
handlePointerLeave() {
|
|
@@ -1638,16 +1708,20 @@
|
|
|
1638
1708
|
this.mode = 'root';
|
|
1639
1709
|
this.verticalDir = 'up';
|
|
1640
1710
|
this.horizontalDir = 'right';
|
|
1711
|
+
this.outsideClickHandler = null;
|
|
1712
|
+
this.outsideClickTimer = null;
|
|
1641
1713
|
}
|
|
1642
1714
|
onConnect() {
|
|
1643
1715
|
this.state.on('settingsOpen', () => {
|
|
1644
1716
|
// When settings close, reset to root mode
|
|
1645
1717
|
if (!this.state.settingsOpen) {
|
|
1646
1718
|
this.mode = 'root';
|
|
1719
|
+
this.removeOutsideClickListener();
|
|
1647
1720
|
}
|
|
1648
1721
|
else {
|
|
1649
1722
|
// Compute placement when opening
|
|
1650
1723
|
this.computePlacement();
|
|
1724
|
+
this.addOutsideClickListener();
|
|
1651
1725
|
}
|
|
1652
1726
|
this.render();
|
|
1653
1727
|
}, { signal: this.signal });
|
|
@@ -1658,6 +1732,8 @@
|
|
|
1658
1732
|
this.state.on('subtitleTracks', () => this.render(), { signal: this.signal });
|
|
1659
1733
|
this.state.on('currentSubtitleTrack', () => this.render(), { signal: this.signal });
|
|
1660
1734
|
this.state.on('playbackRate', () => this.render(), { signal: this.signal });
|
|
1735
|
+
// Clean up outside-click listener when component disconnects
|
|
1736
|
+
this.signal.addEventListener('abort', () => this.removeOutsideClickListener());
|
|
1661
1737
|
this.render();
|
|
1662
1738
|
}
|
|
1663
1739
|
/**
|
|
@@ -1685,53 +1761,76 @@
|
|
|
1685
1761
|
this.mode = 'root';
|
|
1686
1762
|
this.render();
|
|
1687
1763
|
}
|
|
1764
|
+
/**
|
|
1765
|
+
* Returns the display label for the currently selected value in a category.
|
|
1766
|
+
*/
|
|
1767
|
+
currentValueLabel(mode) {
|
|
1768
|
+
const i18n = this.i18n;
|
|
1769
|
+
if (mode === 'quality') {
|
|
1770
|
+
const levels = this.state.qualityLevels;
|
|
1771
|
+
const current = this.state.currentQuality;
|
|
1772
|
+
if (current === -1)
|
|
1773
|
+
return i18n.t('settings.auto');
|
|
1774
|
+
const level = levels[current];
|
|
1775
|
+
return level?.height ? `${level.height}p` : i18n.t('settings.auto');
|
|
1776
|
+
}
|
|
1777
|
+
if (mode === 'speed') {
|
|
1778
|
+
const rate = this.state.playbackRate;
|
|
1779
|
+
return rate === 1 ? i18n.t('settings.normal') : `${rate}x`;
|
|
1780
|
+
}
|
|
1781
|
+
if (mode === 'audio') {
|
|
1782
|
+
const tracks = this.state.audioTracks;
|
|
1783
|
+
const current = this.state.currentAudioTrack;
|
|
1784
|
+
const track = tracks[current];
|
|
1785
|
+
return track?.name || track?.lang || i18n.t('settings.default');
|
|
1786
|
+
}
|
|
1787
|
+
if (mode === 'subtitles') {
|
|
1788
|
+
const current = this.state.currentSubtitleTrack;
|
|
1789
|
+
if (current === -1)
|
|
1790
|
+
return i18n.t('settings.off');
|
|
1791
|
+
const tracks = this.state.subtitleTracks;
|
|
1792
|
+
const track = tracks[current];
|
|
1793
|
+
return track?.name || track?.lang || `Track ${current}`;
|
|
1794
|
+
}
|
|
1795
|
+
return '';
|
|
1796
|
+
}
|
|
1688
1797
|
renderRootMenu() {
|
|
1689
1798
|
const qualityLevels = this.state.qualityLevels;
|
|
1690
1799
|
const audioTracks = this.state.audioTracks;
|
|
1691
1800
|
const subtitleTracks = this.state.subtitleTracks;
|
|
1801
|
+
const i18n = this.i18n;
|
|
1692
1802
|
const showQuality = qualityLevels.length > 0;
|
|
1693
1803
|
const showSpeed = this.config.speed === true;
|
|
1694
1804
|
const showAudio = audioTracks.length > 1;
|
|
1695
1805
|
const showSubtitles = subtitleTracks.length > 0;
|
|
1806
|
+
const row = (iconName, label, value, mode) => b `
|
|
1807
|
+
<li>
|
|
1808
|
+
<button class="eb-settings-category" @click="${() => this.navigateTo(mode)}">
|
|
1809
|
+
<span class="eb-settings-category__icon">${icon(iconName)}</span>
|
|
1810
|
+
<span class="eb-settings-category__label">${label}</span>
|
|
1811
|
+
<span class="eb-settings-category__value">${value}</span>
|
|
1812
|
+
<span class="eb-settings-category__chevron">${icon('chevron-right')}</span>
|
|
1813
|
+
</button>
|
|
1814
|
+
</li>
|
|
1815
|
+
`;
|
|
1696
1816
|
return b `
|
|
1697
1817
|
<ul class="eb-settings-menu eb-settings-root">
|
|
1698
|
-
${
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
</button>
|
|
1703
|
-
</li>
|
|
1704
|
-
` : ''}
|
|
1705
|
-
${showSpeed ? b `
|
|
1706
|
-
<li>
|
|
1707
|
-
<button class="eb-settings-category" @click="${() => this.navigateTo('speed')}">
|
|
1708
|
-
Speed
|
|
1709
|
-
</button>
|
|
1710
|
-
</li>
|
|
1711
|
-
` : ''}
|
|
1712
|
-
${showAudio ? b `
|
|
1713
|
-
<li>
|
|
1714
|
-
<button class="eb-settings-category" @click="${() => this.navigateTo('audio')}">
|
|
1715
|
-
Audio
|
|
1716
|
-
</button>
|
|
1717
|
-
</li>
|
|
1718
|
-
` : ''}
|
|
1719
|
-
${showSubtitles ? b `
|
|
1720
|
-
<li>
|
|
1721
|
-
<button class="eb-settings-category" @click="${() => this.navigateTo('subtitles')}">
|
|
1722
|
-
Subtitles
|
|
1723
|
-
</button>
|
|
1724
|
-
</li>
|
|
1725
|
-
` : ''}
|
|
1818
|
+
${showAudio ? row('audio', i18n.t('settings.audio'), this.currentValueLabel('audio'), 'audio') : ''}
|
|
1819
|
+
${showSubtitles ? row('subtitle', i18n.t('settings.subtitles'), this.currentValueLabel('subtitles'), 'subtitles') : ''}
|
|
1820
|
+
${showSpeed ? row('speed', i18n.t('settings.speed'), this.currentValueLabel('speed'), 'speed') : ''}
|
|
1821
|
+
${showQuality ? row('quality', i18n.t('settings.quality'), this.currentValueLabel('quality'), 'quality') : ''}
|
|
1726
1822
|
</ul>
|
|
1727
1823
|
`;
|
|
1728
1824
|
}
|
|
1729
1825
|
renderSubMenu(title, items, onSelect) {
|
|
1730
1826
|
return b `
|
|
1731
1827
|
<div class="eb-settings-submenu">
|
|
1732
|
-
<
|
|
1733
|
-
${
|
|
1734
|
-
|
|
1828
|
+
<div class="eb-settings-header">
|
|
1829
|
+
<button class="eb-settings-back" @click="${() => this.navigateBack()}">
|
|
1830
|
+
${icon('chevron-left')}
|
|
1831
|
+
</button>
|
|
1832
|
+
<span class="eb-settings-header__title">${title}</span>
|
|
1833
|
+
</div>
|
|
1735
1834
|
<ul class="eb-settings-menu">
|
|
1736
1835
|
${items.map((item) => b `
|
|
1737
1836
|
<li>
|
|
@@ -1751,14 +1850,14 @@
|
|
|
1751
1850
|
const levels = this.state.qualityLevels;
|
|
1752
1851
|
const currentQuality = this.state.currentQuality;
|
|
1753
1852
|
const items = getQualityItems(levels, currentQuality);
|
|
1754
|
-
return this.renderSubMenu('
|
|
1853
|
+
return this.renderSubMenu(this.i18n.t('settings.quality'), items, (item) => {
|
|
1755
1854
|
this.bus.emit('settings-select-quality', { index: item.value });
|
|
1756
1855
|
});
|
|
1757
1856
|
}
|
|
1758
1857
|
renderSpeedMenu() {
|
|
1759
1858
|
const currentRate = this.state.playbackRate;
|
|
1760
1859
|
const items = getSpeedItems(currentRate);
|
|
1761
|
-
return this.renderSubMenu('
|
|
1860
|
+
return this.renderSubMenu(this.i18n.t('settings.speed'), items, (item) => {
|
|
1762
1861
|
this.bus.emit('settings-select-speed', { rate: item.value });
|
|
1763
1862
|
});
|
|
1764
1863
|
}
|
|
@@ -1766,7 +1865,7 @@
|
|
|
1766
1865
|
const tracks = this.state.audioTracks;
|
|
1767
1866
|
const currentTrack = this.state.currentAudioTrack;
|
|
1768
1867
|
const items = getAudioItems(tracks, currentTrack);
|
|
1769
|
-
return this.renderSubMenu('
|
|
1868
|
+
return this.renderSubMenu(this.i18n.t('settings.audio'), items, (item) => {
|
|
1770
1869
|
this.bus.emit('settings-select-audio', { index: item.value });
|
|
1771
1870
|
});
|
|
1772
1871
|
}
|
|
@@ -1774,10 +1873,37 @@
|
|
|
1774
1873
|
const tracks = this.state.subtitleTracks;
|
|
1775
1874
|
const currentTrack = this.state.currentSubtitleTrack;
|
|
1776
1875
|
const items = getSubtitleItems(tracks, currentTrack);
|
|
1777
|
-
return this.renderSubMenu('
|
|
1876
|
+
return this.renderSubMenu(this.i18n.t('settings.subtitles'), items, (item) => {
|
|
1778
1877
|
this.bus.emit('settings-select-subtitle', { index: item.value });
|
|
1779
1878
|
});
|
|
1780
1879
|
}
|
|
1880
|
+
addOutsideClickListener() {
|
|
1881
|
+
this.removeOutsideClickListener();
|
|
1882
|
+
// Defer to next tick so the opening click doesn't immediately close
|
|
1883
|
+
this.outsideClickTimer = setTimeout(() => {
|
|
1884
|
+
this.outsideClickTimer = null;
|
|
1885
|
+
// Guard: panel may have closed before this timer fires
|
|
1886
|
+
if (!this.state?.settingsOpen)
|
|
1887
|
+
return;
|
|
1888
|
+
this.outsideClickHandler = (event) => {
|
|
1889
|
+
const wrapper = this.el?.querySelector('.eb-settings-wrapper');
|
|
1890
|
+
if (wrapper && !wrapper.contains(event.target)) {
|
|
1891
|
+
this.state.settingsOpen = false;
|
|
1892
|
+
}
|
|
1893
|
+
};
|
|
1894
|
+
document.addEventListener('click', this.outsideClickHandler, { capture: true });
|
|
1895
|
+
}, 0);
|
|
1896
|
+
}
|
|
1897
|
+
removeOutsideClickListener() {
|
|
1898
|
+
if (this.outsideClickTimer !== null) {
|
|
1899
|
+
clearTimeout(this.outsideClickTimer);
|
|
1900
|
+
this.outsideClickTimer = null;
|
|
1901
|
+
}
|
|
1902
|
+
if (this.outsideClickHandler !== null) {
|
|
1903
|
+
document.removeEventListener('click', this.outsideClickHandler, { capture: true });
|
|
1904
|
+
this.outsideClickHandler = null;
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1781
1907
|
toggleSettings() {
|
|
1782
1908
|
this.state.settingsOpen = !this.state.settingsOpen;
|
|
1783
1909
|
}
|
|
@@ -3642,6 +3768,13 @@
|
|
|
3642
3768
|
*/
|
|
3643
3769
|
mount(container) {
|
|
3644
3770
|
this._container = container;
|
|
3771
|
+
// Clear container DOM so a fresh <video> element is created on each mount.
|
|
3772
|
+
// This prevents EME/MediaKeys conflicts — setMediaKeys(null) is async and
|
|
3773
|
+
// hls.js destroy() doesn't wait for it, so reusing the same <video> element
|
|
3774
|
+
// causes "The existing ContentDecryptor" errors on skin switch.
|
|
3775
|
+
container.textContent = '';
|
|
3776
|
+
// Clear lit-html's internal render state so render() treats the container as fresh
|
|
3777
|
+
delete container['_$litPart$'];
|
|
3645
3778
|
// Clear any stale theme/style from a previous mount cycle
|
|
3646
3779
|
container.removeAttribute('data-theme');
|
|
3647
3780
|
container.removeAttribute('style');
|
|
@@ -4857,6 +4990,7 @@
|
|
|
4857
4990
|
// Private — NEVER in PlayerState (Pitfall 2)
|
|
4858
4991
|
this.driver = null;
|
|
4859
4992
|
this.tokenManager = null;
|
|
4993
|
+
this.autoQuality = true;
|
|
4860
4994
|
// Holds state reference for named driver event handlers
|
|
4861
4995
|
this.eventState = null;
|
|
4862
4996
|
this.liveSyncDisabled = false;
|
|
@@ -4916,6 +5050,14 @@
|
|
|
4916
5050
|
if (this.driver === null)
|
|
4917
5051
|
return;
|
|
4918
5052
|
this.driver.currentLevel = index;
|
|
5053
|
+
// When index is -1 (Auto/ABR), hls.js will fire LEVEL_SWITCHED with the
|
|
5054
|
+
// actual resolved level. We need to keep currentQuality as -1 so the UI
|
|
5055
|
+
// shows "Auto" as selected. Track ABR mode to prevent LEVEL_SWITCHED
|
|
5056
|
+
// from overwriting it.
|
|
5057
|
+
this.autoQuality = index === -1;
|
|
5058
|
+
if (this.state !== null) {
|
|
5059
|
+
this.state.currentQuality = index;
|
|
5060
|
+
}
|
|
4919
5061
|
}
|
|
4920
5062
|
setAudioTrack(index) {
|
|
4921
5063
|
if (this.driver === null)
|
|
@@ -4977,7 +5119,7 @@
|
|
|
4977
5119
|
token: config.token,
|
|
4978
5120
|
tokenType: config.tokenType,
|
|
4979
5121
|
srcInTokenRequest: config.srcInTokenRequest,
|
|
4980
|
-
extraParamsCallback: config.extraParamsCallback,
|
|
5122
|
+
extraParamsCallback: (config.engineSettings.extraParamsCallback ?? config.extraParamsCallback),
|
|
4981
5123
|
onCDNTokenError: config.engineSettings.onCDNTokenError
|
|
4982
5124
|
});
|
|
4983
5125
|
// Fetch initial token
|
|
@@ -4988,7 +5130,7 @@
|
|
|
4988
5130
|
if (this.detached)
|
|
4989
5131
|
return;
|
|
4990
5132
|
}
|
|
4991
|
-
console.info('HlsEngine: loading hls.js from', hlsjsUrl)
|
|
5133
|
+
// console.info('HlsEngine: loading hls.js from', hlsjsUrl)
|
|
4992
5134
|
const Hls = await loadScript(hlsjsUrl, 'Hls');
|
|
4993
5135
|
// Guard: abort if detached during CDN script load
|
|
4994
5136
|
if (this.detached)
|
|
@@ -5001,7 +5143,7 @@
|
|
|
5001
5143
|
// Build driver config — only spread known engineSettings keys that hls.js recognises,
|
|
5002
5144
|
// not the entire engineSettings bag (which may contain player-specific keys like
|
|
5003
5145
|
// extraParamsCallback that should NOT leak into the hls.js constructor config).
|
|
5004
|
-
const { emeEnabled, drmSystems, ...hlsEngineSettings } = config.engineSettings;
|
|
5146
|
+
const { emeEnabled: _emeEnabled, drmSystems: _drmSystems, ...hlsEngineSettings } = config.engineSettings;
|
|
5005
5147
|
// Remove player-specific keys that are NOT hls.js config options
|
|
5006
5148
|
const hlsSafeSettings = { ...hlsEngineSettings };
|
|
5007
5149
|
delete hlsSafeSettings['extraParamsCallback'];
|
|
@@ -5145,8 +5287,12 @@
|
|
|
5145
5287
|
const state = this.eventState;
|
|
5146
5288
|
if (!state)
|
|
5147
5289
|
return;
|
|
5148
|
-
|
|
5149
|
-
|
|
5290
|
+
// In ABR mode (autoQuality), keep currentQuality as -1 so the UI shows "Auto".
|
|
5291
|
+
// Only update to the actual level index when the user picked a specific quality.
|
|
5292
|
+
if (!this.autoQuality) {
|
|
5293
|
+
const switchedData = data;
|
|
5294
|
+
state.currentQuality = switchedData.level;
|
|
5295
|
+
}
|
|
5150
5296
|
}
|
|
5151
5297
|
_onAudioTracksUpdated(_event, data) {
|
|
5152
5298
|
const state = this.eventState;
|
|
@@ -5525,7 +5671,7 @@
|
|
|
5525
5671
|
};
|
|
5526
5672
|
// Register with AbortSignal so it auto-removes when engine is detached
|
|
5527
5673
|
window.addEventListener('unhandledrejection', this.dvrErrorHandler, { signal });
|
|
5528
|
-
console.info('DashEngine: loading dashjs from', dashjsUrl)
|
|
5674
|
+
// console.info('DashEngine: loading dashjs from', dashjsUrl)
|
|
5529
5675
|
const dashjs = await loadScript(dashjsUrl, 'dashjs');
|
|
5530
5676
|
const player = dashjs.MediaPlayer().create();
|
|
5531
5677
|
if (!player) {
|
|
@@ -5691,7 +5837,9 @@
|
|
|
5691
5837
|
this.lib.start();
|
|
5692
5838
|
// Clean up on abort
|
|
5693
5839
|
signal.addEventListener('abort', () => {
|
|
5694
|
-
this.lib.stop
|
|
5840
|
+
if (this.lib !== null && typeof this.lib.stop === 'function') {
|
|
5841
|
+
this.lib.stop();
|
|
5842
|
+
}
|
|
5695
5843
|
this.lib = null;
|
|
5696
5844
|
}, { once: true });
|
|
5697
5845
|
}
|
|
@@ -6187,10 +6335,17 @@
|
|
|
6187
6335
|
}
|
|
6188
6336
|
}
|
|
6189
6337
|
// ---------------------------------------------------------------------------
|
|
6338
|
+
// Version
|
|
6339
|
+
// ---------------------------------------------------------------------------
|
|
6340
|
+
// Injected at build time by Rollup's @rollup/plugin-virtual or replaced by bundler.
|
|
6341
|
+
// Falls back to 'dev' when running unbundled (tests, dev server).
|
|
6342
|
+
const VERSION = typeof __EB_PLAYER_VERSION__ !== 'undefined' ? __EB_PLAYER_VERSION__ : 'dev';
|
|
6343
|
+
// ---------------------------------------------------------------------------
|
|
6190
6344
|
// window.EBPlayer assignment
|
|
6191
6345
|
// ---------------------------------------------------------------------------
|
|
6192
6346
|
if (typeof window !== 'undefined') {
|
|
6193
|
-
|
|
6347
|
+
console.info(`%cEBPlayer v${VERSION}`, 'color: #1FA9DD; font-weight: bold');
|
|
6348
|
+
window.EBPlayer = { start, stop, destroy, AVAILABLE_THEMES, THEME_LAYOUTS, version: VERSION };
|
|
6194
6349
|
}
|
|
6195
6350
|
|
|
6196
6351
|
/**
|