| Crates.io | mouse-telemetry |
| lib.rs | mouse-telemetry |
| version | 0.2.0 |
| created_at | 2026-01-17 17:53:32.086025+00 |
| updated_at | 2026-01-17 17:53:32.086025+00 |
| description | Captures mouse data and computes derived metrics for downstream analysis/tasks |
| homepage | |
| repository | https://github.com/jrcalgo/generative-mouse-trajectories |
| max_upload_size | |
| id | 2050860 |
| size | 105,947 |
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.
You can run the collector in two ways:
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:
Use your own event source, push events to the collector, and run only the recorder thread.
use std::{sync::Arc, thread, time::Duration};
use mouse_collector::mouse_collector::MouseCollector;
#[tokio::main]
async fn main() {
let collector: Arc<MouseCollector> = MouseCollector::new(false, false).await;
// Write output to a custom directory/filename
collector.set_data_dir("data".to_string());
if let Ok(mut name) = collector.record_filename.write() {
*name = "session_01.csv".to_string();
}
// Start only the CSV recording thread
let _recorder = collector.start_recording_thread();
// Feed your own events
collector.push_move((100.0, 100.0));
collector.push_move((120.0, 110.0));
collector.push_move((180.0, 140.0));
// A left-click marks the end of the current batch and triggers CSV write
collector.push_left_click((180.0, 140.0));
thread::sleep(Duration::from_millis(500));
}
get_latest_derived_summary() → single compact stringget_latest_derived_stats() → Veclet summary = collector.get_latest_derived_summary();
let stats = collector.get_latest_derived_stats();
println!("{summary}");
for s in stats { println!("{s}"); }
data/mouse_data_YYYYMMDD_HHMMSS.csv (auto-increments if the file exists)collector.set_data_dir("my_data".to_string());
if let Ok(mut name) = collector.record_filename.write() {
*name = "experiment_a.csv".to_string();
}
These influence stability of velocity/acceleration estimates:
// Clamp very small dt (seconds) to avoid huge derivatives (default ~0.004)
collector.set_min_derivative_dt(0.003);
// Exponential moving average alpha in (0, 1]; higher = more responsive
collector.set_smoothing_alpha(0.35);
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).
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) |
winit for portable window/input handling (Linux, Windows, macOS).push_move / push_left_click.push_left_click to finalize.data directory exists or call set_data_dir. Also confirm your process has write permissions.set_smoothing_alpha or increase set_min_derivative_dt.