About
A screen capture crate for Windows/macOS/Linux.
The docs.rs pages cover the Windows and macOS backends only: the Linux one binds PipeWire,
whose headers the docs.rs build image does not carry, so cargo doc locally is the only way
to read platform for Linux.
Usage
A capture is a [CaptureConfig] you create(), and a [CaptureDescriptor] you pull frames
from. Video and audio get a channel each.
Seeing it work
The quickest way to watch a capture is the winit example, a preview window that draws the
captured frames into itself:
It opens an always-on-top window, waits until that window has drawn a frame of its own, and
only then raises the system picker. Pick a source and it appears in the window; Esc quits.
On Windows and macOS the preview hides itself from the capture through [VideoConfig::hide],
on Linux no protocol allows that, so expect exactly that.
For somewhere with no display and no picker, cargo test --features dummy swaps the whole
platform module for a fake backend that generates frames, and runs the capture test headless.
Video only
size() is known by the time create returns; every frame carries its own size, pixel
format and capture timestamp anyway.
use ;
Video and audio
Two channels means two receivers to drain, so take whichever has a frame ready. Give audio
the deeper capacity of the two. sample_rate() answers None until the system has settled
the format, which on Linux and macOS happens after create returns -- every [AudioFrame]
carries its own rate, so the first frame always answers it.
use select;
use ;
Letting the user choose
Target::Pick raises the system picker and blocks until the user has chosen, so it must not
run on the thread driving the UI: the Windows picker is parented to the HWND you pass, whose
message pump would be the one blocked, and the macOS picker answers on the main queue. Linux
always shows the portal's picker, whatever the target, and only Primary/Monitor (monitors
only) and Pick (everything) narrow what it offers.
use thread;
use ;
Errors worth matching
CaptureError carries no free-form strings: every case a caller can act on is a variant.
A missing capability is Unsupported, which is usually worth retrying without the feature
that asked for it -- audio needs macOS 13+, and on Linux a connection to the PipeWire daemon
that a sandbox holding only the portal's screencast remote does not have.
use ;
/// `Ok(None)` when the user changed their mind; everything else is a real failure.
To restart a running capture with a different configuration, use
[CaptureDescriptor::update_config] rather than creating a second one: it takes the old
descriptor by value and drops it first, so the old capture cannot restore the very windows
the new one just hid.
Features
dummy: A dummy implementation that returns random 1080x720 images (AV_PIX_FMT_BGRA). No audio is produced.
AI Involvement
In this repo, commits by @kingwingfly are manually coded, while those by @kingwingfly-ai are coded by agents (Claude + OpenAI).