Rootless cursor tracking from DRM cursor plane #92, a critically damped spring camera, custom zoom combos, and a layer-shell recording island. About 56 MB of RAM at 1080p60.
翻譯準備中
媒體GitHub @KunalSiyag上線中營運者未確認
試用過了嗎? 點一下就好,不需要登入。
尚未收集儲存庫資訊。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
Screen recorder for Linux Wayland, written in Rust, whose camera follows your cursor. Rootless DRM cursor tracking, spring-physics auto-zoom, NVENC/VAAPI encoding.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Website · Download v1.2.0 · Promo video (10 s, 1080p60) · How it works · Write-up on DEV · Contributing
HyperGSR (gpu-recorder-rs) is a screen recorder for Linux, written in Rust. It reads the cursor straight from the GPU's hardware cursor plane, without root, and moves a critically damped spring camera to wherever you are working, the way Screen Studio does on macOS. Capture goes through PipeWire and the XDG desktop portal, and encoding runs on NVENC or VAAPI.
It runs on native Wayland (COSMIC, GNOME, KDE Plasma, Hyprland, Sway) and on X11.
XQueryPointer go blind or stall once a native Wayland window has focus. HyperGSR opens /dev/dri/card* through libdrm and reads CRTC_X, CRTC_Y and FB_ID from the hardware cursor plane at 60 Hz./dev/input, which needs the input group (sudo usermod -aG input $USER, then log in again). Only devices with mouse buttons and no letter keys are opened, so keystrokes are never read. Clicks also trigger auto-zoom.| 1.0× wide, cursor travelling | 2.0× auto, cursor resting |
|---|---|
Both frames come from the same 60 FPS output of --export-demo.
The compact bar shows the DRM cursor position, the current zoom (1.0× Wide, 2.0× Auto or Lock), the recording timer and the Studio toggle.
Click Studio to open the live cursor camera, zoom-combo recorder, zoom depth and spring presets.
| Dark | Light |
|---|---|
--web serves a browser control panel on http://127.0.0.1:7878 with the same camera, cursor effects, encoder choice and the gpu-screen-recorder inspector.
The website runs the same spring model in your browser, so you can try the camera before installing anything.
| Light | Dark |
|---|---|
| Resident memory | CPU at 1080p60 | Cursor source | Camera solver |
|---|---|---|---|
| 56 MB | < 1.5 % | DRM plane #92 at 60 Hz | 240 Hz, ζ = 1.0 |
Measured during a 1080p60 recording on a hybrid AMD Radeon + NVIDIA RTX 3050 laptop under COSMIC, with NVENC preset P4. Your numbers will depend on GPU, compositor and resolution. Run gpu-recorder-rs --report to see the encoders and cursor planes it finds on your machine.
HyperGSR is published on npm as hypergsr:
npx hypergsr --report
npx hypergsr
# Or install the CLI globally
npm install -g hypergsr
hypergsr --web
To launch HyperGSR from your app menu like any other desktop app, add a menu entry and icon for your user after the global install:
hypergsr --install-desktop # writes ~/.local/share/applications/io.github.KunalSiyag.gpu_recorder_rs.desktop
hypergsr --uninstall-desktop # removes the entry and icon again
The entry starts the native binary inside the installed package, so it keeps working
without Node.js on the desktop's PATH. Run --install-desktop again if you reinstall
HyperGSR under a different Node.js version or npm prefix. Run --uninstall-desktop
before npm uninstall -g hypergsr.
The package bundles the native recorder, PipeWire capture helper, and UI icons. It needs Node.js 22+ and a Linux x86-64 desktop with glibc. It does not support macOS, Windows, ARM, or Alpine/musl. The bundled binaries need glibc 2.39 or newer (Ubuntu 24.04+, Fedora 40+, or similar); older distributions should use the build from source instructions below.
You still need GTK 4.10+, gtk4-layer-shell, libdrm, X11 libraries, PipeWire,
libportal, FFmpeg, and an XDG desktop portal. See the distro dependency instructions
below. npm does not install system packages, run sudo, compile Rust on the user's
machine, or download binaries from GitHub during installation.
All recorder arguments and environment variables are forwarded unchanged. Relative
paths such as hypergsr --export-demo ./demo.mp4 resolve from your current directory.
To build and try the package locally, install the native build dependencies below, then:
npm test
npm pack
npm install -g ./hypergsr-1.2.0.tgz --ignore-scripts
hypergsr --report
npm pack builds both native binaries from source using the locked Cargo dependencies,
then checks the architecture, version, helper, and icons before creating the tarball.
Only the launcher and native runtime files are shipped, alongside the package metadata,
README, and license. npm run build:native builds the bundle without packing it.
Keep the npm and Cargo versions in sync. Maintainers should use the Ubuntu 24.04 CI
artifact for distribution rather than binaries built on a newer distro.
Each GitHub release has a hypergsr.flatpak bundle that installs HyperGSR as a
sandboxed desktop app with its own menu entry. The bundle includes gtk4-layer-shell,
libportal, the capture helper, and an FFmpeg build with NVENC (NVIDIA driver 530 or
newer), VAAPI, and x264. It uses the GNOME 50 runtime from Flathub.
flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo
curl -LO https://github.com/KunalSiyag/gpu-recorder-rs/releases/latest/download/hypergsr.flatpak
flatpak install --user hypergsr.flatpak
flatpak run io.github.KunalSiyag.gpu_recorder_rs
HyperGSR is not on Flathub, so flatpak update will not upgrade it. Install the
newer bundle from the next release to upgrade. To reinstall a bundle of the version
you already have (for example a fresh build), add --reinstall, otherwise Flatpak
stops with "This version of io.github.KunalSiyag.gpu_recorder_rs is already installed":
flatpak install --user --reinstall hypergsr.flatpak
On COSMIC the Flatpak prints "it appears your Wayland compositor does not support the
Session Lock protocol" at startup. This warning is harmless: gtk4-layer-shell checks for
every protocol it knows, and COSMIC hides the privileged session-lock protocol from
sandboxed apps. HyperGSR never locks the screen, and the docked bar still works. The sandbox can access your GPU
devices (for the hardware cursor and encoders), your Videos folder, Wayland, and the
local network for Web Studio. Screen capture goes through the desktop portal. To
build the bundle yourself, see packaging/flatpak.
The repository includes tested PKGBUILDs. Build and install the prebuilt release with:
git clone https://github.com/KunalSiyag/gpu-recorder-rs.git
cd gpu-recorder-rs/packaging/aur/hypergsr-bin
makepkg -si
Use packaging/aur/hypergsr-git instead to build the latest main from source.
Download hypergsr-v1.2.0-linux-x86_64.tar.gz from the latest release, then:
tar xzf hypergsr-v1.2.0-linux-x86_64.tar.gz
./target/release/gpu-recorder-rs
You still need the runtime libraries listed below (GTK 4, gtk4-layer-shell, libdrm, PipeWire, libportal, FFmpeg).
git clone https://github.com/KunalSiyag/gpu-recorder-rs.git
cd gpu-recorder-rs
./install.sh
Or install the dependencies yourself and build with Cargo:
Ubuntu 25.10+ / Debian 13:
sudo apt update && sudo apt install -y \
build-essential pkg-config cargo rustc clang \
libgtk-4-dev libgtk4-layer-shell-dev libdrm-dev libx11-dev \
libpipewire-0.3-dev libportal-dev ffmpeg
Ubuntu 24.04 / 25.04 / Pop!_OS 24.04: libgtk4-layer-shell-dev isn't packaged before Ubuntu 25.10. ./install.sh builds it from source automatically. To do it by hand, install everything above except that package, then:
sudo apt install -y meson ninja-build libwayland-dev libwayland-bin wayland-protocols
git clone --depth 1 --branch v1.3.0 https://github.com/wmww/gtk4-layer-shell.git
cd gtk4-layer-shell
meson setup build -Dexamples=false -Ddocs=false -Dtests=false -Dintrospection=false -Dvapi=false
ninja -C build && sudo ninja -C build install && sudo ldconfig
Fedora:
sudo dnf install -y \
cargo rust gtk4-devel gtk4-layer-shell-devel libdrm-devel \
libX11-devel pipewire-devel libportal-devel ffmpeg
Arch Linux:
sudo pacman -S --needed \
rust gtk4 gtk4-layer-shell libdrm libx11 pipewire libportal ffmpeg
cargo build --release
./target/release/gpu-recorder-rs
With the same dependencies installed, you can also install it from crates.io:
cargo install gpu-recorder-rs
gpu-recorder-rs
The build compiles the PipeWire capture helper into the binary. On first use it is unpacked to
~/.local/share/hypergsr/<version>/, along with the UI icons.
Running the binary with no arguments opens the Dynamic Island.
# Start in the light theme with the Studio drawer open
HYPERGSR_THEME=light HYPERGSR_EXPANDED=1 ./target/release/gpu-recorder-rs
# Start or stop recording in the running island (bind this to a key);
# pause or continue it
./target/release/gpu-recorder-rs --toggle-recording
./target/release/gpu-recorder-rs --pause-recording
# Record 5 seconds from the command line, with the island's saved settings
# (--pause 2:3 pauses for 3 s once 2 s are recorded)
./target/release/gpu-recorder-rs --record-seconds 5
# Open a video in the editor (in the running island, if there is one)
./target/release/gpu-recorder-rs --edit ~/Videos/HyperGSR_<time>.mp4
# Run instant replay for 60 s, then save the last 30 s
./target/release/gpu-recorder-rs --replay 30 60
# Re-render a capture with saved cursor telemetry and the current background
# (add a cursor track, <capture>.cursor, to draw the studio cursor)
# Add --aspect wide|vertical|square, --format mp4|webm|gif, --cut <from>:<to>
# (seconds; leave <to> empty for "to the end") and --webcam <clip>@<sec>
./target/release/gpu-recorder-rs --render-capture capture.mp4 \
~/.cache/hypergsr/telemetry/HyperGSR_<time>.json out.mp4
# Render a self-contained 60 FPS auto-zoom showcase MP4
./target/release/gpu-recorder-rs --export-demo ./hypergsr_demo.mp4
# Print detected GPU encoders, DRM cursor planes and pipeline info as JSON
./target/release/gpu-recorder-rs --report
# Serve the Web Studio on http://127.0.0.1:7878
./target/release/gpu-recorder-rs --web
# Run the unit tests
cargo test
Shortcuts. Wayland does not let apps grab keys globally, so the shortcuts
are desktop keybindings that run --toggle-recording and --pause-recording.
Click Set up in the Record tab to add Ctrl+Alt+R (start/stop) and
Ctrl+Alt+P (pause) on COSMIC or GNOME (COSMIC's shortcut file is backed up
first); on other desktops, bind the commands yourself. If HyperGSR is not
running, Ctrl+Alt+R starts it and begins recording. While instant replay runs,
Ctrl+Alt+R saves a clip.
While recording, the island shrinks to a small pill (timer, zoom, Stop) that stays above other windows; drag it by its left end to move it out of the way.
Recordings are saved to ~/Videos; Change… next to "Save to" in the Record tab
picks another folder (the Flatpak can only write where its file chooser grants
access). The folder, source, audio, frame rate, quality and background you pick in
the Studio drawer (and the cursor size) are remembered in
~/.config/hypergsr/settings.json.
| Variable | Effect |
|---|---|
HYPERGSR_ENCODER=x264 | Skip hardware encoders and use libx264 |
HYPERGSR_OPEN_STUDIO=1, HYPERGSR_STUDIO_TAB=record or camera | Start with the Studio drawer open on that tab |
HYPERGSR_GDK_BACKEND=x11 or wayland | Override the island's display backend (X11 is the default on GNOME) |
HYPERGSR_NATIVE_CURSOR=1 | Let the desktop draw the cursor into the video instead of the smoothed studio cursor |
HYPERGSR_WEBCAM=/dev/videoN | Record this camera instead of the first one |
HYPERGSR_KEEP_PROJECTS=0 | Delete each raw capture after saving instead of keeping it for the editor |
Editing keeps a little on disk. So the editor can re-render with zoom,
cursor and background applied afresh, the raw capture of the five most recent
recordings (at most 6 GB) is kept in ~/.cache/hypergsr/projects, with the
webcam clip and telemetry. Older ones are deleted automatically; any other video
can still be trimmed and re-exported as it looks. The instant-replay buffer
lives in ~/.cache/hypergsr/replay while it runs.
The Flatpak has no access to cameras, so the Webcam row is unavailable there.
With several displays, auto-zoom follows the cursor only while it is on the recorded one and holds the wide view while it is elsewhere. With the studio cursor, the portal says exactly when the cursor is over the recording, which also lets a single window be zoomed. Otherwise displays are told apart by resolution, so two identical screens are treated as one, and window recordings are not zoomed.
If a recording fails, the reason is shown in the island, and the capture
helper's and FFmpeg's messages are in ~/.cache/hypergsr/capture.log.
Auto-zoom handles most recordings. When you want control during a live tutorial or demo:
| Feature | How it works |
|---|---|
| Record Combo… | Click Record Combo… in the Studio drawer, then press any key, mouse button or shake gesture within 5 seconds to bind it as your zoom trigger. |
| Built-in presets | Shake / middle-click, double-click, right-click, Ctrl+Alt, Ctrl+Shift, Super+Z, Mouse4 / Mouse5 |
| Action modes | Toggle lock: press once to zoom in, again to return to 1.0×.Hold: stays zoomed while held and releases smoothly.Cycle: steps through 1×, 2× and 2.8×. |
| Scroll-wheel zoom | Scroll over the camera preview, or use Lock / Unlock Zoom, to set depth from 1.0× to 3.2×. |
HyperGSR started as a reverse-engineering pass over gpu-screen-recorder 6.1.4, to find out why cursor tracking and user-installed Flatpak bridges fail on Wayland. What it kept, what it replaced and why is written up in RE_ANALYSIS.md. For the longer story behind the cursor plane trick and the spring camera, read Cursor-following auto-zoom on Linux Wayland: reading the cursor from the GPU in Rust on DEV.
flowchart LR
subgraph Wayland["Linux Wayland + kernel DRM"]
PW["PipeWire ScreenCast\nXDG portal"]
DRM["/dev/dri/card*\nDRM cursor plane\n(CRTC_X, CRTC_Y, FB_ID)"]
LS["zwlr_layer_shell_v1\nlayer surface"]
end
subgraph HyperGSR["HyperGSR"]
CAP["hypergsr-pw-capture\n+ restore token"]
CUR["DrmCursorReader\n+ gesture detector"]
ZOOM["240 Hz spring camera\n+ trajectory planner"]
GUI["GTK 4 Dynamic Island"]
ENC["NVENC / VAAPI\nauto-zoom renderer"]
end
PW --> CAP --> ENC
DRM --> CUR --> ZOOM
ZOOM --> GUI
ZOOM --> ENC
GUI <--> LS
Cursor from the GPU, not the compositor (src/cursor.rs). DrmCursorReader enables DRM_CLIENT_CAP_UNIVERSAL_PLANES and DRM_CLIENT_CAP_ATOMIC, finds the cursor plane and reads its position and framebuffer at 60 Hz. The plane already holds the exact position the display controller is drawing, so no compositor protocol is needed.
A spring with exactly enough damping (src/zoom_engine.rs). Pan and zoom are springs with damping set to 2√k, the critical point, integrated at 240 Hz substeps. The camera reaches its target as fast as it can without overshooting:
$$\ddot{\mathbf{x}} = -k(\mathbf{x} - \mathbf{x}_{\text{target}}) - 2\sqrt{k},\dot{\mathbf{x}}$$
Two-pass trajectory planning (build_smooth_60fps_camera_frames in src/encoder.rs). After recording, the cursor telemetry is turned into bounded zoom segments (about 1.75 s per focus cluster), with pull-back to 1.0× during fast travel and smooth transitions.
Wall-clock capture (src/pw_portal_capture.c). The helper sends a frame to FFmpeg only when the compositor delivers a new one (plus a keepalive), and FFmpeg stamps each with the wall clock and fills gaps at a constant frame rate. Video time zero is the first captured frame, which is also when cursor telemetry starts, so zooms land exactly where you clicked.
One-pass studio render (src/studio_render.rs). FFmpeg decodes the capture on the GPU into NV12, a multithreaded compositor applies the zoom and places the frame on the background (src/backgrounds.rs), and NVENC, VAAPI or x264 encodes the final MP4, with decoding, compositing and encoding overlapped. A 46 s 1080p60 test clip with zoom and background renders in about 14 s on an RTX 3050 laptop. When neither zoom, background nor a studio cursor changes a pixel, the capture is only remuxed.
OBS and gpu-screen-recorder are excellent general-purpose recorders. HyperGSR does one thing they don't do out of the box: a camera that follows the cursor on Wayland.
gpu-screen-recorder 6.1.4 | OBS Studio | Screen Studio | HyperGSR | |
|---|---|---|---|---|
| Runs on Linux Wayland | Yes (Flatpak --user bridge broken) | Yes | No, macOS only | Yes |
| Cursor tracking on native Wayland | X11 XFixes only | Depends on compositor | n/a | DRM cursor plane |
| Automatic zoom | No | Plugins, manual | Yes | Yes, spring camera |
| Custom zoom triggers | No | Basic hotkeys | Limited | Keys, mouse buttons, shake, wheel |
| Idle memory | ~45 MB | ~340 MB | ~650 MB (Electron) | ~56 MB |
| Path | What's in it |
|---|---|
src/main.rs | CLI modes and startup (preloads gtk4-layer-shell on Wayland) |
src/gui.rs | GTK 4 Dynamic Island, Studio drawer and themes (load_dynamic_island_css()) |
src/cursor.rs | DRM and X11 cursor readers, shake detection, click ripples |
src/zoom_engine.rs | Spring camera, auto-zoom modes and zoom-combo bindings |
src/encoder.rs | Capture session (helper process, status, telemetry) and the trajectory planner |
src/ffmpeg.rs | Encoder detection (NVENC, VAAPI, x264) and FFmpeg argument sets |
src/studio_render.rs | NV12 zoom and background compositor, decode/composite/encode pipeline |
src/backgrounds.rs | Background presets, image backgrounds, shadow and rounded-corner mask |
Ctrl+C, Super+Enter)av1_nvenc, av1_vaapi)Pull requests are welcome. CONTRIBUTING.md covers setup, and these are good places to start:
| Idea | Where | Difficulty |
|---|---|---|
| A new Island theme (Catppuccin, Nord, Gruvbox, Tokyo Night) | src/gui.rs load_dynamic_island_css() | Easy |
| A new camera preset (bouncy, slow cinematic, instant snap) | src/zoom_engine.rs | Easy |
| A new gesture trigger (circle cursor, hot corner) | src/zoom_engine.rs ZoomComboBinding, src/cursor.rs | Medium |
| New shader effects (spotlight vignette, keystroke HUD) | src/shaders.rs, src/encoder.rs | Medium |
| Multi-monitor capture or an audio waveform overlay | src/pw_portal_capture.c | Advanced |
If HyperGSR is useful to you, a star helps other Linux and Rust developers find it.
The interface uses Inter by Rasmus Andersson, bundled
under the SIL Open Font License (assets/fonts/Inter-LICENSE.txt).
zwlr_layer_shell_v1 on COSMIC, KDE, Hyprland and Sway, and as an always-on-top X11 window on GNOME. Wayland's screen-cast portal cannot leave a window out of a recording, so Hide bar hides the island while recording instead; it comes back while paused (paused time is cut) and when you stop.bin/hypergsr-pw-capture) stores the portal restore_token, so later recordings skip the picker. Choose… in the drawer shows the picker again.A cursor of its own (src/cursor_track.rs). With the portal's metadata cursor mode, the helper writes the cursor's image and position beside the video instead of into it. The render smooths the path with a Gaussian over the whole recording (no lag, since the future is known), keeps jumps between displays sharp, and blends the cursor into the NV12 frame after the zoom, so it scales with the camera.
Cuts instead of stops (src/state.rs, src/editor.rs). The countdown and pauses run on a live capture and are recorded as video-time ranges; the render skips those frames and cuts the audio to match with one aselect filter. A trim in the editor is just two more ranges, mapped through the ones the recording already had, so every export re-renders from the original capture.
One clock for screen and camera (src/webcam.rs). The webcam's FFmpeg keeps the V4L2 driver's CLOCK_MONOTONIC frame stamps, and the capture helper reports video time zero on the same clock, so the render picks the camera frame for each output frame directly, across pauses and resumed screen shares.
src/settings.rs |
| Persisted recorder settings (source, area, audio, quality, background) |
src/studio_panel.rs | Record and background cards in the Studio drawer |
src/editor.rs | Trim and re-export window (shape, format, effects) |
src/project.rs | Recent recordings kept re-renderable for the editor |
src/cursor_track.rs | Recorded cursor track: parsing, smoothing, drawing, click ripples |
src/webcam.rs | Webcam recording, clock alignment and the bubble |
src/replay.rs | Instant-replay segment ring and clip saving |
src/shortcuts.rs | Desktop keybindings and the D-Bus actions they trigger |
src/region_select.rs | Full-screen overlay for choosing an area to record |
src/shaders.rs | GLSL for cursor ripples and effects |
src/pw_portal_capture.c | Standalone PipeWire + XDG portal capture helper |
src/web_ui.rs | Web Studio server (--web) |
docs/ | Website, served by GitHub Pages |