vidply 1.0.30 → 1.0.31
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/dev/vidply.esm.js +126 -15
- package/dist/dev/vidply.esm.js.map +2 -2
- package/dist/legacy/vidply.js +127 -15
- package/dist/legacy/vidply.js.map +2 -2
- package/dist/legacy/vidply.min.js +1 -1
- package/dist/legacy/vidply.min.meta.json +5 -5
- package/dist/prod/vidply.esm.min.js +3 -3
- package/dist/vidply.esm.min.meta.json +5 -5
- package/package.json +1 -1
- package/src/controls/ControlBar.js +167 -21
- package/src/utils/VideoFrameCapture.js +11 -2
package/dist/dev/vidply.esm.js
CHANGED
|
@@ -159,9 +159,16 @@ async function captureVideoFrame(video, time, options = {}) {
|
|
|
159
159
|
const timeDiff = Math.abs(video.currentTime - time);
|
|
160
160
|
if (timeDiff < 0.1 && video.readyState >= 2) {
|
|
161
161
|
captureFrame();
|
|
162
|
-
} else {
|
|
162
|
+
} else if (video.readyState >= 1) {
|
|
163
163
|
video.addEventListener("seeked", onSeeked);
|
|
164
164
|
video.currentTime = time;
|
|
165
|
+
} else {
|
|
166
|
+
const onLoadedMetadata = () => {
|
|
167
|
+
video.removeEventListener("loadedmetadata", onLoadedMetadata);
|
|
168
|
+
video.addEventListener("seeked", onSeeked);
|
|
169
|
+
video.currentTime = time;
|
|
170
|
+
};
|
|
171
|
+
video.addEventListener("loadedmetadata", onLoadedMetadata);
|
|
165
172
|
}
|
|
166
173
|
});
|
|
167
174
|
}
|
|
@@ -836,33 +843,48 @@ var ControlBar = class {
|
|
|
836
843
|
}
|
|
837
844
|
const renderer = this.player.renderer;
|
|
838
845
|
const hasVideoMedia = renderer && renderer.media && renderer.media.tagName === "VIDEO";
|
|
839
|
-
const isHTML5Renderer =
|
|
846
|
+
const isHTML5Renderer = hasVideoMedia && renderer.media === this.player.element && !renderer.hls && typeof renderer.seek === "function";
|
|
840
847
|
this.previewSupported = isHTML5Renderer && hasVideoMedia;
|
|
841
848
|
if (this.previewSupported) {
|
|
842
849
|
this.previewVideo = document.createElement("video");
|
|
843
850
|
this.previewVideo.muted = true;
|
|
844
|
-
this.previewVideo.preload = "
|
|
851
|
+
this.previewVideo.preload = "auto";
|
|
852
|
+
this.previewVideo.playsInline = true;
|
|
845
853
|
this.previewVideo.style.position = "absolute";
|
|
846
854
|
this.previewVideo.style.visibility = "hidden";
|
|
847
855
|
this.previewVideo.style.width = "1px";
|
|
848
856
|
this.previewVideo.style.height = "1px";
|
|
849
857
|
this.previewVideo.style.top = "-9999px";
|
|
850
858
|
const mainVideo = renderer.media || this.player.element;
|
|
859
|
+
let videoSrc = null;
|
|
851
860
|
if (mainVideo.src) {
|
|
852
|
-
|
|
861
|
+
videoSrc = mainVideo.src;
|
|
853
862
|
} else {
|
|
854
863
|
const source = mainVideo.querySelector("source");
|
|
855
864
|
if (source) {
|
|
856
|
-
|
|
865
|
+
videoSrc = source.src;
|
|
857
866
|
}
|
|
858
867
|
}
|
|
859
|
-
|
|
860
|
-
this.player.log("
|
|
868
|
+
if (!videoSrc) {
|
|
869
|
+
this.player.log("No video source found for preview", "warn");
|
|
870
|
+
this.previewSupported = false;
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
if (mainVideo.crossOrigin) {
|
|
874
|
+
this.previewVideo.crossOrigin = mainVideo.crossOrigin;
|
|
875
|
+
}
|
|
876
|
+
this.previewVideo.addEventListener("error", (e) => {
|
|
877
|
+
this.player.log("Preview video failed to load:", e, "warn");
|
|
861
878
|
this.previewSupported = false;
|
|
862
879
|
});
|
|
880
|
+
this.previewVideo.addEventListener("loadedmetadata", () => {
|
|
881
|
+
this.previewVideoReady = true;
|
|
882
|
+
}, { once: true });
|
|
863
883
|
if (this.player.container) {
|
|
864
884
|
this.player.container.appendChild(this.previewVideo);
|
|
865
885
|
}
|
|
886
|
+
this.previewVideo.src = videoSrc;
|
|
887
|
+
this.previewVideoReady = false;
|
|
866
888
|
}
|
|
867
889
|
}
|
|
868
890
|
/**
|
|
@@ -874,6 +896,45 @@ var ControlBar = class {
|
|
|
874
896
|
if (!this.previewSupported || !this.previewVideo) {
|
|
875
897
|
return null;
|
|
876
898
|
}
|
|
899
|
+
if (!this.previewVideoReady) {
|
|
900
|
+
if (this.previewVideo.readyState < 2) {
|
|
901
|
+
await new Promise((resolve, reject) => {
|
|
902
|
+
const timeout = setTimeout(() => {
|
|
903
|
+
reject(new Error("Preview video data load timeout"));
|
|
904
|
+
}, 1e4);
|
|
905
|
+
const cleanup = () => {
|
|
906
|
+
clearTimeout(timeout);
|
|
907
|
+
this.previewVideo.removeEventListener("loadeddata", checkReady);
|
|
908
|
+
this.previewVideo.removeEventListener("canplay", checkReady);
|
|
909
|
+
this.previewVideo.removeEventListener("error", onError);
|
|
910
|
+
};
|
|
911
|
+
const checkReady = () => {
|
|
912
|
+
if (this.previewVideo.readyState >= 2) {
|
|
913
|
+
cleanup();
|
|
914
|
+
this.previewVideoReady = true;
|
|
915
|
+
resolve();
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
const onError = () => {
|
|
919
|
+
cleanup();
|
|
920
|
+
reject(new Error("Preview video failed to load"));
|
|
921
|
+
};
|
|
922
|
+
if (this.previewVideo.readyState >= 1) {
|
|
923
|
+
this.previewVideo.addEventListener("loadeddata", checkReady);
|
|
924
|
+
}
|
|
925
|
+
this.previewVideo.addEventListener("canplay", checkReady);
|
|
926
|
+
this.previewVideo.addEventListener("error", onError);
|
|
927
|
+
if (this.previewVideo.readyState >= 2) {
|
|
928
|
+
checkReady();
|
|
929
|
+
}
|
|
930
|
+
}).catch(() => {
|
|
931
|
+
this.previewSupported = false;
|
|
932
|
+
return null;
|
|
933
|
+
});
|
|
934
|
+
} else {
|
|
935
|
+
this.previewVideoReady = true;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
877
938
|
const cacheKey = Math.floor(time);
|
|
878
939
|
if (this.previewThumbnailCache.has(cacheKey)) {
|
|
879
940
|
return this.previewThumbnailCache.get(cacheKey);
|
|
@@ -885,7 +946,7 @@ var ControlBar = class {
|
|
|
885
946
|
maxHeight: 90
|
|
886
947
|
});
|
|
887
948
|
if (dataURL) {
|
|
888
|
-
if (this.previewThumbnailCache.size
|
|
949
|
+
if (this.previewThumbnailCache.size >= 20) {
|
|
889
950
|
const firstKey = this.previewThumbnailCache.keys().next().value;
|
|
890
951
|
this.previewThumbnailCache.delete(firstKey);
|
|
891
952
|
}
|
|
@@ -898,19 +959,32 @@ var ControlBar = class {
|
|
|
898
959
|
* @param {number} time - Time in seconds
|
|
899
960
|
*/
|
|
900
961
|
async updatePreviewThumbnail(time) {
|
|
901
|
-
if (!this.previewSupported) {
|
|
962
|
+
if (!this.previewSupported || !this.controls.progressPreview) {
|
|
902
963
|
return;
|
|
903
964
|
}
|
|
904
965
|
if (this.previewThumbnailTimeout) {
|
|
905
966
|
clearTimeout(this.previewThumbnailTimeout);
|
|
906
967
|
}
|
|
907
968
|
this.previewThumbnailTimeout = setTimeout(async () => {
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
this.controls.progressPreview
|
|
911
|
-
|
|
969
|
+
try {
|
|
970
|
+
const thumbnail = await this.generatePreviewThumbnail(time);
|
|
971
|
+
if (thumbnail && this.controls.progressPreview) {
|
|
972
|
+
this.controls.progressPreview.style.backgroundImage = `url("${thumbnail}")`;
|
|
973
|
+
this.controls.progressPreview.style.display = "block";
|
|
974
|
+
this.controls.progressPreview.style.backgroundRepeat = "no-repeat";
|
|
975
|
+
this.controls.progressPreview.style.backgroundPosition = "center";
|
|
976
|
+
} else {
|
|
977
|
+
if (this.controls.progressPreview) {
|
|
978
|
+
this.controls.progressPreview.style.display = "none";
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
this.currentPreviewTime = time;
|
|
982
|
+
} catch (error) {
|
|
983
|
+
this.player.log("Preview thumbnail update failed:", error, "warn");
|
|
984
|
+
if (this.controls.progressPreview) {
|
|
985
|
+
this.controls.progressPreview.style.display = "none";
|
|
986
|
+
}
|
|
912
987
|
}
|
|
913
|
-
this.currentPreviewTime = time;
|
|
914
988
|
}, 100);
|
|
915
989
|
}
|
|
916
990
|
setupProgressBarEvents() {
|
|
@@ -944,7 +1018,9 @@ var ControlBar = class {
|
|
|
944
1018
|
this.controls.progressTooltipTime.textContent = TimeUtils.formatTime(time);
|
|
945
1019
|
this.controls.progressTooltip.style.left = `${left}px`;
|
|
946
1020
|
this.controls.progressTooltip.style.display = "block";
|
|
947
|
-
this.
|
|
1021
|
+
if (this.previewSupported) {
|
|
1022
|
+
this.updatePreviewThumbnail(time);
|
|
1023
|
+
}
|
|
948
1024
|
}
|
|
949
1025
|
});
|
|
950
1026
|
progress.addEventListener("mouseleave", () => {
|
|
@@ -2231,6 +2307,10 @@ var ControlBar = class {
|
|
|
2231
2307
|
this.updateDuration();
|
|
2232
2308
|
this.ensureQualityButton();
|
|
2233
2309
|
this.updateQualityIndicator();
|
|
2310
|
+
this.updatePreviewVideoSource();
|
|
2311
|
+
});
|
|
2312
|
+
this.player.on("sourcechange", () => {
|
|
2313
|
+
this.updatePreviewVideoSource();
|
|
2234
2314
|
});
|
|
2235
2315
|
this.player.on("volumechange", () => this.updateVolumeDisplay());
|
|
2236
2316
|
this.player.on("progress", () => this.updateBuffered());
|
|
@@ -2698,6 +2778,37 @@ var ControlBar = class {
|
|
|
2698
2778
|
hide() {
|
|
2699
2779
|
this.element.style.display = "none";
|
|
2700
2780
|
}
|
|
2781
|
+
/**
|
|
2782
|
+
* Update preview video source when player source changes (for playlists)
|
|
2783
|
+
* Also re-initializes if preview wasn't set up initially
|
|
2784
|
+
*/
|
|
2785
|
+
updatePreviewVideoSource() {
|
|
2786
|
+
const renderer = this.player.renderer;
|
|
2787
|
+
if (!renderer || !renderer.media || renderer.media.tagName !== "VIDEO") {
|
|
2788
|
+
return;
|
|
2789
|
+
}
|
|
2790
|
+
if (!this.previewSupported && !this.previewVideo) {
|
|
2791
|
+
this.initPreviewThumbnail();
|
|
2792
|
+
}
|
|
2793
|
+
if (!this.previewSupported || !this.previewVideo) {
|
|
2794
|
+
return;
|
|
2795
|
+
}
|
|
2796
|
+
const mainVideo = renderer.media;
|
|
2797
|
+
const newSrc = mainVideo.src || mainVideo.querySelector("source")?.src;
|
|
2798
|
+
if (newSrc && this.previewVideo.src !== newSrc) {
|
|
2799
|
+
this.previewThumbnailCache.clear();
|
|
2800
|
+
this.previewVideoReady = false;
|
|
2801
|
+
this.previewVideo.src = newSrc;
|
|
2802
|
+
if (mainVideo.crossOrigin) {
|
|
2803
|
+
this.previewVideo.crossOrigin = mainVideo.crossOrigin;
|
|
2804
|
+
}
|
|
2805
|
+
this.previewVideo.addEventListener("loadedmetadata", () => {
|
|
2806
|
+
this.previewVideoReady = true;
|
|
2807
|
+
}, { once: true });
|
|
2808
|
+
} else if (newSrc && !this.previewVideoReady && this.previewVideo.readyState >= 1) {
|
|
2809
|
+
this.previewVideoReady = true;
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2701
2812
|
/**
|
|
2702
2813
|
* Cleanup preview thumbnail resources
|
|
2703
2814
|
*/
|