Replace bundled static.gif with a live RGB-split glitch effect

Rebuilt the track-transition "static overlay" as a chromatic-aberration
glitch on the *live* album art instead of a bundled, pre-baked animated
GIF: two duplicate, differently-tinted copies of the actual art (via
filter.Hue, confirmed real and working), each cropped to a shifting
horizontal band, plus scanlines and viewfinder-style corner tick marks.

Loosely modeled on SUB/WAVE's own web UI, which does something similar to
its cover art on track change (found via its compiled CSS/JS: a
.v3-cover-live class gating an RGB-split band glitch, sweeping scanlines,
and corner tick marks). The exact keyframe timing past the first step
wasn't visible in the minified output, so GLITCH_STATES is an original
jitter sequence in the same spirit, not a reproduction of unseen code.

This is the third design for this effect: sparse noise specks, then a
version derived from a real "VHS glitch" stock-footage clip (dropped
because recognizable footage content showed through at 32x32, and it
compressed worse than procedural noise), now this. Since it needs no
bundled asset, the app goes back to a single-file upload -- reverted the
Deploy section accordingly.

Verified: renders cleanly across all zoom-level/static-overlay
combinations, payload stays well under the 460KB limit, and
render.Sequence's lack of looping (confirmed in pixlet's own source)
means the RGB-split jitter plays once per show_static window and settles
to just scanlines/ticks over clean art for the remainder, not a
constant distraction for the whole window.
This commit is contained in:
poprhythm committed 2026-10-08 15:58:15 -04:00
1 parent 8e101b997e
commit 2993e9e9a9
3 files changed
+148 -48

No files matched your search

+38 -34
View File
@@ -31,8 +31,8 @@ app's config when adding it to a device.
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-glitch effect (a jagged horizontal static band, plus scattered noise
specks) over the album art during the first/last few seconds of a
chromatic-aberration glitch (RGB-split bands, scanlines, and corner tick
marks) over the album art during the first/last few seconds of a
track, as a transition cue.
## How it works
@@ -116,33 +116,39 @@ 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-glitch 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` — a jagged horizontal static band plus
scattered noise specks, over a transparent background, procedurally
generated with Pillow, not sourced from any existing footage)
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. An earlier version
tried deriving this effect from a real "VHS glitch" stock-footage clip
(downloaded, downsampled, and thresholded for transparency) instead of
generating it — dropped because, even licensed as free-to-use, cropping
- When enabled (Static overlay config), shows a brief chromatic-aberration
glitch over the album art during the first/last `STATIC_OVERLAY_SECONDS`
(5s) of a track, as a transition cue: two duplicate, differently-tinted
copies of the *actual* art, each cropped to a shifting horizontal band
(RGB-split look), plus scanlines and viewfinder-style corner tick marks.
Loosely modeled on SUB/WAVE's own web UI, which does something similar
to its cover art on track change (found via its compiled CSS/JS — not
published anywhere as a spec, and the exact keyframe timing past the
first step wasn't visible in the minified output, so the specific
jitter sequence here, `GLITCH_STATES`, is an original sequence in the
same spirit rather than a reproduction of unseen code).
Built from the live, already-zoomed art via `filter.Hue`, not a bundled
asset — pixlet's `filter` module can recolor an arbitrary widget, so the
glitch bands reflect whatever's actually on screen. The RGB-split jitter
plays once per `show_static` window via `render.Sequence` (which doesn't
loop — confirmed in pixlet's own source, it just stops painting once its
total frame count is used up) and then goes quiet, while the scanlines
and corner ticks persist for the whole window as a constant texture.
Went through two earlier, discarded designs before landing here, both
bundled pre-baked animated GIFs rather than working from the live art:
first sparse noise specks, then a version derived from a real "VHS
glitch" stock-footage clip (downloaded, downsampled, and thresholded for
transparency) — dropped because, even licensed as free-to-use, cropping
it down to 32x32 let recognizable footage content show through at any
opacity that read as an actual "band" rather than sparse noise, and it
compressed noticeably worse than procedural noise does. 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.
opacity that read as an actual "band" rather than noise, and it
compressed noticeably worse than procedural noise. The current
live-`filter.Hue` version needs no bundled asset at all, so this app is
back to a single-file upload. 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.
- 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 —
@@ -215,12 +221,10 @@ ever changes.
## Deploy
On the Tronbyt server, go to the device's **Add App** page → **Upload app**,
and upload a zip of this repo's contents (`subwave_nowplaying.star` +
`images/`, zipped at the root, no extra parent folder) — it bundles
`images/static.gif` for the static-overlay effect, so a single-file upload
of just the `.star` file will fail. Configure the Station URL field when
adding it to your device's schedule.
Upload `subwave_nowplaying.star` directly through your Tronbyt server's
"Upload app" button on a device's Add App page (single file, no bundled
assets — no need to zip). Configure the Station URL field when adding it to
your device's schedule.
```
zip -r subwave-nowplaying.zip subwave_nowplaying.star images/
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.