Changeset f2943c1 in Klonkt for src/routes/admin-media.js


Ignore:
Timestamp:
06/30/2026 07:50:05 PM (2 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
65a0697
Parents:
01e3678
Message:

refactor(video-cover, media): stream frames + size cap, drop unused poster, de-dup media listing

  • VideoCoverService: composite frames straight to disk (one canvas in memory, not all N) + guard an oversized cover (MAX_FRAMES / W*H*frames) so it keeps the still image instead of spiking memory/CPU; drop the never-used JPG poster (the iOS swap uses the WebP as the video poster).
  • admin-media: extract imageEntries() shared by the list view and the cleanup route (was duplicated).

Co-Authored-By: Claude <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/routes/admin-media.js

    r01e3678 rf2943c1  
    4848function statMtime(name) { try { return fs.statSync(path.join(POST_IMAGES_DIR, name)).mtimeMs; } catch { return 0; } }
    4949
    50 router.get('/', requireGod, (req, res) => {
    51   const site = res.locals.site;
    52   if (!site) return res.status(404).send('Site required');
    53   const used = usageMap(site.id);
     50// All non-sibling images, each with its loop-MP4 sibling + how many posts use it. Shared by the
     51// list view and the cleanup route so the readdir/filter/usage logic lives in one place.
     52function imageEntries(siteId) {
     53  const used = usageMap(siteId);
    5454  let all = [];
    5555  try { all = fs.readdirSync(POST_IMAGES_DIR).filter(f => !f.startsWith('.')); } catch { /* dir may not exist yet */ }
    5656  const present = new Set(all);
    57   const items = all
     57  return all
    5858    .filter(f => IMG_EXT.test(f) && !isSibling(f))
    5959    .map(f => {
     
    6262      const hasVideo = present.has(mp4);
    6363      const ids = new Set([...(used.get(f) || []), ...(hasVideo ? (used.get(mp4) || []) : [])]);
    64       return {
    65         file: f,
    66         url: `/media/post-images/${f}`,
    67         kb: Math.round((statSize(f) + (hasVideo ? statSize(mp4) : 0)) / 1024),
    68         hasVideo,
    69         usedCount: ids.size,
    70         _mtime: statMtime(f),
    71       };
    72     })
     64      return { file: f, stem, mp4, hasVideo, usedCount: ids.size };
     65    });
     66}
     67
     68router.get('/', requireGod, (req, res) => {
     69  const site = res.locals.site;
     70  if (!site) return res.status(404).send('Site required');
     71  const items = imageEntries(site.id)
     72    .map(e => ({
     73      file: e.file,
     74      url: `/media/post-images/${e.file}`,
     75      kb: Math.round((statSize(e.file) + (e.hasVideo ? statSize(e.mp4) : 0)) / 1024),
     76      hasVideo: e.hasVideo,
     77      usedCount: e.usedCount,
     78      _mtime: statMtime(e.file),
     79    }))
    7380    .sort((a, b) => b._mtime - a._mtime); // newest first
    7481  renderPage(req, res, 'pages/admin-media', {
     
    101108  const site = res.locals.site;
    102109  if (!site) return res.status(404).json({ ok: false, error: 'Site required' });
    103   const used = usageMap(site.id);
    104   let all = [];
    105   try { all = fs.readdirSync(POST_IMAGES_DIR).filter(f => !f.startsWith('.')); } catch { /* */ }
    106   const present = new Set(all);
    107110  let removed = 0;
    108   for (const f of all.filter(x => IMG_EXT.test(x) && !isSibling(x))) {
    109     const stem = f.replace(/\.[^.]+$/, '');
    110     const mp4 = `${stem}-v.mp4`;
    111     const ids = new Set([...(used.get(f) || []), ...(present.has(mp4) ? (used.get(mp4) || []) : [])]);
    112     if (ids.size) continue; // still in use
    113     for (const name of [f, mp4, `${stem}-v.jpg`]) {
     111  for (const e of imageEntries(site.id)) {
     112    if (e.usedCount) continue; // still in use
     113    for (const name of [e.file, e.mp4, `${e.stem}-v.jpg`]) {
    114114      try { fs.unlinkSync(path.join(POST_IMAGES_DIR, name)); removed++; } catch { /* */ }
    115115    }
Note: See TracChangeset for help on using the changeset viewer.