Remove course thumbnails and the ffmpeg dependency
Course cards go back to the colour-block art that previously sat under the captured frame, so the UI is unchanged apart from losing the photo. - Drop thumb.php, generateThumbnails(), captureThumbnail() and ensureThumbnailColumns(), plus the first-video tracking the scanner only kept to pick a frame source. - Drop the ffprobe fallback in probeDuration(); the pure-PHP mvhd parse is now the only scan-time probe, with the player's report on first play as the remaining fallback. - Drop THUMBNAILS_DIR/THUMBNAIL_SEEK_PERCENT from config, the thumbnail_* columns from schema.sql, the thumbnail counters from scan output, .thumb img from the stylesheet, and the matching README parts. Existing databases keep two now-unused folders.thumbnail_* columns; they are inert and can be dropped by hand if wanted. Claude-Session: https://claude.ai/code/session_014oyi9DMdhALrGz989MNNZJ
This commit is contained in:
+5
-9
@@ -348,14 +348,10 @@
|
||||
const bar = (percent, hue) =>
|
||||
`<div class="bar"${hue ? ` style="--c:${hue}"` : ''}><span style="width:${Math.max(0, Math.min(100, percent))}%"></span></div>`;
|
||||
|
||||
// A course thumbnail is a real captured frame when the scanner made one
|
||||
// (see generateThumbnails() server-side); until then, or if the request
|
||||
// 404s, onerror drops the broken <img> and the colour block underneath
|
||||
// (already painted — cat/dur/play/percent all sit above it) shows through.
|
||||
function thumb(hue, { cat, dur, play, percent, courseId } = {}) {
|
||||
// Courses have no cover art, so the card art is a colour block in the
|
||||
// course's own hue, with the cat/dur/play/percent overlays on top.
|
||||
function thumb(hue, { cat, dur, play, percent } = {}) {
|
||||
return `<div class="thumb" style="--c:${hue}">
|
||||
${courseId ? `<img src="thumb.php?course_id=${courseId}" alt="" loading="lazy"
|
||||
onerror="this.remove()">` : ''}
|
||||
${cat ? `<span class="thumb-cat">${esc(cat)}</span>` : ''}
|
||||
${dur ? `<span class="thumb-dur">${esc(dur)}</span>` : ''}
|
||||
${play ? `<span class="thumb-play"><span>${iconFill('play', 20)}</span></span>` : ''}
|
||||
@@ -367,7 +363,7 @@
|
||||
function courseCard(c) {
|
||||
const hue = hueOf(c.id);
|
||||
return `<a class="course-card" href="#/folder/${c.id}">
|
||||
${thumb(hue, { cat: SHELF_NAME[c.state], dur: fmtLong(c.duration), courseId: c.id })}
|
||||
${thumb(hue, { cat: SHELF_NAME[c.state], dur: fmtLong(c.duration) })}
|
||||
<div class="course-card-body">
|
||||
<div class="course-title">${esc(c.name)}</div>
|
||||
<div class="course-meta">${esc(courseMeta(c))}</div>
|
||||
@@ -540,7 +536,7 @@
|
||||
const left = resume.duration ? Math.max(0, resume.duration - resume.position) : 0;
|
||||
const hue = hueOf(resume.course_id ?? resume.id);
|
||||
return `<div class="hero">
|
||||
<div class="hero-art">${thumb(hue, { play: true, percent: pct, courseId: resume.course_id })}</div>
|
||||
<div class="hero-art">${thumb(hue, { play: true, percent: pct })}</div>
|
||||
<div class="hero-body">
|
||||
<span class="hero-eyebrow">Continue watching</span>
|
||||
<div class="hero-title">${esc(resume.name)}</div>
|
||||
|
||||
@@ -568,17 +568,6 @@ button, input { font-family: inherit; font-size: inherit; }
|
||||
}
|
||||
.thumb::before { top: -30%; right: -12%; width: 62%; background: rgba(255, 255, 255, .2); }
|
||||
.thumb::after { left: -8%; bottom: -32%; width: 48%; background: rgba(16, 15, 13, .14); }
|
||||
/* A captured frame sits above the decorative blobs (opaque, so it fully
|
||||
hides them once loaded) but below the text/icon overlays. onerror removes
|
||||
this element on a 404, leaving the colour-block placeholder untouched. */
|
||||
.thumb img {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
z-index: 1;
|
||||
}
|
||||
.thumb-cat {
|
||||
position: absolute;
|
||||
left: 10px; top: 8px;
|
||||
|
||||
Reference in New Issue
Block a user