# mpvpaper: an mpv-backed video wallpaper for wlroots compositors

> mpvpaper is a small C program that plays a video as your desktop wallpaper on wlroots based Wayland compositors such as sway, by handing the surface to mpv through libmpv and accepting mpv options directly. It is deliberately narrow: no X11, no GNOME, and no configuration file.

**GhostNaN/mpvpaper** — A video wallpaper program for wlroots based wayland compositors.

- Repository: https://github.com/GhostNaN/mpvpaper
- Stars: 1,641 · Forks: 54
- Language: C
- License: GPL-3.0
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/ghostnan-mpvpaper

## The scope: one wallpaper program, one compositor family

mpvpaper is described as a wallpaper program for wlroots based wayland compositors, such as sway, that lets you play videos with mpv as your wallpaper.

That sentence is the entire specification, and its narrowness is the design. The README describes this scope without detailing any fallback for other desktop environments. The program assumes a wlroots based compositor and hands a video to mpv.

The mechanism follows from that. The build requirements are ninja, meson and libmpv, and the dependencies are mpv and wlroots. So mpv does the decoding, the audio handling and the playback state, and mpvpaper's job is to create the surface on the right output and connect mpv to it. That is why the usage is a single line with a video path, and why mpv options pass straight through.

The intended user is someone who already chose sway or a similar compositor and wants a moving wallpaper rather than a still image. The most likely user is someone who already runs mpv daily and wants their wallpaper to obey the same preferences.

## Building with meson, and what has to be present first

The build is a standard meson project and the README gives the full sequence:

```bash
# Clone
git clone --single-branch https://github.com/GhostNaN/mpvpaper
# Build
cd mpvpaper
meson setup build --prefix=/usr/local
ninja -C build
# Install
ninja -C build install
```

The prefix of /usr/local is explicit in the example, which matters on a distribution where /usr/local/bin is not on your PATH, and it means an unprivileged install needs the prefix changed to somewhere inside your home directory.

The prerequisites are worth stating separately because they are where a first attempt fails. You need mpv and wlroots as dependencies, and you need the libmpv development package in addition to meson and ninja. libmpv is the client library, so a machine that can run the mpv application is not necessarily a machine that has the headers to build against it.

The repository layout is compact and matches a small C project: meson.build at the root, src/ for the program, inc/ for headers, proto/ for what appears to be protocol definitions, mpvpaper.man for the manual page, and scripts/ for the examples the README points at.

## Usage: output name first, then the video

The simplest invocation takes an output name and a path:

```bash
mpvpaper DP-2 /path/to/video
```

The output name is the first argument and the examples use connector names such as DP-2 and HDMI-A-1. There is a shortcut for every output:

```bash
mpvpaper ALL /path/to/video
```

mpv options are forwarded with --mpv-options or the short form -o, and they take mpv's own syntax:

```bash
mpvpaper -o "no-audio --loop-playlist shuffle" HDMI-A-1 www.url/to/playlist
```

That example shows three things at once: a multi-option string, a shuffle playlist from a URL rather than a local file, and the fact that the video argument can be anything mpv accepts rather than only a path. Since mpv does the opening, a local file, a URL and a playlist are all equally valid.

The one operational trap is the output name. If you pass a connector name that does not exist on the machine, there is no wallpaper and no obvious complaint, because the argument is a string and the program has nothing to compare it against. Using ALL sidesteps the problem entirely when you only have one screen, and when you have several, checking your connector naming is the first thing to do when nothing appears.

## Controlling a forked process through the mpv IPC socket

Keyboard bindings work the way they do in mpv, because the player is mpv. The README states you can control mpvpaper just like mpv in the terminal with keyboard bindings.

The harder case is a forked process. When mpvpaper is running in the background you have no terminal attached, so the program offers the standard mpv route: start an input IPC server and talk to it over a socket.

```bash
mpvpaper -o "input-ipc-server=/tmp/mpv-socket" DP-1 /path/to/video
```

Then commands go in with socat, for example toggling pause:

```bash
echo 'cycle pause' | socat - /tmp/mpv-socket
```

That is worth pausing on, because it means a systemd unit, a keybinding or a script can control the wallpaper using the whole mpv command interface rather than a bespoke control scheme. The README points to the mpv manual for the available commands, and to a scripts page in the repository for ideas.

There is a man page at mpvpaper.man for the details beyond this README, which is where the full option list lives given that the README covers only the common cases.

## Limitations: no X11, no desktop integration, no persistence

The first limitation is the compositor family. The README identifies wlroots based compositors, such as sway, as the target and describes no fallback for other desktop environments.

The second is that nothing here persists the wallpaper across a reboot. The README shows a command, not a service, and the scripts directory is described as ideas and references rather than a supplied set of units. Wiring it into your compositor's startup configuration is left to you, which is a small task for someone who already configures sway and an afternoon for someone who does not.

The third is the dependency chain. mpv, wlroots and libmpv all have to be present and compatible, and because wlroots is a moving target across compositor versions, a wlroots upgrade is the most likely thing to break a build that worked last month.

The fourth is resource cost, which follows from the architecture rather than being documented: mpv decodes video continuously for as long as the wallpaper runs. The no-audio option in the README example exists because audio from a wallpaper is rarely wanted, but the decoding work itself is not optional, and on a laptop that is a battery decision.

## How swaybg and glpaper differ

The acknowledgements name the ancestry: glpaper and swaybg provided the initial boilerplate code. Comparing against them explains what mpvpaper adds and what it gives up.

swaybg draws a solid colour, an image or a border onto the background layer. It has no media decoding at all, which means it costs almost nothing and needs no player. mpvpaper adds a full video pipeline to that layer, which is the entire point and also the entire cost.

mpvpaper can forward mpv options and expose mpv's command interface, as shown by its documented -o and IPC examples.

The other comparison is a dedicated video wallpaper compositor or a screensaver tool. Those tend to bundle their own player and configuration, which sounds simpler until you want a specific mpv option. Here, no-audio and loop-playlist shuffle are one -o string, and there is nothing to configure because there is no configuration.

So the choice is: swaybg if a still image is enough, mpvpaper if you want video with mpv's behaviour, and something bundled if you would rather not depend on mpv at all.

## Licence, release naming and what to check

mpvpaper is licensed under GPLv3, with the LICENSE file at the repository root, and the README points to it. That is a note about the terms rather than legal advice; for a wallpaper program the practical implication is that a modified binary you distribute carries the same obligations.

The release names are unusual and worth knowing before you search for them: 1.7 is titled Starting Engines from 2024-08-05, 1.8 is Spacing Out from 2025-05-10, and 1.9 is Solving Trajectories from 2026-07-18.

The repository is not archived and the last push was on 2026-08-29, so the source is current with the 1.9 release rather than trailing far behind it.

Before building, check four things. Confirm your compositor is wlroots based, because that decides whether this applies at all. Confirm the libmpv development package is installed, not just the mpv binary. Check your output connector naming so the first argument matches a real output. And read mpvpaper.man, since the README covers only the common invocations and the manual page is where the rest of the options are.

## Conclusion

Use mpvpaper if you run sway or another wlroots compositor and want a video wallpaper with mpv's full playback control, since forwarding options like no-audio and loop-playlist shuffle through -o is the reason to choose it over a static wallpaper tool. Do not use it on GNOME, KDE or any X11 session: the program targets wlroots based compositors and there is no X11 path described. Verify first that libmpv, mpv and wlroots development packages are present before building, and that the output name you pass as the first argument matches your connector naming, because ALL is the documented way to target every output and a wrong connector name means no wallpaper rather than an error.

## FAQ

### How do I build and install mpvpaper?

Clone with git clone --single-branch https://github.com/GhostNaN/mpvpaper, then run meson setup build --prefix=/usr/local, ninja -C build and ninja -C build install. Build requirements are ninja, meson and libmpv, and the program depends on mpv and wlroots.

### How do I play a video on every monitor with mpvpaper?

Pass ALL as the first argument instead of a specific output name, as in mpvpaper ALL /path/to/video. For a single display you can name the connector directly, for example mpvpaper DP-2 /path/to/video.

### How do I pass mpv options to mpvpaper?

Use --mpv-options or the short form -o, with mpv's own option syntax inside a quoted string. The README's example is mpvpaper -o "no-audio --loop-playlist shuffle" HDMI-A-1 www.url/to/playlist, which also shows the video argument can be a URL.

### How do I control mpvpaper while it is running in the background?

Enable mpv's IPC server through mpvpaper, for example mpvpaper -o "input-ipc-server=/tmp/mpv-socket" DP-1 /path/to/video, then send commands through socat. Toggling pause is echo 'cycle pause' | socat - /tmp/mpv-socket, and the mpv manual documents the available commands.

### Which compositors does mpvpaper work with?

It targets wlroots based wayland compositors such as sway. There is no X11 path described in the README, so it does not apply to GNOME or KDE desktop sessions running on X11.

## Sources

- [GhostNaN/mpvpaper on GitHub](https://github.com/GhostNaN/mpvpaper)
- [Issues](https://github.com/GhostNaN/mpvpaper/issues)
- [License: GPL-3.0](https://github.com/GhostNaN/mpvpaper/blob/master/LICENSE)
- [README](https://github.com/GhostNaN/mpvpaper/blob/master/README.md)
- [Releases](https://github.com/GhostNaN/mpvpaper/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ghostnan-mpvpaper
