Index: src/routes/activitypub.js
===================================================================
--- src/routes/activitypub.js	(revision 7d01696196f37e165850a2e39428e7ea68dba231)
+++ src/routes/activitypub.js	(revision 9ed940e294372071d487529d16df7a871ecd7bcf)
@@ -319,5 +319,8 @@
       import('child_process').then(({ execFile }) => {
         const poster = req.file.path + '.poster.jpg';
-        execFile('ffmpeg', ['-y', '-ss', '1', '-i', req.file.path, '-frames:v', '1', '-vf', "scale='min(640,iw)':-2", poster],
+        // FFMPEG_PATH lets a static build in ~/bin do the work without a
+        // system install; unset means "whatever is on PATH", and neither is
+        // an error when absent.
+        execFile(process.env.FFMPEG_PATH || 'ffmpeg', ['-y', '-ss', '1', '-i', req.file.path, '-frames:v', '1', '-vf', "scale='min(640,iw)':-2", poster],
           { timeout: 30000 }, (e) => { if (e && e.code !== 'ENOENT') console.warn('[media] poster failed:', e.message); });
       }).catch(() => { /* never blocks the upload */ });
