vidply 1.0.32 → 1.0.33
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-LIFBU6UD.js} +48 -3
- package/dist/dev/vidply.HLSRenderer-LIFBU6UD.js.map +7 -0
- package/dist/dev/{vidply.HTML5Renderer-FXBZQL6Y.js → vidply.HTML5Renderer-YWMVYWFS.js} +2 -2
- package/dist/dev/{vidply.TranscriptManager-T677KF4N.js → vidply.TranscriptManager-R7NJRU7E.js} +2 -2
- package/dist/dev/{vidply.chunk-GS2JX5RQ.js → vidply.chunk-PMRKJBGH.js} +5 -2
- package/dist/dev/vidply.chunk-PMRKJBGH.js.map +7 -0
- package/dist/dev/{vidply.chunk-W2LSBD6Y.js → vidply.chunk-UVO24MXU.js} +33 -3
- package/dist/dev/vidply.chunk-UVO24MXU.js.map +7 -0
- package/dist/dev/{vidply.de-SNL6AJ4D.js → vidply.de-CEGBLV67.js} +4 -1
- package/dist/dev/vidply.de-CEGBLV67.js.map +7 -0
- package/dist/dev/vidply.esm.js +364 -63
- package/dist/dev/vidply.esm.js.map +2 -2
- package/dist/legacy/vidply.js +459 -63
- package/dist/legacy/vidply.js.map +3 -3
- package/dist/legacy/vidply.min.js +1 -1
- package/dist/legacy/vidply.min.meta.json +15 -15
- package/dist/prod/vidply.HLSRenderer-ESR6NAMI.min.js +6 -0
- package/dist/prod/{vidply.HTML5Renderer-KKW3OLHM.min.js → vidply.HTML5Renderer-6ROXQSQY.min.js} +1 -1
- package/dist/prod/{vidply.TranscriptManager-WFZSW6NR.min.js → vidply.TranscriptManager-B65LKXGG.min.js} +1 -1
- package/dist/prod/vidply.chunk-7HVHEUHH.min.js +6 -0
- package/dist/prod/vidply.chunk-IQKD4GUB.min.js +6 -0
- package/dist/prod/vidply.de-IHKC573T.min.js +6 -0
- package/dist/prod/vidply.esm.min.js +4 -4
- package/dist/vidply.esm.min.meta.json +33 -33
- package/package.json +1 -1
- package/src/controls/ControlBar.js +104 -70
- package/src/core/Player.js +217 -3
- package/src/features/PlaylistManager.js +175 -17
- 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-YWMVYWFS.js.map} +0 -0
- /package/dist/dev/{vidply.TranscriptManager-T677KF4N.js.map → vidply.TranscriptManager-R7NJRU7E.js.map} +0 -0
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
"format": "esm"
|
|
12
12
|
},
|
|
13
13
|
"src/i18n/languages/en.js": {
|
|
14
|
-
"bytes":
|
|
14
|
+
"bytes": 7637,
|
|
15
15
|
"imports": [],
|
|
16
16
|
"format": "esm"
|
|
17
17
|
},
|
|
18
18
|
"src/i18n/languages/de.js": {
|
|
19
|
-
"bytes":
|
|
19
|
+
"bytes": 9427,
|
|
20
20
|
"imports": [],
|
|
21
21
|
"format": "esm"
|
|
22
22
|
},
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"format": "esm"
|
|
110
110
|
},
|
|
111
111
|
"src/controls/ControlBar.js": {
|
|
112
|
-
"bytes":
|
|
112
|
+
"bytes": 147152,
|
|
113
113
|
"imports": [
|
|
114
114
|
{
|
|
115
115
|
"path": "src/utils/DOMUtils.js",
|
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
"format": "esm"
|
|
187
187
|
},
|
|
188
188
|
"src/renderers/HTML5Renderer.js": {
|
|
189
|
-
"bytes":
|
|
189
|
+
"bytes": 10921,
|
|
190
190
|
"imports": [],
|
|
191
191
|
"format": "esm"
|
|
192
192
|
},
|
|
@@ -346,7 +346,7 @@
|
|
|
346
346
|
"format": "esm"
|
|
347
347
|
},
|
|
348
348
|
"src/renderers/HLSRenderer.js": {
|
|
349
|
-
"bytes":
|
|
349
|
+
"bytes": 12151,
|
|
350
350
|
"imports": [
|
|
351
351
|
{
|
|
352
352
|
"path": "src/renderers/HTML5Renderer.js",
|
|
@@ -362,7 +362,7 @@
|
|
|
362
362
|
"format": "esm"
|
|
363
363
|
},
|
|
364
364
|
"src/core/Player.js": {
|
|
365
|
-
"bytes":
|
|
365
|
+
"bytes": 224782,
|
|
366
366
|
"imports": [
|
|
367
367
|
{
|
|
368
368
|
"path": "src/utils/EventEmitter.js",
|
|
@@ -473,7 +473,7 @@
|
|
|
473
473
|
"format": "esm"
|
|
474
474
|
},
|
|
475
475
|
"src/features/PlaylistManager.js": {
|
|
476
|
-
"bytes":
|
|
476
|
+
"bytes": 57201,
|
|
477
477
|
"imports": [
|
|
478
478
|
{
|
|
479
479
|
"path": "src/utils/DOMUtils.js",
|
|
@@ -529,10 +529,10 @@
|
|
|
529
529
|
},
|
|
530
530
|
"bytes": 4730
|
|
531
531
|
},
|
|
532
|
-
"dist/prod/vidply.HLSRenderer-
|
|
532
|
+
"dist/prod/vidply.HLSRenderer-ESR6NAMI.min.js": {
|
|
533
533
|
"imports": [
|
|
534
534
|
{
|
|
535
|
-
"path": "dist/prod/vidply.HTML5Renderer-
|
|
535
|
+
"path": "dist/prod/vidply.HTML5Renderer-6ROXQSQY.min.js",
|
|
536
536
|
"kind": "dynamic-import"
|
|
537
537
|
}
|
|
538
538
|
],
|
|
@@ -542,10 +542,10 @@
|
|
|
542
542
|
"entryPoint": "src/renderers/HLSRenderer.js",
|
|
543
543
|
"inputs": {
|
|
544
544
|
"src/renderers/HLSRenderer.js": {
|
|
545
|
-
"bytesInOutput":
|
|
545
|
+
"bytesInOutput": 6514
|
|
546
546
|
}
|
|
547
547
|
},
|
|
548
|
-
"bytes":
|
|
548
|
+
"bytes": 6658
|
|
549
549
|
},
|
|
550
550
|
"dist/prod/vidply.SoundCloudRenderer-MOR2CUFH.min.js": {
|
|
551
551
|
"imports": [],
|
|
@@ -564,15 +564,15 @@
|
|
|
564
564
|
"dist/prod/vidply.esm.min.js": {
|
|
565
565
|
"imports": [
|
|
566
566
|
{
|
|
567
|
-
"path": "dist/prod/vidply.chunk-
|
|
567
|
+
"path": "dist/prod/vidply.chunk-7HVHEUHH.min.js",
|
|
568
568
|
"kind": "import-statement"
|
|
569
569
|
},
|
|
570
570
|
{
|
|
571
|
-
"path": "dist/prod/vidply.chunk-
|
|
571
|
+
"path": "dist/prod/vidply.chunk-IQKD4GUB.min.js",
|
|
572
572
|
"kind": "import-statement"
|
|
573
573
|
},
|
|
574
574
|
{
|
|
575
|
-
"path": "dist/prod/vidply.TranscriptManager-
|
|
575
|
+
"path": "dist/prod/vidply.TranscriptManager-B65LKXGG.min.js",
|
|
576
576
|
"kind": "dynamic-import"
|
|
577
577
|
},
|
|
578
578
|
{
|
|
@@ -584,7 +584,7 @@
|
|
|
584
584
|
"kind": "dynamic-import"
|
|
585
585
|
},
|
|
586
586
|
{
|
|
587
|
-
"path": "dist/prod/vidply.HLSRenderer-
|
|
587
|
+
"path": "dist/prod/vidply.HLSRenderer-ESR6NAMI.min.js",
|
|
588
588
|
"kind": "dynamic-import"
|
|
589
589
|
},
|
|
590
590
|
{
|
|
@@ -609,7 +609,7 @@
|
|
|
609
609
|
"bytesInOutput": 1009
|
|
610
610
|
},
|
|
611
611
|
"src/controls/ControlBar.js": {
|
|
612
|
-
"bytesInOutput":
|
|
612
|
+
"bytesInOutput": 63355
|
|
613
613
|
},
|
|
614
614
|
"src/controls/CaptionManager.js": {
|
|
615
615
|
"bytesInOutput": 7279
|
|
@@ -624,18 +624,18 @@
|
|
|
624
624
|
"bytesInOutput": 19117
|
|
625
625
|
},
|
|
626
626
|
"src/core/Player.js": {
|
|
627
|
-
"bytesInOutput":
|
|
627
|
+
"bytesInOutput": 80485
|
|
628
628
|
},
|
|
629
629
|
"src/features/PlaylistManager.js": {
|
|
630
|
-
"bytesInOutput":
|
|
630
|
+
"bytesInOutput": 24268
|
|
631
631
|
},
|
|
632
632
|
"src/index.js": {
|
|
633
633
|
"bytesInOutput": 1869
|
|
634
634
|
}
|
|
635
635
|
},
|
|
636
|
-
"bytes":
|
|
636
|
+
"bytes": 212078
|
|
637
637
|
},
|
|
638
|
-
"dist/prod/vidply.de-
|
|
638
|
+
"dist/prod/vidply.de-IHKC573T.min.js": {
|
|
639
639
|
"imports": [],
|
|
640
640
|
"exports": [
|
|
641
641
|
"de"
|
|
@@ -643,10 +643,10 @@
|
|
|
643
643
|
"entryPoint": "src/i18n/languages/de.js",
|
|
644
644
|
"inputs": {
|
|
645
645
|
"src/i18n/languages/de.js": {
|
|
646
|
-
"bytesInOutput":
|
|
646
|
+
"bytesInOutput": 7512
|
|
647
647
|
}
|
|
648
648
|
},
|
|
649
|
-
"bytes":
|
|
649
|
+
"bytes": 7647
|
|
650
650
|
},
|
|
651
651
|
"dist/prod/vidply.es-3IJCQLJ7.min.js": {
|
|
652
652
|
"imports": [],
|
|
@@ -687,10 +687,10 @@
|
|
|
687
687
|
},
|
|
688
688
|
"bytes": 8204
|
|
689
689
|
},
|
|
690
|
-
"dist/prod/vidply.HTML5Renderer-
|
|
690
|
+
"dist/prod/vidply.HTML5Renderer-6ROXQSQY.min.js": {
|
|
691
691
|
"imports": [
|
|
692
692
|
{
|
|
693
|
-
"path": "dist/prod/vidply.chunk-
|
|
693
|
+
"path": "dist/prod/vidply.chunk-7HVHEUHH.min.js",
|
|
694
694
|
"kind": "import-statement"
|
|
695
695
|
}
|
|
696
696
|
],
|
|
@@ -701,22 +701,22 @@
|
|
|
701
701
|
"inputs": {},
|
|
702
702
|
"bytes": 192
|
|
703
703
|
},
|
|
704
|
-
"dist/prod/vidply.chunk-
|
|
704
|
+
"dist/prod/vidply.chunk-7HVHEUHH.min.js": {
|
|
705
705
|
"imports": [],
|
|
706
706
|
"exports": [
|
|
707
707
|
"a"
|
|
708
708
|
],
|
|
709
709
|
"inputs": {
|
|
710
710
|
"src/renderers/HTML5Renderer.js": {
|
|
711
|
-
"bytesInOutput":
|
|
711
|
+
"bytesInOutput": 5387
|
|
712
712
|
}
|
|
713
713
|
},
|
|
714
|
-
"bytes":
|
|
714
|
+
"bytes": 5521
|
|
715
715
|
},
|
|
716
|
-
"dist/prod/vidply.TranscriptManager-
|
|
716
|
+
"dist/prod/vidply.TranscriptManager-B65LKXGG.min.js": {
|
|
717
717
|
"imports": [
|
|
718
718
|
{
|
|
719
|
-
"path": "dist/prod/vidply.chunk-
|
|
719
|
+
"path": "dist/prod/vidply.chunk-IQKD4GUB.min.js",
|
|
720
720
|
"kind": "import-statement"
|
|
721
721
|
}
|
|
722
722
|
],
|
|
@@ -731,10 +731,10 @@
|
|
|
731
731
|
},
|
|
732
732
|
"bytes": 43042
|
|
733
733
|
},
|
|
734
|
-
"dist/prod/vidply.chunk-
|
|
734
|
+
"dist/prod/vidply.chunk-IQKD4GUB.min.js": {
|
|
735
735
|
"imports": [
|
|
736
736
|
{
|
|
737
|
-
"path": "dist/prod/vidply.de-
|
|
737
|
+
"path": "dist/prod/vidply.de-IHKC573T.min.js",
|
|
738
738
|
"kind": "dynamic-import"
|
|
739
739
|
},
|
|
740
740
|
{
|
|
@@ -771,7 +771,7 @@
|
|
|
771
771
|
"bytesInOutput": 2348
|
|
772
772
|
},
|
|
773
773
|
"src/i18n/languages/en.js": {
|
|
774
|
-
"bytesInOutput":
|
|
774
|
+
"bytesInOutput": 6385
|
|
775
775
|
},
|
|
776
776
|
"src/i18n/translations.js": {
|
|
777
777
|
"bytesInOutput": 340
|
|
@@ -801,7 +801,7 @@
|
|
|
801
801
|
"bytesInOutput": 776
|
|
802
802
|
}
|
|
803
803
|
},
|
|
804
|
-
"bytes":
|
|
804
|
+
"bytes": 40477
|
|
805
805
|
},
|
|
806
806
|
"dist/prod/vidply.YouTubeRenderer-MFC2GMAC.min.js": {
|
|
807
807
|
"imports": [],
|
package/package.json
CHANGED
|
@@ -27,6 +27,10 @@ export class ControlBar {
|
|
|
27
27
|
init() {
|
|
28
28
|
this.createElement();
|
|
29
29
|
this.createControls();
|
|
30
|
+
// Ensure time UI reflects any prefilled state (e.g. initialDuration)
|
|
31
|
+
// even when media metadata is deferred and 'loadedmetadata' won't fire yet.
|
|
32
|
+
this.updateDuration();
|
|
33
|
+
this.updateProgress();
|
|
30
34
|
this.attachEvents();
|
|
31
35
|
this.setupAutoHide();
|
|
32
36
|
this.setupOverflowDetection();
|
|
@@ -846,22 +850,44 @@ export class ControlBar {
|
|
|
846
850
|
|
|
847
851
|
// Helper methods to check for available features
|
|
848
852
|
hasChapterTracks() {
|
|
853
|
+
// 1) Prefer already-loaded TextTracks (fast + accurate)
|
|
849
854
|
const textTracks = this.player.element.textTracks;
|
|
850
855
|
for (let i = 0; i < textTracks.length; i++) {
|
|
851
|
-
if (textTracks[i].kind === 'chapters')
|
|
852
|
-
return true;
|
|
856
|
+
if (textTracks[i].kind === 'chapters') return true;
|
|
853
857
|
}
|
|
858
|
+
|
|
859
|
+
// 2) Fallback to DOM <track> elements (works before tracks are fully loaded)
|
|
860
|
+
const trackEls = Array.from(this.player.element.querySelectorAll('track[kind="chapters"]'));
|
|
861
|
+
if (trackEls.length > 0) return true;
|
|
862
|
+
|
|
863
|
+
// 3) Playlist metadata fallback (works even when we intentionally defer loading)
|
|
864
|
+
const current = this.player.playlistManager?.getCurrentTrack?.();
|
|
865
|
+
if (current?.tracks && Array.isArray(current.tracks)) {
|
|
866
|
+
return current.tracks.some(t => t?.kind === 'chapters');
|
|
854
867
|
}
|
|
868
|
+
|
|
855
869
|
return false;
|
|
856
870
|
}
|
|
857
871
|
|
|
858
872
|
hasCaptionTracks() {
|
|
873
|
+
// 1) Prefer already-loaded TextTracks
|
|
859
874
|
const textTracks = this.player.element.textTracks;
|
|
860
875
|
for (let i = 0; i < textTracks.length; i++) {
|
|
861
|
-
if (textTracks[i].kind === 'captions' || textTracks[i].kind === 'subtitles')
|
|
876
|
+
if (textTracks[i].kind === 'captions' || textTracks[i].kind === 'subtitles') return true;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// 2) Fallback to DOM <track> elements
|
|
880
|
+
const trackEls = Array.from(this.player.element.querySelectorAll('track'));
|
|
881
|
+
if (trackEls.some(el => (el.getAttribute('kind') === 'captions' || el.getAttribute('kind') === 'subtitles'))) {
|
|
862
882
|
return true;
|
|
863
883
|
}
|
|
884
|
+
|
|
885
|
+
// 3) Playlist metadata fallback
|
|
886
|
+
const current = this.player.playlistManager?.getCurrentTrack?.();
|
|
887
|
+
if (current?.tracks && Array.isArray(current.tracks)) {
|
|
888
|
+
return current.tracks.some(t => t?.kind === 'captions' || t?.kind === 'subtitles');
|
|
864
889
|
}
|
|
890
|
+
|
|
865
891
|
return false;
|
|
866
892
|
}
|
|
867
893
|
|
|
@@ -963,6 +989,8 @@ export class ControlBar {
|
|
|
963
989
|
this.currentPreviewTime = null;
|
|
964
990
|
this.previewThumbnailTimeout = null;
|
|
965
991
|
this.previewSupported = false;
|
|
992
|
+
this.previewVideoReady = false;
|
|
993
|
+
this.previewVideoInitialized = false;
|
|
966
994
|
|
|
967
995
|
// Check if preview is supported (HTML5 video only)
|
|
968
996
|
// Check if element is a video
|
|
@@ -972,80 +1000,75 @@ export class ControlBar {
|
|
|
972
1000
|
return;
|
|
973
1001
|
}
|
|
974
1002
|
|
|
975
|
-
//
|
|
976
|
-
//
|
|
977
|
-
|
|
1003
|
+
// IMPORTANT: do NOT create/load the preview video until the user has started playback at least once.
|
|
1004
|
+
// Otherwise we'd trigger heavy MP4 network traffic just by hovering the progress bar.
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
/**
|
|
1008
|
+
* Lazily create the hidden preview video (only after playback started once)
|
|
1009
|
+
*/
|
|
1010
|
+
ensurePreviewVideoInitialized() {
|
|
1011
|
+
if (this.previewVideoInitialized) return;
|
|
1012
|
+
if (!this.player?.state?.hasStartedPlayback) return;
|
|
1013
|
+
|
|
978
1014
|
const renderer = this.player.renderer;
|
|
979
1015
|
const hasVideoMedia = renderer && renderer.media && renderer.media.tagName === 'VIDEO';
|
|
980
|
-
|
|
981
|
-
// Check if it's HTML5Renderer by checking:
|
|
982
|
-
// 1. Has media property that is a video element
|
|
983
|
-
// 2. Media is the same as player.element (HTML5Renderer sets this.media = player.element)
|
|
984
|
-
// 3. Doesn't have hls property (HLSRenderer has hls property)
|
|
985
|
-
// 4. Has seek method (all renderers have this, but combined with above checks it's reliable)
|
|
986
|
-
const isHTML5Renderer = hasVideoMedia &&
|
|
1016
|
+
const isHTML5Renderer = hasVideoMedia &&
|
|
987
1017
|
renderer.media === this.player.element &&
|
|
988
1018
|
!renderer.hls &&
|
|
989
1019
|
typeof renderer.seek === 'function';
|
|
990
|
-
|
|
1020
|
+
|
|
991
1021
|
this.previewSupported = isHTML5Renderer && hasVideoMedia;
|
|
1022
|
+
if (!this.previewSupported) return;
|
|
992
1023
|
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
this.previewVideo.style.width = '1px';
|
|
1002
|
-
this.previewVideo.style.height = '1px';
|
|
1003
|
-
this.previewVideo.style.top = '-9999px';
|
|
1004
|
-
|
|
1005
|
-
// Copy source and attributes from main video
|
|
1006
|
-
const mainVideo = renderer.media || this.player.element;
|
|
1007
|
-
let videoSrc = null;
|
|
1008
|
-
|
|
1009
|
-
if (mainVideo.src) {
|
|
1010
|
-
videoSrc = mainVideo.src;
|
|
1011
|
-
} else {
|
|
1012
|
-
const source = mainVideo.querySelector('source');
|
|
1013
|
-
if (source) {
|
|
1014
|
-
videoSrc = source.src;
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
if (!videoSrc) {
|
|
1019
|
-
this.player.log('No video source found for preview', 'warn');
|
|
1020
|
-
this.previewSupported = false;
|
|
1021
|
-
return;
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
// Copy crossOrigin if set (important for CORS)
|
|
1025
|
-
if (mainVideo.crossOrigin) {
|
|
1026
|
-
this.previewVideo.crossOrigin = mainVideo.crossOrigin;
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
// Handle errors gracefully
|
|
1030
|
-
this.previewVideo.addEventListener('error', (e) => {
|
|
1031
|
-
this.player.log('Preview video failed to load:', e, 'warn');
|
|
1032
|
-
this.previewSupported = false;
|
|
1033
|
-
});
|
|
1034
|
-
|
|
1035
|
-
// Wait for metadata to be loaded before using
|
|
1036
|
-
this.previewVideo.addEventListener('loadedmetadata', () => {
|
|
1037
|
-
this.previewVideoReady = true;
|
|
1038
|
-
}, { once: true });
|
|
1039
|
-
|
|
1040
|
-
// Append to player container (hidden) BEFORE setting src
|
|
1041
|
-
if (this.player.container) {
|
|
1042
|
-
this.player.container.appendChild(this.previewVideo);
|
|
1024
|
+
const mainVideo = renderer.media || this.player.element;
|
|
1025
|
+
let videoSrc = null;
|
|
1026
|
+
if (mainVideo.src) {
|
|
1027
|
+
videoSrc = mainVideo.src;
|
|
1028
|
+
} else {
|
|
1029
|
+
const source = mainVideo.querySelector('source');
|
|
1030
|
+
if (source) {
|
|
1031
|
+
videoSrc = source.src;
|
|
1043
1032
|
}
|
|
1044
|
-
|
|
1045
|
-
// Set source after appending to DOM
|
|
1046
|
-
this.previewVideo.src = videoSrc;
|
|
1047
|
-
this.previewVideoReady = false;
|
|
1048
1033
|
}
|
|
1034
|
+
|
|
1035
|
+
if (!videoSrc) {
|
|
1036
|
+
this.player.log('No video source found for preview', 'warn');
|
|
1037
|
+
this.previewSupported = false;
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
// Create a hidden video element for capturing frames
|
|
1042
|
+
this.previewVideo = document.createElement('video');
|
|
1043
|
+
this.previewVideo.muted = true;
|
|
1044
|
+
this.previewVideo.preload = 'auto'; // Need more than metadata to capture frames
|
|
1045
|
+
this.previewVideo.playsInline = true;
|
|
1046
|
+
this.previewVideo.style.position = 'absolute';
|
|
1047
|
+
this.previewVideo.style.visibility = 'hidden';
|
|
1048
|
+
this.previewVideo.style.width = '1px';
|
|
1049
|
+
this.previewVideo.style.height = '1px';
|
|
1050
|
+
this.previewVideo.style.top = '-9999px';
|
|
1051
|
+
|
|
1052
|
+
if (mainVideo.crossOrigin) {
|
|
1053
|
+
this.previewVideo.crossOrigin = mainVideo.crossOrigin;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
this.previewVideo.addEventListener('error', (e) => {
|
|
1057
|
+
this.player.log('Preview video failed to load:', e, 'warn');
|
|
1058
|
+
this.previewSupported = false;
|
|
1059
|
+
});
|
|
1060
|
+
|
|
1061
|
+
this.previewVideo.addEventListener('loadedmetadata', () => {
|
|
1062
|
+
this.previewVideoReady = true;
|
|
1063
|
+
}, { once: true });
|
|
1064
|
+
|
|
1065
|
+
if (this.player.container) {
|
|
1066
|
+
this.player.container.appendChild(this.previewVideo);
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
this.previewVideo.src = videoSrc;
|
|
1070
|
+
this.previewVideoReady = false;
|
|
1071
|
+
this.previewVideoInitialized = true;
|
|
1049
1072
|
}
|
|
1050
1073
|
|
|
1051
1074
|
/**
|
|
@@ -1218,10 +1241,21 @@ export class ControlBar {
|
|
|
1218
1241
|
// Update tooltip position
|
|
1219
1242
|
this.controls.progressTooltip.style.left = `${left}px`;
|
|
1220
1243
|
this.controls.progressTooltip.style.display = 'block';
|
|
1221
|
-
|
|
1222
|
-
//
|
|
1244
|
+
|
|
1245
|
+
// Only show preview thumbnails after the user has started playback at least once.
|
|
1246
|
+
// Before that, show just the timestamp (no empty preview box).
|
|
1247
|
+
if (!this.player?.state?.hasStartedPlayback) {
|
|
1248
|
+
if (this.controls.progressPreview) {
|
|
1249
|
+
this.controls.progressPreview.style.display = 'none';
|
|
1250
|
+
}
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
this.ensurePreviewVideoInitialized();
|
|
1223
1255
|
if (this.previewSupported) {
|
|
1224
1256
|
this.updatePreviewThumbnail(time);
|
|
1257
|
+
} else if (this.controls.progressPreview) {
|
|
1258
|
+
this.controls.progressPreview.style.display = 'none';
|
|
1225
1259
|
}
|
|
1226
1260
|
}
|
|
1227
1261
|
});
|