Give a video its shape before it has any data
CI / Typecheck, test, build (pull_request) Successful in 26s

A Reddit video sat in the wrong box until you pressed play, for two reasons
that looked like one.

The renderer put only `aspect-ratio` on the `<video>`. A video with no data
has a natural size of 300x150, and WebKit sizes a replaced element from that
rather than from the ratio, so a portrait video got a squat landscape box and
kept it until playback supplied real dimensions. Chromium stretch-fits
instead and gets it right, which is why this only showed on Safari. A
video's size before its data arrives is its poster's, so one with no poster
of its own now gets an empty SVG of the right shape as a stand-in: a data
URI, so it costs no request. Measured in both engines across portrait,
landscape, square and small.

And Reddit's videos with sound had no poster to be sized by, because
`fromRedditVideo` attached the still from `preview.images` to the MP4 branch
alone. The still belongs to the video, not to the format it is served in, so
every post with sound showed an empty box where a silent one showed a frame.
It now goes on both.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PLkmgp1fWbA4XbarxKdRKt
This commit is contained in:
2026-08-30 23:37:59 -03:00
co-authored by Claude Opus 5
parent 4669fe0b6a
commit 5b4378a838
5 changed files with 57 additions and 9 deletions
+21
View File
@@ -90,6 +90,27 @@ test('a video gets native controls and a source, not an iframe', () => {
assert.ok(!page.includes('<iframe'));
});
test('a video with no poster still carries its shape, so the box is right before play', () => {
// WebKit sizes a video from its natural size, which without data or a
// poster is 300x150 — a portrait video sat in a landscape box until you
// pressed play. The poster is where the shape comes from until then.
const page = renderPost(withMedia([
{ kind: 'video', url: 'https://video.example/p.m3u8', hls: true, direct: true, width: 720, height: 1280 },
]));
assert.ok(page.includes('aspect-ratio: 720 / 1280;'));
assert.match(page, /poster="data:image\/svg\+xml,[^"]*width%3D%22720%22[^"]*height%3D%221280%22/);
});
test('a real poster is left in place, and an unmeasured video gets none', () => {
const withPoster = renderPost(withMedia([
{ kind: 'video', url: 'https://cdn/v.mp4', width: 720, height: 1280, poster: { url: 'https://cdn/p.jpg' } },
]));
assert.match(withPoster, /poster="\/m\//);
assert.ok(!withPoster.includes('data:image/svg'));
assert.ok(!renderPost(withMedia([{ kind: 'video', url: 'https://cdn/v.mp4' }])).includes('poster='));
});
test('the copy button carries the clean original URL, and so does the page text', () => {
const page = renderPost(post());
assert.ok(page.includes('data-url="https://www.instagram.com/p/ABC/"'));