Video decodes on the GPU. Always.
Media Foundation with D3D11VA, and no CPU fallback — deliberately. A software decoder burns a core for as long as it is on screen, on exactly the machines this is for.
Muivly
Native, Windows, open source. Built for the old laptop with integrated graphics and 8 GB of RAM — the machine the alternatives tax all day, every day.
v0.1.0 — the first release
A promise you cannot check is marketing.
Measured on a two-monitor hybrid laptop — integrated plus discrete GPU, so two decoders, which is the worst case Muivly has. 1080p video at 30 fps.
| While… | CPU (one core) |
|---|---|
| the desktop is visible | 13.7% |
| every monitor is covered | 0.4% |
Memory is the honest weak spot, and it is where most of the work has gone. Worst case again — a 4K clip decoded on both GPUs:
| Working set | Private bytes | Threads | |
|---|---|---|---|
| Before | 610 MB | 790 MB | 80–82 |
| Now | 540 MB | 706 MB | 79–81 |
None of these numbers are yours. muivly-core --benchmark clip.mp4 plays a
wallpaper for thirty seconds and prints what it cost on your machine — the
real engine on the real desktop, not a separate measuring path.
Rules, not optimisations.
Every one of these is a hard rule in the repository. A change that breaks one is not merged, however well it works.
Media Foundation with D3D11VA, and no CPU fallback — deliberately. A software decoder burns a core for as long as it is on screen, on exactly the machines this is for.
A decoded frame stays on the GPU as a D3D11 texture. It never round-trips through system memory on its way to the screen.
The same video on three screens is decoded once and the texture shared. Screens on different GPUs get one decode each, because sharing across adapters would break the rule above.
Fullscreen game in front? Rendering stops — not slows. After twenty seconds the decoders are handed back too, so the memory goes with the CPU time. The last frame stays on screen.
Coverage detection never fires for a visible desktop with an empty chair in front of it. After five minutes untouched the picture stands still. Windows’ own idle counter — no input hook, no keystroke ever seen.
The wallpaper does not get more expensive when you start a build; everything else does. Above 80% of the machine it drops to 10 fps until things quieten down.
A lower frame rate on battery, and under Windows’ battery saver it stops moving altogether. Both on by default, because the machines this is for are the ones where it matters.
It uses a WebView, which costs RAM. That is a cost you pay only while the window is open — never while the wallpaper is running.
The lightest thing that can be on a desktop.
Drop in an .hlsl file with one function and it plays like any other
wallpaper — with no decoder, no picture buffers and no codec threads behind it. On a
1080p desktop the entire wallpaper is one texture and one program.
// param speed 0.1 3.0 1.0 How fast it moves
float4 mainImage(float2 uv)
{
float pulse = 0.5 + 0.5 * sin(iTime * speed);
return float4(uv.x, uv.y, pulse + iBand(0), 1.0);
}
// param line becomes a control in the
settings window, named by the file.
.glsl and it is translated
on the way in — line for line, so a compile error still points at the line you wrote.
iBand(0..7) splits what the machine is
playing into bands. The capture behind it has no thread of its own and is opened only
while a shader that reads it is on screen.
One choice, not seven.
Everything above is about what the engine refuses to spend. This is the part you actually touch: a settings window that closes to the tray, and a wallpaper that keeps running whether or not it is open.
Frame rate, memory budget, how long out of sight before the video is let go, how long the desk must be empty, what to fall to while the machine is busy, and two for the battery — seven real choices, and seven questions nobody opens a wallpaper app wanting to answer. They are one choice with four answers, from barely touch this machine to as good as it gets. Every dial is still there behind them.
Videos, photographs, GIFs and shaders in one place, with playlists that play in the order you wrote them or shuffled — a whole pass through the list before anything repeats. Every monitor can show something different, or one wallpaper can span all of them from a single decode.
A rule by the clock or by the Windows theme, so the desktop is not the same at midnight as at nine. Scenes remember an arrangement across every screen under a name. Applications you name freeze it while they are in front, for the work that wants the machine without covering the desktop.
Global shortcuts for next, pause and mute. A right-click item in Explorer that makes any file the wallpaper without opening a window. A tray menu with the same. Closing the settings window costs the wallpaper nothing, because the two were never the same process.
No telemetry. No account. No update pings.
HKEY_CURRENT_USER, which is
why the installer never asks for administrator rights.
v0.1.0, and it is a first release.
An installer that needs no administrator rights, or a portable zip you unzip and run.
Each has a .sha256 beside it, so you can check that what you downloaded is
what was built.
Windows 10 (1903+) or Windows 11, 64-bit, and a GPU with hardware video decode — essentially anything from 2014 onward, integrated graphics included. HEVC and AV1 need Microsoft’s free codec extensions from the Store; Muivly names the missing one when a file needs it.
Windows will warn you that the installer is unsigned. It is unsigned because a code-signing certificate costs a few hundred a year and there is no money behind this project — the alternative to the warning is not a safer download, it is no download. The source is right there if you would rather build it yourself.
It is a first release in the honest sense: memory is still above where it needs to be,
and it has been run on far fewer machines than Windows has shapes. If something is
wrong on yours, an issue with the output of muivly-core --caps in it is
the most useful thing you can send.