Skip to content

Add a walkthrough video and Korea-themed sample photos - #14

Merged
subwaymatch merged 19 commits into
mainfrom
claude/beautiful-cannon-gsx1z7
Oct 16, 2026
Merged

subwaymatch merged 19 commits into
mainfrom
claude/beautiful-cannon-gsx1z7

Conversation

@subwaymatch

@subwaymatch subwaymatch commented Oct 16, 2026 •

Copy link
Copy Markdown
Owner

This PR does three things:

  • It adds video/, a Remotion project that renders a walkthrough video with music and sound effects.
  • It puts the video on the docs site's overview page.
  • It replaces every sample photo in the docs with minimal, Korea-themed ones, and the video uses those photos.

Docs sample photos

  • scripts/generate_photos.py now generates 13 minimal photos of Korean subjects with gpt-image-2.5-flare at quality: low: a palace pond at sunrise, a portrait in hanbok and gat, a Seoul alley at night, bibimbap, lotus lanterns, palace eaves, the Jeju coast, a bamboo forest, a celadon tea set in a hanok, Gamcheon Culture Village, a fishing harbor, a hanbok silhouette and a snowy hanok. Each keeps what its recipes rely on, such as a hazy harbor, a night street, or a silhouette against a white sky.
  • scripts/docs_examples.py has the new slugs and alt text. The few recipe descriptions that named something in a photo are updated, for example "the beard and the woven gat hat" and "the turquoise houses violet".
  • Two recipes were tuned to the new photos:
    • The flat-photo Levels points (0.16 → black, 0.82 → white) now match the harbor's actual tonal range, which is about 0.17–0.80.
    • The red-filter B&W recipe moves to the Jeju coast, so the sky and clouds carry the effect. On the dark palace eaves it came out almost entirely black.
  • The README's operation gallery (docs/previews/) is now generated from the Gamcheon Culture Village photo instead of test-images/piano-man-01.jpg. The README markdown is unchanged and still matches generate_previews.py --markdown.
  • scripts/build_docs.py rebuilt every page and image. The old photos and their renders are removed.

Video on the docs site

  • The overview page (index.html) has a new Video section after the interactive looks. It's a plain <video controls> showing docs/video/layeris.mp4, with docs/video/poster.jpg (the intro's logo and wordmark) as its poster.
  • The overview's sidebar links to the section.
  • The styling is a small .video rule in docs/assets/site.css, matching the page's other images.
  • The Remotion project renders straight into docs/video/ (npm run render, npm run poster), so there's a single copy of the MP4.

Video

The video is 1920×1080, 30 fps, 52.1 s, H.264 in BT.709, with AAC audio. It walks through the package rather than selling it, styled like the docs site: white page, the docs' fonts and syntax colors, and section headings with a rule above. The layeris wordmark is typed in DM Mono, as on the docs home page.

  • Intro: the logo vector's three layers draw their outlines while fanned out, then settle into place as the fills fade in. The wordmark then types in.
  • 01 Install: pip install layeris, with pip's Collecting and Downloading lines and a quick progress bar before the success line. The wheel name and size match pip wheel . for 0.4.0.
  • 02 Chain operations: the hanbok portrait, edited one chained call at a time.
  • 03 Blend modes: all 14 modes on the Jeju coast.
  • 04 Curves: r and b control points easing into place on the bamboo forest.
  • 05 Looks: cross-processed (Gamcheon Culture Village), cyanotype (palace pond), and a duotone loaded with apply_from_json (palace eaves).
  • Outro: logo, wordmark, install command, links and license.

video/scripts/build_assets.py renders every edited image in the video from docs/photos/ with layeris. It records the exact code that ran in video/src/data/assets.json, and the video reads its code snippets from that file. Fonts are bundled through @fontsource, and all npm versions are pinned.

Sound

  • Sound effects: these come from video/scripts/generate_sound_effect.py, using the ElevenLabs Sound Effects API.
    • A short shimmer (video/public/logo.mp3) plays as the logo's outlines start to draw.
    • A soft keystroke (video/public/key.mp3) plays on the exact frame each letter of the wordmark appears.
  • Music: a mellow lo-fi instrumental (Rhodes chords over a laid-back beat with upright bass, about 86 BPM). It starts as the logo fades out at the end of the intro (4.3 s) and fades over the last second.
    • It's video/public/music.mp3, generated by video/scripts/generate_music.py with the ElevenLabs Music API (music_v2_5, lofi style).
    • This take is 52.1 s long, so the video fades out its last second. By then the take is already winding down.
    • New takes from the script are sized to the 47.8 s the music plays for.
  • Levels: the final mix is about -15.9 LUFS, with a -1.3 dBFS peak.

Checks

  • pytest: 313 passed.
  • Every image that docs/*.html and the README reference exists.
  • npx tsc --noEmit passes for the video.
  • I reviewed contact sheets of the new photos, all 24 recipe results and the README previews, and frames extracted from the rendered MP4.
  • I measured where each sound sits in the final file and its loudness. The detected keystroke onsets fall within about 15 ms of their letters' frames.
  • I took screenshots of the overview page served locally, and the MP4 is served with a 200.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj

claude added 11 commits October 16, 2026 03:20
A silent 1920x1080 video under video/ that walks through install,
chained operations, the 14 blend modes, per-channel curves and three
looks (one loaded from a JSON preset), styled after the docs site with
DM Mono for the wordmark and code. The logo vector is animated: its
three layers draw in fanned out and settle into place.

Every edit shown is rendered by layeris itself: scripts/build_assets.py
writes the results and a manifest holding the exact code that ran. The
source photos were generated with gpt-image-2.5-flare at low quality
by scripts/generate_photos.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
The caret appeared beside the logo while it was still moving up, so
typing now starts once the move ends, and the intro holds a little
longer. Rendering with the BT.709 color space gives a standard
limited-range yuv420p file instead of full-range yuvj420p.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
1920x1080, 30 fps, 76.4 seconds, H.264 in BT.709, no audio track.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
The logo assembles at twice the speed and the wordmark types at two
frames per letter, so the intro takes 5 seconds instead of 8. The
install scene shows only pip install, and the outro drops the version
and uses a smaller wordmark to leave more space below.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
1920x1080, 30 fps, 71.9 seconds, H.264 in BT.709, no audio track.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
Shorter holds, faster typing and wipes, and quicker scene exits bring
the video from 71.9 to 51.3 seconds. Looks now follow each other
directly: the code swaps and the next photo fades in over the previous
result, instead of each look fading out to a blank page first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
1920x1080, 30 fps, 51.3 seconds, H.264 in BT.709, no audio track.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
Regenerates all 13 sample photos with gpt-image-2.5-flare at low
quality: a palace pond at sunrise, a portrait in hanbok and gat, a
Seoul alley at night, bibimbap, lotus lanterns, palace eaves, the Jeju
coast, a bamboo forest, a celadon tea set in a hanok, Gamcheon Culture
Village, a fishing harbor, a hanbok silhouette and a snowy hanok. Each
keeps the qualities its recipes rely on (a hazy harbor, a night
street, a silhouette against white sky and so on).

Recipe photos, alt text and the few descriptions that named what was
in a photo are updated to match. The flat-photo Levels points now fit
the new harbor's tonal range, the red-filter recipe moves to the Jeju
coast so its sky and clouds carry the effect, and the README's
operation gallery now uses the Gamcheon Culture Village photo instead
of test-images/piano-man-01.jpg. Every page and image is rebuilt with
scripts/build_docs.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
The install scene now shows pip's Collecting and Downloading lines with
a quick progress bar before the success line, using the real wheel
name and size for 0.4.0.

The video's own photo set and generator are gone: build_assets.py now
renders from docs/photos/, using six of the new Korea-themed photos
(the hanbok portrait, Jeju coast, bamboo forest, Gamcheon Culture
Village, palace pond and palace eaves). The chain scene's code is a
size smaller to fit the longer file name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
1920x1080, 30 fps, 52.1 seconds, H.264 in BT.709, no audio track.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
@subwaymatch subwaymatch changed the title Add a Remotion walkthrough video of layeris Add a walkthrough video and Korea-themed sample photos Oct 16, 2026
A Korean traditional instrumental in the manner of gayageum ensemble
arrangements of Pachelbel's Canon: gayageums entering in canon over the
Canon's ground bass in D, with janggu, geomungo, daegeum and haegeum.
scripts/generate_music.py generates it with the ElevenLabs Music API
(music_v2_5) at the video's exact length; the prompt describes the
music rather than naming the piece, which the API rejects.

The track builds through the middle and resolves as the outro plays.
src/Video.tsx mixes it in at 85% volume (about -14.7 LUFS).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
1920x1080, 30 fps, 52.1 seconds, H.264 in BT.709 with AAC audio at
about -14.8 LUFS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
The gugak track didn't work out, so this is a general instrumental
instead: felt piano over a light beat and plucked synth arpeggios at
about 99 BPM, on a four-chord loop that changes once per bar. It builds
around the blend-modes scene and rings out under the outro.

generate_music.py now holds three prompt styles (piano, marimba, lofi)
sharing one brief. Of four takes, this one had the steadiest tempo, the
clearest chord movement and a clean ending; it's mixed at 80% (about
-14.6 LUFS).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
1920x1080, 30 fps, 52.1 seconds, H.264 in BT.709 with AAC audio at
about -14.6 LUFS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
Swaps in the lo-fi take (Rhodes chords over a laid-back beat, about 86
BPM). It now starts as the logo fades out at the end of the intro
instead of on the first frame, and fades over the last second, by which
point the take is already winding down.

The intro instead gets a short shimmer as the logo's outlines start to
draw, from the new scripts/generate_sound_effect.py (ElevenLabs Sound
Effects API). generate_music.py now defaults to the lofi style and sizes
new takes to the 47.8 seconds the music plays for.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
1920x1080, 30 fps, 52.1 seconds, H.264 in BT.709 with AAC audio at
about -15.9 LUFS. The music starts at 4.3 s, as the logo fades out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
One soft keystroke from the ElevenLabs Sound Effects API, trimmed to
start at the click and normalized to a -6 dBFS peak, plays on the frame
each letter of "layeris" appears, at slightly varied levels.
generate_sound_effect.py now takes the effects to generate by name
(logo, key) and does the trimming and normalizing itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
1920x1080, 30 fps, 52.1 seconds, H.264 in BT.709 with AAC audio.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lpfz52CucHEw9WyhgzPjmj
@subwaymatch
subwaymatch merged commit 7954857 into main Oct 16, 2026
4 checks passed
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.

2 participants