feat(desktop): add screen recording (task 0029)
Add a wf-recorder module, enabled by the desktop aggregator. Super+Shift+R picks a region with slurp and toggles a video-only capture (no audio), stopped with SIGINT so the file finalises, saved to ~/Videos/Recordings. Start and saved notifications fire via notify-send. A Waybar custom/recording widget samples the wf-recorder process once a second and shows a video glyph while a capture runs.
This commit is contained in:
@@ -15,6 +15,7 @@ in
|
||||
modules.desktop.hypridle.enable = lib.mkDefault true;
|
||||
modules.desktop.login.enable = lib.mkDefault true;
|
||||
modules.desktop.mako.enable = lib.mkDefault true;
|
||||
modules.desktop.recording.enable = lib.mkDefault true;
|
||||
modules.desktop.rofi.enable = lib.mkDefault true;
|
||||
modules.desktop.screenshot.enable = lib.mkDefault true;
|
||||
modules.desktop.terminal.enable = lib.mkDefault true;
|
||||
|
||||
54
modules/desktop/recording.nix
Normal file
54
modules/desktop/recording.nix
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
# Keybound screen recording: pick a region, then toggle a video-only capture.
|
||||
let
|
||||
cfg = config.modules.desktop.recording;
|
||||
user = config.user.name;
|
||||
|
||||
slurp = "${pkgs.slurp}/bin/slurp";
|
||||
wf-recorder = "${pkgs.wf-recorder}/bin/wf-recorder";
|
||||
notify-send = "${pkgs.libnotify}/bin/notify-send";
|
||||
pgrep = "${pkgs.procps}/bin/pgrep";
|
||||
pkill = "${pkgs.procps}/bin/pkill";
|
||||
date = "${pkgs.coreutils}/bin/date";
|
||||
mkdir = "${pkgs.coreutils}/bin/mkdir";
|
||||
|
||||
recDir = "$HOME/Videos/Recordings";
|
||||
|
||||
# A single key both starts and stops.
|
||||
# A running wf-recorder is stopped with SIGINT so it finalises the file.
|
||||
# Otherwise slurp picks a region and wf-recorder runs in the foreground until
|
||||
# that stop arrives, so this instance lives for the whole recording and then
|
||||
# reports it saved.
|
||||
# No -a means no audio is captured.
|
||||
toggle = pkgs.writeShellScript "screen-record-toggle" ''
|
||||
if ${pgrep} -x wf-recorder >/dev/null; then
|
||||
${pkill} -INT -x wf-recorder
|
||||
exit 0
|
||||
fi
|
||||
|
||||
region=$(${slurp}) || exit 0
|
||||
${mkdir} -p "${recDir}"
|
||||
file="${recDir}/recording-$(${date} +%Y%m%d-%H%M%S).mp4"
|
||||
|
||||
${notify-send} -a "Screen recording" "Recording started" "Region capture, no audio."
|
||||
${wf-recorder} -g "$region" -f "$file"
|
||||
${notify-send} -a "Screen recording" "Recording saved" "$file"
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.modules.desktop.recording.enable = lib.mkEnableOption "wf-recorder screen recording";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
home-manager.users.${user} = {
|
||||
# $mod is defined by the compositor config these binds share.
|
||||
wayland.windowManager.hyprland.settings.bind = [
|
||||
"$mod SHIFT, R, exec, ${toggle}"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -28,6 +28,16 @@ let
|
||||
${pkgs.mako}/bin/makoctl mode -t dnd >/dev/null 2>&1
|
||||
${pkgs.procps}/bin/pkill -RTMIN+8 waybar
|
||||
'';
|
||||
|
||||
# Lit while a wf-recorder capture is running.
|
||||
# Empty text collapses the widget when idle, so it shows nothing until then.
|
||||
recStatus = pkgs.writeShellScript "waybar-recording-status" ''
|
||||
if ${pkgs.procps}/bin/pgrep -x wf-recorder >/dev/null; then
|
||||
printf '{"text":"${g "f03d"}","tooltip":"Recording","class":"recording"}\n'
|
||||
else
|
||||
printf '{"text":"","class":"idle"}\n'
|
||||
fi
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.modules.desktop.waybar.enable = lib.mkEnableOption "the Waybar status bar";
|
||||
@@ -52,6 +62,7 @@ in
|
||||
modules-left = [ "hyprland/workspaces" ];
|
||||
modules-center = [ "clock" ];
|
||||
modules-right = [
|
||||
"custom/recording"
|
||||
"mpris"
|
||||
"wireplumber"
|
||||
"network"
|
||||
@@ -134,6 +145,14 @@ in
|
||||
interval = "once";
|
||||
signal = 8;
|
||||
};
|
||||
|
||||
# Recording state has no event to hook, so the widget samples the
|
||||
# wf-recorder process once a second.
|
||||
"custom/recording" = {
|
||||
return-type = "json";
|
||||
exec = "${recStatus}";
|
||||
interval = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user