| 1 | #!/bin/sh |
| 2 | |
| 3 | # Usage: |
| 4 | # `$0`: Ask for recording type via dmenu |
| 5 | # `$0 screencast`: Record both audio and screen |
| 6 | # `$0 video`: Record only screen |
| 7 | # `$0 audio`: Record only audio |
| 8 | # `$0 kill`: Kill existing recording |
| 9 | # |
| 10 | # If there is already a running instance, user will be prompted to end it. |
| 11 | |
| 12 | getdim() { xrandr | grep -oP '(?<=current ).*(?=,)' | tr -d ' ' ;} |
| 13 | |
| 14 | updateicon() { \ |
| 15 | echo "$1" > /tmp/recordingicon |
| 16 | pkill -RTMIN+9 "${STATUSBAR:-dwmblocks}" |
| 17 | } |
| 18 | |
| 19 | killrecording() { |
| 20 | recpid="$(cat /tmp/recordingpid)" |
| 21 | kill -15 "$recpid" |
| 22 | rm -f /tmp/recordingpid |
| 23 | updateicon "" |
| 24 | pkill -RTMIN+9 "${STATUSBAR:-dwmblocks}" |
| 25 | } |
| 26 | |
| 27 | screencast() { \ |
| 28 | ffmpeg -y \ |
| 29 | -f x11grab \ |
| 30 | -framerate 30 \ |
| 31 | -s "$(getdim)" \ |
| 32 | -i "$DISPLAY" \ |
| 33 | -r 24 \ |
| 34 | -use_wallclock_as_timestamps 1 \ |
| 35 | -f alsa -thread_queue_size 1024 -i default \ |
| 36 | -c:v h264 \ |
| 37 | -crf 0 -preset ultrafast -c:a aac \ |
| 38 | "$HOME/screencast-$(date '+%y%m%d-%H%M-%S').mp4" & |
| 39 | echo $! > /tmp/recordingpid |
| 40 | updateicon "⏺️🎙️" |
| 41 | } |
| 42 | |
| 43 | video() { ffmpeg \ |
| 44 | -f x11grab \ |
| 45 | -framerate 30 \ |
| 46 | -s "$(getdim)" \ |
| 47 | -i "$DISPLAY" \ |
| 48 | -c:v libx264 -qp 0 -r 30 \ |
| 49 | "$HOME/video-$(date '+%y%m%d-%H%M-%S').mkv" & |
| 50 | echo $! > /tmp/recordingpid |
| 51 | updateicon "⏺️" |
| 52 | } |
| 53 | |
| 54 | webcamhidef() { ffmpeg \ |
| 55 | -f v4l2 \ |
| 56 | -i /dev/video0 \ |
| 57 | -video_size 1920x1080 \ |
| 58 | "$HOME/webcam-$(date '+%y%m%d-%H%M-%S').mkv" & |
| 59 | echo $! > /tmp/recordingpid |
| 60 | updateicon "🎥" |
| 61 | } |
| 62 | |
| 63 | webcam() { ffmpeg \ |
| 64 | -f v4l2 \ |
| 65 | -i /dev/video0 \ |
| 66 | -video_size 640x480 \ |
| 67 | "$HOME/webcam-$(date '+%y%m%d-%H%M-%S').mkv" & |
| 68 | echo $! > /tmp/recordingpid |
| 69 | updateicon "🎥" |
| 70 | } |
| 71 | |
| 72 | |
| 73 | audio() { \ |
| 74 | ffmpeg \ |
| 75 | -f alsa -i default \ |
| 76 | -c:a flac \ |
| 77 | "$HOME/audio-$(date '+%y%m%d-%H%M-%S').flac" & |
| 78 | echo $! > /tmp/recordingpid |
| 79 | updateicon "🎙️" |
| 80 | } |
| 81 | |
| 82 | askrecording() { \ |
| 83 | choice=$(printf "screencast\\nvideo\\nvideo selected\\naudio\\nwebcam\\nwebcam (hi-def)" | dmenu -i -p "Select recording style:") |
| 84 | case "$choice" in |
| 85 | screencast) screencast;; |
| 86 | audio) audio;; |
| 87 | video) video;; |
| 88 | *selected) videoselected;; |
| 89 | webcam) webcam;; |
| 90 | "webcam (hi-def)") webcamhidef;; |
| 91 | esac |
| 92 | } |
| 93 | |
| 94 | asktoend() { \ |
| 95 | response=$(printf "No\\nYes" | dmenu -i -p "Recording still active. End recording?") && |
| 96 | [ "$response" = "Yes" ] && killrecording |
| 97 | } |
| 98 | |
| 99 | videoselected() |
| 100 | { |
| 101 | slop -f "%x %y %w %h" > /tmp/slop |
| 102 | read -r X Y W H < /tmp/slop |
| 103 | rm /tmp/slop |
| 104 | |
| 105 | ffmpeg \ |
| 106 | -f x11grab \ |
| 107 | -framerate 30 \ |
| 108 | -video_size "$W"x"$H" \ |
| 109 | -i :0.0+"$X,$Y" \ |
| 110 | -c:v libx264 -qp 0 -r 30 \ |
| 111 | "$HOME/box-$(date '+%y%m%d-%H%M-%S').mkv" & |
| 112 | echo $! > /tmp/recordingpid |
| 113 | updateicon "⏺️" |
| 114 | } |
| 115 | |
| 116 | case "$1" in |
| 117 | screencast) screencast;; |
| 118 | audio) audio;; |
| 119 | video) video;; |
| 120 | *selected) videoselected;; |
| 121 | kill) killrecording;; |
| 122 | *) ([ -f /tmp/recordingpid ] && asktoend && exit) || askrecording;; |
| 123 | esac |