wlr-shot
Screen capture for wlroots compositors, built on the shared
wlr-capture engine (ext-image-copy-capture-v1, correct
strides, occlusion-independent).
Status: early. It captures an output, a region (interactive
-sor-g/slurp), or a window — as a screenshot (PNG/JPEG/PPM) or an H.264 recording / timelapse.
Usage
||
|||
Source (pick one; defaults to the sole output):
-s, --select— interactively drag a region on a frozen overlay (spans all outputs;Esccancels,Enterconfirms). No external tool needed.-o, --output NAME— a whole output (e.g.DP-4).--all— the whole layout: every output combined into one image.-g, --geometry "X,Y WxH"— a logical region (the format slurp prints), stitched across every output it covers. Pairs with slurp:wlr-shot screenshot -g "$(slurp)" shot.png.-w, --window ID— a window, by itsext-foreign-toplevelidentifier (as printed bywlr-chooser).--pick-window— launchwlr-chooserto choose the window interactively.-a, --active-window— the focused window.--current-output— the focused output.
The last two need the compositor's focus info. Wayland exposes no portable way to
query focus, so these use compositor IPC: Sway (swaymsg) is supported today;
Hyprland / niri are natural future additions. Without a supported compositor they
error with a hint (use --pick-window / -o NAME instead).
Encoding & destination:
-t, --type—png(default),jpeg, orppm.-q, --quality— JPEG quality, 1–100 (default 90).-c, --clipboard— copy to the Wayland clipboard instead of writing a file. A small daemon detaches to serve the selection (wlrootsdata-control, the protocolwl-copyuses) until another client replaces it — the clipboard is pull-based, so the data must outlive the command.--clipboard-foregroundkeeps it in the foreground (for scripts/debugging). Needs a compositor exposingzwlr_data_control_manager_v1.FILE— destination, or-for stdout (the default). Ignored with--clipboard.--list-outputs— printNAME<TAB>WxH+X,Y(logical geometry) and exit.
Resolution: a whole output, or a region within a single output, is captured at native (physical) resolution — so a fractionally-scaled monitor keeps full pixel detail. A region spanning several outputs is composited at logical resolution.
Recording (record)
Stream a source to a file whose format follows the extension: .mp4/.mkv for
H.264 video, or .gif/.webp for an animated image (downscaled — GIF to 800 px,
WebP to 1280 px on the long side — and best used on a region, since per-frame GIF
quantization on a full 4K output is slow). The same source flags as screenshot apply — -o/sole output,
--current-output, -w ID/--pick-window, -a, -g, and -s — except a region
(-g/-s) records a single output for now (the one its top-left corner sits
on). Recording a window (-w/--pick-window) follows it across workspaces and
even while occluded.
--encoder—auto(default) prefers hardware (NVENC, then VAAPI) and falls back to softwarelibx264. Force one withnvenc/vaapi/software.--device PATH— DRM render node for VAAPI (default/dev/dri/renderD128).--fps N— frame rate (default 30). Capture is damage-driven (a frame only arrives when the screen changes), so a normal recording emits a constant--fps, repeating the last frame through static stretches;--timelapseinstead samples one frame per interval and plays them back at--fps, so the footage is sped up.--timelapse INTERVAL— sample one frame everyINTERVAL(2s,500ms,1m).-d, --duration SECS— stop automatically; otherwise Ctrl-C ends and finalises the file. (Recording a window also ends when the window closes.)- Audio — a video recording captures system audio (the default sink's monitor)
as an AAC track by default, via native PipeWire.
--no-audiorecords silently;--audio-source NODEcaptures a specific node instead (e.g. a microphone). Needs theaudiobuild feature (on by default; links libpipewire). GIF/WebP carry no audio. For a PipeWire-less host, build with--features audio-fallbackto add a Pulse/ALSA path (via FFmpeg's libavdevice, no extra system dep), tried after PipeWire.
Recording needs the video build feature (on by default), which links the system
FFmpeg libraries. A screenshots-only build drops it: cargo build -p wlr-shot --no-default-features --features i18n.
Requirements
A wlroots compositor exposing ext-image-copy-capture-v1,
ext-image-capture-source-v1 and ext-output-image-capture-source-manager-v1
(Sway ≥ 1.12 / wlroots ≥ 0.20). xdg-output is used for accurate logical
geometry when present.
The default build (with record) links the system FFmpeg libraries, so it needs
their development packages at build time — on Debian/Ubuntu: libavcodec-dev libavformat-dev libavutil-dev libavfilter-dev libavdevice-dev libswscale-dev libswresample-dev libva-dev (and clang for the bindings). Hardware encoding needs
the matching runtime: NVIDIA's libnvidia-encode for NVENC, or a VAAPI driver for
your GPU. None of this is required for the screenshots-only build.
License
MIT OR Apache-2.0.