-
-
Notifications
You must be signed in to change notification settings - Fork 92
Add comprehensive examples section to README #171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughA new screen capture example was added to the project, demonstrating frame capture at 60 FPS with cropping, cursor/highlight overlays, and saving PNGs to a directory. The Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ExampleApp as screenshots.rs
participant OS
participant FileSystem
User->>ExampleApp: Run example
ExampleApp->>OS: Check platform support & permissions
OS-->>ExampleApp: Permission granted/denied
ExampleApp->>ExampleApp: Configure capture options
ExampleApp->>ExampleApp: Start capture loop
loop Until Enter pressed
ExampleApp->>OS: Capture frame
OS-->>ExampleApp: Return frame (BGRA)
ExampleApp->>ExampleApp: Convert BGRA to RGBA
ExampleApp->>FileSystem: Save PNG image
ExampleApp->>ExampleApp: Print progress every 30 frames
end
User->>ExampleApp: Press Enter
ExampleApp->>ExampleApp: Stop capture, print summary
Estimated code review effortπ― 2 (Simple) | β±οΈ ~8 minutes Poem
Note π MCP (Model Context Protocol) integration is now available in Early Access!Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context. β¨ Finishing Touches
π§ͺ Generate unit tests
πͺ§ TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
π§Ή Nitpick comments (3)
.gitignore (1)
5-5
: Scope the ignore to the examples directory (optional).Current pattern will ignore any directory named captured_frames anywhere in the repo. If you want to restrict to the exampleβs output, scope it.
-captured_frames/ +examples/captured_frames/README.md (1)
113-119
: Clarify output path and tighten phrasing (βPNG imagesβ β βPNGsβ).LanguageTool flagged βPNG imagesβ as tautological. Also, the example writes to examples/captured_frames/.
-**What it does:** -- Captures your screen at 60 FPS -- Saves frames as PNG images in a `captured_frames/` directory +**What it does:** +- Captures your screen at 60 FPS +- Saves frames as PNGs in `examples/captured_frames/`examples/screenshots.rs (1)
137-143
: Faster BGRAβRGBA conversion: swap channels in-place on a clone.Reduces per-pixel allocations and copies.
- // Convert BGRA to RGBA (swap red and blue channels) - let mut rgba_data = Vec::with_capacity(bgra_frame.data.len()); - for chunk in bgra_frame.data.chunks(4) { - if chunk.len() == 4 { - rgba_data.extend_from_slice(&[chunk[2], chunk[1], chunk[0], chunk[3]]); - } - } + // Convert BGRA to RGBA (swap red and blue channels) + let mut rgba_data = bgra_frame.data.clone(); + for px in rgba_data.chunks_mut(4) { + // px = [B, G, R, A] -> [R, G, B, A] + px.swap(0, 2); + }
π Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
β Files ignored due to path filters (1)
Cargo.lock
is excluded by!**/*.lock
π Files selected for processing (4)
.gitignore
(1 hunks)Cargo.toml
(1 hunks)README.md
(1 hunks)examples/screenshots.rs
(1 hunks)
π§° Additional context used
πͺ LanguageTool
README.md
[style] ~115-~115: This phrase is redundant (βGβ stands for βgraphicβ). Use simply βPNGsβ.
Context: ...your screen at 60 FPS - Saves frames as PNG images in a captured_frames/
directory - Cro...
(ACRONYM_TAUTOLOGY)
@@ -19,6 +19,7 @@ categories = ["graphics", "multimedia", "multimedia::video"] | |||
futures = "0.3.31" | |||
sysinfo = "0.30.0" | |||
thiserror = "2.0.12" | |||
image = "0.25.2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π‘ Verification agent
β Verification inconclusive
Move image
to dev-dependencies to avoid bloating library consumers.
image
is only used by the examples. Keeping it under [dependencies] makes every user of the library pull it in unnecessarily.
Apply this change:
[dependencies]
futures = "0.3.31"
sysinfo = "0.30.0"
thiserror = "2.0.12"
-image = "0.25.2"
Add this section outside the changed block:
[dev-dependencies]
image = "0.25.2"
Verify image
isnβt used in library code:
π Script executed:
#!/bin/bash
# Check that 'image' usage is confined to examples, not src/
rg -n --hidden -S '(^use\s+image::)|(^extern\s+crate\s+image)|(\bimage::)' -g "src/**"
Length of output: 88
Move image
to dev-dependencies
Verified via rg
that image
isnβt referenced in src/
, so it can safely be relocated to avoid bloating library consumers.
Next steps:
- Remove
image = "0.25.2"
from[dependencies]
in Cargo.toml - Add it under a new
[dev-dependencies]
section
Suggested change in Cargo.toml:
[dependencies]
futures = "0.3.31"
sysinfo = "0.30.0"
thiserror = "2.0.12"
-image = "0.25.2"
+[dev-dependencies]
+image = "0.25.2"
π Committable suggestion
βΌοΈ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
image = "0.25.2" | |
[dependencies] | |
futures = "0.3.31" | |
sysinfo = "0.30.0" | |
thiserror = "2.0.12" | |
[dev-dependencies] | |
image = "0.25.2" |
π€ Prompt for AI Agents
In Cargo.toml at line 22, the `image` crate is currently listed under
`[dependencies]` but is not used in the main source code. To avoid bloating
library consumers, remove the line `image = "0.25.2"` from the `[dependencies]`
section and add it under a new `[dev-dependencies]` section instead.
// Create Capturer | ||
let mut capturer = Capturer::build(options).unwrap(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π οΈ Refactor suggestion
Avoid unwrap()
on capturer construction; provide context on failure.
Use expect
(or proper error handling) to avoid panics without context.
- let mut capturer = Capturer::build(options).unwrap();
+ let mut capturer = Capturer::build(options)
+ .expect("Failed to build Capturer (check platform support/permissions/options)");
π Committable suggestion
βΌοΈ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// Create Capturer | |
let mut capturer = Capturer::build(options).unwrap(); | |
// Create Capturer | |
let mut capturer = Capturer::build(options) | |
.expect("Failed to build Capturer (check platform support/permissions/options)"); |
π€ Prompt for AI Agents
In examples/screenshots.rs around lines 55 to 57, replace the use of unwrap() on
the Capturer::build call with expect() to provide a clear error message if
construction fails. This will avoid panics without context by giving a
descriptive message explaining why the capturer creation failed.
// Create output directory | ||
let output_dir = "examples/captured_frames"; | ||
if !Path::new(output_dir).exists() { | ||
fs::create_dir(output_dir).unwrap(); | ||
println!("π Created output directory: {}", output_dir); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π οΈ Refactor suggestion
Use create_dir_all
and avoid unwrap()
for better resilience.
This handles pre-existing parents and gives clearer failure messages.
- let output_dir = "examples/captured_frames";
- if !Path::new(output_dir).exists() {
- fs::create_dir(output_dir).unwrap();
- println!("π Created output directory: {}", output_dir);
- }
+ let output_dir = "examples/captured_frames";
+ if !Path::new(output_dir).exists() {
+ fs::create_dir_all(output_dir)
+ .expect("Failed to create output directory");
+ println!("π Created output directory: {}", output_dir);
+ }
π€ Prompt for AI Agents
In examples/screenshots.rs around lines 58 to 63, replace fs::create_dir with
fs::create_dir_all to ensure all parent directories are created if missing.
Also, avoid using unwrap() by properly handling the Result returned from
create_dir_all, such as using expect with a clear error message or matching on
the Result to handle errors gracefully.
// Try to get the next frame | ||
match capturer.get_next_frame() { | ||
Ok(frame) => { | ||
frame_count += 1; | ||
|
||
// Save frame as image | ||
if let Err(e) = save_frame_as_image(&frame, frame_count, output_dir) { | ||
eprintln!("Error saving frame {frame_count}: {e}"); | ||
} | ||
|
||
// Print capture info every 30 frames (every 0.5 seconds at 60 FPS) | ||
if frame_count % 30 == 0 { | ||
let elapsed = start_time.elapsed().as_secs_f64(); | ||
let fps = frame_count as f64 / elapsed; | ||
println!( | ||
"πΈ Captured frame {frame_count} | FPS: {fps:.1} | Elapsed: {elapsed:.1}s" | ||
); | ||
} | ||
} | ||
Err(mpsc::RecvError) => { | ||
// No frame available yet, continue | ||
continue; | ||
} | ||
} | ||
|
||
// Small delay to prevent excessive CPU usage | ||
thread::sleep(Duration::from_millis(16)); // ~60 FPS | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π‘ Verification agent
π§© Analysis chain
High-CPU spin: continue
skips the sleep; also avoid coupling to mpsc::RecvError
.
When no frame is available, the continue
bypasses the sleep, causing a busy loop. Also, matching a concrete mpsc::RecvError
ties this code to a specific error type; prefer a wildcard unless you intend to branch on variants.
- Err(mpsc::RecvError) => {
- // No frame available yet, continue
- continue;
- }
+ Err(_) => {
+ // No frame available yet
+ }
Verify get_next_frame
βs error type to ensure the wildcard match is appropriate:
π Script executed:
#!/bin/bash
# Try to locate the signature and error type of `get_next_frame`
rg -n "fn\s+get_next_frame\s*\(" -A 5
rg -n "get_next_frame\s*\(" -A 2 | sed -n '1,120p'
Length of output: 1031
Reduce busy-loop by allowing sleep on errors
Removing the continue
ensures the per-loop sleep still runs when no frame is ready, preventing a high-CPU spin. Using a wildcard error pattern also decouples from the concrete mpsc::RecvError
.
β’ File: examples/screenshots.rs
β’ Lines ~89β97
Suggested diff:
- Err(mpsc::RecvError) => {
- // No frame available yet, continue
- continue;
- }
+ Err(_) => {
+ // No frame available yet; fall through to sleep
+ }
π Committable suggestion
βΌοΈ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// Try to get the next frame | |
match capturer.get_next_frame() { | |
Ok(frame) => { | |
frame_count += 1; | |
// Save frame as image | |
if let Err(e) = save_frame_as_image(&frame, frame_count, output_dir) { | |
eprintln!("Error saving frame {frame_count}: {e}"); | |
} | |
// Print capture info every 30 frames (every 0.5 seconds at 60 FPS) | |
if frame_count % 30 == 0 { | |
let elapsed = start_time.elapsed().as_secs_f64(); | |
let fps = frame_count as f64 / elapsed; | |
println!( | |
"πΈ Captured frame {frame_count} | FPS: {fps:.1} | Elapsed: {elapsed:.1}s" | |
); | |
} | |
} | |
Err(mpsc::RecvError) => { | |
// No frame available yet, continue | |
continue; | |
} | |
} | |
// Small delay to prevent excessive CPU usage | |
thread::sleep(Duration::from_millis(16)); // ~60 FPS | |
} | |
// Try to get the next frame | |
match capturer.get_next_frame() { | |
Ok(frame) => { | |
frame_count += 1; | |
// Save frame as image | |
if let Err(e) = save_frame_as_image(&frame, frame_count, output_dir) { | |
eprintln!("Error saving frame {frame_count}: {e}"); | |
} | |
// Print capture info every 30 frames (every 0.5 seconds at 60 FPS) | |
if frame_count % 30 == 0 { | |
let elapsed = start_time.elapsed().as_secs_f64(); | |
let fps = frame_count as f64 / elapsed; | |
println!( | |
"πΈ Captured frame {frame_count} | FPS: {fps:.1} | Elapsed: {elapsed:.1}s" | |
); | |
} | |
} | |
Err(_) => { | |
// No frame available yet; fall through to sleep | |
} | |
} | |
// Small delay to prevent excessive CPU usage | |
thread::sleep(Duration::from_millis(16)); // ~60 FPS | |
} |
π€ Prompt for AI Agents
In examples/screenshots.rs around lines 89 to 97, the current code uses
`continue` on `mpsc::RecvError`, which skips the per-loop sleep and causes a
busy-loop with high CPU usage. To fix this, remove the `continue` statement so
the thread sleep still executes even when no frame is ready. Also, replace the
specific `Err(mpsc::RecvError)` pattern with a wildcard `Err(_)` to decouple
from the concrete error type.
π Add Examples Documentation
This PR adds a comprehensive "Examples" section to the README that explains how to run the various examples included in the project.
β¨ What's Added
screenshots
example including:cargo run --example screenshots
src/main.rs
οΏ½οΏ½ Why This Matters
π Changes Made
This documentation makes the project much more accessible to developers who want to experiment with the screen capture capabilities through the provided examples.
Summary by CodeRabbit
New Features
Documentation
Chores