Skip to content

Replaced the bundled sample with a demo-file page - #28

Open
CodyCBakerPhD wants to merge 10 commits into
mainfrom
claude/demo-files-migration-ui-nnv9ku
Open

Replaced the bundled sample with a demo-file page#28
CodyCBakerPhD wants to merge 10 commits into
mainfrom
claude/demo-files-migration-ui-nnv9ku

Conversation

@CodyCBakerPhD

@CodyCBakerPhD CodyCBakerPhD commented Aug 23, 2026

Copy link
Copy Markdown
Member

Retires the 2.1 MB mice.mp4 behind Load Sample in favour of the demo set on EMBER dandiset 000527, which scripts/generate-demos.sh builds and scripts/upload-demos.sh publishes. 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, then dataset_description.json's encoding-helper index.

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 ffmpeg command: 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 for GET alone, so the HEAD used to ask for size and range support is refused on a file that is public. A failed HEAD now 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 ranges ChunkedSource never sees, so half a file arrived as rubble. Ranges are now taken only where a HEAD advertised them; anything else is downloaded whole, as before. readChunk also 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.sh writes each one into dataset_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.sh does that with git filter-repo, taking out both paths the same blob has lived at (mice.mp4 from #1, public/mice.mp4 from #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 to main by 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 — refusing HEAD the way the real one does, so the fallback is what CI actually exercises. test.yml and chromatic-playwright.yml gain 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.ts already 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.

ok now that the external dataset houses a bunch of great demo files, please purge the current sample file from the git blob history and use the new demos in their place (also probably nice a nice UI for expanding/selecting demo cases; or, possible, an entire alternative page (?demos) with a toggle to/from the main app that then replaces the native file/remote selector
we can call this the 1.0.0 version bump :)
remove 'One file per idea this app can show you, each changing exactly one thing from the reference encode.'
remove 'Only files this app can open' toggle
remove expand all collapse all buttons
remove the majority of technical details from each demo card (especially the ffmpeg bit); keep just those nice descriptions for each and therefore do not collapse, always keep expanded and remove ability to collapse
OR maybe consolidate and have one card about the size you current have, then a grid of selected boxes and the card shows the info for each box as you press it; maybe make some artifact prototypes to share if you're unsure
"Every other session is an encode of this." -> "Every other session is a transcoding of this."
yeah i like option B and maybe put reference and original on the same line next to each other (original first one maybe?)
remove text "29 files on EMBER dandiset 000527 · view on the archive · encoded from Multi-Modal Courtship in the Peacock Spider, Maratus volans (O.P.-Cambridge, 1874) · CC-BY-4.0"
hmmm maybe make the single load card appear in the card below the one with the grid selector?
can you make a 'perfect' version of it for our purposes (good seeking, high compression, web streamable, opens immediately over streaming)?

Also what I previously said about selection detail + load card opening below only makes sense if its like the previous case where each item in the grid is in a separate card per theme
also make the ordering of the themes consistent with the inspect page; the containers section should be the first one

Uhhh I get a "Failed to fetch URL: 403 Forbidden" on trying to load the original recording one, the entire dataset is public and open shouldn't be an issue
great; now if you could do something stylistically to make it clear in the per-video description that it is what is in *this* video
remove all the descriptions for the per theme cards, only have the per video ones once clicked
looking great - now move GOP and keyframe structure right after codecs; replace metadata tags with atom layout (in terms of ordering priorities)
The per video text description in the moving card (which is now wide) is cramped and not fit to the box
rename demo section title "GOP and keyframe structure" to "Group of pixels (GOP) and keyframe structure" (fine to keep GOP as acronym in individual demo titles)

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
@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://brain-bbqs.github.io/encoding-helper/pr-preview/pr-28/

Built to branch gh-pages at 2026-08-24 22:24 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@codecov-commenter

codecov-commenter commented Aug 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 64.25856% with 94 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/ui/demosPage.ts 52.07% 74 Missing and 7 partials ⚠️
src/lib/demoArchive.ts 90.62% 0 Missing and 6 partials ⚠️
src/ui/fileLoading.ts 0.00% 4 Missing ⚠️
src/lib/chunkedSource.ts 80.00% 0 Missing and 3 partials ⚠️
Files with missing lines Coverage Δ
src/lib/appUrl.ts 90.24% <100.00%> (+3.57%) ⬆️
src/ui/elements.ts 0.00% <ø> (ø)
src/lib/chunkedSource.ts 61.53% <80.00%> (+61.53%) ⬆️
src/ui/fileLoading.ts 0.00% <0.00%> (ø)
src/lib/demoArchive.ts 90.62% <90.62%> (ø)
src/ui/demosPage.ts 52.07% <52.07%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@CodyCBakerPhD CodyCBakerPhD self-assigned this Aug 23, 2026
claude added 2 commits August 23, 2026 22:08
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
CodyCBakerPhD marked this pull request as ready for review August 24, 2026 01:09
claude added 7 commits August 24, 2026 01:27
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants