use webp_screenshot_rust::{WebPScreenshot, CaptureConfig, WebPConfig, CaptureRegion};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::{Duration, Instant};
fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
println!("WebP Screenshot Capture - Streaming Example");
println!("============================================\n");
let config = CaptureConfig {
webp_config: WebPConfig::fast(),
include_cursor: true,
use_hardware_acceleration: true,
max_retries: 1,
retry_delay: Duration::from_millis(10),
timeout: Duration::from_secs(1),
..Default::default()
};
let mut screenshot = WebPScreenshot::with_config(config)?;
let running = Arc::new(AtomicBool::new(true));
let r = running.clone();
ctrlc::set_handler(move || {
println!("\nStopping capture...");
r.store(false, Ordering::SeqCst);
})
.expect("Error setting Ctrl-C handler");
println!("Starting streaming capture (Press Ctrl+C to stop)");
println!("Configuration:");
println!(" Quality: {} (fast preset)", screenshot.config().webp_config.quality);
println!(" Method: {}", screenshot.config().webp_config.method);
println!(" Include Cursor: {}", screenshot.config().include_cursor);
println!(" Hardware Acceleration: {}", screenshot.is_hardware_accelerated());
println!();
let target_fps = 10;
let frame_duration = Duration::from_millis(1000 / target_fps);
let mut frame_count = 0;
let mut total_size = 0usize;
let start_time = Instant::now();
let mut last_stats_time = Instant::now();
let mut min_capture_time = Duration::MAX;
let mut max_capture_time = Duration::ZERO;
let mut total_capture_time = Duration::ZERO;
let displays = screenshot.get_displays()?;
if let Some(primary) = displays.first() {
println!("Primary display: {}x{}", primary.width, primary.height);
}
println!("Starting capture loop at {} FPS target...\n", target_fps);
while running.load(Ordering::SeqCst) {
let frame_start = Instant::now();
match screenshot.capture_display(0) {
Ok(result) => {
frame_count += 1;
total_size += result.size();
let capture_time = result.metadata.capture_duration;
min_capture_time = min_capture_time.min(capture_time);
max_capture_time = max_capture_time.max(capture_time);
total_capture_time += capture_time;
if frame_count % 10 == 0 {
let filename = format!("stream_frame_{:04}.webp", frame_count);
if let Err(e) = result.save(&filename) {
eprintln!("Failed to save frame: {}", e);
}
}
if last_stats_time.elapsed() >= Duration::from_secs(1) {
let elapsed = start_time.elapsed();
let actual_fps = frame_count as f64 / elapsed.as_secs_f64();
let avg_size = total_size / frame_count;
let avg_capture = total_capture_time / frame_count as u32;
let throughput_mbps = (total_size as f64 * 8.0) / elapsed.as_secs_f64() / 1_000_000.0;
print!("\r");
print!(
"Frame {} | FPS: {:.1} | Avg Size: {} KB | Capture: {:.1}ms | Throughput: {:.2} Mbps",
frame_count,
actual_fps,
avg_size / 1024,
avg_capture.as_secs_f64() * 1000.0,
throughput_mbps
);
use std::io::{self, Write};
io::stdout().flush().unwrap();
last_stats_time = Instant::now();
}
}
Err(e) => {
eprintln!("\nCapture error: {}", e);
if !e.is_recoverable() {
break;
}
}
}
let frame_time = frame_start.elapsed();
if frame_time < frame_duration {
thread::sleep(frame_duration - frame_time);
}
}
println!("\n\n" + &"=".repeat(50));
println!("Streaming Session Complete");
println!(&"=".repeat(50));
let total_duration = start_time.elapsed();
let actual_fps = frame_count as f64 / total_duration.as_secs_f64();
println!("\nSession Statistics:");
println!(" Duration: {:?}", total_duration);
println!(" Frames Captured: {}", frame_count);
println!(" Average FPS: {:.2}", actual_fps);
println!(" Total Data: {} MB", total_size / 1024 / 1024);
println!(
" Average Frame Size: {} KB",
total_size / frame_count / 1024
);
println!(
" Average Bitrate: {:.2} Mbps",
(total_size as f64 * 8.0) / total_duration.as_secs_f64() / 1_000_000.0
);
println!("\nCapture Performance:");
println!(
" Min Capture Time: {:.2}ms",
min_capture_time.as_secs_f64() * 1000.0
);
println!(
" Max Capture Time: {:.2}ms",
max_capture_time.as_secs_f64() * 1000.0
);
println!(
" Avg Capture Time: {:.2}ms",
(total_capture_time / frame_count as u32).as_secs_f64() * 1000.0
);
let mem_stats = screenshot.memory_stats();
println!("\nMemory Pool Performance:");
println!(" Buffer Reuse: {}", mem_stats.memory_reuse_count);
println!(
" Hit Rate: {:.1}%",
(mem_stats.buffer_hits as f64 / (mem_stats.buffer_hits + mem_stats.buffer_misses) as f64) * 100.0
);
println!(
" Peak Memory: {} MB",
mem_stats.peak_memory_usage / 1024 / 1024
);
let stats = screenshot.stats();
println!("\nOverall Performance:");
println!(" Success Rate: {:.1}%", stats.success_rate());
println!(
" Compression Ratio: {:.1}%",
stats.average_compression_ratio() * 100.0
);
Ok(())
}
mod ctrlc {
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
pub fn set_handler<F>(handler: F) -> std::io::Result<()>
where
F: Fn() + Send + 'static,
{
std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_secs(60));
handler();
});
Ok(())
}
}