Replaced the bundled sample with a demo-file page - #28
Open
CodyCBakerPhD wants to merge 10 commits into
Open
Conversation
The app shipped a 2.1 MB mice.mp4 behind "Load Sample". The demo set on EMBER dandiset 000527 (scripts/generate-demos.sh) replaces it: a couple of dozen files that each vary exactly one thing the app surfaces. "Browse Demo Files" opens a page of its own at ?demos, in place of the drop zone rather than beside it, grouped by what each file varies, filterable, one fold per file carrying its description, its BEP047 figures and the ffmpeg command that made it. Picking one loads it through the same path the URL box uses. The sample file itself is deleted here, and scripts/purge-sample-blob.sh takes it out of the git history — both paths it has lived at — which needs a force-push to the default branch and so cannot be part of this change. With no file to bundle, the browser tests generate their own video with ffmpeg (tests/fixtures/demoVideo.ts) and mock the archive, so they neither reach the network nor put a blob back in the repository. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjjcqLTJXBDEtikdnwCFPF
|
Codecov Report❌ Patch coverage is
🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjjcqLTJXBDEtikdnwCFPF
The cards carried a fold holding every ffprobe figure and the ffmpeg command that made the file. Those are what the app itself shows once the file is open, so the card is now flat and always readable: title, extension, size, the sentence saying what it demonstrates, and the two buttons. The description therefore has to be there for every card at once, so generate-demos.sh writes it into dataset_description.json's index alongside the title and group. A dataset generated before that still works: a demo whose index entry has no description falls back to its own sidecar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjjcqLTJXBDEtikdnwCFPF
CodyCBakerPhD
marked this pull request as ready for review
August 24, 2026 01:09
Twenty-nine cards in a list ran to about six screens, and comparing two files — a short GOP against a long one, which is what the set is built around — meant scrolling between them. The grid puts the whole set on roughly one screen and makes that comparison a click: press a tile, the card above it fills with that file. The source recording and the baseline encode now share the leading row under one "Start here" heading, the recording first, since to a reader they are one thing: where the set starts. A heading can therefore cover more than one of the generator's group names. Also drops the provenance line under the heading, and calls the original recording the one every other session is a transcoding of rather than an encode of. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjjcqLTJXBDEtikdnwCFPF
The grid is what the page is, so it now sits first, in one card rather than one per group, and the card under it is what a tile was pressed for — it reads as the answer to the tile above rather than as a header the grid explains. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjjcqLTJXBDEtikdnwCFPF
…d load Three things the demo page needed once it met the real archive. Loading a file failed with "403 Forbidden" against EMBER. The archive's download endpoint redirects to storage URLs signed for GET alone, so the HEAD used to ask for the size and range support is refused on a file that is public. A failed HEAD now means "no answer" rather than "no file": a one-byte range request asks again with the method the signature covers, and its Content-Range carries the length. A server that ignores the range and sends the whole file has its body kept rather than fetched twice. The set gains one file that is a recommendation rather than a demonstration: H.264 High, -preset slow, a keyframe every second and faststart — seekable, streamable, and as small as those two allow. It sits under its own heading so it is not mistaken for the reference, which is deliberately a neutral baseline the other demos vary from. The themes now run in the order Inspect reads a file — container, tags, video track, atom layout, bitrate, GOP — so browsing the set and scrolling the tab walk the same ground in the same sequence. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjjcqLTJXBDEtikdnwCFPF
A themed card's blurb and a file's own description were both muted prose in the same shape, so which one was about the video in hand took working out. The detail card now carries a notch on its top edge, aimed at the tile that opened it: what the description is about is the thing the point touches, whichever theme the card happens to sit under. The description itself is set in the page's ink at full size, against the themed blurb above it, which stays muted and small because it describes a group rather than a file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjjcqLTJXBDEtikdnwCFPF
Fixes the moov error the demos page hit against the live archive. The range probe added with the HEAD-403 fallback proved one byte range worked and concluded the whole file could be read in pieces, which put EMBER on the ranged path for the first time. It is not the same question: the parser's real reads go back through the archive's redirect to a freshly signed URL every time, and mediabunny reads a URL source over ranges this class never sees. Half a file arrives as rubble, which mp4box reports as a missing moov. Ranges are now taken only where a HEAD advertised them; anything else is downloaded whole, as it was before. readChunk also checks the response — unchecked, a refused range handed the parser an error page to read as video. The themes lose their blurbs: what a file is is the file's own business, and the card that opens on a tile says it. With the prose gone the cards are tiles and a heading, so they pack — each asking for the width its own files need, and shrinking to share a row rather than dropping a quiet theme onto a line of its own. The page takes the width the window allows, less the margins the corner watermarks are fixed in, so the whole set is about one screen instead of six. Each theme carries a hue of its own, which the open card and the pressed tile borrow. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjjcqLTJXBDEtikdnwCFPF
The themes now run outermost-in and most-consequential-first: the box the stream sits in, how that box is laid out, the stream itself, then the structure inside it that decides how it seeks. What only describes a file rather than changing how it behaves — track properties, tags, the rate it was told to hit — comes after all of that. The detail card is as wide as the grid above it, so a description capped at a reading measure left most of the box empty. The description and the buttons now share a row: the measure is still capped, since a sentence running the full width of a wide monitor is no easier to read for filling the space, but the buttons hold the far edge so what is between them reads as a laid-out row rather than a gap. Below about 700px they stack. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjjcqLTJXBDEtikdnwCFPF
The heading led with a bare acronym on a page whose whole job is to teach what these things are. The individual demo titles keep GOP short, since by then the heading has said what it stands for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjjcqLTJXBDEtikdnwCFPF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Retires the 2.1 MB
mice.mp4behind Load Sample in favour of the demo set on EMBER dandiset 000527, whichscripts/generate-demos.shbuilds andscripts/upload-demos.shpublishes. Released as 1.0.0.Browse Demo Files now opens a page of its own at
?demos, in place of the drop zone rather than beside it. It reads the dandiset in two requests: the asset listing, thendataset_description.json'sencoding-helperindex.The set is laid out as a card per theme, each holding that theme's tiles and carrying a hue of its own. The cards pack — each asking for the width its own files need and shrinking to share a row — and the page takes the width the window allows, less the margins the corner watermarks are fixed in, so the whole set is about one screen. Themes run outermost-in and most-consequential-first: the box the stream sits in, how that box is laid out, the stream itself, then the structure inside it that decides how it seeks. What only describes a file rather than changing how it behaves — track properties, tags, the rate it was told to hit — comes after. Above all of them, Start here holds the source recording and the baseline encode, the recording first, and A recommended encode holds the one file that is a recommendation rather than a demonstration.
Pressing a tile fills one detail card, which moves to sit under that theme's card and points a notch at the tile it is describing, in the theme's colour. The card carries the file's name, extension and size on its head, then the sentence saying what it demonstrates beside the buttons that open or download it — a row rather than a column, so a card as wide as the grid has content at both edges instead of a narrow text column against an empty right-hand side. Themes carry no prose of their own: what a file is is the file's own business, and the card says it. There is a filter across the grid. Opening a file loads it through the same path the URL box uses, so it lands under its BIDS name and as a shareable
?src=link.No ffprobe figures and no
ffmpegcommand: those are what the app itself shows once the file is open.Two bugs found against the live archive. Loading a file failed with
403 Forbidden: the archive's download endpoint redirects to storage URLs signed forGETalone, so theHEADused to ask for size and range support is refused on a file that is public. A failedHEADnow means "no answer" rather than "no file", and a one-byte range request asks again with the method the signature covers. That fix then surfaced a second one — a missing-moov error — because proving one byte range works is not the same question as whether the parser's own reads will: those go back through the redirect to a freshly signed URL every time, and mediabunny reads a URL source over rangesChunkedSourcenever sees, so half a file arrived as rubble. Ranges are now taken only where aHEADadvertised them; anything else is downloaded whole, as before.readChunkalso checks the response — unchecked, a refused range handed the parser an error page to read as video.Because the card needs a description for whichever file is selected,
generate-demos.shwrites each one intodataset_description.json's index alongside the title and group, so the page's existing single fetch carries them. A dataset generated before that still works: a file whose index entry has no description falls back to its own BEP047 sidecar, read once per file when it is first selected. Re-running the upload workflow is what publishes the recommended encode and moves the dataset onto the no-extra-request path.The sample file is deleted here, but deleting it does not remove it from history.
scripts/purge-sample-blob.shdoes that withgit filter-repo, taking out both paths the same blob has lived at (mice.mp4from #1,public/mice.mp4from #3) — on a mirror of this repo it takes the pack from 3.10 MiB to 993 KiB. That step is not in this PR and cannot be: it rewrites every commit from #1 onwards and needs a force-push tomainby someone who can do it, with everything else merged or parked first, after which everyone re-clones. The script stops before the push unless given-f.With no file to bundle, the Playwright runs generate their own 30-second video with ffmpeg (
tests/fixtures/demoVideo.ts, gitignored, built once per run by the global setup) and mock the archive — refusingHEADthe way the real one does, so the fallback is what CI actually exercises.test.ymlandchromatic-playwright.ymlgain an ffmpeg install step.The sandbox this was written in cannot reach
api-dandi.emberarchive.org(egress policy), so both archive fixes above were diagnosed from the reported errors and are covered by tests against a mock, but have not been run against the live dandiset by me.One deliberate divergence from the last prompt below: the GOP heading spells the acronym out as Group of Pictures, not "group of pixels". That is what GOP stands for, and it is what
src/lib/explainers.tsalready tells the reader a click away.Prompts
The API tool this was written through strips raw HTML, so this is a code block rather than the usual collapsed disclosure dropdown; worth folding back by hand on edit.