GIF Screen Recorder
A GTK4 screen recording utility written in Rust, compatible with Wayland.
- Record entire screen, record a specific window, or select a region to record
- Works on all Wayland compositors — uses the XDG Desktop Portal ScreenCast API (GNOME, KDE, Sway, Hyprland, etc.)
- FPS selector — choose 5, 10, 15, 20, 24, or 30 fps (default 15)
- Floating recording indicator — a small window with a Stop button appears while recording
- Keyboard shortcut — press Ctrl+Shift+R to stop recording at any time
- Animated GIF spinner — a processing window shows while ffmpeg converts the recording
- Auto-crop for window recordings — black borders added by the portal are automatically removed
- Output is saved as a high-quality GIF to
~/Pictures/ - MCP server — a
gif-that-for-you-mcpbinary exposes recording as a Model Context Protocol tool
| Component | Purpose |
|---|---|
| GTK 4.6+ | UI toolkit |
xdg-desktop-portal |
Standard Wayland screen sharing API |
| GStreamer + PipeWire plugin | Records from the portal's PipeWire stream |
GStreamer libav plugin (gst-libav) |
Provides the FFV1 lossless video codec |
ffmpeg |
Converts the captured video to an animated GIF |
Install on Arch Linux:
sudo pacman -S gtk4 xdg-desktop-portal \
gstreamer gst-plugins-base gst-plugins-good gst-libav \
gst-plugin-pipewire ffmpegInstall on Ubuntu / Debian (24.04+):
sudo apt install libgtk-4-dev xdg-desktop-portal \
gstreamer1.0-tools gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good gstreamer1.0-libav \
gstreamer1.0-pipewire ffmpegPortal backends — you also need a portal backend matching your compositor:
| Compositor | Package |
|---|---|
| GNOME | xdg-desktop-portal-gnome (usually pre-installed) |
| KDE Plasma | xdg-desktop-portal-kde (usually pre-installed) |
| Sway / wlroots | xdg-desktop-portal-wlr |
| Hyprland | xdg-desktop-portal-hyprland |
| Tool | Version | Notes |
|---|---|---|
| Rust + Cargo | 1.70+ | Install via rustup |
| GLib / GTK4 development headers | 4.6+ | Included in libgtk-4-dev / gtk4 packages above |
| pkg-config | any | Used by Cargo build scripts to locate system libraries |
On Arch: sudo pacman -S base-devel
On Ubuntu/Debian: sudo apt install build-essential pkg-config
cargo build --releaseThis produces two binaries under target/release/:
| Binary | Description |
|---|---|
gif-that-for-you |
Main GTK4 application |
gif-that-for-you-mcp |
MCP server for AI agent integration |
install.sh installs the binaries, .desktop entry, AppStream metainfo, and icon into a standard prefix. It builds the release binaries automatically if they're missing. By default it installs to ~/.local (no sudo) or to /usr/local when run as root. Set PREFIX to override.
./install.sh # installs to ~/.local
sudo ./install.sh # installs to /usr/local
PREFIX=/opt/gtfy ./install.sh # installs to a custom prefix
./install.sh uninstall # removes everything installed aboveIf ~/.local/bin is not on your $PATH, the script prints a one-line hint with the export command to add it.
The manifest io.github.kmwallio.GifThatForYou.yml targets the GNOME 49 SDK.
Install flatpak-builder and the required runtimes:
# Install flatpak-builder (Arch)
sudo pacman -S flatpak-builder
# Install flatpak-builder (Ubuntu/Debian)
sudo apt install flatpak-builder
# Add Flathub and install the GNOME 49 SDK
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install flathub org.gnome.Platform//49 org.gnome.Sdk//49
flatpak install flathub org.freedesktop.Sdk.Extension.rust-stable//24.08Download the source archives and compute their sha256 values, then replace the FILL_IN placeholders in the manifest:
wget https://ffmpeg.org/releases/ffmpeg-7.1.tar.xz
sha256sum ffmpeg-7.1.tar.xz
wget https://gstreamer.freedesktop.org/src/gst-libav/gst-libav-1.26.0.tar.xz
sha256sum gst-libav-1.26.0.tar.xzNote: If the GNOME 49 SDK already bundles
gst-libav, you can remove that entire module block from the manifest. Check with:flatpak info --show-extensions org.gnome.Sdk//49 | grep -i libav
Flatpak builds run without internet access, so all crate dependencies must be pre-fetched:
pip install aiohttp toml
curl -LO https://raw.githubusercontent.com/flatpak/flatpak-builder-tools/master/cargo/flatpak-cargo-generator.py
python3 flatpak-cargo-generator.py Cargo.lock -o cargo-sources.jsonCommit cargo-sources.json alongside the manifest. It only needs to be regenerated when Cargo.lock changes.
flatpak-builder --user --install --force-clean build-dir \
io.github.kmwallio.GifThatForYou.ymlRun the installed Flatpak:
flatpak run io.github.kmwallio.GifThatForYouflatpak-builder --force-clean build-dir io.github.kmwallio.GifThatForYou.yml
flatpak-builder --run build-dir io.github.kmwallio.GifThatForYou.yml gif-that-for-you- Launch the application:
./target/release/gif-that-for-you
- Select a frame rate from the dropdown (default: 15 fps).
- Choose a recording mode:
- Record Entire Screen — records the full display.
- Record Window… — lets you pick a specific window; black borders are cropped automatically.
- Select Region… — draw a crop rectangle first, then record.
- A system dialog appears asking you to select which screen or window to share.
- A small floating Recording… indicator appears with a ■ Stop button.
- Click ■ Stop (or press Ctrl+Shift+R) to stop.
- An "Animating GIF…" window appears while ffmpeg processes the recording.
- The GIF is saved to
~/Pictures/recording-<timestamp>.gif.
The gif-that-for-you-mcp binary implements the Model Context Protocol over stdin/stdout (newline-delimited JSON-RPC). It exposes two tools:
start_recording— opens the XDG portal picker and starts capturing.stop_recording— stops the capture and returns the path to the saved GIF.- Optional parameter:
fps(integer, 1–30, default 15)
- Optional parameter:
- The app uses the XDG Desktop Portal
org.freedesktop.portal.ScreenCastD-Bus API to negotiate screen access. This works across all major Wayland compositors. - The portal returns a PipeWire stream; a GStreamer pipeline (
pipewiresrc → videoconvert → avenc_ffv1 → matroskamux) records it losslessly to a temporary MKV file. - When you stop recording, ffmpeg converts the MKV to a high-quality palette-based GIF using
floyd_steinbergdithering and per-frame palette optimization. - For window recordings, a second ffmpeg pass runs
cropdetecton the trimmed video to locate and strip the black border the portal places around the window. - If you selected a crop region, the crop is applied during the GIF conversion step.
- The region selector works by overlaying a full-screen transparent GTK4 window. Press Escape to cancel the selection.
- Portal interaction is implemented directly using GIO's D-Bus bindings — no extra Rust crates beyond
gtk4,glib, andserde_jsonare required. - The PipeWire file descriptor is kept open until GStreamer finishes writing, then closed cleanly to avoid MKV/EBML corruption.
