wl-screenrec keeps raw video off the CPU with dma-buf and VAAPI
High performance wlroots screen recording, featuring hardware encoding
At a glance
- What is it?
- wl-screenrec records a wlroots Wayland compositor by pulling frames as dma-buf handles and letting the GPU do format conversion and encoding, so the raw pixels never reach the processor. It needs a compositor with the right protocols and a VAAPI-capable Intel or Radeon GPU.
- Who is it for?
- wl-screenrec fits a Wayland user on a machine with an Intel or Radeon GPU who wants to record their desktop without the CPU usage that a software pipeline costs, and it suits anyone who already runs wlroots and accepts the protocol requirements that come with it. It does not fit an X11 user, a compositor outside the listed set, or anyone with a GPU that cannot do VAAPI encoding.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 27 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The pixel path that never touches the processor
The design of wl-screenrec is one sentence: it uses dma-buf transfers to get the surface, and uses the GPU to do both the pixel format conversion and the encoding, meaning the raw video data never touches the CPU. That is the whole difference between this and a recorder that copies frames into user memory and hands them to a software encoder. The frames arrive as buffer handles shared with the compositor, the conversion to the encoder's preferred format happens in the same device, and the encoded output is what finally leaves. The README is explicit that this leaves the processor free to run your applications. The published benchmark compares that claim against wf-recorder on a 4kp60 display with an i9-11900H and a vkcube window on screen: wf-recorder sits at about 500% CPU, wf-recorder with hardware encoding at around 75%, and wl-screenrec at roughly 2.5%. The author calls the setup relatively unscientific but notes the numbers seem stable.
Four protocols decide whether it can run at all
The system requirements are stated as compositor protocols rather than as a list of hardware, and there is no fallback path. The compositor must support wlr-screencopy-unstable-v1 or ext-image-copy-capture-v1 for capture, linux-dmabuf-v1 for the buffer sharing that makes the zero-copy path possible, and xdg-output-unstable-v1 for output naming. The compatibility table lists eleven compositors that meet this criteria, including Cage, COSMIC, Hyprland, Jay, Labwc, Louvre, Mir, niri, Sway, Treeland and Wayfire, with version numbers for each. The table is generated by a script in the repository, compatible-compositors.nu, so the list is maintained rather than written once. Anything outside that set is not tested, and the protocol requirements are the reason the tool cannot simply run under GNOME or KDE.
VAAPI on Intel and Radeon, with one transform caveat
Encoding goes through VAAPI, and the documentation recommends consulting your distribution for setup. The known good configurations are Intel integrated GPUs and Radeon GPUs. The footnote on Radeon matters more than it looks: Mesa's VAAPI implementation does not support transform, so wl-screenrec will not work if you have a monitor with a transform applied to it. That is a specific, silent failure mode, since the monitor can look perfectly normal to the compositor while the recorder cannot use it. The dependency set in Cargo.toml shows the shape of the implementation, with ffmpeg-next and ffmpeg-sys-next at 9.0.0 for the encoding pipeline, drm 0.15.0 for direct DRM access, ash behind an experimental-vulkan feature flag, wayland-client and wayland-protocols including the unstable and staging protocol sets, clap 4 for the command line, and signal-hook plus signal-hook-mio for the signal handling that the history feature depends on.
Installing it from the AUR, cargo, or a distribution package
There are several install routes and the README treats them equally. On Arch the AUR packages are paru -S wl-screenrec for the stable version or the git variant. Building from source needs ffmpeg 6 or later as a required dependency, with ffmpeg 5 possibly working but untested, and the cargo invocation installs either the stable release or the git version depending on which URL you pass:
cargo install wl-screenrec # stable versionThe AUR route is equally short:
paru -S wl-screenrecFedora is directed at the cargo route, with a list of DNF packages needed first, libdrm-devel, freeglut-devel, clang and ffmpeg-free-devel, plus full ffmpeg and codecs from RPM Fusion for hardware acceleration. Debian and its derivatives need the libav development packages, libdrm-dev and clang for rust-ffmpeg-sys, and intel-media-va-driver with mesa-vulkan-drivers for the codecs. FreeBSD has a pkg install path. The project version in Cargo.toml is 0.3.2 on edition 2024, with the most recent release tag being v0.3.1 from 2026-08-10 and the last push on 2026-09-26.
Recording a region, audio, and the rolling history buffer
The usage surface is compact and each option maps to a real recording scenario. Capturing the entire output works with no arguments when you have one output, and you can name one with -o and an output identifier. A region is selected with -g, which accepts the output of slurp or a manual x,y WxH string, and is mutually exclusive with selecting an output. Audio capture is enabled with --audio, and the capture device can be named with --audio-device for desktop audio, where the monitor source is what you want. The history option is the most interesting one: --history 10 records the most recent ten seconds into memory instead of writing to the file, and then a killall -USR1 wl-screenrec signal flushes those ten seconds onto the file and switches to normal appending. That gives you a clipboard style rewind buffer for a demo you want to keep only the good part of.
444 subsampling and the v4l2loopback path
Two capabilities are worth calling out because they go beyond a plain recorder. The first is 444 video, which means no pixel format compression, enabled with --encode-pixfmt vuyx for 8-bit 444 or xrgb10 for 10-bit 444, alongside a --codec choice such as hevc. The documentation warns to check vainfo -a for supported pixel formats because support is heavily hardware dependent, and gives a personal example where only HEVC supports 444 formats on the machine in question and all the 8-bit RGB formats failed. The second is output to a v4l2loopback device, which turns the recorder into a camera source for applications such as Zoom: you load the module with modprobe v4l2loopback, find the dummy device with v4l2-ctl --list-devices, and pass the file to --ffmpeg-muxer v4l2. There is also a --no-cursor option and a --no-hw fallback that downloads frames onto the processor and uses a software encoder.
Where this sits against wf-recorder and the X11 world
The realistic alternative is wf-recorder, which the benchmark table measures directly, and the X11 toolchain of ffmpeg with x11grab. The difference in approach is the same one the whole project is built on. wf-recorder relies on compositor-side copies and, in the VAAPI configuration, still lands around 75% CPU, while wl-screenrec keeps the copy inside the GPU and lands near 2.5%, at the cost of about 30% more GPU video utilisation and 91% more GPU 3D. The visible symptom in the benchmark is that both wf-recorder setups show stuttering in the vkcube window while wl-screenrec does not appear to stutter at all. The price of the approach is the protocol requirement list, so a user on X11 or on a compositor outside the table has no option here, and a machine without VAAPI has to fall back to software encoding.
Editorial conclusion
wl-screenrec fits a Wayland user on a machine with an Intel or Radeon GPU who wants to record their desktop without the CPU usage that a software pipeline costs, and it suits anyone who already runs wlroots and accepts the protocol requirements that come with it. It does not fit an X11 user, a compositor outside the listed set, or anyone with a GPU that cannot do VAAPI encoding. Verify first that your compositor implements wlr-screencopy-unstable-v1 or ext-image-copy-capture-v1 along with linux-dmabuf-v1, that vainfo lists a usable encode entry point, and that your ffmpeg is version 6 or later before you start.
Frequently asked questions
Which Wayland compositors are supported by wl-screenrec?
The compositor must support wlr-screencopy-unstable-v1 or ext-image-copy-capture-v1, linux-dmabuf-v1 and xdg-output-unstable-v1. The README lists eleven compositors that meet this, including Sway, Hyprland, niri, Labwc, Wayfire, Mir, Cage, Jay, Louvre, COSMIC and Treeland.
How do I install wl-screenrec from source?
Install ffmpeg 6 or later, which is a required dependency, then run cargo install wl-screenrec for the stable version or cargo install --git with the repository URL for the git version. Fedora users also need libdrm-devel, freeglut-devel, clang and ffmpeg-free-devel from DNF.
Does wl-screenrec record audio and can it record a region?
Yes. The --audio flag enables audio capture, with --audio-device selecting a specific source such as a monitor device for desktop audio. A region is captured with -g, which accepts the output of slurp or a manual x,y WxH geometry and is mutually exclusive with selecting a single output.
What is the --history option for in wl-screenrec?
It keeps the most recent seconds in memory rather than writing them to the file, for example --history 10. Sending a USR1 signal with killall then flushes that buffer onto the file and switches the recorder to appending as it normally would.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rosalyntg-wl-screenrec)Was this useful?