Rotate the background with every track
The poster behind the frame was one of two, picked by hand and then left there all night. It now turns over on every track change the way the animations do, and never as the same picture twice: a shuffle bag over whatever images sit in assets/, each shown at a random zoom between 1.15 and 1.9 and cropped around a randomly chosen point of the poster. The list is read from the directory rather than written out in config.js. The old one named two files that are no longer there, which is the failure mode a hand-kept list has; now a poster joins the rotation, with its own button on the queue page, by being dropped in the folder. Zoom never goes below 1.15. These are portrait prints and the screen is wide, so cover fits the poster's full width and crops vertically — at 1 the paper margin shows as a grey stripe down both sides. 1.15 cuts at least 13% off the width of every crop a 1920x1080 screen can produce. The crop is drawn into a screen-sized canvas rather than handed to CSS as an object-fit rule on a full-size <img>. The scans are 3508x4950, which is a 70MB texture per layer and two of them composited for the length of the fade; instead each pick is fetched, resized off the main thread to roughly screen resolution, drawn once, and closed. A swap costs about 400ms of async work, all of it before the fade begins, and no full-size bitmap is held anywhere. Nothing about the posters' resolution reaches the compositor, so assets/ can keep the 300 dpi originals. Backgrounds pin and unpin like animations: DEFAULT_BACKGROUND is now the auto cycle, the queue page's row leads with Auto, and isBackground() guards the socket handler and the restored queue.json against a key that no longer names a file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H9v2Xoa6eoeGYpK6gp95k9
This commit is contained in:
@@ -3,9 +3,11 @@
|
||||
A YouTube playlist player for parties. Two browser windows run side by side:
|
||||
|
||||
- **Player** (`http://localhost:3000/`) — fullscreen poster background with a
|
||||
small video frame that moves around, switching animation on every track (see
|
||||
[Animations](#animations)). Consecutive videos overlap in a 5 second
|
||||
audio/video crossfade, so there is never silence between tracks.
|
||||
small video frame that moves around. Both the animation (see
|
||||
[Animations](#animations)) and the poster behind it (see
|
||||
[Backgrounds](#backgrounds)) change on every track. Consecutive videos
|
||||
overlap in a 5 second audio/video crossfade, so there is never silence
|
||||
between tracks.
|
||||
- **Queue** (`http://localhost:3000/queue`) — add videos by URL, drag to
|
||||
reorder, delete, see how much playtime is left, and pick the background and
|
||||
animation.
|
||||
@@ -33,9 +35,32 @@ autoplay, so the first click is what unlocks audio. One click per session.
|
||||
whenever a length is still unknown.
|
||||
- The queue is saved to `queue.json` on every change and restored at startup.
|
||||
- Settings live in `config.js`: overlap length, frame size, drift speed, corner
|
||||
screenshot interval and margin, the drag animation's size range, port, and
|
||||
the selectable backgrounds and animations. Anything the browser needs must
|
||||
also be mirrored in the `/config.js` route in `server/index.js`.
|
||||
screenshot interval and margin, the drag animation's size range, the
|
||||
background zoom range, port, and the animation list. Everything there except
|
||||
`PORT` is mirrored to the browser by the generated `/config.js` route in
|
||||
`server/index.js`, so a new constant needs no second list.
|
||||
|
||||
## Backgrounds
|
||||
|
||||
Every image file in `assets/` is a background — drop one in, restart, and it
|
||||
joins the rotation with a button on the queue page named after the file. There
|
||||
is no list to maintain.
|
||||
|
||||
Like the animations, the background changes on every track: a different poster,
|
||||
at a random zoom between 1.15× and 1.9×, cropped around a randomly chosen point
|
||||
of it, cross-fading over about a second. The posters are portrait prints and
|
||||
the screen is wide, so the crop is mostly a question of which band of the
|
||||
poster to keep — the zoom never goes below 1.15×, because at 1× a wide screen
|
||||
shows the poster's full width, paper margin included.
|
||||
|
||||
Each crop is resized off the main thread and drawn into a screen-sized canvas
|
||||
(`public/player/backdrop.js`), so the cross-fade never has to composite a
|
||||
17-megapixel layer, and the full-size scans are never held in memory. This is
|
||||
why `assets/` can hold 300 dpi print files without the player caring.
|
||||
|
||||
The queue page's **Background** buttons pin one poster the same way the
|
||||
animation buttons pin one animation; **Auto** hands selection back to the same
|
||||
shuffle bag the animations use.
|
||||
|
||||
## Animations
|
||||
|
||||
|
||||
Reference in New Issue
Block a user