Files
2026-07-30 16:04:29 -03:00

4.6 KiB

Context

The desktop already uses Home Manager modules under modules/home-manager and keeps Hyprland keybinds in modules/home-manager/hyprland/default.nix. The new capability is a small user-session workflow, not a daemon: select a region with slurp, record it with the Wayland-native wf-recorder, encode the result with ffmpeg, and publish the finished file with wl-copy.

The same Hyprland bind must start and stop the workflow. The first invocation needs to remain alive while recording; a later invocation needs a stable way to find and signal that process. The implementation also needs to avoid leaving partial files in the screenshots directory when selection is cancelled or encoding fails.

Goals / Non-Goals

Goals:

  • Encapsulate packages, script, option, output directory, and runtime state in modules/home-manager/gif-recorder.
  • Use a single toggle command suitable for a Hyprland bind.
  • Select a rectangular region interactively through slurp.
  • Save optimized GIF output in ~/Pictures/Screenshots and copy it as image/gif with wl-copy.
  • Keep host wiring minimal: import/enable in hosts/jpporta-nixos/home.nix, bind in the existing Hyprland module.

Non-Goals:

  • Full-screen or window recording modes.
  • A recording history, notification UI, configurable encoder settings, or a separate stop bind.
  • A new service or background daemon.
  • Changes to the existing screenshot flow.

Decisions

D1. One shell script owns the toggle state

The module installs one gif-recorder executable and uses a runtime-directory state file containing the active script PID. If the state file names a live process, a new invocation sends it SIGINT; otherwise it runs slurp and starts a recording. This keeps the bind to one command and avoids adding a service or IPC layer.

Alternative: use separate start/stop scripts or a systemd user service. Rejected because they add commands and lifecycle machinery for one short-lived action.

D2. Use wf-recorder, slurp, ffmpeg, and wl-copy

These tools are small, composable Wayland utilities already suited to the requested flow. wf-recorder receives the geometry selected by slurp; ffmpeg handles palette generation and GIF encoding; wl-copy --type image/gif makes the resulting file available to Wayland clipboard consumers.

Alternative: OBS or a screenshot/GIF application. Rejected because a GUI recorder is heavier than the requested Hyprshot-like interaction.

D3. Encode through a temporary video file

Recording first to a temporary Matroska file keeps the output atomic: the final timestamped GIF is moved into ~/Pictures/Screenshots only after ffmpeg succeeds. The encoder uses a palette-generation filter and a bounded frame rate/width to avoid the worst GIF size and color-quality problems without introducing configuration options.

Alternative: record directly to GIF. Rejected because palette generation and interruption handling are worse, and wf-recorder is designed primarily for video output.

D4. Store state under XDG_RUNTIME_DIR

The state file belongs in ${XDG_RUNTIME_DIR:-/tmp} and is removed on normal completion or cancellation. It is session-local and avoids polluting the home directory with a lock file.

Risks / Trade-offs

  • [GIFs are inherently large and limited to 256 colors] -> Cap output at a modest frame rate and width; keep the original temporary recording out of the screenshots directory.
  • [A crashed process can leave a stale state file] -> Check whether the recorded PID is alive before treating the workflow as active, and remove stale state before starting.
  • [Clipboard consumers differ in GIF support] -> Publish with the explicit image/gif MIME type; the saved file remains the fallback when a consumer cannot paste animated images.
  • [The second bind may be pressed while region selection is active] -> Keep the controlling script PID in the state file before invoking slurp, and handle interruption by cleaning up without creating output.

Migration Plan

  1. Apply the Home Manager configuration for jpporta-nixos.
  2. Press the new Hyprland bind and select a region; press it again to stop and wait for encoding.
  3. Verify the GIF in ~/Pictures/Screenshots and paste it into a GIF-capable Wayland application.
  4. Roll back by disabling/removing the module import and bind; no persistent data migration is required, and existing GIF files are left untouched.

Open Questions

  • The exact key combination should follow the existing screenshot bind convention in the Hyprland module; implementation should reuse that convention rather than introduce a new modifier scheme.