LazyScroll AI is a PC desktop application that uses webcam-based eye tracking to control scrolling.
Main behavior:
- Look down → scroll down
- Look up → scroll up
- Look center → stop scrolling
- Hotkey → enable/disable the system
- User can adjust scroll speed and sensitivity
The project must start as a simple MVP before adding UI and advanced features.
Create the base Python project structure.
- Create folder structure:
lazyscroll-ai/
├── main.py
├── requirements.txt
├── README.md
├── PLAN.md
├── AGENTS.md
├── camera/
├── vision/
├── control/
├── config/
├── utils/
└── ui/
- Create
requirements.txt:
opencv-python
mediapipe
numpy
pyautogui
keyboard
pyside6
pyinstaller-
Add empty
__init__.pyfiles where needed. -
Do not build UI yet.
The project structure exists and dependencies are listed.
Open webcam and display realtime video.
- Implement
camera/webcam.py - Create a
Webcamclass. - Support:
- open camera
- read frame
- release camera
- In
main.py, show webcam preview using OpenCV. - Press
qto quit.
Running:
python main.pyshows webcam feed.
Detect face landmarks using MediaPipe Face Mesh.
- Implement
vision/face_mesh.py - Create a
FaceMeshDetectorclass. - Input: OpenCV frame
- Output:
- processed frame
- face landmarks
- Draw landmarks for debugging.
Webcam preview shows face/eye landmarks.
Extract iris and eye landmark positions.
- Implement
vision/iris_tracker.py - Extract landmarks for:
- left eye
- right eye
- left iris
- right iris
- Calculate iris vertical position relative to eye height.
{
"left_eye_y_ratio": 0.52,
"right_eye_y_ratio": 0.50,
"average_y_ratio": 0.51
}Terminal prints current eye Y ratio in realtime.
Classify eye direction.
- Implement
vision/gaze_detector.py - Create gaze states:
LOOK_UP
LOOK_CENTER
LOOK_DOWN
UNKNOWN- Use simple thresholds first:
if y_ratio < up_threshold:
LOOK_UP
elif y_ratio > down_threshold:
LOOK_DOWN
else:
LOOK_CENTER- Print gaze state in terminal.
Terminal shows:
LOOK_UP
LOOK_CENTER
LOOK_DOWN
Prevent unstable gaze detection.
- Implement
utils/smoothing.py - Add moving average buffer.
- Smooth the eye Y ratio before classification.
- Add hold duration logic:
- user must look up/down for at least 0.5s before triggering action
- Add cooldown:
- after action starts/stops, wait briefly before changing state
Gaze state becomes stable and does not flicker too much.
Control desktop scrolling.
- Implement
control/scroll_engine.py - Use PyAutoGUI to scroll.
- Support:
- scroll up
- scroll down
- stop
- configurable speed
- Do not scroll if app is disabled.
if enabled:
if gaze_state == "LOOK_DOWN":
scroll_down()
elif gaze_state == "LOOK_UP":
scroll_up()
else:
stop_scroll()Looking down scrolls the active window down.
Allow user to enable/disable LazyScroll quickly.
- Implement
control/hotkeys.py - Add hotkey:
Ctrl + Alt + S
- Toggle app enabled/disabled.
- Print current status.
User can pause/resume auto scroll anytime.
Save settings and calibration data.
- Create
config/settings.json - Create
config/calibration.json
{
"enabled": false,
"scroll_speed": 5,
"scroll_interval_ms": 80,
"hold_duration_ms": 700,
"cooldown_ms": 300,
"debug": true
}{
"up_threshold": 0.38,
"down_threshold": 0.62,
"center_y": 0.50
}- Implement config load/save utility.
Allow user to calibrate eye thresholds.
- Implement
vision/calibration.py - Ask user to look:
- center
- up
- down
- Record average Y ratio for each state.
- Save thresholds to
config/calibration.json.
Detection adapts to the user's webcam, face angle, and eye shape.
Build a simple PySide6 control panel.
- Implement
ui/main_window.py - UI should include:
- Start / Stop button
- Current gaze state
- Scroll speed slider
- Sensitivity slider
- Calibration button
- Debug camera preview toggle
Do not build UI before the core logic works.
Build executable file.
- Test app normally:
python main.py- Build with PyInstaller:
pyinstaller --onefile main.py- Test
.exe.
Follow this order strictly:
- Webcam
- Face Mesh
- Iris Tracking
- Gaze Detection
- Smoothing
- Scroll Engine
- Hotkey
- Config
- Calibration
- UI
- Build EXE
Do not skip phases. Do not build advanced features before MVP works.