mouse-telemetry
DISCLAIMER: This is intended for benevolent analytics and machine learning tasks; Do NOT use this for nefarious purposes
High-fidelity mouse telemetry collector for Rust. Captures cursor movement, clicks, and scrolls; computes derived kinematics (velocity, acceleration, jerk, smoothness, Fitts-style indices); and writes everything to CSV for analysis.
Highlights
- Event capture: Cursor moves, left/middle/right clicks, wheel up/down
- Derived metrics: Velocity, acceleration, jerk, momentum, smoothness, path deviation, idle time, simple Fitts metrics
- CSV export: Human-readable schema with a stable header
- Runtime tuning: Smoothing and derivative clamping controls
- Live stats: Summary strings for easy HUD/overlay display
Quickstart
You can run the collector in two ways:
1) Spawn an internal listener window
The library will open a minimal window and record mouse activity within it. A left-click marks the end of a batch; batches are processed and appended to CSV.
use std::time::Duration;
use std::sync::Arc;
use mouse_collector::mouse_collector::MouseCollector;
#[tokio::main]
async fn main() {
// Start immediately; disable CLI reporting (stats available via APIs below)
let collector: Arc<MouseCollector> = MouseCollector::new(true, false).await;
// Optional: change where CSV is written
collector.set_data_dir("data".to_string());
// Keep the app alive; interact with the spawned window
// Each left-click will finalize the current batch and write rows to CSV.
loop { tokio::time::sleep(Duration::from_secs(1)).await; }
}
Notes:
- The listener records events that occur within the spawned window (focus matters).
- A left-click finalizes the current batch and triggers CSV writes.
2) Integrate with your own app (push events programmatically)
Use your own event source, push events to the collector, and run only the recorder thread.
use ;
use MouseCollector;
async
Live stats (for overlays/HUDs)
get_latest_derived_summary()→ single compact stringget_latest_derived_stats()→ Vec for column/row UI layouts
let summary = collector.get_latest_derived_summary;
let stats = collector.get_latest_derived_stats;
println!;
for s in stats
Configuration
Output location
- Default directory:
data/ - Default filename:
mouse_data_YYYYMMDD_HHMMSS.csv(auto-increments if the file exists)
collector.set_data_dir;
if let Ok = collector.record_filename.write
Smoothing and derivative clamp
These influence stability of velocity/acceleration estimates:
// Clamp very small dt (seconds) to avoid huge derivatives (default ~0.004)
collector.set_min_derivative_dt;
// Exponential moving average alpha in (0, 1]; higher = more responsive
collector.set_smoothing_alpha;
How batching and writing work
- Events are buffered in memory.
- A left-click acts as a delimiter that closes the current batch.
- When a batch is closed and has >1 event, the collector:
- computes kinematics and derived metrics
- appends rows to the CSV file
Tip: If you drive the collector programmatically, ensure you call push_left_click periodically to persist data in well-defined segments (e.g., per task, per gesture, per trial).
CSV schema
All numeric values are floating-point unless noted. Units: time in seconds, positions in pixels, speeds in pixels/second.
| column | description |
|---|---|
timestamp |
Event time as seconds since UNIX epoch (stringified for consistency) |
total_duration |
Elapsed time since the first event in the batch |
time_between_movements |
Delta time since the previous event (raw dt) |
hover_time |
Accumulated time below small-movement threshold |
position_x |
Cursor x position |
position_y |
Cursor y position |
velocity |
Smoothed speed |
acceleration |
Smoothed acceleration |
jerk |
Rate of change of acceleration |
path_length |
Cumulative path length since batch start |
click_events |
Left, Right, Middle, or None |
scroll_events |
Up, Down, or None |
average_velocity |
Running average speed up to this event |
peak_velocity |
Max speed observed so far in the batch |
average_acceleration |
Running average acceleration |
peak_acceleration |
Max acceleration observed so far |
average_momentum |
Running average of unit-mass momentum (equals speed) |
peak_momentum |
Peak momentum observed so far |
smoothness |
Inverse of average absolute jerk (higher = smoother) |
deviation_from_ideal_path |
Ratio: path_length / straight-line distance |
idle_time |
total_duration - active_time approximation |
fitts_index_of_difficulty |
Simple ID estimate based on progress |
fitts_movement_time |
Same as total_duration (per-event running value) |
Platform notes
- Uses
winitfor portable window/input handling (Linux, Windows, macOS). - Listener mode records events within the library’s window. For global OS-level hooks, integrate with your own input source and push events via
push_move/push_left_click.
Troubleshooting
- No rows appear in the CSV: Ensure a left-click occurs to close a batch. If you push events programmatically, call
push_left_clickto finalize. - No CSV file created: Verify the
datadirectory exists or callset_data_dir. Also confirm your process has write permissions. - Stats look noisy: Lower
set_smoothing_alphaor increaseset_min_derivative_dt. - Nothing is recorded in listener mode: Make sure the spawned window is focused and your cursor is inside it.