vidply 1.0.29 → 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.HLSRenderer-UMPUDSYL.js +266 -0
- package/dist/dev/vidply.HLSRenderer-UMPUDSYL.js.map +7 -0
- package/dist/dev/vidply.HTML5Renderer-FXBZQL6Y.js +12 -0
- package/dist/dev/vidply.HTML5Renderer-FXBZQL6Y.js.map +7 -0
- package/dist/dev/vidply.chunk-W2LSBD6Y.js +251 -0
- package/dist/dev/vidply.chunk-W2LSBD6Y.js.map +7 -0
- package/dist/dev/vidply.esm.js +374 -5
- package/dist/dev/vidply.esm.js.map +3 -3
- package/dist/legacy/vidply.js +378 -3
- package/dist/legacy/vidply.js.map +3 -3
- package/dist/legacy/vidply.min.js +1 -1
- package/dist/legacy/vidply.min.meta.json +25 -7
- package/dist/prod/vidply.HLSRenderer-3CG7BZKA.min.js +6 -0
- package/dist/prod/vidply.HTML5Renderer-KKW3OLHM.min.js +6 -0
- package/dist/prod/vidply.chunk-34RH2THY.min.js +6 -0
- package/dist/prod/vidply.esm.min.js +4 -4
- package/dist/vidply.css +20 -1
- package/dist/vidply.esm.min.meta.json +34 -16
- package/dist/vidply.min.css +1 -1
- package/package.json +2 -2
- package/src/controls/ControlBar.js +325 -3
- package/src/core/Player.js +4868 -4776
- package/src/renderers/HTML5Renderer.js +7 -0
- package/src/styles/vidply.css +20 -1
- package/src/utils/VideoFrameCapture.js +119 -0
package/dist/legacy/vidply.js
CHANGED
|
@@ -1741,6 +1741,11 @@
|
|
|
1741
1741
|
this.media.addEventListener("loadedmetadata", () => {
|
|
1742
1742
|
this.player.state.duration = this.media.duration;
|
|
1743
1743
|
this.player.emit("loadedmetadata");
|
|
1744
|
+
if (this.media.tagName === "VIDEO") {
|
|
1745
|
+
this.player.autoGeneratePoster().catch((error) => {
|
|
1746
|
+
this.player.log("Failed to auto-generate poster:", error, "warn");
|
|
1747
|
+
});
|
|
1748
|
+
}
|
|
1744
1749
|
});
|
|
1745
1750
|
this.media.addEventListener("play", () => {
|
|
1746
1751
|
this.player.state.playing = true;
|
|
@@ -5574,6 +5579,88 @@
|
|
|
5574
5579
|
setTimeout(execute, timeout);
|
|
5575
5580
|
}
|
|
5576
5581
|
|
|
5582
|
+
// src/utils/VideoFrameCapture.js
|
|
5583
|
+
async function captureVideoFrame(video, time, options = {}) {
|
|
5584
|
+
if (!video || video.tagName !== "VIDEO") {
|
|
5585
|
+
return null;
|
|
5586
|
+
}
|
|
5587
|
+
const {
|
|
5588
|
+
restoreState = true,
|
|
5589
|
+
quality = 0.9,
|
|
5590
|
+
maxWidth,
|
|
5591
|
+
maxHeight
|
|
5592
|
+
} = options;
|
|
5593
|
+
const wasPlaying = !video.paused;
|
|
5594
|
+
const originalTime = video.currentTime;
|
|
5595
|
+
const originalMuted = video.muted;
|
|
5596
|
+
if (restoreState) {
|
|
5597
|
+
video.muted = true;
|
|
5598
|
+
}
|
|
5599
|
+
return new Promise((resolve) => {
|
|
5600
|
+
const captureFrame = () => {
|
|
5601
|
+
try {
|
|
5602
|
+
let width = video.videoWidth || 640;
|
|
5603
|
+
let height = video.videoHeight || 360;
|
|
5604
|
+
if (maxWidth && width > maxWidth) {
|
|
5605
|
+
const ratio = maxWidth / width;
|
|
5606
|
+
width = maxWidth;
|
|
5607
|
+
height = Math.round(height * ratio);
|
|
5608
|
+
}
|
|
5609
|
+
if (maxHeight && height > maxHeight) {
|
|
5610
|
+
const ratio = maxHeight / height;
|
|
5611
|
+
height = maxHeight;
|
|
5612
|
+
width = Math.round(width * ratio);
|
|
5613
|
+
}
|
|
5614
|
+
const canvas = document.createElement("canvas");
|
|
5615
|
+
canvas.width = width;
|
|
5616
|
+
canvas.height = height;
|
|
5617
|
+
const ctx = canvas.getContext("2d");
|
|
5618
|
+
ctx.drawImage(video, 0, 0, width, height);
|
|
5619
|
+
const dataURL = canvas.toDataURL("image/jpeg", quality);
|
|
5620
|
+
if (restoreState) {
|
|
5621
|
+
video.currentTime = originalTime;
|
|
5622
|
+
video.muted = originalMuted;
|
|
5623
|
+
if (wasPlaying && !video.paused) {
|
|
5624
|
+
video.play().catch(() => {
|
|
5625
|
+
});
|
|
5626
|
+
}
|
|
5627
|
+
}
|
|
5628
|
+
resolve(dataURL);
|
|
5629
|
+
} catch (error) {
|
|
5630
|
+
if (restoreState) {
|
|
5631
|
+
video.currentTime = originalTime;
|
|
5632
|
+
video.muted = originalMuted;
|
|
5633
|
+
if (wasPlaying && !video.paused) {
|
|
5634
|
+
video.play().catch(() => {
|
|
5635
|
+
});
|
|
5636
|
+
}
|
|
5637
|
+
}
|
|
5638
|
+
resolve(null);
|
|
5639
|
+
}
|
|
5640
|
+
};
|
|
5641
|
+
const onSeeked = () => {
|
|
5642
|
+
video.removeEventListener("seeked", onSeeked);
|
|
5643
|
+
requestAnimationFrame(() => {
|
|
5644
|
+
requestAnimationFrame(captureFrame);
|
|
5645
|
+
});
|
|
5646
|
+
};
|
|
5647
|
+
const timeDiff = Math.abs(video.currentTime - time);
|
|
5648
|
+
if (timeDiff < 0.1 && video.readyState >= 2) {
|
|
5649
|
+
captureFrame();
|
|
5650
|
+
} else if (video.readyState >= 1) {
|
|
5651
|
+
video.addEventListener("seeked", onSeeked);
|
|
5652
|
+
video.currentTime = time;
|
|
5653
|
+
} else {
|
|
5654
|
+
const onLoadedMetadata = () => {
|
|
5655
|
+
video.removeEventListener("loadedmetadata", onLoadedMetadata);
|
|
5656
|
+
video.addEventListener("seeked", onSeeked);
|
|
5657
|
+
video.currentTime = time;
|
|
5658
|
+
};
|
|
5659
|
+
video.addEventListener("loadedmetadata", onLoadedMetadata);
|
|
5660
|
+
}
|
|
5661
|
+
});
|
|
5662
|
+
}
|
|
5663
|
+
|
|
5577
5664
|
// src/controls/ControlBar.js
|
|
5578
5665
|
var ControlBar = class {
|
|
5579
5666
|
constructor(player) {
|
|
@@ -6211,13 +6298,184 @@
|
|
|
6211
6298
|
this.controls.progressTooltip = DOMUtils.createElement("div", {
|
|
6212
6299
|
className: "".concat(this.player.options.classPrefix, "-progress-tooltip")
|
|
6213
6300
|
});
|
|
6301
|
+
this.controls.progressPreview = DOMUtils.createElement("div", {
|
|
6302
|
+
className: "".concat(this.player.options.classPrefix, "-progress-preview"),
|
|
6303
|
+
attributes: {
|
|
6304
|
+
"aria-hidden": "true"
|
|
6305
|
+
}
|
|
6306
|
+
});
|
|
6307
|
+
this.controls.progressTooltip.appendChild(this.controls.progressPreview);
|
|
6308
|
+
this.controls.progressTooltipTime = DOMUtils.createElement("div", {
|
|
6309
|
+
className: "".concat(this.player.options.classPrefix, "-progress-tooltip-time")
|
|
6310
|
+
});
|
|
6311
|
+
this.controls.progressTooltip.appendChild(this.controls.progressTooltipTime);
|
|
6214
6312
|
progressContainer.appendChild(this.controls.buffered);
|
|
6215
6313
|
progressContainer.appendChild(this.controls.played);
|
|
6216
6314
|
this.controls.played.appendChild(this.controls.progressHandle);
|
|
6217
6315
|
progressContainer.appendChild(this.controls.progressTooltip);
|
|
6218
6316
|
this.controls.progress = progressContainer;
|
|
6317
|
+
this.initPreviewThumbnail();
|
|
6219
6318
|
this.setupProgressBarEvents();
|
|
6220
6319
|
}
|
|
6320
|
+
/**
|
|
6321
|
+
* Initialize preview thumbnail functionality for HTML5 video
|
|
6322
|
+
*/
|
|
6323
|
+
initPreviewThumbnail() {
|
|
6324
|
+
this.previewThumbnailCache = /* @__PURE__ */ new Map();
|
|
6325
|
+
this.previewVideo = null;
|
|
6326
|
+
this.currentPreviewTime = null;
|
|
6327
|
+
this.previewThumbnailTimeout = null;
|
|
6328
|
+
this.previewSupported = false;
|
|
6329
|
+
const isVideo = this.player.element && this.player.element.tagName === "VIDEO";
|
|
6330
|
+
if (!isVideo) {
|
|
6331
|
+
return;
|
|
6332
|
+
}
|
|
6333
|
+
const renderer = this.player.renderer;
|
|
6334
|
+
const hasVideoMedia = renderer && renderer.media && renderer.media.tagName === "VIDEO";
|
|
6335
|
+
const isHTML5Renderer = hasVideoMedia && renderer.media === this.player.element && !renderer.hls && typeof renderer.seek === "function";
|
|
6336
|
+
this.previewSupported = isHTML5Renderer && hasVideoMedia;
|
|
6337
|
+
if (this.previewSupported) {
|
|
6338
|
+
this.previewVideo = document.createElement("video");
|
|
6339
|
+
this.previewVideo.muted = true;
|
|
6340
|
+
this.previewVideo.preload = "auto";
|
|
6341
|
+
this.previewVideo.playsInline = true;
|
|
6342
|
+
this.previewVideo.style.position = "absolute";
|
|
6343
|
+
this.previewVideo.style.visibility = "hidden";
|
|
6344
|
+
this.previewVideo.style.width = "1px";
|
|
6345
|
+
this.previewVideo.style.height = "1px";
|
|
6346
|
+
this.previewVideo.style.top = "-9999px";
|
|
6347
|
+
const mainVideo = renderer.media || this.player.element;
|
|
6348
|
+
let videoSrc = null;
|
|
6349
|
+
if (mainVideo.src) {
|
|
6350
|
+
videoSrc = mainVideo.src;
|
|
6351
|
+
} else {
|
|
6352
|
+
const source = mainVideo.querySelector("source");
|
|
6353
|
+
if (source) {
|
|
6354
|
+
videoSrc = source.src;
|
|
6355
|
+
}
|
|
6356
|
+
}
|
|
6357
|
+
if (!videoSrc) {
|
|
6358
|
+
this.player.log("No video source found for preview", "warn");
|
|
6359
|
+
this.previewSupported = false;
|
|
6360
|
+
return;
|
|
6361
|
+
}
|
|
6362
|
+
if (mainVideo.crossOrigin) {
|
|
6363
|
+
this.previewVideo.crossOrigin = mainVideo.crossOrigin;
|
|
6364
|
+
}
|
|
6365
|
+
this.previewVideo.addEventListener("error", (e) => {
|
|
6366
|
+
this.player.log("Preview video failed to load:", e, "warn");
|
|
6367
|
+
this.previewSupported = false;
|
|
6368
|
+
});
|
|
6369
|
+
this.previewVideo.addEventListener("loadedmetadata", () => {
|
|
6370
|
+
this.previewVideoReady = true;
|
|
6371
|
+
}, { once: true });
|
|
6372
|
+
if (this.player.container) {
|
|
6373
|
+
this.player.container.appendChild(this.previewVideo);
|
|
6374
|
+
}
|
|
6375
|
+
this.previewVideo.src = videoSrc;
|
|
6376
|
+
this.previewVideoReady = false;
|
|
6377
|
+
}
|
|
6378
|
+
}
|
|
6379
|
+
/**
|
|
6380
|
+
* Generate preview thumbnail for a specific time
|
|
6381
|
+
* @param {number} time - Time in seconds
|
|
6382
|
+
* @returns {Promise<string>} Data URL of the thumbnail
|
|
6383
|
+
*/
|
|
6384
|
+
async generatePreviewThumbnail(time) {
|
|
6385
|
+
if (!this.previewSupported || !this.previewVideo) {
|
|
6386
|
+
return null;
|
|
6387
|
+
}
|
|
6388
|
+
if (!this.previewVideoReady) {
|
|
6389
|
+
if (this.previewVideo.readyState < 2) {
|
|
6390
|
+
await new Promise((resolve, reject) => {
|
|
6391
|
+
const timeout = setTimeout(() => {
|
|
6392
|
+
reject(new Error("Preview video data load timeout"));
|
|
6393
|
+
}, 1e4);
|
|
6394
|
+
const cleanup = () => {
|
|
6395
|
+
clearTimeout(timeout);
|
|
6396
|
+
this.previewVideo.removeEventListener("loadeddata", checkReady);
|
|
6397
|
+
this.previewVideo.removeEventListener("canplay", checkReady);
|
|
6398
|
+
this.previewVideo.removeEventListener("error", onError);
|
|
6399
|
+
};
|
|
6400
|
+
const checkReady = () => {
|
|
6401
|
+
if (this.previewVideo.readyState >= 2) {
|
|
6402
|
+
cleanup();
|
|
6403
|
+
this.previewVideoReady = true;
|
|
6404
|
+
resolve();
|
|
6405
|
+
}
|
|
6406
|
+
};
|
|
6407
|
+
const onError = () => {
|
|
6408
|
+
cleanup();
|
|
6409
|
+
reject(new Error("Preview video failed to load"));
|
|
6410
|
+
};
|
|
6411
|
+
if (this.previewVideo.readyState >= 1) {
|
|
6412
|
+
this.previewVideo.addEventListener("loadeddata", checkReady);
|
|
6413
|
+
}
|
|
6414
|
+
this.previewVideo.addEventListener("canplay", checkReady);
|
|
6415
|
+
this.previewVideo.addEventListener("error", onError);
|
|
6416
|
+
if (this.previewVideo.readyState >= 2) {
|
|
6417
|
+
checkReady();
|
|
6418
|
+
}
|
|
6419
|
+
}).catch(() => {
|
|
6420
|
+
this.previewSupported = false;
|
|
6421
|
+
return null;
|
|
6422
|
+
});
|
|
6423
|
+
} else {
|
|
6424
|
+
this.previewVideoReady = true;
|
|
6425
|
+
}
|
|
6426
|
+
}
|
|
6427
|
+
const cacheKey = Math.floor(time);
|
|
6428
|
+
if (this.previewThumbnailCache.has(cacheKey)) {
|
|
6429
|
+
return this.previewThumbnailCache.get(cacheKey);
|
|
6430
|
+
}
|
|
6431
|
+
const dataURL = await captureVideoFrame(this.previewVideo, time, {
|
|
6432
|
+
restoreState: false,
|
|
6433
|
+
quality: 0.8,
|
|
6434
|
+
maxWidth: 160,
|
|
6435
|
+
maxHeight: 90
|
|
6436
|
+
});
|
|
6437
|
+
if (dataURL) {
|
|
6438
|
+
if (this.previewThumbnailCache.size >= 20) {
|
|
6439
|
+
const firstKey = this.previewThumbnailCache.keys().next().value;
|
|
6440
|
+
this.previewThumbnailCache.delete(firstKey);
|
|
6441
|
+
}
|
|
6442
|
+
this.previewThumbnailCache.set(cacheKey, dataURL);
|
|
6443
|
+
}
|
|
6444
|
+
return dataURL;
|
|
6445
|
+
}
|
|
6446
|
+
/**
|
|
6447
|
+
* Update preview thumbnail display
|
|
6448
|
+
* @param {number} time - Time in seconds
|
|
6449
|
+
*/
|
|
6450
|
+
async updatePreviewThumbnail(time) {
|
|
6451
|
+
if (!this.previewSupported || !this.controls.progressPreview) {
|
|
6452
|
+
return;
|
|
6453
|
+
}
|
|
6454
|
+
if (this.previewThumbnailTimeout) {
|
|
6455
|
+
clearTimeout(this.previewThumbnailTimeout);
|
|
6456
|
+
}
|
|
6457
|
+
this.previewThumbnailTimeout = setTimeout(async () => {
|
|
6458
|
+
try {
|
|
6459
|
+
const thumbnail = await this.generatePreviewThumbnail(time);
|
|
6460
|
+
if (thumbnail && this.controls.progressPreview) {
|
|
6461
|
+
this.controls.progressPreview.style.backgroundImage = 'url("'.concat(thumbnail, '")');
|
|
6462
|
+
this.controls.progressPreview.style.display = "block";
|
|
6463
|
+
this.controls.progressPreview.style.backgroundRepeat = "no-repeat";
|
|
6464
|
+
this.controls.progressPreview.style.backgroundPosition = "center";
|
|
6465
|
+
} else {
|
|
6466
|
+
if (this.controls.progressPreview) {
|
|
6467
|
+
this.controls.progressPreview.style.display = "none";
|
|
6468
|
+
}
|
|
6469
|
+
}
|
|
6470
|
+
this.currentPreviewTime = time;
|
|
6471
|
+
} catch (error) {
|
|
6472
|
+
this.player.log("Preview thumbnail update failed:", error, "warn");
|
|
6473
|
+
if (this.controls.progressPreview) {
|
|
6474
|
+
this.controls.progressPreview.style.display = "none";
|
|
6475
|
+
}
|
|
6476
|
+
}
|
|
6477
|
+
}, 100);
|
|
6478
|
+
}
|
|
6221
6479
|
setupProgressBarEvents() {
|
|
6222
6480
|
const progress = this.controls.progress;
|
|
6223
6481
|
const updateProgress = (clientX) => {
|
|
@@ -6244,13 +6502,21 @@
|
|
|
6244
6502
|
progress.addEventListener("mousemove", (e) => {
|
|
6245
6503
|
if (!this.isDraggingProgress) {
|
|
6246
6504
|
const { time } = updateProgress(e.clientX);
|
|
6247
|
-
|
|
6248
|
-
|
|
6505
|
+
const rect = progress.getBoundingClientRect();
|
|
6506
|
+
const left = e.clientX - rect.left;
|
|
6507
|
+
this.controls.progressTooltipTime.textContent = TimeUtils.formatTime(time);
|
|
6508
|
+
this.controls.progressTooltip.style.left = "".concat(left, "px");
|
|
6249
6509
|
this.controls.progressTooltip.style.display = "block";
|
|
6510
|
+
if (this.previewSupported) {
|
|
6511
|
+
this.updatePreviewThumbnail(time);
|
|
6512
|
+
}
|
|
6250
6513
|
}
|
|
6251
6514
|
});
|
|
6252
6515
|
progress.addEventListener("mouseleave", () => {
|
|
6253
6516
|
this.controls.progressTooltip.style.display = "none";
|
|
6517
|
+
if (this.previewThumbnailTimeout) {
|
|
6518
|
+
clearTimeout(this.previewThumbnailTimeout);
|
|
6519
|
+
}
|
|
6254
6520
|
});
|
|
6255
6521
|
progress.addEventListener("keydown", (e) => {
|
|
6256
6522
|
if (e.key === "ArrowLeft") {
|
|
@@ -7530,6 +7796,10 @@
|
|
|
7530
7796
|
this.updateDuration();
|
|
7531
7797
|
this.ensureQualityButton();
|
|
7532
7798
|
this.updateQualityIndicator();
|
|
7799
|
+
this.updatePreviewVideoSource();
|
|
7800
|
+
});
|
|
7801
|
+
this.player.on("sourcechange", () => {
|
|
7802
|
+
this.updatePreviewVideoSource();
|
|
7533
7803
|
});
|
|
7534
7804
|
this.player.on("volumechange", () => this.updateVolumeDisplay());
|
|
7535
7805
|
this.player.on("progress", () => this.updateBuffered());
|
|
@@ -7997,6 +8267,52 @@
|
|
|
7997
8267
|
hide() {
|
|
7998
8268
|
this.element.style.display = "none";
|
|
7999
8269
|
}
|
|
8270
|
+
/**
|
|
8271
|
+
* Update preview video source when player source changes (for playlists)
|
|
8272
|
+
* Also re-initializes if preview wasn't set up initially
|
|
8273
|
+
*/
|
|
8274
|
+
updatePreviewVideoSource() {
|
|
8275
|
+
var _a;
|
|
8276
|
+
const renderer = this.player.renderer;
|
|
8277
|
+
if (!renderer || !renderer.media || renderer.media.tagName !== "VIDEO") {
|
|
8278
|
+
return;
|
|
8279
|
+
}
|
|
8280
|
+
if (!this.previewSupported && !this.previewVideo) {
|
|
8281
|
+
this.initPreviewThumbnail();
|
|
8282
|
+
}
|
|
8283
|
+
if (!this.previewSupported || !this.previewVideo) {
|
|
8284
|
+
return;
|
|
8285
|
+
}
|
|
8286
|
+
const mainVideo = renderer.media;
|
|
8287
|
+
const newSrc = mainVideo.src || ((_a = mainVideo.querySelector("source")) == null ? void 0 : _a.src);
|
|
8288
|
+
if (newSrc && this.previewVideo.src !== newSrc) {
|
|
8289
|
+
this.previewThumbnailCache.clear();
|
|
8290
|
+
this.previewVideoReady = false;
|
|
8291
|
+
this.previewVideo.src = newSrc;
|
|
8292
|
+
if (mainVideo.crossOrigin) {
|
|
8293
|
+
this.previewVideo.crossOrigin = mainVideo.crossOrigin;
|
|
8294
|
+
}
|
|
8295
|
+
this.previewVideo.addEventListener("loadedmetadata", () => {
|
|
8296
|
+
this.previewVideoReady = true;
|
|
8297
|
+
}, { once: true });
|
|
8298
|
+
} else if (newSrc && !this.previewVideoReady && this.previewVideo.readyState >= 1) {
|
|
8299
|
+
this.previewVideoReady = true;
|
|
8300
|
+
}
|
|
8301
|
+
}
|
|
8302
|
+
/**
|
|
8303
|
+
* Cleanup preview thumbnail resources
|
|
8304
|
+
*/
|
|
8305
|
+
cleanupPreviewThumbnail() {
|
|
8306
|
+
if (this.previewThumbnailTimeout) {
|
|
8307
|
+
clearTimeout(this.previewThumbnailTimeout);
|
|
8308
|
+
this.previewThumbnailTimeout = null;
|
|
8309
|
+
}
|
|
8310
|
+
if (this.previewVideo && this.previewVideo.parentNode) {
|
|
8311
|
+
this.previewVideo.parentNode.removeChild(this.previewVideo);
|
|
8312
|
+
this.previewVideo = null;
|
|
8313
|
+
}
|
|
8314
|
+
this.previewThumbnailCache.clear();
|
|
8315
|
+
}
|
|
8000
8316
|
destroy() {
|
|
8001
8317
|
if (this.hideTimeout) {
|
|
8002
8318
|
clearTimeout(this.hideTimeout);
|
|
@@ -8004,6 +8320,7 @@
|
|
|
8004
8320
|
if (this.overflowResizeObserver) {
|
|
8005
8321
|
this.overflowResizeObserver.disconnect();
|
|
8006
8322
|
}
|
|
8323
|
+
this.cleanupPreviewThumbnail();
|
|
8007
8324
|
if (this.element && this.element.parentNode) {
|
|
8008
8325
|
this.element.parentNode.removeChild(this.element);
|
|
8009
8326
|
}
|
|
@@ -10635,6 +10952,64 @@
|
|
|
10635
10952
|
return posterPath;
|
|
10636
10953
|
}
|
|
10637
10954
|
}
|
|
10955
|
+
/**
|
|
10956
|
+
* Generate a poster image from video frame at specified time
|
|
10957
|
+
* @param {number} time - Time in seconds (default: 10)
|
|
10958
|
+
* @returns {Promise<string|null>} Data URL of the poster image or null if failed
|
|
10959
|
+
*/
|
|
10960
|
+
async generatePosterFromVideo(time = 10) {
|
|
10961
|
+
if (this.element.tagName !== "VIDEO") {
|
|
10962
|
+
return null;
|
|
10963
|
+
}
|
|
10964
|
+
const renderer = this.renderer;
|
|
10965
|
+
if (!renderer || !renderer.media || renderer.media.tagName !== "VIDEO") {
|
|
10966
|
+
return null;
|
|
10967
|
+
}
|
|
10968
|
+
const video = renderer.media;
|
|
10969
|
+
if (!video.duration || video.duration < time) {
|
|
10970
|
+
time = Math.min(time, Math.max(1, video.duration * 0.1));
|
|
10971
|
+
}
|
|
10972
|
+
let videoToUse = video;
|
|
10973
|
+
if (this.controlBar && this.controlBar.previewVideo && this.controlBar.previewSupported) {
|
|
10974
|
+
videoToUse = this.controlBar.previewVideo;
|
|
10975
|
+
}
|
|
10976
|
+
const restoreState = videoToUse === video;
|
|
10977
|
+
return await captureVideoFrame(videoToUse, time, {
|
|
10978
|
+
restoreState,
|
|
10979
|
+
quality: 0.9
|
|
10980
|
+
});
|
|
10981
|
+
}
|
|
10982
|
+
/**
|
|
10983
|
+
* Auto-generate poster from video if none is provided
|
|
10984
|
+
*/
|
|
10985
|
+
async autoGeneratePoster() {
|
|
10986
|
+
const hasPoster = this.element.getAttribute("poster") || this.element.poster || this.options.poster;
|
|
10987
|
+
if (hasPoster) {
|
|
10988
|
+
return;
|
|
10989
|
+
}
|
|
10990
|
+
if (this.element.tagName !== "VIDEO") {
|
|
10991
|
+
return;
|
|
10992
|
+
}
|
|
10993
|
+
if (!this.state.duration || this.state.duration === 0) {
|
|
10994
|
+
await new Promise((resolve) => {
|
|
10995
|
+
const onLoadedMetadata = () => {
|
|
10996
|
+
this.element.removeEventListener("loadedmetadata", onLoadedMetadata);
|
|
10997
|
+
resolve();
|
|
10998
|
+
};
|
|
10999
|
+
if (this.element.readyState >= 1) {
|
|
11000
|
+
resolve();
|
|
11001
|
+
} else {
|
|
11002
|
+
this.element.addEventListener("loadedmetadata", onLoadedMetadata);
|
|
11003
|
+
}
|
|
11004
|
+
});
|
|
11005
|
+
}
|
|
11006
|
+
const posterDataURL = await this.generatePosterFromVideo(10);
|
|
11007
|
+
if (posterDataURL) {
|
|
11008
|
+
this.element.poster = posterDataURL;
|
|
11009
|
+
this.log("Auto-generated poster from video frame at 10 seconds", "info");
|
|
11010
|
+
this.showPosterOverlay();
|
|
11011
|
+
}
|
|
11012
|
+
}
|
|
10638
11013
|
showPosterOverlay() {
|
|
10639
11014
|
if (!this.videoWrapper || this.element.tagName !== "VIDEO") {
|
|
10640
11015
|
return;
|
|
@@ -10643,7 +11018,7 @@
|
|
|
10643
11018
|
if (!poster) {
|
|
10644
11019
|
return;
|
|
10645
11020
|
}
|
|
10646
|
-
const resolvedPoster = this.resolvePosterPath(poster);
|
|
11021
|
+
const resolvedPoster = poster.startsWith("data:") ? poster : this.resolvePosterPath(poster);
|
|
10647
11022
|
this.videoWrapper.style.setProperty("--vidply-poster-image", 'url("'.concat(resolvedPoster, '")'));
|
|
10648
11023
|
this.videoWrapper.classList.add("vidply-forced-poster");
|
|
10649
11024
|
if (this._isAudioContent && this.container) {
|