Loop art zoom back-and-forth instead of one-shot reveal, to reduce refresh jumpiness

This commit is contained in:
poprhythm committed 2026-09-29 15:21:52 -04:00
1 parent 27e29705c9
commit 83b817c3b2
2 files changed
+57 -21

No files matched your search

+27 -7
View File
@@ -28,18 +28,38 @@ app's config when adding it to a device.
instead of stale track info.
- If a track has no `subsonic_id`, or the cover fetch fails, falls back to a
full-width layout with no art rather than a broken image.
- Album art gets a slow "Ken Burns" reveal: starts zoomed into one corner of
the image, eases out to show the full frame over ~60s. Rendered oversized
(45x45 vs. the 32x32 display slot) and scaled down from 1.0 to ~0.71,
since `animation.Scale` above 1.0 has no visible effect on a widget whose
declared size already matches its container. Which corner it starts in is
derived from the track's `subsonic_id` (not true randomness) so a
still-playing track re-rendered on the `NOWPLAYING_TTL` cache doesn't
- Album art gets a slow "Ken Burns" breathing effect: eases from one corner
of the image out to the full frame, then back into that same corner, on a
continuous ~60s round-trip loop (not a one-shot reveal — see below).
Rendered oversized (45x45 vs. the 32x32 display slot) and scaled between
1.0 and ~0.71, since `animation.Scale` above 1.0 has no visible effect on
a widget whose declared size already matches its container. Which corner
it uses is derived from the track's `subsonic_id` (not true randomness) so
a still-playing track re-rendered on the `NOWPLAYING_TTL` cache doesn't
jarringly jump corners — only a genuinely new track does. Verified this
doesn't blow the payload budget: counterintuitively, a *slower* zoom
compresses *smaller*, since more adjacent ticks become pixel-identical at
this resolution and WebP dedupes them — measured 97-264KB depending on the
art's own visual complexity, all well under the 460KB device limit.
**Why a loop, not a one-shot reveal:** a one-way "start in corner, end on
full frame, then hold" version looked jumpy in practice — since the app
re-renders on `NOWPLAYING_TTL`, each fresh render restarts its own
animation from tick 0, so whatever the *previous* pushed image happened to
be showing gets abruptly replaced by a fresh "zoomed into a corner" frame.
Looping back-and-forth doesn't eliminate that (a server-side re-render
always restarts at tick 0 regardless of app logic), but ending exactly
where it started means the animation also loops seamlessly *on-device*
between refreshes, which reads as far less jarring than a one-way reveal
that snaps back. Considered using genuinely random per-frame content (like
`ormakers-tronbyt`'s LoRa segment, which pre-crops 60 frames directly from
a high-resolution *static* source photo via offline Pillow processing) for
a sharper zoom, but that technique fundamentally doesn't transfer here:
album art is fetched live per-track at render time, and pixlet's Starlark
sandbox has no image-cropping/pixel-analysis capability at all (confirmed
by checking its full module list) — so there's no way to pre-bake or
crop-at-render-time from a source we don't have until the request hits
the live station.
- Shows the current show name (`context.activeShow.name`) and host name
(`dj.name`) below the artist, separated by a thin divider line, and the
local time/temperature (`context.clock`/`context.weather`) below that —
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.