Rust屏幕捕获库ScreenCaptureKit的使用,实现高效屏幕录制与截图功能

Rust屏幕捕获库ScreenCaptureKit的使用,实现高效屏幕录制与截图功能

以下是基于ScreenCaptureKit的Rust完整示例代码,展示如何实现屏幕录制和截图功能:

use screencapturekit::{
    SCContentFilter, SCShareableContent, SCStream, SCStreamOutputType, SCStreamConfig, 
    SCPixelFormat, SCColorSpace
};
use std::{fs::File, sync::mpsc, time::Duration};
use image::{ImageBuffer, Rgba};

// 屏幕截图示例
fn capture_screenshot() -> Result<(), Box<dyn std::error::Error>> {
    // 获取当前可用的屏幕内容
    let available_content = SCShareableContent::current()?;
    
    // 选择主显示器
    let main_display = available_content.displays
        .into_iter()
        .find(|d| d.is_main)
        .ok_or("主显示器未找到")?;

    // 创建内容过滤器
    let filter = SCContentFilter::new_display(main_display, false);

    // 配置流参数
    let config = SCStreamConfig {
        width: main_display.width as u32,
        height: main_display.height as u32,
        pixel_format: SCPixelFormat::BGRA8888,
        color_space: SCColorSpace::sRGB,
        shows_cursor: true,
        ..Default::default()
    };

    // 创建通信通道
    let (tx, rx) = mpsc::channel();

    // 创建并配置流
    let mut stream = SCStream::new(config)?;
    stream.add_output(SCStreamOutputType::Screen, move |sample, error| {
        if let Some(sample) = sample {
            if let Some(buffer) = sample.get_sample_buffer() {
                if let Some(image_buffer) = buffer.get_image_buffer() {
                    tx.send(image_buffer.clone()).unwrap();
                }
            }
        }
        if let Some(error) = error {
            eprintln!("捕获错误: {:?}", error);
        }
    })?;

    // 开始捕获
    stream.start_capture()?;
    
    // 等待并获取图像数据
    let image_buffer = rx.recv_timeout(Duration::from_secs(5))?;
    
    // 停止捕获
    stream.stop_capture()?;

    // 处理图像数据
    let width = image_buffer.width as u32;
    let height = image_buffer.height as u32;
    let bytes_per_row = image_buffer.bytes_per_row as usize;
    
    // 创建图像缓冲区
    let image = ImageBuffer::<Rgba<u8>, _>::from_raw(width, height, {
        let mut vec = Vec::with_capacity((width * height * 4) as usize);
        for y in 0..height {
            let start = (y * bytes_per_row as u32) as usize;
            let end = start + (width * 4) as usize;
            vec.extend_from_slice(&image_buffer.data[start..end]);
        }
        vec
    }).ok_or("创建图像缓冲区失败")?;

    // 保存为PNG文件
    let mut file = File::create("screen_capture.png")?;
    image.save(&mut file, image::ImageFormat::Png)?;
    
    println!("屏幕截图已保存为screen_capture.png");
    Ok(())
}

// 屏幕录制示例
fn screen_recording(duration_secs: u64) -> Result<(), Box<dyn std::error::Error>> {
    // 获取可共享内容
    let content = SCShareableContent::current()?;
    let display = content.displays[0].clone();
    
    // 配置录制参数
    let config = SCStreamConfig {
        width: display.width as u32,
        height: display.height as u32,
        pixel_format: SCPixelFormat::BGRA8888,
        color_space: SCColorSpace::sRGB,
        shows_cursor: true,
        ..Default::default()
    };

    // 创建流
    let mut stream = SCStream::new(config)?;
    
    // 添加输出处理器
    stream.add_output(SCStreamOutputType::Screen, |sample, error| {
        match sample {
            Some(s) => println!("收到帧: {:?}", s),
            None => {}
        }
        if let Some(e) = error {
            eprintln!("录制错误: {:?}", e);
        }
    })?;

    // 开始录制
    stream.start_capture()?;
    println!("开始屏幕录制...");
    
    // 录制指定时长
    std::thread::sleep(Duration::from_secs(duration_secs));
    
    // 停止录制
    stream.stop_capture()?;
    println!("屏幕录制完成");
    
    Ok(())
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 执行屏幕截图
    capture_screenshot()?;
    
    // 执行5秒屏幕录制
    screen_recording(5)?;
    
    Ok(())
}

代码说明

  1. capture_screenshot函数:

    • 获取当前屏幕内容
    • 配置捕获参数(分辨率、像素格式等)
    • 使用通道接收捕获的图像数据
    • 将图像保存为PNG文件
  2. screen_recording函数:

    • 设置基本录制参数
    • 启动屏幕录制
    • 持续指定时长后停止
  3. 主要功能:

    • 支持截图和录制两种模式
    • 可配置分辨率、光标显示等参数
    • 使用Rust的通道进行线程间通信

使用建议

  1. 在Cargo.toml中添加依赖:
[dependencies]
screencapturekit = "0.1"
image = "0.24"
  1. 需要先在系统设置中授予"屏幕录制"权限

  2. 该库仅支持macOS系统


1 回复

Rust屏幕捕获库ScreenCaptureKit的使用指南

ScreenCaptureKit是一个高效的Rust库,用于实现屏幕录制和截图功能。它提供了简单易用的API,可以捕获整个屏幕、特定窗口或屏幕的某个区域。

基本功能

  1. 捕获整个屏幕
  2. 捕获特定窗口
  3. 捕获屏幕的指定区域
  4. 录制屏幕视频

安装

在Cargo.toml中添加依赖:

[dependencies]
screen_capture_kit = "0.1.0"

基本使用方法

1. 捕获整个屏幕截图

use screen_capture_kit::{ScreenCapture, CaptureConfig};

fn main() {
    // 创建ScreenCapture实例
    let capture = ScreenCapture::new().unwrap();
    
    // 配置捕获所有显示器
    let config = CaptureConfig::default()
        .capture_all_displays(true);
    
    // 捕获图像并保存
    let image = capture.capture_image(&config).unwrap();
    image.save("screenshot.png").unwrap();
    println!("截图已保存为 screenshot.png");
}

2. 捕获特定窗口

use screen_capture_kit::{ScreenCapture, CaptureConfig, WindowInfo};

fn main() {
    let capture = ScreenCapture::new().unwrap();
    
    // 获取所有窗口列表
    let windows = capture.list_windows().unwrap();
    for window in &windows {
        println!("窗口: {} (ID: {})", window.title, window.window_id);
    }
    
    // 捕获第一个窗口
    if let Some(window) = windows.first() {
        let config = CaptureConfig::default()
            .window_id(window.window_id);
        
        let image = capture.capture_image(&config).unwrap();
        image.save("window_capture.png").unwrap();
    }
}

3. 捕获屏幕指定区域

use screen_capture_kit::{ScreenCapture, CaptureConfig, Rect};

fn main() {
    let capture = ScreenCapture::new().unwrap();
    
    // 定义捕获区域
    let region = Rect {
        x: 100,
        y: 100,
        width: 800,
        height: 600,
    };
    
    let config = CaptureConfig::default()
        .region(region);
    
    let image = capture.capture_image(&config).unwrap();
    image.save("region_capture.png").unwrap();
}

4. 屏幕录制

use screen_capture_kit::{ScreenCapture, CaptureConfig, RecorderConfig};
use std::time::Duration;

fn main() {
    let capture = ScreenCapture::new().unwrap();
    let config = CaptureConfig::default()
        .capture_all_displays(true);
    
    // 配置录制参数
    let recorder_config = RecorderConfig::new("recording.mp4")
        .fps(30)
        .quality(85);
    
    // 开始录制
    let mut recorder = capture.start_recording(&config, &recorder_config).unwrap();
    
    // 录制5秒
    std::thread::sleep(Duration::from_secs(5));
    
    // 停止录制
    recorder.stop().unwrap();
    println!("录制已保存为 recording.mp4");
}

高级功能

带回调的实时捕获

use screen_capture_kit::{ScreenCapture, CaptureConfig, FrameHandler};

// 自定义帧处理器
struct MyHandler;

impl FrameHandler for MyHandler {
    fn handle_frame(&mut self, frame: &[u8], width: u32, height: u32) {
        println!("收到帧: {}x{}, 大小: {}字节", width, height, frame.len());
        // 在这里处理帧数据
    }
}

fn main() {
    let capture = ScreenCapture::new().unwrap();
    let config = CaptureConfig::default()
        .capture_all_displays(true);
    
    let handler = MyHandler;
    let mut stream = capture.start_stream(&config, handler).unwrap();
    
    // 运行10秒
    std::thread::sleep(Duration::from_secs(10));
    
    stream.stop().unwrap();
}

多显示器支持

use screen_capture_kit::{ScreenCapture, CaptureConfig, DisplayInfo};

fn main() {
    let capture = ScreenCapture::new().unwrap();
    
    // 获取所有显示器信息
    let displays = capture.list_displays().unwrap();
    for (i, display) in displays.iter().enumerate() {
        println!("显示器 {}: {}x{}", i, display.width, display.height);
    }
    
    // 捕获第二个显示器
    if displays.len() > 1 {
        let config = CaptureConfig::default()
            .display_id(displays[1].display_id);
        
        let image = capture.capture_image(&config).unwrap();
        image.save("display2.png").unwrap();
    }
}

完整示例代码

下面是一个结合了多种功能的完整示例,展示如何创建一个简单的屏幕捕获工具:

use screen_capture_kit::{
    ScreenCapture, 
    CaptureConfig,
    WindowInfo,
    DisplayInfo,
    Rect,
    RecorderConfig,
    FrameHandler
};
use std::time::Duration;

// 自定义帧处理器实现
struct CustomFrameHandler;

impl FrameHandler for CustomFrameHandler {
    fn handle_frame(&mut self, frame: &[u8], width: u32, height: u32) {
        println!("处理帧数据: {}x{} ({}字节)", width, height, frame.len());
    }
}

fn main() {
    // 初始化ScreenCapture
    let capture = match ScreenCapture::new() {
        Ok(c) => c,
        Err(e) => {
            eprintln!("初始化失败: {}", e);
            return;
        }
    };

    // 1. 列出所有窗口
    println!("可用窗口:");
    if let Ok(windows) = capture.list_windows() {
        for window in windows {
            println!("- {} (ID: {})", window.title, window.window_id);
        }
    }

    // 2. 列出所有显示器
    println!("\n可用显示器:");
    if let Ok(displays) = capture.list_displays() {
        for (i, display) in displays.iter().enumerate() {
            println!("{}: {}x{}", i, display.width, display.height);
        }
    }

    // 3. 捕获全屏截图
    println!("\n捕获全屏截图...");
    let fullscreen_config = CaptureConfig::default()
        .capture_all_displays(true);
    
    if let Ok(image) = capture.capture_image(&fullscreen_config) {
        if let Err(e) = image.save("fullscreen.png") {
            eprintln!("保存截图失败: {}", e);
        } else {
            println!("全屏截图已保存为 fullscreen.png");
        }
    }

    // 4. 捕获特定区域
    println!("\n捕获区域截图...");
    let region = Rect {
        x: 100,
        y: 100,
        width: 800,
        height: 600,
    };
    
    let region_config = CaptureConfig::default()
        .region(region);
    
    if let Ok(image) = capture.capture_image(&region_config) {
        if let Err(e) = image.save("region.png") {
            eprintln!("保存区域截图失败: {}", e);
        } else {
            println!("区域截图已保存为 region.png");
        }
    }

    // 5. 屏幕录制
    println!("\n开始屏幕录制...");
    let recorder_config = RecorderConfig::new("output.mp4")
        .fps(30)
        .quality(80);
    
    if let Ok(mut recorder) = capture.start_recording(&fullscreen_config, &recorder_config) {
        println!("录制中...等待5秒");
        std::thread::sleep(Duration::from_secs(5));
        
        recorder.stop().unwrap();
        println!("录制已保存为 output.mp4");
    }

    // 6. 实时流处理
    println!("\n开始实时流处理...");
    let handler = CustomFrameHandler;
    if let Ok(mut stream) = capture.start_stream(&fullscreen_config, handler) {
        println!("流处理中...等待3秒");
        std::thread::sleep(Duration::from_secs(3));
        
        stream.stop().unwrap();
        println!("流处理结束");
    }
}

性能优化建议

  1. 对于视频录制,适当调整帧率和质量平衡性能与输出大小
  2. 捕获特定区域而非整个屏幕可显著提高性能
  3. 考虑使用回调处理帧数据而不是保存每一帧到内存
  4. 对于长时间录制,使用文件流式写入而非内存缓冲

注意事项

  1. 在macOS上需要屏幕录制权限
  2. 在Windows上需要管理员权限才能捕获某些窗口
  3. 捕获的帧数据格式通常是RGBA,处理时需注意

ScreenCaptureKit提供了强大而灵活的屏幕捕获功能,适用于各种屏幕录制和截图场景。通过合理配置,可以实现高性能的屏幕捕获应用。

回到顶部