Add an optional TV-static overlay during track start/end

Shows a brief static effect (sparse noise specks, bundled as a small
animated GIF) over the album art during the first/last 5 seconds of a
track, as a transition cue. Implemented via render.Stack compositing a
bundled images/static.gif over the zoomed art -- pixlet has no per-frame
procedural drawing hook, so the noise is pre-baked with Pillow rather
than generated at render time; render.Image plays animated GIFs back
natively, independent of the zoom's own animation timeline.

Tuned the GIF's frame count/density/flicker speed down after an initial
version pushed total payload within a few percent of the 460KB device
limit on some album art -- more, faster-changing frames give WebP less
opportunity to dedupe near-identical frames, which compounds with the
zoom animation's own dedupe needs. Final version adds ~50KB regardless of
art complexity, verified via a pinned-cover test harness for reliable
before/after comparison (the live station's currently-playing track kept
changing between test runs otherwise).

Added a "Static overlay" On/Off schema toggle (default On) per request.
This commit is contained in:
poprhythm committed 2026-10-02 22:32:24 -04:00
1 parent f6893bdcdf
commit 5a54376f8e
3 files changed
+69 -3

No files matched your search

+22
View File
@@ -30,6 +30,9 @@ app's config when adding it to a device.
*every* refresh, not just when the track changes, so a long track gets
to show off different sections of its art over time instead of being
stuck on one spot for its whole runtime.
- **Static overlay** — On (default) or Off. When on, shows a brief
TV-static effect (sparse noise specks) over the album art during the
first/last few seconds of a track, as a transition cue.
## How it works
@@ -112,6 +115,25 @@ app's config when adding it to a device.
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.
- When enabled (Static overlay config), shows a brief TV-static effect
over the album art during the first/last `STATIC_OVERLAY_SECONDS` (5s)
of a track, as a transition cue. Implemented as a small bundled animated
GIF (`images/static.gif` — sparse noise specks over a transparent
background, built with Pillow) composited over the zoomed art via
`render.Stack`, not generated at render time: pixlet's Starlark sandbox
has no per-frame procedural drawing hook, and `animation.Transformation`
only interpolates between fixed keyframes, so there's no way to get
genuine random noise out of it. `render.Image` plays back animated GIFs
natively, looping independently of the zoom's own animation timeline.
Like the progress bar, this only works correctly on a long-lived server
with a persistent cache — a one-shot `pixlet render` CLI call always
sees `elapsed=0`, so it'll always show the "starting" static, never the
"ending" one. Tuned the GIF's frame count/density/flicker speed down
(fewer, sparser, slower-changing frames) after an initial version came
within a few percent of the 460KB device limit on some album art — more
distinct frames changing more often give WebP less opportunity to
dedupe near-identical frames, and that cost compounds with the zoom
animation already using up dedupe headroom of its own.
- 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.