Changeset e276d03 in Klonkt
- Timestamp:
- 07/16/2026 12:20:51 PM (8 weeks ago)
- Branches:
- main
- Children:
- 226b563
- Parents:
- a85f539
- git-author:
- Robin <roboburr@…> (07/12/2026 10:31:19 PM)
- git-committer:
- Robin <roboburr@…> (07/16/2026 12:20:51 PM)
- File:
-
- 1 edited
-
src/services/ThumbnailService.js (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/ThumbnailService.js
ra85f539 re276d03 193 193 if (!ct.startsWith('image/') && !isVideo) return null; 194 194 if (isVideo) { 195 // Remote video → poster frame (feed/tile posters). Don't buffer the whole file: re-fetch 196 // a bounded head (first 4MB) — enough for ffmpeg to decode the first frame of a faststart 197 // mp4 (the web-streaming norm). A moov-at-end file just fails → null → the route's 302 198 // fallback, same as before this path existed. 195 // Remote video → poster frame (feed/tile posters). A bounded head (first 4MB) only decodes 196 // a faststart mp4 (moov atom up front). Many platforms (Loops.video, phone exports) put the 197 // moov atom at the END, so a head-only fetch fails → no thumbnail. So: if the file is small 198 // enough (content-length within VIDEO_CAP) grab it WHOLE — that works regardless of moov 199 // position. Only when the size is unknown or very large do we fall back to a bounded head 200 // (best-effort; a large moov-at-end file still yields null → the route's 302 fallback). 201 const VIDEO_CAP = 64 * 1024 * 1024; // 64MB — covers short-form clips incl. moov-at-end 202 const clen = parseInt(r.headers.get('content-length') || '0', 10); 199 203 try { if (r.body && r.body.cancel) r.body.cancel(); } catch { /* ignore */ } 200 const rv = await safeFetch(url, { headers: { Range: 'bytes=0-4194303' } }); 201 if (!rv.ok && rv.status !== 206) return null; 204 let rv; 205 if (clen && clen <= VIDEO_CAP) { 206 rv = await safeFetch(url); 207 if (!rv.ok) return null; 208 } else { 209 rv = await safeFetch(url, { headers: { Range: 'bytes=0-8388607' } }); // 8MB head fallback 210 if (!rv.ok && rv.status !== 206) return null; 211 } 202 212 buf = Buffer.from(await rv.arrayBuffer()); 203 if (!buf.length ) return null;213 if (!buf.length || buf.length > VIDEO_CAP) return null; 204 214 } else { 205 215 if (parseInt(r.headers.get('content-length') || '0', 10) > 12 * 1024 * 1024) return null; … … 210 220 return null; 211 221 } 212 if ( buf.length > 12 * 1024 * 1024) return null;222 if (!isVideo && buf.length > 12 * 1024 * 1024) return null; // video already capped at VIDEO_CAP 213 223 // ffmpeg-static can't decode an animated WebP (the doomed downscale just logs an error), and a 214 224 // flattened GIF/animated WebP loses its motion → skip it and let the route serve the ORIGINAL
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)