Visibility tears down. It does not pause.
When nothing can see the wallpaper, the decoder and its session are destroyed. The window server keeps showing the last frame for free, and playback resumes from the saved timestamp.
A live wallpaper built around one constraint:
it should cost almost nothing when you aren't looking at it.
Most video wallpaper apps wrap a media player around whatever file you drop in, and leave it decoding whether or not the desktop is visible. That is why they show up in Activity Monitor and Task Manager, and why laptop fans spin. LiveWall takes the opposite approach — every design decision trades features for resources.
This is the coverage gate, running live. The desktop is sampled on the same 64×40 grid the apps use. Leave less than 8% uncovered and the decoder is torn down after 0.4 s. It only comes back above 15%. The gap stops a window edge sitting on the line from flipping the decoder on and off.
All four apps are one program written in four languages. These five decisions are what keep them one project.
When nothing can see the wallpaper, the decoder and its session are destroyed. The window server keeps showing the last frame for free, and playback resumes from the saved timestamp.
The OS reports a desktop with one visible corner as "visible". LiveWall measures the uncovered fraction on a 64×40 grid instead. It stops below 8% and resumes above 15%.
Each tick pulls one decoded frame and hands it straight to the compositor. There's no read-ahead queue and no media clock. At 4K 10-bit, one frame is ~20 MB, so a read-ahead queue gets expensive fast.
Naming a pixel format costs a kernel round trip per frame. Not naming one cut copyNextSampleBuffer from 65 profiler samples to 4. LiveWall takes the decoder's native 4:2:0 output and converts it in the compositor, where it's free.
Every video is converted on import, and only the converted file is ever played. The playback path never sees an unknown codec, an oversized frame, 60 fps, an audio track or a B-frame. Your original file is never touched.
Measured on an M3 Pro against the real playback path. Same clip each time, one variable changed per row. Hardware decode costs the same at any frame size. What's left is the app's own per-frame work, and that grows with frames per second and nothing else.
Both pipelines decode the same clip. The top one buffers ahead like a media player does. The bottom one is LiveWall: one tick, one sample, shown immediately. Its buffer pool stays at the minimum.
The assets have no B-frames, so every frame must be decoded whether it's shown or not. Lowering the tick rate would just play the clip in slow motion. So any one of these conditions stops playback, and the last frame stays on screen. Tap a card to trigger it.
Each problem below would cost something on every frame if the file were played as-is. Converting at import fixes it once. The conversion uses the system encoder, with no bundled ffmpeg. Bundling it would add 40–70 MB, plus a licensing question, to a 504 KB app.
Each port uses its platform's own APIs: no cross-platform runtime, no web view, and nothing that runs in the background without a reason. Each README covers how the port stays cheap, what was measured, and what it gives up.
Both clips come from LiveWall's own procedural field, not from stock footage. They're original work under the repo's MIT licence, and you can regenerate them with tools/make-samples.sh.
SSIM measured across the loop seam. 1.0 would mean the last frame and the first frame are identical. You won't see the cut.
Grab a build from Releases, or build from source. Then pick Add Video… from the menu.