IT 인터넷/일반
[Rust] 화면 캡쳐
Banjubu
2024. 10. 28. 17:53
반응형
macos 기준이에요.
Cargo.toml
[package]
name = "screen_capture"
version = "0.1.0"
edition = "2021"
description = "Screen Capture Application for macOS"
[package.metadata.bundle]
name = "Screen Capture"
identifier = "com.example.screen-capture"
icon = ["32x32.png", "128x128.png", "128x128@2x.png"]
version = "0.1.0"
copyright = "Copyright (c) Example Company 2024. All rights reserved."
category = "Developer Tool"
short_description = "Screen capture utility for macOS"
[dependencies]
anyhow = "1.0"
dirs = "5.0"
core-graphics = "0.22.3"
src/main.rs
use std::fs;
use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH};
use std::process::Command;
use anyhow::{Result, Context};
use core_graphics::display::CGDisplay;
struct ScreenCaptureApp {
save_path: PathBuf,
}
impl ScreenCaptureApp {
fn new() -> Result<Self> {
let mut save_path = dirs::picture_dir()
.context("Failed to get Pictures directory")?;
save_path.push("ScreenCaptures");
if !save_path.exists() {
fs::create_dir_all(&save_path)?;
}
Ok(Self { save_path })
}
fn request_screen_capture_permission() -> Result<()> {
let script = r#"
tell application "System Settings"
activate
reveal pane id "com.apple.settings.Security-Privacy.Privacy"
delay 1
tell application "System Events"
tell process "System Settings"
click radio button "Screen & System Audio Recording" of scroll area 1 of group 1 of window 1
end tell
end tell
end tell
"#;
Command::new("osascript")
.arg("-e")
.arg(script)
.output()?;
println!("시스템 설정에서 화면 녹화 권한을 허용해 주세요.");
println!("권한을 허용한 후, Enter 키를 눌러 계속하세요...");
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
Ok(())
}
fn capture_all_displays(&self) -> Result<Vec<PathBuf>> {
let mut captured_files = Vec::new();
let display_count = self.get_display_count()?;
println!("발견된 디스플레이 수: {}", display_count);
for display_id in 1..=display_count {
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)?
.as_secs();
let filename = format!("screenshot_display_{}_at_{}.png", display_id, timestamp);
let file_path = self.save_path.join(&filename);
println!("디스플레이 {} 캡처 시도 중...", display_id);
let result = Command::new("screencapture")
.args(["-D", &display_id.to_string(), "-x"]) // 각 디스플레이 캡처
.arg(&file_path)
.output();
match result {
Ok(output) => {
if output.status.success() {
println!("디스플레이 {} 캡처 성공: {}", display_id, filename);
if let Ok(metadata) = fs::metadata(&file_path) {
println!("파일 크기: {} bytes", metadata.len());
}
captured_files.push(file_path);
} else {
println!("디스플레이 {} 캡처 실패. 권한을 확인하세요.", display_id);
Self::request_screen_capture_permission()?;
}
},
Err(e) => {
println!("디스플레이 {} 캡처 중 오류 발생: {}", display_id, e);
Self::request_screen_capture_permission()?;
}
}
}
Ok(captured_files)
}
fn get_display_count(&self) -> Result<u32> {
let display_ids = CGDisplay::active_displays().expect("Failed to get active displays");
Ok(display_ids.len() as u32)
}
fn open_in_finder(&self, paths: &[PathBuf]) -> Result<()> {
if !paths.is_empty() {
if let Some(path) = paths[0].parent() {
Command::new("open")
.arg(path)
.output()?;
}
}
Ok(())
}
}
fn main() -> Result<()> {
let app = ScreenCaptureApp::new()?;
let captured_files = app.capture_all_displays()?;
if !captured_files.is_empty() {
println!("\n모든 디스플레이의 스크린샷이 성공적으로 저장되었습니다!");
println!("저장 위치: {}", app.save_path.display());
app.open_in_finder(&captured_files)?;
}
Ok(())
}
빌드 및 번들링
cargo clean
cargo build
cargo bundle
실행 후 '시스템 설정 > 개인정보 보호 및 보안 > 화면 및 시스템 오디오 녹음'에서 해당 앱을 허용해주세요.
이미지는 시스템의 '그림 > ScreenCaptures' 폴더에 생성됩니다.
반응형
LIST