Capture a window using CaptureStream
mainTo capture a specific window, you must first ensure you have capture privileges, identify the target content using a CapturableContentFilter, and then initialize a CaptureStream with a CaptureConfig. The stream provides frames via an event handler callback.
Workflow
- Request Access: Use
CaptureStream::test_access(false)to check for existing permissions, orCaptureStream::request_access(false).awaitto request them. - Filter Content: Use
CapturableContent::new(filter)with a filter likeCapturableContentFilter::NORMAL_WINDOWSto find available windows. - Configure: Create a
CaptureConfigusingCaptureConfig::with_window(window, pixel_format). - Stream: Initialize
CaptureStream::new(token, config, callback)where the callback handlesStreamEvent::Video(frame)events.
use std::time::Duration;
use crabgrab::prelude::*;
// spin up the async runtime
let runtime = tokio::runtime::Builder::new_multi_thread().build().unwrap();
// run our capture code in an async context
let future = runtime.spawn(async {
// ensure we have priveleges to capture content
let token = match CaptureStream::test_access(false) {
Some(token) => token,
None => CaptureStream::request_access(false).await.expect("Expected capture access")
};
// filter to normal windows
let filter = CapturableContentFilter::NORMAL_WINDOWS;
// get capturable content matching the filter
let content = CapturableContent::new(filter).await.unwrap();
// find the window we want to capture
let window = content.windows().filter(|window| {
let app_identifier = window.application().identifier();
app_identifier.to_lowercase().contains("finder") || app_identifier.to_lowercase().contains("explorer")
}).next();
match window {
Some(window) => {
println!("capturing window: {}", window.title());
// create a capture config using the first supported pixel format
let config = CaptureConfig::with_window(window, CaptureStream::supported_pixel_formats()[0]).unwrap();
// create a capture stream with an event handler callback
let mut stream = CaptureStream::new(token, config, |stream_event| {
match stream_event {
Ok(event) => {
match event {
StreamEvent::Video(frame) => {
println!("Got frame: {}", frame.frame_id());
},
_ => {}
}
},
Err(error) => {
println!("Stream error: {:?}", error);
}
}
}).unwrap();
// wait for a while to capture some frames
tokio::task::block_in_place(|| std::thread::sleep(Duration::from_millis(4000)));
stream.stop().unwrap();
},
None => { println!("Failed to find window"); }
}
});
// wait for the future to complete
runtime.block_on(future).unwrap();
// shutdown the async runtime
runtime.shutdown_timeout(Duration::from_millis(10000));