Changeset e67828e in Klonkt
- Timestamp:
- 07/01/2026 10:38:02 PM (2 months ago)
- Branches:
- main
- Children:
- 0877771
- Parents:
- 5e52448
- Files:
-
- 5 edited
-
CHANGELOG.de.md (modified) (1 diff)
-
CHANGELOG.md (modified) (1 diff)
-
CHANGELOG.nl.md (modified) (1 diff)
-
src/services/ThumbnailService.js (modified) (2 diffs)
-
src/views/pages/news.ejs (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
CHANGELOG.de.md
r5e52448 re67828e 42 42 43 43 ### Behoben 44 - **Entfernte Videos zeigen ein Vorschaubild.** Ein Video im News-Feed oder auf einer Zirkel-Kachel 45 (z.B. von Loops oder PeerTube) erschien als schwarze Fläche, bis man auf Abspielen drückte; jetzt 46 gibt es ein echtes Posterbild. (Längere Videos behalten bewusst ihre Steuerung — nur Clips unter 47 30 Sekunden laufen automatisch wie ein GIF.) 44 48 - **Erwähnungen, Hashtags und Links in Klammern funktionieren jetzt.** Eine Erwähnung wie 45 49 `(@benutzer@server)`, ein `(#hashtag)` oder eine URL in Klammern föderierte als reiner Text — -
CHANGELOG.md
r5e52448 re67828e 37 37 38 38 ### Fixed 39 - **Remote videos show a preview frame.** A video in the News feed or a Circle tile (e.g. from 40 Loops or PeerTube) used to appear as a black box until you pressed play; it now shows a real 41 poster frame. (Longer videos keep their player controls by design — only clips under 30 seconds 42 autoplay like a GIF.) 39 43 - **Mentions, hashtags and links inside brackets now work.** A mention like `(@user@server)`, a 40 44 `(#hashtag)` or a bracketed URL federated as plain text — and the mentioned person was never -
CHANGELOG.nl.md
r5e52448 re67828e 40 40 41 41 ### Opgelost 42 - **Remote video's tonen een preview-frame.** Een video in de News-feed of op een Cirkel-tegel 43 (bv. van Loops of PeerTube) verscheen als zwart vlak tot je op afspelen drukte; er staat nu een 44 echt poster-frame. (Langere video's houden bewust hun bediening — alleen clips onder de 30 45 seconden spelen automatisch als een GIF.) 42 46 - **Vermeldingen, hashtags en links tussen haakjes werken nu.** Een vermelding als 43 47 `(@gebruiker@server)`, een `(#hashtag)` of een URL tussen haakjes federeerde als platte tekst — -
src/services/ThumbnailService.js
r5e52448 re67828e 185 185 if (fs.existsSync(cached)) return cached; 186 186 187 let buf ;187 let buf, isVideo = false; 188 188 try { 189 189 const r = await safeFetch(url); 190 190 if (!r.ok) return null; 191 if (!(r.headers.get('content-type') || '').startsWith('image/')) return null; 192 if (parseInt(r.headers.get('content-length') || '0', 10) > 12 * 1024 * 1024) return null; 193 buf = Buffer.from(await r.arrayBuffer()); 191 const ct = r.headers.get('content-type') || ''; 192 isVideo = ct.startsWith('video/'); 193 if (!ct.startsWith('image/') && !isVideo) return null; 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. 199 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; 202 buf = Buffer.from(await rv.arrayBuffer()); 203 if (!buf.length) return null; 204 } else { 205 if (parseInt(r.headers.get('content-length') || '0', 10) > 12 * 1024 * 1024) return null; 206 buf = Buffer.from(await r.arrayBuffer()); 207 } 194 208 } catch (e) { 195 209 console.warn('[thumb-remote] fetch failed for', url, '-', e.message); … … 199 213 // ffmpeg-static can't decode an animated WebP (the doomed downscale just logs an error), and a 200 214 // flattened GIF/animated WebP loses its motion → skip it and let the route serve the ORIGINAL 201 // (keeps the animation; mirrors the local path's isAnimatedSrc guard). 202 if (isAnimatedBuf(buf)) return null; 215 // (keeps the animation; mirrors the local path's isAnimatedSrc guard). Video heads skip this 216 // (they're not webp/gif) and go straight to the single-frame extract. 217 if (!isVideo && isAnimatedBuf(buf)) return null; 203 218 204 219 await fs.promises.mkdir(path.dirname(cached), { recursive: true }); -
src/views/pages/news.ejs
r5e52448 re67828e 122 122 </div> 123 123 <% } %> 124 <% vids.forEach(function(m){ %><video class="tl-media-video" src="<%= m.url %>" controls preload="metadata" playsinline></video><% }); %>124 <% vids.forEach(function(m){ %><video class="tl-media-video" src="<%= m.url %>" poster="<%= thumb(m.url, 1280) %>" controls preload="metadata" playsinline></video><% }); %> 125 125 <% /* A Klonkt audio post carries an embed player (embedHtml/embedUrl) that already 126 126 covers these tracks, so don't ALSO render the raw Audio attachments as bare
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)