xcap

repository·master·Indexed 21 days ago

https://github.com/nashaofu/xcap

A cross-platform screen capture library written in Rust. xcap supports screenshots and video recording across Linux (X11, Wayland), macOS, Windows (>=8.1), and HarmonyOS (OpenHarmony/OHOS). It provides a high-level API featuring the Monitor type for display management and region capture, the Window type for capturing specific application windows, and VideoRecorder for capturing video frames.

Tokens
4.1K
Snippets
10
Records
17
Agent score
77%

What's inside xcap

  1. Overview of XCap

    master

    XCap is a cross-platform screen capture library written in Rust. It supports capturing screenshots and recording video across multiple operating systems.

    Supported Platforms and Features:

    • Linux (X11): Full support for screen/window screenshots and screen recording. Window recording is currently under development.
    • Linux (Wayland): Screen/window screenshots and screen recording are supported but may have limitations in specific scenarios. Window recording is under development.
    • MacOS: Full support for screen/window screenshots and screen recording. Window recording is under development.
    • Windows (>=8.1): Full support for screen/window screenshots and screen recording. Window recording is under development.
  2. Install Linux dependencies for XCap

    master

    To compile and run XCap on Linux, you must install specific system dependencies depending on your distribution.

    Debian/Ubuntu:

    apt-get install pkg-config libclang-dev libxcb1-dev libxrandr-dev libdbus-1-dev libpipewire-0.3-dev libwayland-dev libegl-dev

    Alpine:

    apk add pkgconf llvm19-dev clang19-dev libxcb-dev libxrandr-dev dbus-dev pipewire-dev wayland-dev mesa-dev

    ArchLinux:

    pacman -S base-devel clang libxcb libxrandr dbus libpipewire
    apt-get install pkg-config libclang-dev libxcb1-dev libxrandr-dev libdbus-1-dev libpipewire-0.3-dev libwayland-dev libegl-dev
  3. Capture screenshots of windows

    master

    Use Window::all() to get a list of all open windows. You can iterate through them and use window.capture_image() to take a screenshot of each. Note that minimized windows cannot be captured; check window.is_minimized() before attempting a capture.

    use fs_extra::dir;
    use std::time::Instant;
    use xcap::Window;
    
    fn normalized(filename: &str) -> String {
        filename.replace(['|', '\', ':', '/'], "")
    }
    
    fn main() {
        let start = Instant::now();
        let windows = Window::all().unwrap();
    
        dir::create_all("target/windows", true).unwrap();
    
        let mut i = 0;
        for window in windows {
            // 最小化的窗口不能截屏
            if window.is_minimized().unwrap() {
                continue;
            }
    
            println!(
                "Window: {:?} {:?} {:?}",
                window.title().unwrap(),
                (
                    window.x().unwrap(),
                    window.y().unwrap(),
                    window.width().unwrap(),
                    window.height().unwrap()
                ),
                (
                    window.is_minimized().unwrap(),
                    window.is_maximized().unwrap()
                )
            );
    
            let image = window.capture_image().unwrap();
            image
                .save(format!(
                    "target/windows/window-{}-{}.png",
                    i,
                    normalized(&window.title().unwrap())
                ))
                .unwrap();
    
            i += 1;
        }
    
        println!("运行耗时: {:?}", start.elapsed());
    }
  4. Record video from a monitor

    master

    To record video, obtain a video recorder from a monitor using monitor.video_recorder(). This returns a tuple containing the video_recorder and a receiver sx (likely a channel) that emits video frames. You can then call .start() and .stop() on the recorder to control the recording lifecycle.

    use std::{thread, time::Duration};
    use xcap::Monitor;
    
    fn main() {
        let monitor = Monitor::from_point(100, 100).unwrap();
    
        let (video_recorder, sx) = monitor.video_recorder().unwrap();
    
        thread::spawn(move || loop {
            match sx.recv() {
                Ok(frame) => {
                    println!("frame: {:?}", frame.width);
                }
                _ => continue,
            }
        });
    
        println!("start");
        video_recorder.start().unwrap();
        thread::sleep(Duration::from_secs(2));
        println!("stop");
        video_recorder.stop().unwrap();
        thread::sleep(Duration::from_secs(2));
        println!("start");
        video_recorder.start().unwrap();
        thread::sleep(Duration::from_secs(2));
        println!("stop");
        video_recorder.stop().unwrap();
    }
  5. Capture a specific region of a monitor

    master

    To capture a specific rectangular area of a monitor, use monitor.capture_region(x, y, width, height). This is useful for partial screenshots.

    use fs_extra::dir;
    use std::time::Instant;
    use xcap::Monitor;
    
    fn normalized(filename: String) -> String {
        filename.replace(['|', '\', ':', '/'], "")
    }
    
    fn main() -> Result<(), Box<dyn std::error::Error>> {
        let monitors = Monitor::all()?;
        dir::create_all("target/monitors", true).unwrap();
    
        let monitor = monitors
            .into_iter()
            .find(|m| m.is_primary().unwrap_or(false))
            .expect("No primary monitor found");
    
        let monitor_width = monitor.width()?;
        let monitor_height = monitor.height()?;
    
        let region_width = 400u32;
        let region_height = 300u32;
    
        let x = ((monitor_width as i32) - (region_width as i32)) / 2;
        let y = ((monitor_height as i32) - (region_height as i32)) / 2;
        let start = Instant::now();
    
        let image = monitor.capture_region(x, y, region_width, region_height)?;
        println!(
            "Time to record region of size {}x{}: {:?}",
            image.width(),
            image.height(),
            start.elapsed()
        );
    
        image
            .save(format!(
                "target/monitors/monitor-{}-region.png",
                normalized(monitor.friendly_name().unwrap())
            ))
            .unwrap();
    
        Ok(())
    }
  6. Capture all monitors using Monitor::all()

    master

    You can iterate through all available monitors on the system using Monitor::all(). Each monitor instance allows you to capture its full screen as an image.

    use fs_extra::dir;
    use std::time::Instant;
    use xcap::Monitor;
    
    fn normalized(filename: String) -> String {
        filename.replace(['|', '\', ':', '/'], "")
    }
    
    fn main() {
        let start = Instant::now();
        let monitors = Monitor::all().unwrap();
    
        dir::create_all("target/monitors", true).unwrap();
    
        for monitor in monitors {
            let image = monitor.capture_image().unwrap();
    
            image
                .save(format!(
                    "target/monitors/monitor-{}.png",
                    normalized(monitor.friendly_name().unwrap())
                ))
                .unwrap();
        }
    
        println!("运行耗时: {:?}", start.elapsed());
    }
  7. Capture images and video from a monitor

    master

    The Monitor struct allows for both static image capture and video recording.

    Static Image Capture

    • capture_image(): Captures the entire monitor as an RgbaImage.
    • capture_region(x, y, width, height): Captures a specific rectangular area of the monitor.
      • Note: If the requested region extends beyond the monitor's bounds, it will return an XCapError::InvalidCaptureRegion error.

    Video Recording

    • video_recorder(): Initializes a video recording session. It returns a tuple containing:
      1. A VideoRecorder instance to control the recording.
      2. A std::sync::mpsc::Receiver<Frame> used to receive individual video frames.
    use xcap::Monitor;
    
    let monitor = Monitor::all().unwrap()[0].clone();
    
    // Capture a region
    let img = monitor.capture_region(0, 0, 500, 500).unwrap();
    
    // Start video recording
    let (recorder, frame_receiver) = monitor.video_recorder().unwrap();
    // Use recorder and frame_receiver to handle video stream...
  8. Capture a window image with capture_image()

    master

    You can capture the visual content of a specific window as an RgbaImage using the capture_image() method. This is useful for taking screenshots of individual application windows.

    use xcap::Window;
    use image::RgbaImage;
    
    let windows = Window::all()?;
    if let Some(window) = windows.first() {
        let image: RgbaImage = window.capture_image()?;
        image.save("window_capture.png").unwrap();
    }
  9. List all available windows with Window::all()

    master

    To get a list of all currently open windows on the system, use the Window::all() method. The returned windows are sorted by their z-coordinate (stacking order).

    use xcap::Window;
    
    let windows = Window::all().expect("Failed to list windows");
    for window in windows {
        println!("Window: {:?}", window.title());
    }
  10. Get monitor properties and metadata

    master

    The Monitor struct provides several methods to inspect the characteristics of a display. All methods return an XCapResult.

    Identity and Naming

    • id(): Returns a unique u32 identifier for the screen.
    • name(): Returns the display name.
    • friendly_name(): Returns a user-friendly display name.

    Geometry and Position

    • x(): The screen's X coordinate.
    • y(): The screen's Y coordinate.
    • width(): The screen's pixel width.
    • height(): The screen's pixel height.
    • rotation(): The screen rotation in clockwise degrees (e.g., 0, 90, 180, 270).

    Display Characteristics

    • scale_factor(): The output device's pixel scale factor.
    • frequency(): The screen refresh rate.
    • is_primary(): Returns true if the screen is the main display.
    • is_builtin(): Returns true if the screen is a built-in display (e.g., a laptop screen).
  11. List all monitors or find a monitor by coordinates

    master

    You can retrieve a list of all available monitors using Monitor::all(). Alternatively, if you have specific screen coordinates, you can use Monitor::from_point(x, y) to identify and return the Monitor instance that contains that point.

    Both methods return an XCapResult, so you must handle potential errors (e.g., if no monitors are found or the point is invalid).

    use xcap::Monitor;
    
    // Get all monitors
    let monitors = Monitor::all().unwrap();
    for monitor in monitors {
        println!("Found monitor: {}", monitor.name().unwrap());
    }
    
    // Get monitor at specific coordinates
    let monitor = Monitor::from_point(100, 100).unwrap();
  12. Get window metadata and properties

    master

    The Window struct provides several methods to inspect the properties of a specific window. All methods return an XCapResult to handle potential platform-specific errors.

    // Basic identification
    let id = window.id()?;
    let pid = window.pid()?;
    let app_name = window.app_name()?;
    let title = window.title()?;
    
    // Position and size
    let x = window.x()?;
    let y = window.y()?;
    let z = window.z();
    let width = window.width()?;
    let height = window.height()?;
    
    // State and environment
    let monitor = window.current_monitor()?;
    let is_minimized = window.is_minimized()?;
    let is_maximized = window.is_maximized()?;
    let is_focused = window.is_focused()?;