Show course runtime on library cards via ffprobe
Add ffmpeg to the Docker image so ffprobe can read each video/audio file's duration server-side. Results are cached to a small persistent per-course JSON file keyed by (relative path, size, mtime), so a file only gets probed once - a container restart or the library scan's in-memory cache expiring never re-runs ffprobe on unchanged files. Course cards in the library browser (grid, list, and search) now show total runtime alongside the media-file count, so you know the time commitment before opening a course. Durations under a minute are suppressed rather than showing a noisy "0m". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1644,12 +1644,15 @@
|
||||
const progressBar = pct
|
||||
? `<div class="grid-card-progress-track"><div class="grid-card-progress-fill" style="width: ${pct}%;"></div></div>`
|
||||
: '';
|
||||
const metaBits = [`${item.media_files} media file${item.media_files === 1 ? '' : 's'}`];
|
||||
if (item.duration_display) metaBits.push(item.duration_display);
|
||||
if (pct) metaBits.push(`${pct}% done`);
|
||||
return `
|
||||
<div class="library-grid-card" onclick="${clickHandler}">
|
||||
${selectableAttrs(item)}
|
||||
<div class="grid-card-thumb-wrap">${iconHtml}</div>
|
||||
<div class="grid-card-name" title="${escapeAttr(item.name)}">${item.name}</div>
|
||||
<div class="grid-card-meta">${item.media_files} media file${item.media_files === 1 ? '' : 's'}${pct ? ` · ${pct}% done` : ''}</div>
|
||||
<div class="grid-card-meta">${metaBits.join(' · ')}</div>
|
||||
${progressBar}
|
||||
</div>
|
||||
`;
|
||||
@@ -1688,7 +1691,7 @@
|
||||
</div>
|
||||
<div class="lesson-meta">
|
||||
${progressBadge}
|
||||
<span>${item.media_files} media file${item.media_files === 1 ? '' : 's'}</span>
|
||||
<span>${item.media_files} media file${item.media_files === 1 ? '' : 's'}${item.duration_display ? ` · ${item.duration_display}` : ''}</span>
|
||||
<button class="btn btn-secondary btn-sm" onclick="event.stopPropagation(); queueCourse('${safePath}', this)" title="Add to Next Up">${ICON_SVGS.pin}</button>
|
||||
</div>
|
||||
${progressBar}
|
||||
|
||||
Reference in New Issue
Block a user