Rust屏幕捕获库windows-capture的使用:高效截取Windows屏幕和窗口内容的Rust插件

Rust屏幕捕获库windows-capture的使用:高效截取Windows屏幕和窗口内容的Rust插件

Windows Capture是一个高效的Rust库,可让您轻松使用Windows Graphics Capture API捕获屏幕内容。该库使您可以轻松捕获Windows计算机的屏幕,并将其用于各种用途,例如创建教学视频、截图或录制游戏画面。凭借其直观的界面和强大的功能,Windows Capture是寻找可靠、易用屏幕捕获解决方案的绝佳选择。

特性

  • 仅在需要时更新帧
  • 高性能
  • 易于使用
  • 最新的屏幕捕获API

安装

在您的Cargo.toml中添加以下依赖:

[dependencies]
windows-capture = "1.5.0"

或者运行以下命令:

cargo add windows-capture

使用示例

以下是基础使用示例代码:

use std::io::{self, Write};
use std::time::Instant;

use windows_capture::capture::{Context, GraphicsCaptureApiHandler};
use windows_capture::encoder::{
    AudioSettingsBuilder, ContainerSettingsBuilder, VideoEncoder, VideoSettingsBuilder,
};
use windows_capture::frame::Frame;
use windows_capture::graphics_capture_api::InternalCaptureControl;
use windows_capture::monitor::Monitor;
use windows_capture::settings::{
    ColorFormat, CursorCaptureSettings, DirtyRegionSettings, DrawBorderSettings,
    MinimumUpdateIntervalSettings, SecondaryWindowSettings, Settings,
};

// 捕获处理结构体
struct Capture {
    encoder: Option<VideoEncoder>,
    start: Instant,
}

impl GraphicsCaptureApiHandler for Capture {
    type Flags = String;
    type Error = Box<dyn std::error::Error + Send + Sync>;

    fn new(ctx: Context<Self::Flags>) -> Result<Self, Self::Error> {
        println!("初始化捕获处理器,标志: {}", ctx.flags);

        let encoder = VideoEncoder::new(
            VideoSettingsBuilder::new(1920, 1080),
            AudioSettingsBuilder::default().disabled(true),
            ContainerSettingsBuilder::default(),
            "output.mp4",
        )?;

        Ok(Self { 
            encoder: Some(encoder), 
            start: Instant::now() 
        })
    }

    fn on_frame_arrived(
        &mut self,
        frame: &mut Frame,
        capture_control: InternalCaptureControl,
    ) -> Result<(), Self::Error> {
        print!("\r捕获中: {}秒", self.start.elapsed().as_secs());
        io::stdout().flush()?;

        self.encoder.as_mut().unwrap().send_frame(frame)?;

        if self.start.elapsed().as_secs() >= 10 {
            self.encoder.take().unwrap().finish()?;
            capture_control.stop();
            println!("\n捕获完成");
        }

        Ok(())
    }

    fn on_closed(&mut self) -> Result<(), Self::Error> {
        println!("捕获会话已结束");
        Ok(())
    }
}

fn main() {
    let primary_monitor = Monitor::primary().expect("无法获取主显示器");

    let settings = Settings::new(
        primary_monitor,
        CursorCaptureSettings::Default,
        DrawBorderSettings::Default,
        SecondaryWindowSettings::Default,
        MinimumUpdateIntervalSettings::Default,
        DirtyRegionSettings::Default,
        ColorFormat::Rgba8,
        "自定义标志".to_string(),
    );

    Capture::start(settings).expect("屏幕捕获失败");
}

完整示例代码

以下是一个更完整的示例,展示了如何捕获特定窗口并保存为图片:

use std::path::Path;
use windows_capture::{
    capture::{CaptureControl, GraphicsCaptureApiHandler, Settings},
    frame::ImageFormat,
    window::Window,
};

// 捕获处理结构体 - 用于保存单帧图片
struct Screenshot {
    output_path: String,
}

impl GraphicsCaptureApiHandler for Screenshot {
    type Flags = String;
    type Error = Box<dyn std::error::Error + Send + Sync>;

    fn new(_: windows_capture::capture::Context<Self::Flags>) -> Result<Self, Self::Error> {
        Ok(Self {
            output_path: "screenshot.png".to_string(),
        })
    }

    fn on_frame_arrived(
        &mut self,
        frame: &mut windows_capture::frame::Frame,
        capture_control: windows_capture::graphics_capture_api::InternalCaptureControl,
    ) -> Result<(), Self::Error> {
        // 保存当前帧为PNG图片
        frame.save_as_image(&self.output_path, ImageFormat::Png)?;
        println!("截图已保存到: {}", self.output_path);
        
        // 停止捕获
        capture_control.stop();
        
        Ok(())
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 获取记事本窗口
    let notepad_window = Window::from_title("记事本").expect("找不到记事本窗口");
    
    // 配置捕获设置
    let settings = Settings::new(
        notepad_window,
        windows_capture::settings::CursorCaptureSettings::Default,
        windows_capture::settings::DrawBorderSettings::Default,
        windows_capture::settings::SecondaryWindowSettings::Default,
        windows_capture::settings::MinimumUpdateIntervalSettings::Default,
        windows_capture::settings::DirtyRegionSettings::Default,
        windows_capture::settings::ColorFormat::Rgba8,
        "窗口截图示例".to_string(),
    );

    // 开始捕获
    Screenshot::start(settings)?;
    
    Ok(())
}

文档

详细的API和类型文档可以在文档页面找到。

贡献

欢迎贡献!如果您发现错误或想为库添加新功能,请提交问题或拉取请求。

许可证

该项目采用MIT许可证。


1 回复

Rust屏幕捕获库windows-capture的使用指南

windows-capture是一个高效的Rust库,专门用于在Windows系统上捕获屏幕或窗口内容。它提供了简单易用的API,支持多种捕获模式,适合需要屏幕录制或截图功能的Rust应用程序。

主要特性

  • 支持全屏捕获和单个窗口捕获
  • 高性能,低延迟
  • 提供帧回调机制
  • 支持多显示器配置
  • 可捕获鼠标光标

安装

在Cargo.toml中添加依赖:

[dependencies]
windows-capture = "1.0"

基本使用方法

1. 捕获整个屏幕

use windows_capture::capture::GraphicsCaptureApi;
use windows_capture::frame::Frame;
use windows_capture::monitor::Monitor;
use windows_capture::settings::{Settings, CursorCaptureSettings};

fn main() {
    // 获取主显示器
    let primary_monitor = Monitor::primary().expect("获取主显示器失败");
    
    // 创建捕获设置
    let settings = Settings::new(
        // 要捕获的显示器
        primary_monitor,
        // 光标捕获设置
        CursorCaptureSettings::Default,
        // 绘制边框
        true,
        // 限制捕获帧率
        None,
    );
    
    // 启动捕获
    let graphics_capture_api = GraphicsCaptureApi::new(settings).expect("创建捕获API失败");
    
    // 设置帧回调
    graphics_capture_api.start(|frame| {
        // 处理捕获到的帧
        println!("捕获到帧: {}x{}", frame.width(), frame.height());
        
        // 可以在这里保存帧为图片或进行其他处理
        frame.save_as_image("screenshot.png").expect("保存图片失败");
        
        // 返回true继续捕获,false停止
        true
    }).expect("启动捕获失败");
}

2. 捕获特定窗口

use windows_capture::capture::GraphicsCaptureApi;
use windows_capture::window::Window;
use windows_capture::settings::{Settings, CursorCaptureSettings};

fn main() {
    // 查找记事本窗口
    let notepad_window = Window::from_contains_name("记事本")
        .expect("找不到记事本窗口");
    
    let settings = Settings::new(
        notepad_window,
        CursorCaptureSettings::Default,
        true,
        None,
    );
    
    let graphics_capture_api = GraphicsCaptureApi::new(settings).expect("创建捕获API失败");
    
    graphics_capture_api.start(|frame| {
        println!("捕获到记事本窗口帧: {}x{}", frame.width(), frame.height());
        true
    }).expect("启动捕获失败");
}

3. 捕获多显示器配置

use windows_capture::monitor::Monitor;

fn main() {
    // 获取所有显示器
    let monitors = Monitor::enumerate().expect("获取显示器列表失败");
    
    for monitor in monitors {
        println!("显示器: {} - {}x{}", 
            monitor.name(),
            monitor.width(),
            monitor.height()
        );
    }
}

高级用法

1. 自定义帧处理

use windows_capture::capture::GraphicsCaptureApi;
use windows_capture::monitor::Monitor;
use windows_capture::settings::Settings;
use image::{ImageBuffer, Rgba};

fn main() {
    let primary_monitor = Monitor::primary().unwrap();
    let settings = Settings::new(primary_monitor, None, true, None);
    
    let graphics_capture_api = GraphicsCaptureApi::new(settings).unwrap();
    
    graphics_capture_api.start(|frame| {
        // 将帧转换为image库的ImageBuffer进行处理
        let img: ImageBuffer<Rgba<u8>, _> = frame.to_image_buffer().unwrap();
        
        // 示例:计算平均亮度
        let mut sum = 0u64;
        for pixel in img.pixels() {
            let [r, g, b, _] = pixel.0;
            sum += r as u64 + g as u64 + b as u64;
        }
        let avg_brightness = sum / (img.width() as u64 * img.height() as u64 * 3);
        
        println!("平均亮度: {}", avg_brightness);
        
        true
    }).unwrap();
}

2. 限制帧率

use windows_capture::settings::Settings;
use std::time::Duration;

let settings = Settings::new(
    Monitor::primary().unwrap(),
    None,
    true,
    Some(Duration::from_millis(100)), // 限制为10FPS
);

完整示例demo

下面是一个完整的屏幕捕获示例,包含捕获屏幕、保存截图和简单的帧处理:

use windows_capture::{
    capture::GraphicsCaptureApi,
    frame::Frame,
    monitor::Monitor,
    settings::{Settings, CursorCaptureSettings},
};
use image::{ImageBuffer, Rgba};

fn main() {
    // 1. 获取主显示器
    let primary_monitor = Monitor::primary().expect("无法获取主显示器");
    
    // 2. 配置捕获设置
    let settings = Settings::new(
        primary_monitor,
        CursorCaptureSettings::WithCursor, // 包含鼠标光标
        true, // 绘制边框
        Some(std::time::Duration::from_millis(33)), // 限制30FPS
    );
    
    // 3. 创建捕获API实例
    let capture_api = GraphicsCaptureApi::new(settings).expect("创建捕获API失败");
    
    // 4. 启动捕获并处理帧
    capture_api
        .start(|frame| {
            // 获取帧信息
            println!(
                "捕获到帧 - 大小: {}x{}, 时间戳: {}",
                frame.width(),
                frame.height(),
                frame.timestamp()
            );
            
            // 保存为PNG图片
            frame
                .save_as_image("latest_frame.png")
                .expect("保存图片失败");
            
            // 转换为ImageBuffer进行进一步处理
            if let Ok(img) = frame.to_image_buffer() {
                process_image(&img);
            }
            
            true // 继续捕获
        })
        .expect("启动捕获失败");
}

// 简单的图像处理函数
fn process_image(img: &ImageBuffer<Rgba<u8>, Vec<u8>>) {
    // 示例:计算红色通道平均值
    let red_sum: u64 = img.pixels().map(|p| p[0] as u64).sum();
    let red_avg = red_sum / (img.width() as u64 * img.height() as u64);
    println!("红色通道平均值: {}", red_avg);
}

注意事项

  1. 需要在Windows 10 (1809+)或Windows 11上运行
  2. 需要启用"图形捕获"权限
  3. 某些受保护的窗口(如UAC对话框)可能无法捕获
  4. 捕获性能取决于屏幕分辨率和帧率设置
  5. 需要添加image库到Cargo.toml来处理图像:image = "0.24"

这个库为Rust开发者提供了强大的Windows屏幕捕获能力,适合开发屏幕录制、直播、远程控制等应用程序。

回到顶部