Skip to content

Conversation

@bakaEC
Copy link

@bakaEC bakaEC commented Dec 22, 2025

Pull Request
Description

This PR introduces cursor recording, styling, smoothing, and playback support for video recording and editing. It adds global mouse tracking during recording, persistent cursor data storage, rich cursor rendering , spline-based smoothing, configurable offsets, and dynamic zoom-follow behavior driven by the smoothed cursor track. The feature is fully integrated across recording, timeline, settings, and video playback.

Motivation

  • Cursor movement is a critical visual cue in screen recordings, but previously:
  • Cursor data was not globally captured or persisted
  • Cursor appearance and timing were not configurable
  • Zoom-follow behavior could not align naturally with cursor intent

This PR solves these issues by enabling high-fidelity cursor capture and playback, improving visual clarity, temporal alignment, and overall video polish—especially for tutorial and demo recordings.

Type of Change:
New Feature

Related Issue(s):
N/A

Testing

  • Manual Testing
  • Start a recording session
  • Move the mouse globally (inside and outside the app window)
  • Stop recording and open the editor
  • Enable Cursor Track in the timeline

Adjust:

  • Cursor icon & style
  • Time / position offsets
  • Path smoothing mode (none, quadratic, end2end)
  • Play the video and verify:
  • Cursor motion is smooth and time-aligned
  • Trails, clicks, and icons render correctly
  • Zoom regions with follow enabled track the smoothed cursor
  • Toggle zoom-follow modes and verify snap / release behavior

Regression Checks

  • Verify playhead timing correctness (ms vs s)
  • Ensure cursor disabled state produces no rendering artifacts
  • Confirm cursor data loads correctly from stored recordings

Summary of Key Changes (for reviewers)

  • Global mouse tracking during recording (preload + Electron API)
  • Cursor data normalization, cleanup, storage, and retrieval
  • Cursor track support in timeline and playback
  • SVG cursor icons, trails, click effects, and variants
  • Time-bound spline-based cursor smoothing (quadratic & end2end)
  • Unified cursor offset controls (time + X/Y)
  • Dynamic zoom-follow driven by smoothed cursor path
  • Fix for playhead time unit bug
  • New cursor-related types, defaults, and settings UI

Define pause points as the last sampled position before the next movement begins (not idle detection)

Build cursor paths using centripetal Catmull–Rom splines (α = 0.5) to ensure the curve interpolates all pause points

Bind each spline segment strictly to its original time range to prevent teleporting during playback

Guarantee cursor position exactly matches pause points at their timestamps

Enforce continuous cursor motion between points with linear time parameterization

Fallback to linear interpolation when insufficient pause points are available
- Move time offset into CursorStyle (new fields: offsetMs, offsetX, offsetY)
- Set defaults: offsetMs = 160ms, offsetX = 3px, offsetY = 5px
- Apply offsetMs to playhead calculation and apply offsetX/offsetY to cursor drawing, trails and click effects in VideoPlayback
- Load/store style offsets when reading cursor data
- Add combined "Cursor Offset" UI (time + X/Y) under Style in SettingsPanel (above Path Smoothing), wired to onCursorStyleChange
- Remove references to undefined cursorOffsetMs and clean up related state
- Update types (`CursorStyle`, `DEFAULT_CURSOR_STYLE`)
… "center-on-cursor" zoom follow that uses the existing cursor smoothing output (supports `none`, `quadratic`, and `end2end`) so the camera center tracks the smoothed cursor path rather than raw event points.- Limit follow to active zoom regions only (strength > 0). The follow behavior now activates during region fade-in/fade-out and disables when the region is no longer active; any persistent anchor is cleared on exit.- Snap behavior: when follow is enabled or mode switches to `center`, the camera is snapped immediately to the smoothed cursor position and any anchor is cleared so the ticker can continue following the smoothed target.- Fix playhead time unit bug: remove incorrect extra *1000 when computing `playheadMs` from `currentTimeRef.current` so follow calculations use the correct ms values.- Keep smoothing parameters (quadratic strength, end2end params) in refs for consistent synchronous access from the PIXI ticker.- Add conservative error swallowing around optional follow logic and provide a runtime debug toggle (`__openscreen_debugZoomFollow`) to inspect follow data.
@bakaEC
Copy link
Author

bakaEC commented Dec 22, 2025

This implementation intentionally avoids using uiohook-napi for global mouse event monitoring.
Instead, cursor capture is driven by the recording lifecycle and stop-state boundaries, which:

reduces native dependency surface and platform-specific risks
avoids long-running global hooks outside active recording sessions
keeps cursor data tightly scoped to recording time ranges
This makes the solution more predictable, easier to maintain, and safer across platforms.

@bakaEC
Copy link
Author

bakaEC commented Dec 22, 2025

@ImSakushi
Copy link

ImSakushi commented Dec 24, 2025

it looks so cool!
but it doesn't work on the exported video in my case, only the preview works well.

@bakaEC
Copy link
Author

bakaEC commented Dec 25, 2025

it looks so cool! but it doesn't work on the exported video in my case, only the preview works well.

Thanks!

You’re right — currently cursor rendering only works in preview. Export support hasn’t been implemented yet.
This PR was intentionally scoped to cursor capture, storage, smoothing, and playback architecture, so the export pipeline was left out for now. The export part should be fairly straightforward once maintainers agree that this approach fits the project direction.
I wanted to first get feedback on whether the overall cursor model (data format, smoothing, zoom-follow integration, etc.) makes sense before extending it into the exporter.

If this direction looks good to you, I’m happy to add export support next 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants