From de425d9d68751477a053f18ea298e0c5d95cca8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Sat, 29 Aug 2026 01:34:09 +0100 Subject: [PATCH] .ts is TypeScript here, not a transport stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit caught by deploying: fofos reported `test-setup.ts` as a video. `.ts` is a real video extension — MPEG transport stream — and it was in the list for that reason, but on any machine Officer runs on it is TypeScript approximately always. every source file in every repository was drawing a play badge and spawning an ffmpeg that could only fail. the two ways of being wrong are not the same size. excluded, a genuine transport stream shows a file icon; included, browsing a source tree runs a decoder per file and negative-caches the lot. nobody keeps broadcast captures in a folder they browse from here. m2ts and mts added while in there — the container people actually have, from a camera rather than a tuner, and neither collides with anything. Co-Authored-By: Claude Opus 5 --- src/servers/api/file-browser/thumbnails.ts | 28 +++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/servers/api/file-browser/thumbnails.ts b/src/servers/api/file-browser/thumbnails.ts index 5e1596f8..82de48be 100644 --- a/src/servers/api/file-browser/thumbnails.ts +++ b/src/servers/api/file-browser/thumbnails.ts @@ -44,7 +44,33 @@ import sharp from 'sharp'; * file icons was the most visible gap this had. */ const IMAGE_EXT = new Set(['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'avif', 'tif', 'tiff', 'svg', 'heic', 'heif']); -const VIDEO_EXT = new Set(['mp4', 'mov', 'm4v', 'webm', 'mkv', 'avi', 'wmv', 'flv', 'mpg', 'mpeg', 'ts', '3gp']); +/* + `ts` is NOT here, and that is the one entry worth explaining. + + It is a real video extension — MPEG transport stream — and it was in this list until a deploy to fofos + reported `test-setup.ts` as a video. On any machine Officer runs on, `.ts` is TypeScript approximately + always, so including it meant every source file in every repository drew a play badge and spawned an + ffmpeg that could only fail. + + The two ways of being wrong are not the same size. Excluded, a genuine transport stream shows a file + icon; included, browsing a source tree runs a decoder per file. Nobody stores broadcast captures in a + folder they browse from here. +*/ +const VIDEO_EXT = new Set([ + 'mp4', + 'mov', + 'm4v', + 'webm', + 'mkv', + 'avi', + 'wmv', + 'flv', + 'mpg', + 'mpeg', + '3gp', + 'm2ts', + 'mts', +]); export const thumbnailKind = (name: string): 'image' | 'video' | null => { const ext = extname(name).slice(1).toLowerCase();