480 is a real video rung, with lighter audio

It was reachable only when the SOURCE was smaller than 720, which is backwards: the rung a phone wants
is the one a 720p master never produces. The hero here is 1280x720 and the only file that existed for
it was 7.8 MB of 720p, served to every device.

`b:a` overrides the preset's 96k with 64k. The audio on a hero loop is ambience, and 64k AAC carries
it — the same argument as the preset's crf 26 for the picture. The rung exists for a phone on a mobile
connection and every kilobit is one it is paying for.

The override goes through av-club's documented contract: a preset supplies the options and anything
passed explicitly wins.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-29 23:38:11 +01:00
co-authored by Claude Opus 5
parent c5fe7c0f86
commit b97c87fb5e
+26 -4
View File
@@ -83,15 +83,34 @@ const PLACEHOLDER_QUALITY = 50;
* beside it, and 84 seconds of a single core to make it. Under a running sync that overran av-club's
* idle timeout and the video failed outright, which is how the bug surfaced at all.
*
* `web-480` is the floor, not a rung: it exists so a source smaller than 720 still gets something,
* `web-480` is BOTH a rung and the floor: a phone is served it whatever the source, and a source
* smaller than 720 still gets something,
* rather than nothing or an upscale.
*/
const VIDEO_RUNGS = [
{ file: '1080.mp4', preset: 'web-1080', height: 1080 },
{ file: '720.mp4', preset: 'web-720', height: 720 },
{ file: '1080.mp4', preset: 'web-1080', height: 1080, options: undefined },
{ file: '720.mp4', preset: 'web-720', height: 720, options: undefined },
/*
480 is a real rung now, not only a floor.
It was reachable únicamente when the SOURCE was smaller than 720, which is backwards: the rung a
phone wants is the one a 720p master never produced. The hero here is 1280x720 and the only file
that existed for it was 7.8 MB of 720p, served to everything.
`b:a` overrides the preset's 96k. The audio on a hero loop is ambience — the sound of a tufting
gun — and 64k AAC carries that. It is the same argument as crf 26 for the picture: the rung exists
for a phone on a mobile connection, and every kilobit is one it is paying for.
*/
{ file: '480.mp4', preset: 'web-480', height: 480, options: { 'b:a': '64k' } },
] as const;
const VIDEO_FLOOR = { file: '480.mp4', preset: 'web-480', height: 480 } as const;
/**
* When the source is smaller than every rung.
*
* A 360p upload still needs one servable file. Kept separate from the ladder because it is a fallback
* rather than a choice — it is what happens when the filter above matches nothing.
*/
const VIDEO_FLOOR = { file: '480.mp4', preset: 'web-480', height: 480, options: { 'b:a': '64k' } } as const;
const IMAGE_EXT = new Set(['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'avif', 'tif', 'tiff', 'heic', 'heif']);
const VIDEO_EXT = new Set(['mp4', 'mov', 'm4v', 'webm', 'mkv', 'avi', 'wmv', 'flv', 'mpg', 'mpeg', '3gp', 'm2ts', 'mts']);
@@ -469,6 +488,9 @@ async function buildVideo(
inputPath: sourcePath,
outputPath: join(staging, rung.file),
preset: rung.preset,
// The preset supplies the options and anything given here overrides it — av-club's contract,
// see sidecar/ffmpeg/run.ts. Used only to lighten the audio on the 480 rung.
...(rung.options ? { options: rung.options } : {}),
});
variants.push({ file: rung.file, width: null, height: null, bytes: result.bytes });
}