nirish

config files for niri window manager
Log | Files | Refs | README | LICENSE

screenrecord (4287B)


      1 #!/usr/bin/env bash
      2 
      3 OUTPUT_DIR="${XDG_VIDEOS_DIR:-$HOME/Videos/screenrecordings}"
      4 
      5 if [[ ! -d "$OUTPUT_DIR" ]]; then
      6     mkdir -p "$OUTPUT_DIR"
      7 fi
      8 
      9 SCOPE=""
     10 AUDIO="false"
     11 WEBCAM="false"
     12 
     13 for arg in "$@"; do
     14     case "$arg" in
     15         --with-audio) AUDIO="true" ;;
     16         --with-webcam) WEBCAM="true" ;;
     17         output | region) SCOPE="$arg" ;;
     18     esac
     19 done
     20 
     21 cleanup_webcam() {
     22     pkill -f "WebcamOverlay" 2>/dev/null
     23 }
     24 
     25 start_webcam_overlay() {
     26     cleanup_webcam
     27 
     28     # Get monitor scale
     29     local scale=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .scale')
     30 
     31     # Target width (base 360px, scaled to monitor)
     32     local target_width=$(awk "BEGIN {printf \"%.0f\", 360 * $scale}")
     33 
     34     # Try preferred 16:9 resolutions in order, use first available
     35     local preferred_resolutions=("640x360" "1280x720" "1920x1080")
     36     local video_size_arg=""
     37     local available_formats=$(v4l2-ctl --list-formats-ext -d /dev/video0 2>/dev/null)
     38 
     39     for resolution in "${preferred_resolutions[@]}"; do
     40         if echo "$available_formats" | grep -q "$resolution"; then
     41             video_size_arg="-video_size $resolution"
     42             break
     43         fi
     44     done
     45 
     46     ffplay -f v4l2 $video_size_arg -framerate 30 /dev/video0 \
     47         -vf "scale=${target_width}:-1" \
     48         -window_title "WebcamOverlay" \
     49         -noborder \
     50         -fflags nobuffer -flags low_delay \
     51         -probesize 32 -analyzeduration 0 \
     52         -loglevel quiet &
     53     sleep 1
     54 }
     55 
     56 start_screenrecording() {
     57     local filename="$OUTPUT_DIR/screenrecording-$(date +'%Y-%m-%d_%H-%M-%S').mp4"
     58     local audio_args=""
     59 
     60     # Merge audio tracks into one - separate tracks only play one at a time in most players
     61     [[ "$AUDIO" == "true" ]] && audio_args="-a default_output|default_input"
     62 
     63     gpu-screen-recorder -w "$@" -f 60 -c mp4 -o "$filename" $audio_args &
     64     toggle_screenrecording_indicator
     65 }
     66 
     67 stop_screenrecording() {
     68     pkill -SIGINT -f "gpu-screen-recorder" # SIGINT required to save video properly
     69 
     70     # Wait a maximum of 5 seconds to finish before hard killing
     71     local count=0
     72     while pgrep -f "gpu-screen-recorder" >/dev/null && [ $count -lt 50 ]; do
     73         sleep 0.1
     74         count=$((count + 1))
     75     done
     76 
     77     if pgrep -f "gpu-screen-recorder" >/dev/null; then
     78         pkill -9 -f "gpu-screen-recorder"
     79         cleanup_webcam
     80         notify-send "Screen recording error" "Recording process had to be force-killed. Video may be corrupted." -u critical -t 5000
     81     else
     82         cleanup_webcam
     83         notify-send "Screen recording saved to $OUTPUT_DIR" -t 2000
     84     fi
     85     toggle_screenrecording_indicator
     86 }
     87 
     88 toggle_screenrecording_indicator() {
     89     pkill -RTMIN+8 waybar
     90 }
     91 
     92 screenrecording_active() {
     93     pgrep -f "gpu-screen-recorder" >/dev/null || pgrep -x slurp >/dev/null || pgrep -f "WebcamOverlay" >/dev/null
     94 }
     95 
     96 if screenrecording_active; then
     97     if pgrep -x slurp >/dev/null; then
     98         pkill -x slurp 2>/dev/null
     99     elif pgrep -f "WebcamOverlay" >/dev/null && ! pgrep -f "gpu-screen-recorder" >/dev/null; then
    100         cleanup_webcam
    101     else
    102         stop_screenrecording
    103     fi
    104 elif [[ "$SCOPE" == "output" ]]; then
    105     [[ "$WEBCAM" == "true" ]] && start_webcam_overlay
    106 
    107     if ! output=$(slurp -o -f "%o"); then
    108         [[ "$WEBCAM" == "true" ]] && cleanup_webcam
    109         exit 1
    110     fi
    111 
    112     if [[ -z "$output" ]]; then
    113         notify-send "Error" "Could not detect monitor" -u critical
    114         [[ "$WEBCAM" == "true" ]] && cleanup_webcam
    115         exit 1
    116     fi
    117 
    118     start_screenrecording "$output"
    119 else
    120     [[ "$WEBCAM" == "true" ]] && start_webcam_overlay
    121 
    122     scale=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .scale')
    123 
    124     if ! region=$(slurp -f "%wx%h+%x+%y"); then
    125         [[ "$WEBCAM" == "true" ]] && cleanup_webcam
    126         exit 1
    127     fi
    128 
    129     if [[ "$region" =~ ^([0-9]+)x([0-9]+)\+([0-9]+)\+([0-9]+)$ ]]; then
    130         w=$(awk "BEGIN {printf \"%.0f\", ${BASH_REMATCH[1]} * $scale}")
    131         h=$(awk "BEGIN {printf \"%.0f\", ${BASH_REMATCH[2]} * $scale}")
    132         x=$(awk "BEGIN {printf \"%.0f\", ${BASH_REMATCH[3]} * $scale}")
    133         y=$(awk "BEGIN {printf \"%.0f\", ${BASH_REMATCH[4]} * $scale}")
    134         scaled_region="${w}x${h}+${x}+${y}"
    135     else
    136         scaled_region="$region"
    137     fi
    138 
    139     start_screenrecording region -region "$scaled_region"
    140 fi