1 Commits
1.0.0 ... main

Author SHA1 Message Date
2aa00e162f feat: 智能选择非黑色视频封面帧 2026-04-29 17:02:12 +08:00
2 changed files with 87 additions and 2 deletions

86
main.js
View File

@@ -3790,6 +3790,71 @@ var fillAudioPreviewArtwork = (app, file, cover) => {
img.alt = file.name;
});
};
var waitForSeek = (video, time) => new Promise((resolve) => {
const onSeeked = () => {
video.removeEventListener("seeked", onSeeked);
resolve();
};
video.addEventListener("seeked", onSeeked, { once: true });
try {
video.currentTime = time;
} catch (error) {
video.removeEventListener("seeked", onSeeked);
resolve();
}
});
var isCanvasFrameMostlyBlack = (ctx, width, height) => {
const sampleWidth = Math.max(8, Math.min(64, width));
const sampleHeight = Math.max(8, Math.min(64, height));
const imageData = ctx.getImageData(0, 0, sampleWidth, sampleHeight).data;
let brightPixels = 0;
let totalPixels = 0;
for (let i = 0; i < imageData.length; i += 4) {
const luminance = imageData[i] * 0.2126 + imageData[i + 1] * 0.7152 + imageData[i + 2] * 0.0722;
if (luminance >= 20)
brightPixels++;
totalPixels++;
}
if (!totalPixels)
return true;
return brightPixels / totalPixels < 0.02;
};
var pickNonBlackVideoCoverTime = (video) => __async(null, null, function* () {
const duration = Number.isFinite(video.duration) ? video.duration : 0;
if (duration <= 0.1)
return 0;
const canvas = document.createElement("canvas");
canvas.width = 64;
canvas.height = 64;
const ctx = canvas.getContext("2d", { willReadFrequently: true });
if (!ctx)
return 0;
const checkpoints = [
0.02,
0.06,
0.12,
0.2,
0.35,
0.5,
0.7,
0.85
];
const tried = /* @__PURE__ */ new Set();
for (const ratio of checkpoints) {
const target = Math.min(Math.max(duration * ratio, 0), Math.max(duration - 0.05, 0));
const bucket = Math.round(target * 100);
if (tried.has(bucket))
continue;
tried.add(bucket);
yield waitForSeek(video, target);
if (video.readyState < 2)
continue;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
if (!isCanvasFrameMostlyBlack(ctx, canvas.width, canvas.height))
return target;
}
return 0;
});
var appendAudioPreview = (app, figure, file, settings) => {
figure.addClass("img-gallery-audio-item");
const audioCard = figure.createEl("div", { cls: "img-gallery-audio-card" });
@@ -3821,13 +3886,32 @@ var appendPreviewMedia = (app, figure, file, settings) => {
"object-position": "center center",
display: "block"
});
let coverTime = 0;
let coverInitialized = false;
const ensureVideoCover = () => __async(null, null, function* () {
if (coverInitialized)
return;
coverInitialized = true;
video.pause();
const pickedTime = yield pickNonBlackVideoCoverTime(video);
coverTime = Number.isFinite(pickedTime) ? pickedTime : 0;
yield waitForSeek(video, coverTime);
video.pause();
});
video.addEventListener("loadedmetadata", () => {
void ensureVideoCover();
}, { once: true });
video.addEventListener("mouseenter", () => {
void video.play().catch(() => {
});
});
video.addEventListener("mouseleave", () => {
video.pause();
video.currentTime = 0;
if (coverInitialized) {
void waitForSeek(video, coverTime);
} else {
video.currentTime = 0;
}
});
return video;
}

View File

@@ -2,5 +2,6 @@
"1.0.0": "0.14.6",
"1.1.0": "1.1.8",
"1.1.1": "1.1.8",
"2.0.0": "1.1.8"
"2.0.0": "1.1.8",
"2.0.1": "2.0.1"
}