Last active
October 13, 2024 17:23
-
-
Save patillacode/98ad99410fb3db8cdb88a382bbb4dee7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
################################################################################ | |
# cap - capture your screen | |
# | |
# This script allows you to capture your screen on Linux or macOS systems using | |
# the appropriate tools available on each platform. On Linux, it uses 'slop' | |
# and 'ffmpeg', while on macOS, it utilizes 'screencapture'. The script prompts | |
# you to select a desktop area for recording and saves the recording as an MP4/MOV | |
# file with customizable video quality. | |
# | |
# Usage: cap [options] <output.mp4> | |
# | |
# Options: | |
# -v, --version Display script version | |
# -h, --help Display this help message | |
# -q, --quality <num> (only for Linux) Specify the video quality in the range | |
# 0-51 (best/worst) (default: 28) | |
# | |
# Requirements: | |
# - For Linux: slop, ffmpeg | |
# - For macOS: screencapture | |
################################################################################ | |
# Function to display script version | |
show_version() { | |
echo "cap - capture your screen - 0.0.1" | |
} | |
# Function to display script usage | |
show_usage() { | |
echo "Usage: $0 [options] <output.mp4>" | |
echo "Options:" | |
echo " -v, --version Display script version" | |
echo " -h, --help Display this help message" | |
echo " -q, --quality <num> (only for Linux) Specify the video quality in range 0–51(best/worst)(default: 28)" | |
} | |
# Function to check if the required command exists | |
check_command() { | |
if ! command -v $1 &> /dev/null | |
then | |
echo "$1 command not found. Please install $1." | |
exit 1 | |
fi | |
} | |
# Function to check if an output filename was provided | |
check_filename() { | |
if [ -z "$1" ]; then | |
echo "Usage: $0 [options] <output.mp4>" | |
exit 1 | |
fi | |
} | |
run_checks() { | |
# Check the operating system | |
if [[ "$OSTYPE" == "linux-gnu"* ]]; then | |
# Check if an output filename was provided | |
check_filename "$1" | |
# Set the output file name | |
filename="$1" | |
system="linux" | |
echo "Identified a Linux system... using 'slop' and 'ffmpeg'" | |
check_command "ffmpeg" | |
check_command "slop" | |
elif [[ "$OSTYPE" == "darwin"* ]]; then | |
system="macos" | |
commandtool="screencapture" | |
echo "Identified a macOS system... using 'screencapture'" | |
check_command "screencapture" | |
else | |
echo "Unsupported operating system." | |
exit 1 | |
fi | |
# Process command line options | |
handle_options "$@" | |
} | |
# Function to start the recording | |
start_recording() { | |
if [[ $system == "linux" ]]; then | |
# Set log level to quiet (suppress console output) | |
# Input format: X11 screen capture | |
# Set input video size (width x height) | |
# Input device: X11 display with specified position (x, y) | |
# Input audio device: ALSA pulse audio | |
# Video codec: libx264 (H.264) | |
# Constant Rate Factor: video quality setting (lower value = higher quality) | |
# Set encoding preset to ultrafast for fast encoding | |
# Optimize for low latency streaming | |
# Set pixel format to yuv420p (YUV planar 4:2:0) | |
# Output format: MP4 | |
# Output file name | |
echo "Recording started. Press 'q' to stop recording." | |
ffmpeg -loglevel quiet \ | |
-f x11grab \ | |
-s ${width}x${height} \ | |
-i ${DISPLAY}+$x,$y \ | |
-f alsa -i pulse \ | |
-c:v libx264 \ | |
-crf $quality \ | |
-preset ultrafast \ | |
-tune zerolatency \ | |
-pix_fmt yuv420p \ | |
-f mp4 \ | |
$filename | |
else | |
screencapture -vksU - | |
fi | |
} | |
# Function to handle command line options | |
handle_options() { | |
while [[ $# -gt 0 ]]; do | |
case "$1" in | |
-v|--version) | |
show_version | |
exit 0 | |
;; | |
-h|--help) | |
show_usage | |
exit 0 | |
;; | |
-q|--quality) | |
shift | |
quality="$1" | |
echo "Quality set to $quality" | |
;; | |
*) | |
break | |
;; | |
esac | |
shift | |
done | |
} | |
# Default quality value | |
quality=28 | |
run_checks "$@" | |
if [[ "$system" == "linux" ]]; then | |
# Get the selection coordinates | |
coords=$(slop -f "%x %y %w %h") | |
# Extract the x, y, width, and height values from the coordinates | |
x=$(echo $coords | awk '{print $1}') | |
y=$(echo $coords | awk '{print $2}') | |
width=$(echo $coords | awk '{print $3}') | |
height=$(echo $coords | awk '{print $4}') | |
# Ensure that the height and width are divisible by 2 | |
width=$((width / 2 * 2)) | |
height=$((height / 2 * 2)) | |
# Start the recording | |
start_recording | |
# Display message to user | |
echo "Recording stopped." | |
elif [[ "$system" == "macos" ]]; then | |
start_recording | |
echo "Recording can be found in your desktop." | |
fi | |
It seems like using libx264rgb
instead of libx264
as suggested here increases fps a lot, but the result still is kinda choppy:
2024-10-13_11-27-44.webm.mov
Maybe using hardware encoding is the way to go.
On my AMD GPU machine using h264_amf
insgtead of libx264
results in smooth video (as long as the resolution is not too big):
2024-10-13_11-30-59.webm
I'm glad you found this little script interesting/useful.
I am not an expert when it comes to video configuration tbh, but, as you have tried, it would be a matter of trying maybe different libs and/or video codecs.
FFMPEG is a versatile tool but it does come with a steep learning curve but I am sure you can tweak the script to find the expected quality.
Sorry I couldn't be of more help!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I like this Idea a lot, however the framerate of the resulting video is really bad. The file claims to be 60fps. but the resulting video is extremely choppy, more like 5 fps:
2024-10-13_11-11-01.webm.mov
I tried playing around with the
-framerate 30
option of ffmpeg, but the result is still choppy.Any idea how to fix that?