vidply 1.0.32 → 1.0.34
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/README.md +7 -7
- package/dist/dev/{vidply.HLSRenderer-5MJZR4D2.js → vidply.HLSRenderer-YGWCAICA.js} +49 -4
- package/dist/dev/vidply.HLSRenderer-YGWCAICA.js.map +7 -0
- package/dist/dev/{vidply.HTML5Renderer-FXBZQL6Y.js → vidply.HTML5Renderer-PMNFHAKW.js} +3 -3
- package/dist/dev/{vidply.SoundCloudRenderer-CD7VJKNS.js → vidply.SoundCloudRenderer-RIA3QKP3.js} +2 -2
- package/dist/dev/{vidply.TranscriptManager-T677KF4N.js → vidply.TranscriptManager-T3BVTZHZ.js} +3 -3
- package/dist/dev/{vidply.VimeoRenderer-VPH4RNES.js → vidply.VimeoRenderer-DY2FG7LZ.js} +2 -2
- package/dist/dev/{vidply.YouTubeRenderer-6MGKEFTZ.js → vidply.YouTubeRenderer-EVXXE34A.js} +2 -2
- package/dist/dev/{vidply.chunk-GS2JX5RQ.js → vidply.chunk-74NJTDQI.js} +9 -6
- package/dist/dev/vidply.chunk-74NJTDQI.js.map +7 -0
- package/dist/dev/{vidply.chunk-W2LSBD6Y.js → vidply.chunk-IIN4G4UQ.js} +34 -4
- package/dist/dev/vidply.chunk-IIN4G4UQ.js.map +7 -0
- package/dist/dev/{vidply.de-SNL6AJ4D.js → vidply.de-YBEYEXBL.js} +5 -2
- package/dist/dev/vidply.de-YBEYEXBL.js.map +7 -0
- package/dist/dev/{vidply.es-2QCQKZ4U.js → vidply.es-QA4YSA5S.js} +2 -2
- package/dist/dev/vidply.esm.js +389 -82
- package/dist/dev/vidply.esm.js.map +2 -2
- package/dist/dev/{vidply.fr-FJAZRL4L.js → vidply.fr-LAM3XJZI.js} +2 -2
- package/dist/dev/{vidply.ja-2XQOW53T.js → vidply.ja-FTBFZD66.js} +2 -2
- package/dist/legacy/vidply.js +482 -79
- package/dist/legacy/vidply.js.map +3 -3
- package/dist/legacy/vidply.min.js +2 -2
- package/dist/legacy/vidply.min.meta.json +15 -15
- package/dist/prod/vidply.HLSRenderer-D2KTBEEI.min.js +6 -0
- package/dist/prod/{vidply.HTML5Renderer-KKW3OLHM.min.js → vidply.HTML5Renderer-ZSV6PDOH.min.js} +2 -2
- package/dist/prod/{vidply.SoundCloudRenderer-MOR2CUFH.min.js → vidply.SoundCloudRenderer-BFV5SSIU.min.js} +1 -1
- package/dist/prod/{vidply.TranscriptManager-WFZSW6NR.min.js → vidply.TranscriptManager-GPAOXEK4.min.js} +2 -2
- package/dist/prod/{vidply.VimeoRenderer-3HBMM2WR.min.js → vidply.VimeoRenderer-UQWHQ4LC.min.js} +1 -1
- package/dist/prod/{vidply.YouTubeRenderer-MFC2GMAC.min.js → vidply.YouTubeRenderer-K7A57ICA.min.js} +1 -1
- package/dist/prod/vidply.chunk-OM7DNW5P.min.js +6 -0
- package/dist/prod/vidply.chunk-SQVOYVKH.min.js +6 -0
- package/dist/prod/vidply.de-WCUZUF3T.min.js +6 -0
- package/dist/prod/{vidply.es-3IJCQLJ7.min.js → vidply.es-54CIIDMO.min.js} +1 -1
- package/dist/prod/vidply.esm.min.js +5 -5
- package/dist/prod/{vidply.fr-NC4VEAPH.min.js → vidply.fr-7FYGFFK2.min.js} +1 -1
- package/dist/prod/{vidply.ja-4ZC6ZQLV.min.js → vidply.ja-E4UTAURP.min.js} +1 -1
- package/dist/vidply.css +1 -1
- package/dist/vidply.esm.min.meta.json +45 -45
- package/dist/vidply.min.css +1 -1
- package/package.json +1 -1
- package/src/controls/ControlBar.js +104 -70
- package/src/core/Player.js +217 -3
- package/src/features/PlaylistManager.js +206 -36
- package/src/i18n/languages/de.js +3 -0
- package/src/i18n/languages/en.js +3 -0
- package/src/renderers/HLSRenderer.js +60 -1
- package/src/renderers/HTML5Renderer.js +43 -5
- package/dist/dev/vidply.HLSRenderer-5MJZR4D2.js.map +0 -7
- package/dist/dev/vidply.chunk-GS2JX5RQ.js.map +0 -7
- package/dist/dev/vidply.chunk-W2LSBD6Y.js.map +0 -7
- package/dist/dev/vidply.de-SNL6AJ4D.js.map +0 -7
- package/dist/prod/vidply.HLSRenderer-VWNJD2CB.min.js +0 -6
- package/dist/prod/vidply.chunk-34RH2THY.min.js +0 -6
- package/dist/prod/vidply.chunk-LGTJRPUL.min.js +0 -6
- package/dist/prod/vidply.de-FR3XX54P.min.js +0 -6
- /package/dist/dev/{vidply.HTML5Renderer-FXBZQL6Y.js.map → vidply.HTML5Renderer-PMNFHAKW.js.map} +0 -0
- /package/dist/dev/{vidply.SoundCloudRenderer-CD7VJKNS.js.map → vidply.SoundCloudRenderer-RIA3QKP3.js.map} +0 -0
- /package/dist/dev/{vidply.TranscriptManager-T677KF4N.js.map → vidply.TranscriptManager-T3BVTZHZ.js.map} +0 -0
- /package/dist/dev/{vidply.VimeoRenderer-VPH4RNES.js.map → vidply.VimeoRenderer-DY2FG7LZ.js.map} +0 -0
- /package/dist/dev/{vidply.YouTubeRenderer-6MGKEFTZ.js.map → vidply.YouTubeRenderer-EVXXE34A.js.map} +0 -0
- /package/dist/dev/{vidply.es-2QCQKZ4U.js.map → vidply.es-QA4YSA5S.js.map} +0 -0
- /package/dist/dev/{vidply.fr-FJAZRL4L.js.map → vidply.fr-LAM3XJZI.js.map} +0 -0
- /package/dist/dev/{vidply.ja-2XQOW53T.js.map → vidply.ja-FTBFZD66.js.map} +0 -0
package/dist/legacy/vidply.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Universal, Accessible Video Player
|
|
3
|
-
* (c)
|
|
3
|
+
* (c) 2026 Matthias Peltzer
|
|
4
4
|
* Released under GPL-2.0-or-later License
|
|
5
5
|
*/
|
|
6
6
|
(() => {
|
|
@@ -296,6 +296,9 @@
|
|
|
296
296
|
signLanguageVideo: "Sign Language Video",
|
|
297
297
|
closeSignLanguage: "Close sign language video",
|
|
298
298
|
signLanguageSettings: "Sign language settings",
|
|
299
|
+
startPlaybackFirst: "Please start playback first.",
|
|
300
|
+
startPlaybackForAudioDescription: "Please start playback first to use audio description.",
|
|
301
|
+
startPlaybackForSignLanguage: "Please start playback first to use sign language video.",
|
|
299
302
|
noChapters: "No chapters available",
|
|
300
303
|
noCaptions: "No captions available",
|
|
301
304
|
auto: "Auto",
|
|
@@ -484,6 +487,9 @@
|
|
|
484
487
|
signLanguageVideo: "Gebärdensprache-Video",
|
|
485
488
|
closeSignLanguage: "Gebärdensprache-Video schließen",
|
|
486
489
|
signLanguageSettings: "Gebärdensprache-Einstellungen",
|
|
490
|
+
startPlaybackFirst: "Bitte starten Sie die Wiedergabe zuerst.",
|
|
491
|
+
startPlaybackForAudioDescription: "Bitte starten Sie die Wiedergabe zuerst, um die Audiodeskription zu nutzen.",
|
|
492
|
+
startPlaybackForSignLanguage: "Bitte starten Sie die Wiedergabe zuerst, um das Gebärdensprache-Video zu nutzen.",
|
|
487
493
|
noChapters: "Keine Kapitel verfügbar",
|
|
488
494
|
noCaptions: "Keine Untertitel verfügbar",
|
|
489
495
|
auto: "Automatisch",
|
|
@@ -1726,13 +1732,18 @@
|
|
|
1726
1732
|
constructor(player) {
|
|
1727
1733
|
this.player = player;
|
|
1728
1734
|
this.media = player.element;
|
|
1735
|
+
this._didDeferredLoad = false;
|
|
1729
1736
|
}
|
|
1730
1737
|
async init() {
|
|
1731
1738
|
this.media.controls = false;
|
|
1732
1739
|
this.media.removeAttribute("controls");
|
|
1733
1740
|
this.attachEvents();
|
|
1734
|
-
|
|
1735
|
-
|
|
1741
|
+
if (this.player.options.deferLoad) {
|
|
1742
|
+
this.media.preload = this.player.options.preload || "none";
|
|
1743
|
+
} else {
|
|
1744
|
+
this.media.preload = this.player.options.preload;
|
|
1745
|
+
this.media.load();
|
|
1746
|
+
}
|
|
1736
1747
|
if (this.player.container) {
|
|
1737
1748
|
this.player.container.classList.remove("vidply-external-controls");
|
|
1738
1749
|
}
|
|
@@ -1839,6 +1850,15 @@
|
|
|
1839
1850
|
play() {
|
|
1840
1851
|
const scrollX = window.scrollX;
|
|
1841
1852
|
const scrollY = window.scrollY;
|
|
1853
|
+
if (this.player.options.deferLoad && !this._didDeferredLoad) {
|
|
1854
|
+
try {
|
|
1855
|
+
if (this.media.readyState === 0) {
|
|
1856
|
+
this.media.load();
|
|
1857
|
+
}
|
|
1858
|
+
} catch (e) {
|
|
1859
|
+
}
|
|
1860
|
+
this._didDeferredLoad = true;
|
|
1861
|
+
}
|
|
1842
1862
|
const promise = this.media.play();
|
|
1843
1863
|
window.scrollTo(scrollX, scrollY);
|
|
1844
1864
|
if (promise !== void 0) {
|
|
@@ -1858,6 +1878,22 @@
|
|
|
1858
1878
|
});
|
|
1859
1879
|
}
|
|
1860
1880
|
}
|
|
1881
|
+
/**
|
|
1882
|
+
* Ensure the media element has been loaded at least once (metadata/initial state)
|
|
1883
|
+
* without starting playback. Useful for playlists to behave like single videos.
|
|
1884
|
+
*/
|
|
1885
|
+
ensureLoaded() {
|
|
1886
|
+
if (!this.player.options.deferLoad || this._didDeferredLoad) {
|
|
1887
|
+
return;
|
|
1888
|
+
}
|
|
1889
|
+
try {
|
|
1890
|
+
if (this.media.readyState === 0) {
|
|
1891
|
+
this.media.load();
|
|
1892
|
+
}
|
|
1893
|
+
} catch (e) {
|
|
1894
|
+
}
|
|
1895
|
+
this._didDeferredLoad = true;
|
|
1896
|
+
}
|
|
1861
1897
|
pause() {
|
|
1862
1898
|
this.media.pause();
|
|
1863
1899
|
}
|
|
@@ -4967,6 +5003,8 @@
|
|
|
4967
5003
|
this.player = player;
|
|
4968
5004
|
this.media = player.element;
|
|
4969
5005
|
this.hls = null;
|
|
5006
|
+
this._hlsSourceLoaded = false;
|
|
5007
|
+
this._pendingSrc = null;
|
|
4970
5008
|
}
|
|
4971
5009
|
async init() {
|
|
4972
5010
|
if (this.canPlayNatively()) {
|
|
@@ -5007,6 +5045,8 @@
|
|
|
5007
5045
|
}
|
|
5008
5046
|
this.hls = new window.Hls({
|
|
5009
5047
|
debug: this.player.options.debug,
|
|
5048
|
+
// When deferLoad is enabled, do not start loading until the first play().
|
|
5049
|
+
autoStartLoad: !this.player.options.deferLoad,
|
|
5010
5050
|
enableWorker: true,
|
|
5011
5051
|
lowLatencyMode: false,
|
|
5012
5052
|
backBufferLength: 90,
|
|
@@ -5042,7 +5082,12 @@
|
|
|
5042
5082
|
if (!src) {
|
|
5043
5083
|
throw new Error("No HLS source found");
|
|
5044
5084
|
}
|
|
5045
|
-
this.
|
|
5085
|
+
if (this.player.options.deferLoad) {
|
|
5086
|
+
this._pendingSrc = src;
|
|
5087
|
+
} else {
|
|
5088
|
+
this.hls.loadSource(src);
|
|
5089
|
+
this._hlsSourceLoaded = true;
|
|
5090
|
+
}
|
|
5046
5091
|
this.attachHlsEvents();
|
|
5047
5092
|
this.attachMediaEvents();
|
|
5048
5093
|
}
|
|
@@ -5161,9 +5206,45 @@
|
|
|
5161
5206
|
this.player.log("Non-fatal HLS error: " + data.details, "warn");
|
|
5162
5207
|
}
|
|
5163
5208
|
}
|
|
5209
|
+
/**
|
|
5210
|
+
* Ensure the HLS manifest/initial loading is started without starting playback.
|
|
5211
|
+
* This makes playlist selection behave more like single-video initialization.
|
|
5212
|
+
*/
|
|
5213
|
+
ensureLoaded() {
|
|
5214
|
+
if (!this.player.options.deferLoad) {
|
|
5215
|
+
return;
|
|
5216
|
+
}
|
|
5217
|
+
if (!this.hls) {
|
|
5218
|
+
return;
|
|
5219
|
+
}
|
|
5220
|
+
if (this._hlsSourceLoaded) {
|
|
5221
|
+
return;
|
|
5222
|
+
}
|
|
5223
|
+
const src = this._pendingSrc || this.player._pendingSource || this.player.currentSource;
|
|
5224
|
+
if (!src) {
|
|
5225
|
+
return;
|
|
5226
|
+
}
|
|
5227
|
+
try {
|
|
5228
|
+
this.hls.loadSource(src);
|
|
5229
|
+
this._hlsSourceLoaded = true;
|
|
5230
|
+
this.hls.startLoad();
|
|
5231
|
+
} catch (e) {
|
|
5232
|
+
}
|
|
5233
|
+
}
|
|
5164
5234
|
play() {
|
|
5165
5235
|
const scrollX = window.scrollX;
|
|
5166
5236
|
const scrollY = window.scrollY;
|
|
5237
|
+
if (this.player.options.deferLoad && this.hls && !this._hlsSourceLoaded) {
|
|
5238
|
+
const src = this._pendingSrc || this.player.currentSource;
|
|
5239
|
+
if (src) {
|
|
5240
|
+
try {
|
|
5241
|
+
this.hls.loadSource(src);
|
|
5242
|
+
this.hls.startLoad();
|
|
5243
|
+
this._hlsSourceLoaded = true;
|
|
5244
|
+
} catch (e) {
|
|
5245
|
+
}
|
|
5246
|
+
}
|
|
5247
|
+
}
|
|
5167
5248
|
const promise = this.media.play();
|
|
5168
5249
|
window.scrollTo(scrollX, scrollY);
|
|
5169
5250
|
if (promise !== void 0) {
|
|
@@ -5683,6 +5764,8 @@
|
|
|
5683
5764
|
init() {
|
|
5684
5765
|
this.createElement();
|
|
5685
5766
|
this.createControls();
|
|
5767
|
+
this.updateDuration();
|
|
5768
|
+
this.updateProgress();
|
|
5686
5769
|
this.attachEvents();
|
|
5687
5770
|
this.setupAutoHide();
|
|
5688
5771
|
this.setupOverflowDetection();
|
|
@@ -6249,20 +6332,32 @@
|
|
|
6249
6332
|
}
|
|
6250
6333
|
// Helper methods to check for available features
|
|
6251
6334
|
hasChapterTracks() {
|
|
6335
|
+
var _a, _b;
|
|
6252
6336
|
const textTracks = this.player.element.textTracks;
|
|
6253
6337
|
for (let i = 0; i < textTracks.length; i++) {
|
|
6254
|
-
if (textTracks[i].kind === "chapters")
|
|
6255
|
-
|
|
6256
|
-
|
|
6338
|
+
if (textTracks[i].kind === "chapters") return true;
|
|
6339
|
+
}
|
|
6340
|
+
const trackEls = Array.from(this.player.element.querySelectorAll('track[kind="chapters"]'));
|
|
6341
|
+
if (trackEls.length > 0) return true;
|
|
6342
|
+
const current = (_b = (_a = this.player.playlistManager) == null ? void 0 : _a.getCurrentTrack) == null ? void 0 : _b.call(_a);
|
|
6343
|
+
if ((current == null ? void 0 : current.tracks) && Array.isArray(current.tracks)) {
|
|
6344
|
+
return current.tracks.some((t) => (t == null ? void 0 : t.kind) === "chapters");
|
|
6257
6345
|
}
|
|
6258
6346
|
return false;
|
|
6259
6347
|
}
|
|
6260
6348
|
hasCaptionTracks() {
|
|
6349
|
+
var _a, _b;
|
|
6261
6350
|
const textTracks = this.player.element.textTracks;
|
|
6262
6351
|
for (let i = 0; i < textTracks.length; i++) {
|
|
6263
|
-
if (textTracks[i].kind === "captions" || textTracks[i].kind === "subtitles")
|
|
6264
|
-
|
|
6265
|
-
|
|
6352
|
+
if (textTracks[i].kind === "captions" || textTracks[i].kind === "subtitles") return true;
|
|
6353
|
+
}
|
|
6354
|
+
const trackEls = Array.from(this.player.element.querySelectorAll("track"));
|
|
6355
|
+
if (trackEls.some((el) => el.getAttribute("kind") === "captions" || el.getAttribute("kind") === "subtitles")) {
|
|
6356
|
+
return true;
|
|
6357
|
+
}
|
|
6358
|
+
const current = (_b = (_a = this.player.playlistManager) == null ? void 0 : _a.getCurrentTrack) == null ? void 0 : _b.call(_a);
|
|
6359
|
+
if ((current == null ? void 0 : current.tracks) && Array.isArray(current.tracks)) {
|
|
6360
|
+
return current.tracks.some((t) => (t == null ? void 0 : t.kind) === "captions" || (t == null ? void 0 : t.kind) === "subtitles");
|
|
6266
6361
|
}
|
|
6267
6362
|
return false;
|
|
6268
6363
|
}
|
|
@@ -6337,55 +6432,65 @@
|
|
|
6337
6432
|
this.currentPreviewTime = null;
|
|
6338
6433
|
this.previewThumbnailTimeout = null;
|
|
6339
6434
|
this.previewSupported = false;
|
|
6435
|
+
this.previewVideoReady = false;
|
|
6436
|
+
this.previewVideoInitialized = false;
|
|
6340
6437
|
const isVideo = this.player.element && this.player.element.tagName === "VIDEO";
|
|
6341
6438
|
if (!isVideo) {
|
|
6342
6439
|
return;
|
|
6343
6440
|
}
|
|
6441
|
+
}
|
|
6442
|
+
/**
|
|
6443
|
+
* Lazily create the hidden preview video (only after playback started once)
|
|
6444
|
+
*/
|
|
6445
|
+
ensurePreviewVideoInitialized() {
|
|
6446
|
+
var _a, _b;
|
|
6447
|
+
if (this.previewVideoInitialized) return;
|
|
6448
|
+
if (!((_b = (_a = this.player) == null ? void 0 : _a.state) == null ? void 0 : _b.hasStartedPlayback)) return;
|
|
6344
6449
|
const renderer = this.player.renderer;
|
|
6345
6450
|
const hasVideoMedia = renderer && renderer.media && renderer.media.tagName === "VIDEO";
|
|
6346
6451
|
const isHTML5Renderer = hasVideoMedia && renderer.media === this.player.element && !renderer.hls && typeof renderer.seek === "function";
|
|
6347
6452
|
this.previewSupported = isHTML5Renderer && hasVideoMedia;
|
|
6348
|
-
if (this.previewSupported)
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
this.previewVideo.style.top = "-9999px";
|
|
6358
|
-
const mainVideo = renderer.media || this.player.element;
|
|
6359
|
-
let videoSrc = null;
|
|
6360
|
-
if (mainVideo.src) {
|
|
6361
|
-
videoSrc = mainVideo.src;
|
|
6362
|
-
} else {
|
|
6363
|
-
const source = mainVideo.querySelector("source");
|
|
6364
|
-
if (source) {
|
|
6365
|
-
videoSrc = source.src;
|
|
6366
|
-
}
|
|
6367
|
-
}
|
|
6368
|
-
if (!videoSrc) {
|
|
6369
|
-
this.player.log("No video source found for preview", "warn");
|
|
6370
|
-
this.previewSupported = false;
|
|
6371
|
-
return;
|
|
6372
|
-
}
|
|
6373
|
-
if (mainVideo.crossOrigin) {
|
|
6374
|
-
this.previewVideo.crossOrigin = mainVideo.crossOrigin;
|
|
6375
|
-
}
|
|
6376
|
-
this.previewVideo.addEventListener("error", (e) => {
|
|
6377
|
-
this.player.log("Preview video failed to load:", e, "warn");
|
|
6378
|
-
this.previewSupported = false;
|
|
6379
|
-
});
|
|
6380
|
-
this.previewVideo.addEventListener("loadedmetadata", () => {
|
|
6381
|
-
this.previewVideoReady = true;
|
|
6382
|
-
}, { once: true });
|
|
6383
|
-
if (this.player.container) {
|
|
6384
|
-
this.player.container.appendChild(this.previewVideo);
|
|
6453
|
+
if (!this.previewSupported) return;
|
|
6454
|
+
const mainVideo = renderer.media || this.player.element;
|
|
6455
|
+
let videoSrc = null;
|
|
6456
|
+
if (mainVideo.src) {
|
|
6457
|
+
videoSrc = mainVideo.src;
|
|
6458
|
+
} else {
|
|
6459
|
+
const source = mainVideo.querySelector("source");
|
|
6460
|
+
if (source) {
|
|
6461
|
+
videoSrc = source.src;
|
|
6385
6462
|
}
|
|
6386
|
-
this.previewVideo.src = videoSrc;
|
|
6387
|
-
this.previewVideoReady = false;
|
|
6388
6463
|
}
|
|
6464
|
+
if (!videoSrc) {
|
|
6465
|
+
this.player.log("No video source found for preview", "warn");
|
|
6466
|
+
this.previewSupported = false;
|
|
6467
|
+
return;
|
|
6468
|
+
}
|
|
6469
|
+
this.previewVideo = document.createElement("video");
|
|
6470
|
+
this.previewVideo.muted = true;
|
|
6471
|
+
this.previewVideo.preload = "auto";
|
|
6472
|
+
this.previewVideo.playsInline = true;
|
|
6473
|
+
this.previewVideo.style.position = "absolute";
|
|
6474
|
+
this.previewVideo.style.visibility = "hidden";
|
|
6475
|
+
this.previewVideo.style.width = "1px";
|
|
6476
|
+
this.previewVideo.style.height = "1px";
|
|
6477
|
+
this.previewVideo.style.top = "-9999px";
|
|
6478
|
+
if (mainVideo.crossOrigin) {
|
|
6479
|
+
this.previewVideo.crossOrigin = mainVideo.crossOrigin;
|
|
6480
|
+
}
|
|
6481
|
+
this.previewVideo.addEventListener("error", (e) => {
|
|
6482
|
+
this.player.log("Preview video failed to load:", e, "warn");
|
|
6483
|
+
this.previewSupported = false;
|
|
6484
|
+
});
|
|
6485
|
+
this.previewVideo.addEventListener("loadedmetadata", () => {
|
|
6486
|
+
this.previewVideoReady = true;
|
|
6487
|
+
}, { once: true });
|
|
6488
|
+
if (this.player.container) {
|
|
6489
|
+
this.player.container.appendChild(this.previewVideo);
|
|
6490
|
+
}
|
|
6491
|
+
this.previewVideo.src = videoSrc;
|
|
6492
|
+
this.previewVideoReady = false;
|
|
6493
|
+
this.previewVideoInitialized = true;
|
|
6389
6494
|
}
|
|
6390
6495
|
/**
|
|
6391
6496
|
* Generate preview thumbnail for a specific time
|
|
@@ -6511,6 +6616,7 @@
|
|
|
6511
6616
|
this.isDraggingProgress = false;
|
|
6512
6617
|
});
|
|
6513
6618
|
progress.addEventListener("mousemove", (e) => {
|
|
6619
|
+
var _a, _b;
|
|
6514
6620
|
if (!this.isDraggingProgress) {
|
|
6515
6621
|
const { time } = updateProgress(e.clientX);
|
|
6516
6622
|
const rect = progress.getBoundingClientRect();
|
|
@@ -6518,8 +6624,17 @@
|
|
|
6518
6624
|
this.controls.progressTooltipTime.textContent = TimeUtils.formatTime(time);
|
|
6519
6625
|
this.controls.progressTooltip.style.left = "".concat(left, "px");
|
|
6520
6626
|
this.controls.progressTooltip.style.display = "block";
|
|
6627
|
+
if (!((_b = (_a = this.player) == null ? void 0 : _a.state) == null ? void 0 : _b.hasStartedPlayback)) {
|
|
6628
|
+
if (this.controls.progressPreview) {
|
|
6629
|
+
this.controls.progressPreview.style.display = "none";
|
|
6630
|
+
}
|
|
6631
|
+
return;
|
|
6632
|
+
}
|
|
6633
|
+
this.ensurePreviewVideoInitialized();
|
|
6521
6634
|
if (this.previewSupported) {
|
|
6522
6635
|
this.updatePreviewThumbnail(time);
|
|
6636
|
+
} else if (this.controls.progressPreview) {
|
|
6637
|
+
this.controls.progressPreview.style.display = "none";
|
|
6523
6638
|
}
|
|
6524
6639
|
}
|
|
6525
6640
|
});
|
|
@@ -10388,6 +10503,17 @@
|
|
|
10388
10503
|
volume: 0.8,
|
|
10389
10504
|
playbackSpeed: 1,
|
|
10390
10505
|
preload: "metadata",
|
|
10506
|
+
// Optional initial duration (seconds) so UI can show duration
|
|
10507
|
+
// before media metadata is loaded (useful with deferLoad/preload=none).
|
|
10508
|
+
initialDuration: 0,
|
|
10509
|
+
// When enabled, VidPly will not start network loading during init().
|
|
10510
|
+
// - HTML5: does not call element.load() until the first user-initiated play()
|
|
10511
|
+
// - HLS (hls.js): does not load manifest/segments until the first play()
|
|
10512
|
+
// This is useful for pages with many players to avoid high initial bandwidth.
|
|
10513
|
+
deferLoad: false,
|
|
10514
|
+
// When enabled, clicking Audio Description / Sign Language before playback will show
|
|
10515
|
+
// a notice instead of implicitly starting playback/loading.
|
|
10516
|
+
requirePlaybackForAccessibilityToggles: false,
|
|
10391
10517
|
startTime: 0,
|
|
10392
10518
|
playsInline: true,
|
|
10393
10519
|
// Enable inline playback on iOS (prevents native fullscreen)
|
|
@@ -10485,6 +10611,8 @@
|
|
|
10485
10611
|
}, options);
|
|
10486
10612
|
this.options.metadataAlerts = this.options.metadataAlerts || {};
|
|
10487
10613
|
this.options.metadataHashtags = this.options.metadataHashtags || {};
|
|
10614
|
+
this.noticeElement = null;
|
|
10615
|
+
this.noticeTimeout = null;
|
|
10488
10616
|
this.storage = new StorageManager("vidply");
|
|
10489
10617
|
const savedPrefs = this.storage.getPlayerPreferences();
|
|
10490
10618
|
if (savedPrefs) {
|
|
@@ -10499,10 +10627,11 @@
|
|
|
10499
10627
|
ended: false,
|
|
10500
10628
|
buffering: false,
|
|
10501
10629
|
seeking: false,
|
|
10630
|
+
hasStartedPlayback: false,
|
|
10502
10631
|
muted: this.options.muted,
|
|
10503
10632
|
volume: this.options.volume,
|
|
10504
10633
|
currentTime: 0,
|
|
10505
|
-
duration: 0,
|
|
10634
|
+
duration: Number(this.options.initialDuration) > 0 ? Number(this.options.initialDuration) : 0,
|
|
10506
10635
|
playbackSpeed: this.options.playbackSpeed,
|
|
10507
10636
|
fullscreen: false,
|
|
10508
10637
|
pip: false,
|
|
@@ -10591,6 +10720,52 @@
|
|
|
10591
10720
|
});
|
|
10592
10721
|
this.init();
|
|
10593
10722
|
}
|
|
10723
|
+
/**
|
|
10724
|
+
* Show a small in-player notice (non-blocking), also announced to screen readers.
|
|
10725
|
+
*/
|
|
10726
|
+
showNotice(message, { timeout = 2500, priority = "polite" } = {}) {
|
|
10727
|
+
var _a;
|
|
10728
|
+
try {
|
|
10729
|
+
if (!message) return;
|
|
10730
|
+
if (!this.container) return;
|
|
10731
|
+
if ((_a = this.keyboardManager) == null ? void 0 : _a.announce) {
|
|
10732
|
+
this.keyboardManager.announce(message, priority);
|
|
10733
|
+
}
|
|
10734
|
+
if (!this.noticeElement) {
|
|
10735
|
+
const el = document.createElement("div");
|
|
10736
|
+
el.className = "".concat(this.options.classPrefix, "-notice");
|
|
10737
|
+
el.setAttribute("role", "status");
|
|
10738
|
+
el.setAttribute("aria-live", priority);
|
|
10739
|
+
el.setAttribute("aria-atomic", "true");
|
|
10740
|
+
el.style.position = "absolute";
|
|
10741
|
+
el.style.left = "0.75rem";
|
|
10742
|
+
el.style.right = "0.75rem";
|
|
10743
|
+
el.style.top = "0.75rem";
|
|
10744
|
+
el.style.zIndex = "9999";
|
|
10745
|
+
el.style.padding = "0.5rem 0.75rem";
|
|
10746
|
+
el.style.borderRadius = "0.5rem";
|
|
10747
|
+
el.style.background = "rgba(0, 0, 0, 0.75)";
|
|
10748
|
+
el.style.color = "#fff";
|
|
10749
|
+
el.style.fontSize = "0.875rem";
|
|
10750
|
+
el.style.lineHeight = "1.3";
|
|
10751
|
+
el.style.pointerEvents = "none";
|
|
10752
|
+
this.noticeElement = el;
|
|
10753
|
+
this.container.appendChild(el);
|
|
10754
|
+
}
|
|
10755
|
+
this.noticeElement.textContent = message;
|
|
10756
|
+
this.noticeElement.style.display = "block";
|
|
10757
|
+
if (this.noticeTimeout) {
|
|
10758
|
+
clearTimeout(this.noticeTimeout);
|
|
10759
|
+
this.noticeTimeout = null;
|
|
10760
|
+
}
|
|
10761
|
+
this.noticeTimeout = setTimeout(() => {
|
|
10762
|
+
if (this.noticeElement) {
|
|
10763
|
+
this.noticeElement.style.display = "none";
|
|
10764
|
+
}
|
|
10765
|
+
}, timeout);
|
|
10766
|
+
} catch (e) {
|
|
10767
|
+
}
|
|
10768
|
+
}
|
|
10594
10769
|
async init() {
|
|
10595
10770
|
var _a;
|
|
10596
10771
|
try {
|
|
@@ -10767,8 +10942,23 @@
|
|
|
10767
10942
|
if (this.options.height) {
|
|
10768
10943
|
this.container.style.height = typeof this.options.height === "number" ? "".concat(this.options.height, "px") : this.options.height;
|
|
10769
10944
|
}
|
|
10945
|
+
if (this.element.tagName === "VIDEO" && !this.options.height) {
|
|
10946
|
+
const wAttr = parseInt(this.element.getAttribute("width") || "", 10);
|
|
10947
|
+
const hAttr = parseInt(this.element.getAttribute("height") || "", 10);
|
|
10948
|
+
if (Number.isFinite(wAttr) && Number.isFinite(hAttr) && wAttr > 0 && hAttr > 0) {
|
|
10949
|
+
if (!this.container.style.aspectRatio) {
|
|
10950
|
+
this.container.style.aspectRatio = "".concat(wAttr, " / ").concat(hAttr);
|
|
10951
|
+
}
|
|
10952
|
+
if (this.videoWrapper && !this.videoWrapper.style.aspectRatio) {
|
|
10953
|
+
this.videoWrapper.style.aspectRatio = "".concat(wAttr, " / ").concat(hAttr);
|
|
10954
|
+
this.videoWrapper.style.height = "auto";
|
|
10955
|
+
}
|
|
10956
|
+
}
|
|
10957
|
+
}
|
|
10770
10958
|
if (this.options.poster && this.element.tagName === "VIDEO") {
|
|
10771
|
-
|
|
10959
|
+
const resolvedPoster = this.resolvePosterPath(this.options.poster);
|
|
10960
|
+
this.element.poster = resolvedPoster;
|
|
10961
|
+
this.applyPosterAspectRatio(resolvedPoster);
|
|
10772
10962
|
}
|
|
10773
10963
|
if (this.element.tagName === "VIDEO") {
|
|
10774
10964
|
this.createPlayButtonOverlay();
|
|
@@ -10782,6 +10972,7 @@
|
|
|
10782
10972
|
}
|
|
10783
10973
|
});
|
|
10784
10974
|
this.on("play", () => {
|
|
10975
|
+
this.state.hasStartedPlayback = true;
|
|
10785
10976
|
this.hidePosterOverlay();
|
|
10786
10977
|
});
|
|
10787
10978
|
this.on("timeupdate", () => {
|
|
@@ -10795,6 +10986,34 @@
|
|
|
10795
10986
|
}
|
|
10796
10987
|
}, { once: true });
|
|
10797
10988
|
}
|
|
10989
|
+
/**
|
|
10990
|
+
* Apply aspect ratio to the video wrapper based on the poster's intrinsic size.
|
|
10991
|
+
* This helps render correct poster sizing before media metadata is available.
|
|
10992
|
+
*/
|
|
10993
|
+
applyPosterAspectRatio(posterUrl) {
|
|
10994
|
+
try {
|
|
10995
|
+
if (!posterUrl) return;
|
|
10996
|
+
if (this.element.tagName !== "VIDEO") return;
|
|
10997
|
+
if (!this.videoWrapper) return;
|
|
10998
|
+
if (this.options.width || this.options.height) return;
|
|
10999
|
+
if (this._posterAspectAppliedFor === posterUrl) return;
|
|
11000
|
+
this._posterAspectAppliedFor = posterUrl;
|
|
11001
|
+
const img = new Image();
|
|
11002
|
+
img.decoding = "async";
|
|
11003
|
+
img.onload = () => {
|
|
11004
|
+
const w = img.naturalWidth;
|
|
11005
|
+
const h = img.naturalHeight;
|
|
11006
|
+
if (!w || !h) return;
|
|
11007
|
+
this.videoWrapper.style.aspectRatio = "".concat(w, " / ").concat(h);
|
|
11008
|
+
this.videoWrapper.style.height = "auto";
|
|
11009
|
+
if (this.container && !this.container.style.aspectRatio) {
|
|
11010
|
+
this.container.style.aspectRatio = "".concat(w, " / ").concat(h);
|
|
11011
|
+
}
|
|
11012
|
+
};
|
|
11013
|
+
img.src = posterUrl;
|
|
11014
|
+
} catch (e) {
|
|
11015
|
+
}
|
|
11016
|
+
}
|
|
10798
11017
|
createPlayButtonOverlay() {
|
|
10799
11018
|
this.playButtonOverlay = createPlayOverlay();
|
|
10800
11019
|
this.playButtonOverlay.addEventListener("click", () => {
|
|
@@ -11193,7 +11412,25 @@
|
|
|
11193
11412
|
await this.initializeRenderer();
|
|
11194
11413
|
} else {
|
|
11195
11414
|
this.renderer.media = this.element;
|
|
11196
|
-
this.
|
|
11415
|
+
if (this.options.deferLoad) {
|
|
11416
|
+
try {
|
|
11417
|
+
this.element.preload = this.options.preload || "metadata";
|
|
11418
|
+
} catch (e) {
|
|
11419
|
+
}
|
|
11420
|
+
if (this.renderer) {
|
|
11421
|
+
if (typeof this.renderer._didDeferredLoad === "boolean") {
|
|
11422
|
+
this.renderer._didDeferredLoad = false;
|
|
11423
|
+
}
|
|
11424
|
+
if (typeof this.renderer._hlsSourceLoaded === "boolean") {
|
|
11425
|
+
this.renderer._hlsSourceLoaded = false;
|
|
11426
|
+
}
|
|
11427
|
+
if ("_pendingSrc" in this.renderer) {
|
|
11428
|
+
this.renderer._pendingSrc = this._pendingSource || this.currentSource || null;
|
|
11429
|
+
}
|
|
11430
|
+
}
|
|
11431
|
+
} else {
|
|
11432
|
+
this.element.load();
|
|
11433
|
+
}
|
|
11197
11434
|
}
|
|
11198
11435
|
if (isExternalRenderer) {
|
|
11199
11436
|
setTimeout(() => {
|
|
@@ -11238,6 +11475,20 @@
|
|
|
11238
11475
|
this.handleError(error);
|
|
11239
11476
|
}
|
|
11240
11477
|
}
|
|
11478
|
+
/**
|
|
11479
|
+
* Ensure the current renderer has started its initial load (metadata/manifest)
|
|
11480
|
+
* without starting playback. This is useful for playlists to behave like
|
|
11481
|
+
* single videos on selection, while still keeping autoplay off.
|
|
11482
|
+
*/
|
|
11483
|
+
ensureLoaded() {
|
|
11484
|
+
try {
|
|
11485
|
+
if (!this.renderer) return;
|
|
11486
|
+
if (typeof this.renderer.ensureLoaded === "function") {
|
|
11487
|
+
this.renderer.ensureLoaded();
|
|
11488
|
+
}
|
|
11489
|
+
} catch (e) {
|
|
11490
|
+
}
|
|
11491
|
+
}
|
|
11241
11492
|
/**
|
|
11242
11493
|
* Check if we need to change renderer type
|
|
11243
11494
|
* @param {string} src - New source URL
|
|
@@ -11273,6 +11524,11 @@
|
|
|
11273
11524
|
play() {
|
|
11274
11525
|
if (this.renderer) {
|
|
11275
11526
|
this.renderer.play();
|
|
11527
|
+
return;
|
|
11528
|
+
}
|
|
11529
|
+
if (this.playlistManager && Array.isArray(this.playlistManager.tracks) && this.playlistManager.tracks.length > 0) {
|
|
11530
|
+
const index = this.playlistManager.currentIndex >= 0 ? this.playlistManager.currentIndex : 0;
|
|
11531
|
+
this.playlistManager.play(index, true);
|
|
11276
11532
|
}
|
|
11277
11533
|
}
|
|
11278
11534
|
pause() {
|
|
@@ -12602,6 +12858,18 @@
|
|
|
12602
12858
|
this.emit("audiodescriptiondisabled");
|
|
12603
12859
|
}
|
|
12604
12860
|
async toggleAudioDescription() {
|
|
12861
|
+
var _a, _b, _c;
|
|
12862
|
+
if (this.options.requirePlaybackForAccessibilityToggles && !this.renderer && ((_b = (_a = this.playlistManager) == null ? void 0 : _a.tracks) == null ? void 0 : _b.length)) {
|
|
12863
|
+
this.showNotice(i18n.t("player.startPlaybackForAudioDescription"));
|
|
12864
|
+
return;
|
|
12865
|
+
}
|
|
12866
|
+
if (!this.renderer && this.playlistManager && ((_c = this.playlistManager.tracks) == null ? void 0 : _c.length)) {
|
|
12867
|
+
this.audioDescriptionManager.desiredState = !this.audioDescriptionManager.desiredState;
|
|
12868
|
+
this.state.audioDescriptionEnabled = this.audioDescriptionManager.desiredState;
|
|
12869
|
+
this.emit(this.audioDescriptionManager.desiredState ? "audiodescriptionenabled" : "audiodescriptiondisabled");
|
|
12870
|
+
this.play();
|
|
12871
|
+
return;
|
|
12872
|
+
}
|
|
12605
12873
|
return this.audioDescriptionManager.toggle();
|
|
12606
12874
|
}
|
|
12607
12875
|
// Sign Language (delegated to SignLanguageManager)
|
|
@@ -12865,6 +13133,19 @@
|
|
|
12865
13133
|
return this.signLanguageManager.disable();
|
|
12866
13134
|
}
|
|
12867
13135
|
toggleSignLanguage() {
|
|
13136
|
+
var _a, _b, _c;
|
|
13137
|
+
if (this.options.requirePlaybackForAccessibilityToggles && !this.renderer && ((_b = (_a = this.playlistManager) == null ? void 0 : _a.tracks) == null ? void 0 : _b.length)) {
|
|
13138
|
+
this.showNotice(i18n.t("player.startPlaybackForSignLanguage"));
|
|
13139
|
+
return;
|
|
13140
|
+
}
|
|
13141
|
+
if (!this.renderer && this.playlistManager && ((_c = this.playlistManager.tracks) == null ? void 0 : _c.length)) {
|
|
13142
|
+
const wasEnabled = this.signLanguageManager.enabled;
|
|
13143
|
+
const result = this.signLanguageManager.toggle();
|
|
13144
|
+
if (!wasEnabled && this.signLanguageManager.enabled) {
|
|
13145
|
+
this.play();
|
|
13146
|
+
}
|
|
13147
|
+
return result;
|
|
13148
|
+
}
|
|
12868
13149
|
return this.signLanguageManager.toggle();
|
|
12869
13150
|
}
|
|
12870
13151
|
setupSignLanguageInteraction() {
|
|
@@ -13976,6 +14257,7 @@
|
|
|
13976
14257
|
* @param {boolean} autoPlay - Whether to auto-play after creation
|
|
13977
14258
|
*/
|
|
13978
14259
|
async recreatePlayerForTrack(track, autoPlay = false) {
|
|
14260
|
+
var _a;
|
|
13979
14261
|
if (!this.hostElement || !this.PlayerClass) {
|
|
13980
14262
|
console.warn("VidPly Playlist: Cannot recreate player - missing hostElement or PlayerClass");
|
|
13981
14263
|
return false;
|
|
@@ -13997,6 +14279,7 @@
|
|
|
13997
14279
|
if (this.playlistPanel && this.playlistPanel.parentNode) {
|
|
13998
14280
|
this.playlistPanel.parentNode.removeChild(this.playlistPanel);
|
|
13999
14281
|
}
|
|
14282
|
+
const preservedPlayerOptions = ((_a = this.player) == null ? void 0 : _a.options) ? __spreadValues({}, this.player.options) : {};
|
|
14000
14283
|
if (this.player) {
|
|
14001
14284
|
this.player.off("ended", this.handleTrackEnd);
|
|
14002
14285
|
this.player.off("error", this.handleTrackError);
|
|
@@ -14004,7 +14287,8 @@
|
|
|
14004
14287
|
}
|
|
14005
14288
|
this.hostElement.innerHTML = "";
|
|
14006
14289
|
const mediaElement = document.createElement(elementType);
|
|
14007
|
-
|
|
14290
|
+
const preloadValue = preservedPlayerOptions.preload || "metadata";
|
|
14291
|
+
mediaElement.setAttribute("preload", preloadValue);
|
|
14008
14292
|
if (elementType === "video" && track.poster && (mediaType === "video" || mediaType === "hls")) {
|
|
14009
14293
|
mediaElement.setAttribute("poster", track.poster);
|
|
14010
14294
|
}
|
|
@@ -14038,6 +14322,7 @@
|
|
|
14038
14322
|
audioDescriptionDuration: track.audioDescriptionDuration || null,
|
|
14039
14323
|
signLanguageSrc: track.signLanguageSrc || null
|
|
14040
14324
|
};
|
|
14325
|
+
Object.assign(playerOptions, preservedPlayerOptions);
|
|
14041
14326
|
this.player = new this.PlayerClass(mediaElement, playerOptions);
|
|
14042
14327
|
this.player.playlistManager = this;
|
|
14043
14328
|
await new Promise((resolve) => {
|
|
@@ -14200,31 +14485,35 @@
|
|
|
14200
14485
|
if (this.options.autoPlayFirst) {
|
|
14201
14486
|
this.play(0);
|
|
14202
14487
|
} else {
|
|
14203
|
-
this.loadTrack(0)
|
|
14488
|
+
void this.loadTrack(0).catch(() => {
|
|
14489
|
+
});
|
|
14204
14490
|
}
|
|
14205
14491
|
}
|
|
14206
14492
|
this.updatePlaylistVisibilityInFullscreen();
|
|
14207
14493
|
}
|
|
14208
14494
|
/**
|
|
14209
14495
|
* Load a track without playing
|
|
14496
|
+
* This is the playlist equivalent of a "single video initialized but not started yet":
|
|
14497
|
+
* it updates UI selection and loads the media into the player so metadata/manifests
|
|
14498
|
+
* and feature managers can be ready, but it does not start playback.
|
|
14210
14499
|
* @param {number} index - Track index
|
|
14211
14500
|
*/
|
|
14212
14501
|
async loadTrack(index) {
|
|
14502
|
+
var _a, _b;
|
|
14213
14503
|
if (index < 0 || index >= this.tracks.length) {
|
|
14214
14504
|
console.warn("VidPly Playlist: Invalid track index", index);
|
|
14215
14505
|
return;
|
|
14216
14506
|
}
|
|
14217
14507
|
const track = this.tracks[index];
|
|
14508
|
+
this.selectTrack(index);
|
|
14218
14509
|
this.isChangingTrack = true;
|
|
14219
|
-
this.currentIndex = index;
|
|
14220
14510
|
if (this.options.recreatePlayers && this.hostElement && this.PlayerClass) {
|
|
14221
14511
|
const currentMediaType = this.player ? this.player.element.tagName === "AUDIO" ? "audio" : "video" : null;
|
|
14222
14512
|
const newMediaType = this.getTrackMediaType(track);
|
|
14223
14513
|
const newElementType = newMediaType === "audio" || newMediaType === "soundcloud" ? "audio" : "video";
|
|
14224
14514
|
if (currentMediaType !== newElementType) {
|
|
14225
14515
|
await this.recreatePlayerForTrack(track, false);
|
|
14226
|
-
this.
|
|
14227
|
-
this.updatePlaylistUI();
|
|
14516
|
+
this.selectTrack(index);
|
|
14228
14517
|
this.player.emit("playlisttrackchange", {
|
|
14229
14518
|
index,
|
|
14230
14519
|
item: track,
|
|
@@ -14236,16 +14525,22 @@
|
|
|
14236
14525
|
return;
|
|
14237
14526
|
}
|
|
14238
14527
|
}
|
|
14239
|
-
this.player.load({
|
|
14528
|
+
const loadPromise = this.player.load({
|
|
14240
14529
|
src: track.src,
|
|
14241
14530
|
type: track.type,
|
|
14242
14531
|
poster: track.poster,
|
|
14243
14532
|
tracks: track.tracks || [],
|
|
14244
14533
|
audioDescriptionSrc: track.audioDescriptionSrc || null,
|
|
14245
|
-
signLanguageSrc: track.signLanguageSrc || null
|
|
14246
|
-
|
|
14247
|
-
|
|
14248
|
-
this.
|
|
14534
|
+
signLanguageSrc: track.signLanguageSrc || null,
|
|
14535
|
+
signLanguageSources: track.signLanguageSources || {}
|
|
14536
|
+
});
|
|
14537
|
+
if (((_b = (_a = this.player) == null ? void 0 : _a.options) == null ? void 0 : _b.deferLoad) && typeof this.player.ensureLoaded === "function") {
|
|
14538
|
+
Promise.resolve(loadPromise).then(() => {
|
|
14539
|
+
var _a2, _b2;
|
|
14540
|
+
return (_b2 = (_a2 = this.player) == null ? void 0 : _a2.ensureLoaded) == null ? void 0 : _b2.call(_a2);
|
|
14541
|
+
}).catch(() => {
|
|
14542
|
+
});
|
|
14543
|
+
}
|
|
14249
14544
|
this.player.emit("playlisttrackchange", {
|
|
14250
14545
|
index,
|
|
14251
14546
|
item: track,
|
|
@@ -14255,12 +14550,105 @@
|
|
|
14255
14550
|
this.isChangingTrack = false;
|
|
14256
14551
|
}, 150);
|
|
14257
14552
|
}
|
|
14553
|
+
/**
|
|
14554
|
+
* Select a track (UI/selection only; does NOT set the media src / does NOT initialize renderer)
|
|
14555
|
+
*
|
|
14556
|
+
* In "B always" playlist mode, you typically want `loadTrack()` on selection so the
|
|
14557
|
+
* selected item behaves like a single video (metadata/manifest loaded, features ready)
|
|
14558
|
+
* without auto-playing.
|
|
14559
|
+
* @param {number} index - Track index
|
|
14560
|
+
*/
|
|
14561
|
+
selectTrack(index) {
|
|
14562
|
+
var _a, _b, _c, _d;
|
|
14563
|
+
if (index < 0 || index >= this.tracks.length) {
|
|
14564
|
+
console.warn("VidPly Playlist: Invalid track index", index);
|
|
14565
|
+
return;
|
|
14566
|
+
}
|
|
14567
|
+
const track = this.tracks[index];
|
|
14568
|
+
this.currentIndex = index;
|
|
14569
|
+
try {
|
|
14570
|
+
if (((_b = (_a = this.player) == null ? void 0 : _a.element) == null ? void 0 : _b.tagName) === "VIDEO") {
|
|
14571
|
+
if (track.poster) {
|
|
14572
|
+
const posterUrl = typeof this.player.resolvePosterPath === "function" ? this.player.resolvePosterPath(track.poster) : track.poster;
|
|
14573
|
+
this.player.element.poster = posterUrl;
|
|
14574
|
+
(_d = (_c = this.player).applyPosterAspectRatio) == null ? void 0 : _d.call(_c, posterUrl);
|
|
14575
|
+
} else {
|
|
14576
|
+
this.player.element.removeAttribute("poster");
|
|
14577
|
+
}
|
|
14578
|
+
}
|
|
14579
|
+
this.player.audioDescriptionSrc = track.audioDescriptionSrc || null;
|
|
14580
|
+
this.player.signLanguageSrc = track.signLanguageSrc || null;
|
|
14581
|
+
this.player.signLanguageSources = track.signLanguageSources || {};
|
|
14582
|
+
if (track.duration && Number(track.duration) > 0) {
|
|
14583
|
+
this.player.state.duration = Number(track.duration);
|
|
14584
|
+
}
|
|
14585
|
+
if (this.player.audioDescriptionManager) {
|
|
14586
|
+
this.player.audioDescriptionManager.src = track.audioDescriptionSrc || null;
|
|
14587
|
+
this.player.audioDescriptionManager.originalSource = track.src || this.player.originalSrc || null;
|
|
14588
|
+
}
|
|
14589
|
+
if (this.player.signLanguageManager) {
|
|
14590
|
+
this.player.signLanguageManager.src = track.signLanguageSrc || null;
|
|
14591
|
+
this.player.signLanguageManager.sources = track.signLanguageSources || {};
|
|
14592
|
+
this.player.signLanguageManager.currentLanguage = null;
|
|
14593
|
+
}
|
|
14594
|
+
if (track.src && !this.player.originalSrc) {
|
|
14595
|
+
this.player.originalSrc = track.src;
|
|
14596
|
+
}
|
|
14597
|
+
const existing = Array.from(this.player.element.querySelectorAll("track"));
|
|
14598
|
+
existing.forEach((t) => t.remove());
|
|
14599
|
+
if (Array.isArray(track.tracks)) {
|
|
14600
|
+
track.tracks.forEach((tc) => {
|
|
14601
|
+
if (!(tc == null ? void 0 : tc.src)) return;
|
|
14602
|
+
const el = document.createElement("track");
|
|
14603
|
+
el.src = tc.src;
|
|
14604
|
+
el.kind = tc.kind || "captions";
|
|
14605
|
+
el.srclang = tc.srclang || "en";
|
|
14606
|
+
el.label = tc.label || tc.srclang || "Track";
|
|
14607
|
+
if (tc.default) el.default = true;
|
|
14608
|
+
if (tc.describedSrc) {
|
|
14609
|
+
el.setAttribute("data-desc-src", tc.describedSrc);
|
|
14610
|
+
}
|
|
14611
|
+
this.player.element.appendChild(el);
|
|
14612
|
+
});
|
|
14613
|
+
}
|
|
14614
|
+
if (typeof this.player.invalidateTrackCache === "function") {
|
|
14615
|
+
this.player.invalidateTrackCache();
|
|
14616
|
+
}
|
|
14617
|
+
if (this.player.audioDescriptionManager && typeof this.player.audioDescriptionManager.initFromSourceElements === "function") {
|
|
14618
|
+
try {
|
|
14619
|
+
this.player.audioDescriptionManager.captionTracks = [];
|
|
14620
|
+
this.player.audioDescriptionManager.initFromSourceElements(this.player.sourceElements, this.player.trackElements);
|
|
14621
|
+
} catch (e) {
|
|
14622
|
+
}
|
|
14623
|
+
}
|
|
14624
|
+
if (this.player.captionManager && typeof this.player.captionManager.loadTracks === "function") {
|
|
14625
|
+
try {
|
|
14626
|
+
this.player.captionManager.tracks = [];
|
|
14627
|
+
this.player.captionManager.currentTrack = null;
|
|
14628
|
+
this.player.captionManager.loadTracks();
|
|
14629
|
+
} catch (e) {
|
|
14630
|
+
}
|
|
14631
|
+
}
|
|
14632
|
+
if (typeof this.player.updateControlBar === "function") {
|
|
14633
|
+
this.player.updateControlBar();
|
|
14634
|
+
}
|
|
14635
|
+
} catch (e) {
|
|
14636
|
+
}
|
|
14637
|
+
this.updateTrackInfo(track);
|
|
14638
|
+
this.updatePlaylistUI();
|
|
14639
|
+
this.player.emit("playlisttrackselect", {
|
|
14640
|
+
index,
|
|
14641
|
+
item: track,
|
|
14642
|
+
total: this.tracks.length
|
|
14643
|
+
});
|
|
14644
|
+
}
|
|
14258
14645
|
/**
|
|
14259
14646
|
* Play a specific track
|
|
14260
14647
|
* @param {number} index - Track index
|
|
14261
14648
|
* @param {boolean} userInitiated - Whether this was triggered by user action (default: false)
|
|
14262
14649
|
*/
|
|
14263
14650
|
async play(index, userInitiated = false) {
|
|
14651
|
+
var _a, _b;
|
|
14264
14652
|
if (index < 0 || index >= this.tracks.length) {
|
|
14265
14653
|
console.warn("VidPly Playlist: Invalid track index", index);
|
|
14266
14654
|
return;
|
|
@@ -14287,13 +14675,21 @@
|
|
|
14287
14675
|
return;
|
|
14288
14676
|
}
|
|
14289
14677
|
}
|
|
14678
|
+
let srcToLoad = track.src;
|
|
14679
|
+
if (((_b = (_a = this.player) == null ? void 0 : _a.audioDescriptionManager) == null ? void 0 : _b.desiredState) && track.audioDescriptionSrc) {
|
|
14680
|
+
this.player.originalSrc = track.src;
|
|
14681
|
+
this.player.audioDescriptionManager.originalSource = track.src;
|
|
14682
|
+
this.player.audioDescriptionManager.src = track.audioDescriptionSrc;
|
|
14683
|
+
srcToLoad = track.audioDescriptionSrc;
|
|
14684
|
+
}
|
|
14290
14685
|
this.player.load({
|
|
14291
|
-
src:
|
|
14686
|
+
src: srcToLoad,
|
|
14292
14687
|
type: track.type,
|
|
14293
14688
|
poster: track.poster,
|
|
14294
14689
|
tracks: track.tracks || [],
|
|
14295
14690
|
audioDescriptionSrc: track.audioDescriptionSrc || null,
|
|
14296
|
-
signLanguageSrc: track.signLanguageSrc || null
|
|
14691
|
+
signLanguageSrc: track.signLanguageSrc || null,
|
|
14692
|
+
signLanguageSources: track.signLanguageSources || {}
|
|
14297
14693
|
});
|
|
14298
14694
|
this.updateTrackInfo(track);
|
|
14299
14695
|
this.updatePlaylistUI();
|
|
@@ -14474,21 +14870,6 @@
|
|
|
14474
14870
|
console.warn("VidPly Playlist: No container found");
|
|
14475
14871
|
return;
|
|
14476
14872
|
}
|
|
14477
|
-
if (this.player.element.tagName === "AUDIO") {
|
|
14478
|
-
this.trackArtworkElement = DOMUtils.createElement("div", {
|
|
14479
|
-
className: "vidply-track-artwork",
|
|
14480
|
-
attributes: {
|
|
14481
|
-
"aria-hidden": "true"
|
|
14482
|
-
}
|
|
14483
|
-
});
|
|
14484
|
-
this.trackArtworkElement.style.display = "none";
|
|
14485
|
-
const videoWrapper = this.container.querySelector(".vidply-video-wrapper");
|
|
14486
|
-
if (videoWrapper) {
|
|
14487
|
-
this.container.insertBefore(this.trackArtworkElement, videoWrapper);
|
|
14488
|
-
} else {
|
|
14489
|
-
this.container.appendChild(this.trackArtworkElement);
|
|
14490
|
-
}
|
|
14491
|
-
}
|
|
14492
14873
|
this.trackInfoElement = DOMUtils.createElement("div", {
|
|
14493
14874
|
className: "vidply-track-info",
|
|
14494
14875
|
attributes: {
|
|
@@ -14552,6 +14933,28 @@
|
|
|
14552
14933
|
* Update track artwork display (for audio playlists)
|
|
14553
14934
|
*/
|
|
14554
14935
|
updateTrackArtwork(track) {
|
|
14936
|
+
var _a, _b;
|
|
14937
|
+
if (((_b = (_a = this.player) == null ? void 0 : _a.element) == null ? void 0 : _b.tagName) !== "AUDIO") {
|
|
14938
|
+
if (this.trackArtworkElement) {
|
|
14939
|
+
this.trackArtworkElement.style.display = "none";
|
|
14940
|
+
}
|
|
14941
|
+
return;
|
|
14942
|
+
}
|
|
14943
|
+
if (!this.trackArtworkElement && this.container) {
|
|
14944
|
+
this.trackArtworkElement = DOMUtils.createElement("div", {
|
|
14945
|
+
className: "vidply-track-artwork",
|
|
14946
|
+
attributes: {
|
|
14947
|
+
"aria-hidden": "true"
|
|
14948
|
+
}
|
|
14949
|
+
});
|
|
14950
|
+
this.trackArtworkElement.style.display = "none";
|
|
14951
|
+
const videoWrapper = this.container.querySelector(".vidply-video-wrapper");
|
|
14952
|
+
if (videoWrapper) {
|
|
14953
|
+
this.container.insertBefore(this.trackArtworkElement, videoWrapper);
|
|
14954
|
+
} else {
|
|
14955
|
+
this.container.appendChild(this.trackArtworkElement);
|
|
14956
|
+
}
|
|
14957
|
+
}
|
|
14555
14958
|
if (!this.trackArtworkElement) return;
|
|
14556
14959
|
if (track.poster) {
|
|
14557
14960
|
this.trackArtworkElement.style.backgroundImage = "url(".concat(track.poster, ")");
|