#shared-memory #screen-capture #windows #winapi #memory-buffer #desktop-duplication

rusty-duplication

使用 Rust 的桌面复制 API 在 Windows 上捕获屏幕,支持共享内存

10 个版本 (4 个重大更改)

0.5.0 2023 年 5 月 28 日
0.4.5 2023 年 5 月 26 日
0.3.0 2023 年 5 月 16 日
0.2.0 2023 年 5 月 13 日
0.1.0 2023 年 5 月 13 日

#563GUI

Download history 7/week @ 2024-03-13 3/week @ 2024-03-27 3/week @ 2024-04-03 1/week @ 2024-05-22 4/week @ 2024-05-29

每月 102 次下载

MIT 许可证

46KB
1K SLoC

rusty-duplication

license version docs.rs

使用 Rust 的桌面复制 API 在 Windows 上捕获屏幕,支持共享内存。

安装

cargo add rusty-duplication

使用方法

use rusty_duplication::{
  capturer::model::Capturer,
  manager::Manager,
  utils::{FrameInfoExt, OutputDescExt},
};
use std::{fs::File, io::Write, thread, time::Duration};

fn main() {
  // manager will collect monitor info when created
  let manager = Manager::default().unwrap();
  // you can also refresh monitor info manually
  // manager.refresh();

  // you can get monitor info before capturing start
  // for ctx in &manager.contexts {
  //   ctx.dxgi_output_desc().unwrap();
  //   ctx.dxgi_outdupl_desc();
  // }

  // create capturer for a display
  // this will allocate memory buffer to store pixel data
  let mut capturer = manager.contexts[0].simple_capturer().unwrap();

  // you can also get monitor info from a capturer
  let dxgi_outdupl_desc = capturer.dxgi_outdupl_desc().unwrap();
  let dxgi_output_desc = capturer.dxgi_output_desc().unwrap();
  // get resolution width/height
  println!("size: {}x{}", dxgi_outdupl_desc.ModeDesc.Width, dxgi_outdupl_desc.ModeDesc.Height);
  // get position
  println!("left: {}, top: {}, right: {}, bottom: {}", dxgi_output_desc.DesktopCoordinates.left, dxgi_output_desc.DesktopCoordinates.top, dxgi_output_desc.DesktopCoordinates.right, dxgi_output_desc.DesktopCoordinates.bottom);

  // sleep for a while before capture to wait system to update the screen
  thread::sleep(Duration::from_millis(100));

  // capture desktop image and get the frame info
  // `safe_capture` will check if the buffer's size is enough
  let info = capturer.safe_capture().unwrap();

  // check if this is a new frame using the extension method `desktop_updated`
  if info.desktop_updated() {
    println!("captured!");
  }

  // write to a file
  // `buffer()` will return `&[u8]` in BGRA32 format
  let mut file = File::create("capture.bin").unwrap();
  file.write_all(capturer.buffer()).unwrap();
}

高级使用

共享内存

您可以使用共享内存来在进程之间共享缓冲区。

此库提供了一个 SharedCapturer,它将使用 Windows 共享内存来存储缓冲区。只需使用名称调用 DuplicateContext.shared_capturer 即可。

manager.contexts[0].shared_capturer("Global\\MyFileMappingObject").unwrap();

注意:如果您的内存名称以 Global\\ 开头,您可能需要在管理员模式下运行。请参阅 文档

自定义捕获器

此库提供了一些低级 API,例如 DuplicateContext,因此您可以编写自己的捕获器。您可以参考 SimpleCapturer 的实现。

测试

使用 cargo test -- --test-threads=1 运行测试以防止测试并行运行。

注意:在测试期间移动鼠标以确保捕获鼠标指针,还请确保您的鼠标在主监视器上。

鸣谢

本项目基于以下项目

变更日志

依赖项

~129MB
~2M SLoC