Changeset 7d01696 in Klonkt for src/routes/activitypub.js


Ignore:
Timestamp:
07/30/2026 07:56:33 AM (6 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
9ed940e
Parents:
97bcf7e
Message:

Posterframes voor video, ffmpeg-optioneel

shaer-zowq, de serverhelft. Bij een video-upload trekt ffmpeg een frame op
1 seconde naar <naam>.poster.jpg, best-effort en buiten de responspad: op een
machine zonder ffmpeg gebeurt er niets en breekt er niets (de clients halen
dan zelf een frame, native). Vanaf daar reist de poster naar drie plekken:

  • poster= op de gevouwen video-tag, dus het web toont een stilstaand beeld
  • opgeslagen op de c2s_attachments-entry
  • als AS2 icon op het gefedereerde Video-attachment, dus apps en andere servers krijgen de thumbnail-URL cadeau

Inkomend geldt het spiegelbeeld: een remote video-attachment met een icon
houdt hem als poster in media_json, en de C2S-inboxlees serveert hem terug.

Changed files:
src/routes/activitypub.js

  • uploadMedia: ffmpeg-posterframe voor video, best-effort

src/services/ActivityPubService.js

  • c2sCreatePost: poster op entry en tag; buildNote: icon op het attachment; mediaFromNote/timelineAttachments: inkomende posters door

test/c2s-compose.test.js

  • de poster bereikt tag, opslag en attachment; zonder posterbestand wordt er niets gegokt

remarks: 338 tests groen. ffmpeg staat NIET op de VPS; installeren is een
sudo-actie die ik niet mag doen: sudo apt-get install -y ffmpeg. Zonder dat
werkt alles, alleen maken de clients hun thumbnails zelf.

-robo
Co-Authored-By: Claude Opus 5 <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/routes/activitypub.js

    r97bcf7e r7d01696  
    312312      return res.status(400).json({ error: 'Media must be an image, audio or video file' });
    313313    }
     314    // A video gets a poster frame next to it (shaer-zowq), best-effort and
     315    // out of band: ffmpeg pulls one frame at 1s into <name>.poster.jpg. On a
     316    // machine without ffmpeg nothing happens and nothing breaks; the clients
     317    // fall back to extracting a frame natively.
     318    if (mime.startsWith('video/')) {
     319      import('child_process').then(({ execFile }) => {
     320        const poster = req.file.path + '.poster.jpg';
     321        execFile('ffmpeg', ['-y', '-ss', '1', '-i', req.file.path, '-frames:v', '1', '-vf', "scale='min(640,iw)':-2", poster],
     322          { timeout: 30000 }, (e) => { if (e && e.code !== 'ENOENT') console.warn('[media] poster failed:', e.message); });
     323      }).catch(() => { /* never blocks the upload */ });
     324    }
    314325    res.status(201).json({
    315326      url: '/media/reply-media/' + req.file.filename,
Note: See TracChangeset for help on using the changeset viewer.