Update: Changed scripts, added wayland support for screenshots, added ability to control external monitors via ddcutil.

This commit is contained in:
Keyitdev
2026-06-02 19:06:39 +02:00
parent 545e54af53
commit ad19130ded
5 changed files with 224 additions and 151 deletions
+145 -103
View File
@@ -9,145 +9,187 @@ mkdir -p "$screenshot_directory"
mkdir -p "$videos_directory"
mkdir -p "$audio_directory"
# date=$(date '+%d-%m-%Y-%H-%M-%S') #10-08-2025-18-53-58
date=$(date '+%Y-%m-%d_%H-%M-%S') #2025-08-10_18-53-58
screen_resolution="$(xdpyinfo | grep dimensions | sed -r 's/^[^0-9]*([0-9]+x[0-9]+).*$/\1/')"
microphone="$(pacmd list-sources | grep -E '^\s+name: .*alsa_input' | cut -c 8- | sed 's/[<,>]//g')"
desktop="$(pacmd list-sources | grep -E '^\s+name: .*alsa_output' | cut -c 8- | sed 's/[<,>]//g')"
# date=$(date '+%d-%m-%Y-%H-%M-%S_pc') #10-08-2025-18-53-58
filename=$(date '+%Y-%m-%d_%H-%M-%S_pc') #2025-08-10_18-53-58
# Detect display server
if [ -n "$WAYLAND_DISPLAY" ]; then
DISPLAY_SERVER="wayland"\
# h264_nvenc libx264rgb
VIDEO_CODEC="libx264rgb"
FRAMERATE=60
# microphone="$(pactl list sources | grep -A2 'Name:.*input' | grep 'Name:' | head -1 | awk '{print $2}')"
desktop="$(pactl list sources | grep -A2 'Name:.*output' | grep 'Name:' | head -1 | awk '{print $2}')"
else
DISPLAY_SERVER="x11"
# yuv420p yuv444p rgba
VIDEO_CODEC="yuv444p"
FRAMERATE=60
screen_resolution="$(xdpyinfo | grep dimensions | sed -r 's/^[^0-9]*([0-9]+x[0-9]+).*$/\1/')"
fi
get_area(){
slop="$(slop -n -f '%w,%h,%x,%y')"
w=$(echo "$slop" | cut -d ',' -f1)
h=$(echo "$slop" | cut -d ',' -f2)
x=$(echo "$slop" | cut -d ',' -f3)
y=$(echo "$slop" | cut -d ',' -f4)
if [ "$DISPLAY_SERVER" = "wayland" ]; then
slurp_output="$(slurp)"
x=$(echo "$slurp_output" | cut -d' ' -f1 | cut -d',' -f1)
y=$(echo "$slurp_output" | cut -d' ' -f1 | cut -d',' -f2)
w=$(echo "$slurp_output" | cut -d' ' -f2 | cut -d'x' -f1)
h=$(echo "$slurp_output" | cut -d' ' -f2 | cut -d'x' -f2)
else
slop="$(slop -n -f '%w,%h,%x,%y')"
w=$(echo "$slop" | cut -d ',' -f1)
h=$(echo "$slop" | cut -d ',' -f2)
x=$(echo "$slop" | cut -d ',' -f3)
y=$(echo "$slop" | cut -d ',' -f4)
fi
[ $((w%2)) -eq 1 ] && w=$(( w + 1 ))
[ $((h%2)) -eq 1 ] && h=$(( h + 1 ))
[ $((x%2)) -eq 1 ] && x=$(( x + 1 ))
[ $((y%2)) -eq 1 ] && y=$(( y + 1 ))
wh="${w}x${h}"
geometry="${x},${y} ${w}x${h}"
}
# audio devices (Wayland / PulseAudio)
microphone="$(pactl list short sources | grep input | head -1 | awk '{print $1}')"
desktop="$(pactl list short sources | grep output | head -1 | awk '{print $1}')"
screenshot_selected_area(){
ffcast -q -g "$(slop)" png "$screenshot_directory/$date.png"
xclip -selection clipboard -t image/png "$screenshot_directory/$date.png"
notify-send -i "$screenshot_directory/$date.png" "Screenshot" "Area screenshot taken"
if [ "$DISPLAY_SERVER" = "wayland" ]; then
geometry="$(slurp)"
grim -g "$geometry" "$screenshot_directory/$filename.png"
wl-copy < "$screenshot_directory/$filename.png"
else
ffcast -q -g "$(slop)" png "$screenshot_directory/$filename.png"
xclip -selection clipboard -t image/png "$screenshot_directory/$filename.png"
fi
notify-send -i "$screenshot_directory/$filename.png" "Screenshot" "Area screenshot taken"
}
screenshot_full_screen(){
ffcast -q png "$screenshot_directory/$date.png"
xclip -selection clipboard -t image/png "$screenshot_directory/$date.png"
notify-send -i "$screenshot_directory/$date.png" "Screenshot" "Full screen screenshot taken"
if [ "$DISPLAY_SERVER" = "wayland" ]; then
grim "$screenshot_directory/$filename.png"
wl-copy < "$screenshot_directory/$filename.png"
else
ffcast -q png "$screenshot_directory/$filename.png"
xclip -selection clipboard -t image/png "$screenshot_directory/$filename.png"
fi
notify-send -i "$screenshot_directory/$filename.png" "Screenshot" "Full screen screenshot taken"
}
video_selected_area(){
get_area
ffmpeg -hide_banner -loglevel error -show_region 1 \
-f x11grab -video_size "$wh" -framerate 30 -i :0.0+"$x","$y" -pix_fmt yuv420p "$videos_directory/$date.mp4"
ffmpeg -i "$videos_directory/$date.mp4" -ss 00:00:01.000 -vframes 1 "/tmp/$date.png"
notify-send -i "/tmp/$date.png" "Video" "Area video taken"
if [ "$DISPLAY_SERVER" = "wayland" ]; then
geometry="$(slurp)"
wf-recorder -g "$geometry" -c "$VIDEO_CODEC" -r "$FRAMERATE" -f "$videos_directory/$filename.mp4"
grim -g "$geometry" -t png "/tmp/$filename.png"
else
get_area
ffmpeg -hide_banner -loglevel error -show_region 1 \
-f x11grab -video_size "$wh" -framerate "$FRAMERATE" -i :0.0+"$x","$y" -pix_fmt "$VIDEO_CODEC" "$videos_directory/$filename.mp4"
ffmpeg -i "$videos_directory/$filename.mp4" -ss 00:00:01.000 -vframes 1 "/tmp/$filename.png"
fi
notify-send -i "/tmp/$filename.png" "Video" "Area video taken"
}
video_full_screen(){
ffmpeg -hide_banner -loglevel error -show_region 1 \
-f x11grab -video_size "$screen_resolution" -framerate 30 -i :0.0 -pix_fmt yuv420p "$videos_directory/$date.mp4"
ffmpeg -i "$videos_directory/$date.mp4" -ss 00:00:01.000 -vframes 1 "/tmp/$date.png"
notify-send -i "/tmp/$date.png" "Video" "Full screen video taken"
if [ "$DISPLAY_SERVER" = "wayland" ]; then
wf-recorder -c "$VIDEO_CODEC" -r "$FRAMERATE" -f "$videos_directory/$filename.mp4"
ffmpeg -i "$videos_directory/$filename.mp4" -ss 00:00:01.000 -vframes 1 "/tmp/$filename.png" 2>/dev/null
else
ffmpeg -hide_banner -loglevel error -show_region 1 \
-f x11grab -video_size "$screen_resolution" -framerate "$FRAMERATE" -i :0.0 -pix_fmt "$VIDEO_CODEC" "$videos_directory/$filename.mp4"
ffmpeg -i "$videos_directory/$filename.mp4" -ss 00:00:01.000 -vframes 1 "/tmp/$filename.png"
fi
notify-send -i "/tmp/$filename.png" "Video" "Full screen video taken"
}
video_full_screen_rgba(){
ffmpeg -hide_banner -loglevel error -show_region 1 \
-f x11grab -video_size "$screen_resolution" -framerate 30 -i :0.0 -pix_fmt rgba "$videos_directory/$date.mp4"
ffmpeg -i "$videos_directory/$date.mp4" -ss 00:00:01.000 -vframes 1 "/tmp/$date.png"
notify-send -i "/tmp/$date.png" "Video" "Full screen video taken (rgba)"
video_selected_area_audio(){
if [ "$DISPLAY_SERVER" = "wayland" ]; then
geometry="$(slurp)"
wf-recorder -g "$geometry" -c "$VIDEO_CODEC" -r "$FRAMERATE" --audio --audio-device "$desktop" -f "$videos_directory/$filename.mp4"
grim -g "$geometry" -t png "/tmp/$filename.png"
else
get_area
ffmpeg -hide_banner -loglevel error -show_region 1 \
-f x11grab -video_size "$wh" -framerate "$FRAMERATE" -i :0.0+"$x","$y" \
-f alsa -i default -pix_fmt "$VIDEO_CODEC" "$videos_directory/$filename.mp4"
ffmpeg -i "$videos_directory/$filename.mp4" -ss 00:00:01.000 -vframes 1 "/tmp/$filename.png"
fi
notify-send -i "/tmp/$filename.png" "Video" "Area video with desktop audio taken"
}
audio_microphone(){
ffmpeg -f pulse -i "$microphone" -metadata title="$date" "$audio_directory/$date.mp3"
notify-send "Audio" "Microphone audio recorded"
}
audio_desktop(){
ffmpeg -f pulse -i "$desktop" -metadata title="$date" "$audio_directory/$date.mp3"
notify-send "Audio" "Desktop audio recorded"
}
video_selected_area_audio_microphone(){
get_area
ffmpeg -hide_banner -loglevel error -show_region 1 \
-f x11grab -video_size "$wh" -framerate 30 -i :0.0+"$x","$y" \
-f alsa -i default -pix_fmt yuv420p "$videos_directory/$date.mp4"
ffmpeg -i "$videos_directory/$date.mp4" -ss 00:00:01.000 -vframes 1 "/tmp/$date.png"
notify-send -i "/tmp/$date.png" "Video" "Area video with audio taken"
}
video_full_screen_audio_microphone(){
ffmpeg -hide_banner -loglevel error -show_region 1 \
-f x11grab -video_size "$screen_resolution" -framerate 30 -i :0.0 \
-f alsa -i default -pix_fmt yuv420p "$videos_directory/$date.mp4"
ffmpeg -i "$videos_directory/$date.mp4" -ss 00:00:01.000 -vframes 1 "/tmp/$date.png"
notify-send -i "/tmp/$date.png" "Video" "Full screen video with audio taken"
video_full_screen_audio(){
if [ "$DISPLAY_SERVER" = "wayland" ]; then
wf-recorder -c "$VIDEO_CODEC" -r "$FRAMERATE" --audio --audio-device "$desktop" -f "$videos_directory/$filename.mp4"
ffmpeg -i "$videos_directory/$filename.mp4" -ss 00:00:01.000 -vframes 1 "/tmp/$filename.png" 2>/dev/null
else
ffmpeg -hide_banner -loglevel error -show_region 1 \
-f x11grab -video_size "$screen_resolution" -framerate "$FRAMERATE" -i :0.0 \
-f alsa -i default -pix_fmt "$VIDEO_CODEC" "$videos_directory/$filename.mp4"
ffmpeg -i "$videos_directory/$filename.mp4" -ss 00:00:01.000 -vframes 1 "/tmp/$filename.png"
fi
notify-send -i "/tmp/$filename.png" "Video" "Full screen video with desktop audio taken"
}
stop(){
pkill -fxn '(/\S+)*ffmpeg\s.*\sx11grab\s.*'
pkill -fxn '(/\S+)*ffmpeg\s.*\spulse\s.*'
pkill -fxn '(/\S+)*wf-recorder\s.*'
pkill -fxn '(/\S+)*pw-record\s.*'
exit 1
}
help(){
cat << EOF
cat << EOF
Display server: $DISPLAY_SERVER
-h | -help | --help
-s | -stop
-sa | -screenshot_selected_area
-sf | -screenshot_full_screen
-va | -video_selected_area
-vf | -video_full_screen
-am | -audio_microphone
-ad | -audio_desktop
-vaam | -video_selected_area_audio_microphone
-vfam | -video_full_screen_audio_microphone
-vaad | -video_selected_area_audio
-vfad | -video_full_screen_audio
EOF
}
main(){
while [ "$1" != "" ]; do
PARAM="$1"
case $PARAM in
-h | -help | --help)
help
exit 1
;;
-s | -stop)
stop
exit 1
;;
-sa | -screenshot_selected_area)
screenshot_selected_area
;;
-sf | -screenshot_full_screen)
screenshot_full_screen
;;
-va | -video_selected_area)
video_selected_area
;;
-vf | -video_full_screen)
video_full_screen
;;
-vf_rgba | -video_full_screen_rgba)
video_full_screen_rgba
;;
-am | -audio_microphone)
audio_microphone
;;
-ad | -audio_desktop)
audio_desktop
;;
-vaam | -video_selected_area_audio_microphone)
video_selected_area_audio_microphone
;;
-vfam | -video_full_screen_audio_microphone)
video_full_screen_audio_microphone
;;
*)
echo "ERROR: unknown parameter \"$PARAM\""
help
exit 1
;;
case "$1" in
-h|-help|--help)
help
exit 0
;;
-s|-stop)
stop
;;
-sa|-screenshot_selected_area)
screenshot_selected_area
;;
-sf|-screenshot_full_screen)
screenshot_full_screen
;;
-va|-video_selected_area)
video_selected_area
;;
-vf|-video_full_screen)
video_full_screen
;;
-vaad|-video_selected_area_audio)
video_selected_area_audio
;;
-vfad|-video_full_screen_audio)
video_full_screen_audio
;;
*)
echo "ERROR: unknown parameter $1"
help
exit 1
;;
esac
shift
done
# done
set -e
}
main "$1" &
exit 0
main "$@"