#!/usr/bin/env bash # avt: ali's (h264) vid tool # https://gitlab.com/alifurkany/snippets/-/tree/main/shell/bash/avt findmonitor() { pactl list sinks | perl -e ' my $in = ""; while (<>) { $in .= $_; } my @sinks = split("\n\n", $in); foreach (@sinks) { if (/State: RUNNING/) { /Monitor Source: ([^\n]*)/; print $1 . "\n"; exit; } } ' return $? } # shellcheck disable=SC1091 [ -e "$HOME/.avtrc" ] && . "$HOME/.avtrc" # shellcheck disable=SC2034 # DEBUG variable not in use yet [[ ${avt_debug+x} == "x" ]] && set -x && DEBUG=1 print_help() { cat < [outfile] Environment variables: comp_crf: set crf, this should be greater than or equals to rec_crf (default: ${rec_crf:-10}) comp_ac: set audio codec (default: libopus) comp_ba: set audio bitrate (default: 320k) comp_ar: set audio samplerate, this should be less than or equals to rec_ar (default: ${rec_ar:-96000}) $0 nvid / normalize Normalize video & audio for backwards compatibility and lower file size Usage: $0 nvid [outfile] Environment variables: nvid_preset: set preset (default: veryslow) nvid_vrate: replace -crf options nvid_crf: set crf value (default: 19) nvid_rgb: use libx264rgb [set to enable] nvid_pixfmt: set pixel format (default: yuv420p) nvid_profile: set profile (default: high) nvid_ac: set audio codec (default: libopus) nvid_ba: set audio bitrate (default: 160k) nvid_ar: set audio samplerate (default: 48000) avt will try to source ~/.avtrc if it exists. You have access to the findmonitor function in there. EOF } record() { # shellcheck disable=SC2206 devices=(${rec_adev-"$(findmonitor)" "default"}) # shellcheck disable=SC2206 # remove empty elements from array devices=(${devices[@]}) pulse_inputs="" audio_maps="" audio_filter="" i=0 for device in "${devices[@]}"; do i=$(("$i" + 1)) pulse_inputs="$pulse_inputs -f pulse -i $device" audio_maps="$audio_maps -map $i:a" audio_filter="$audio_filter""[$i]" done if [[ "$i" -gt 1 ]]; then audio_filter="$audio_filter amix=inputs=$i [merged]" else an= echo "Audio recording disabled" fi OUTPUTFILE="${1:-$HOME/Desktop/$(date +%F_%H-%M-%S).mkv}" echo "Saving to $OUTPUTFILE" # shellcheck disable=SC2086 ffmpeg -y -thread_queue_size 64 \ -f x11grab -r "${rec_fps:-60}" -s "${rec_res:-1920x1080}" -i "${rec_display:-$DISPLAY}" \ ${an-$pulse_inputs} ${an+-an} \ ${an--filter_complex "$audio_filter"} \ ${an--c:a pcm_s16le -ar "${rec_ar:-96000}"} \ -c:v libx264rgb -profile:v high444 -preset "${rec_preset:-ultrafast}" ${rec_vrate:--crf "${rec_crf:-10}"} -tune zerolatency -r ${rec_fps:-60} \ -map 0:v $audio_maps ${an--map '[merged]:a'} \ "$OUTPUTFILE" EXITCODE=$? if { [[ "$EXITCODE" == 0 ]] || [[ "$EXITCODE" == 255 ]]; } && [[ "${rec_compress+x}" == "x" ]]; then compress "$OUTPUTFILE" return $? else return $EXITCODE fi } compress() { OUTPUTFILE="${2:-$1_comp.mp4}" echo "Saving to $OUTPUTFILE" ffmpeg -y -thread_queue_size 64 \ -i "$1" \ -c:v libx264rgb -pix_fmt rgb24 -profile:v high444 -crf "${comp_crf:-${rec_crf:-10}}" -preset veryslow \ -c:a "${comp_ac:-libopus}" -b:a "${comp_ba:-320k}" -ar "${comp_ar:-${rec_ar:-96000}}" \ -map 0 \ "$OUTPUTFILE" return $? } normalize() { OUTPUTFILE="${2:-$1_nvid.mp4}" echo "Saving to $OUTPUTFILE" # shellcheck disable=SC2086 ffmpeg -y \ -i "$1" \ -c:v libx264${nvid_rgb+rgb} -preset "${nvid_preset:-veryslow}" ${nvid_vrate:--crf "${nvid_crf:-19}"} \ -pix_fmt "${nvid_pixfmt:-yuv420p}" -profile:v "${nvid_profile:-high}" \ -c:a "${nvid_ac:-libopus}" -b:a "${nvid_ba:-160k}" -ar "${nvid_ar:-48000}" \ -map 0 \ "$OUTPUTFILE" return $? } case "$1" in rec | record) # shellcheck disable=SC2068 record ${@:2} ;; comp | compress) # shellcheck disable=SC2068 compress ${@:2} ;; nvid | normalize) # shellcheck disable=SC2068 normalize ${@:2} ;; help) print_help ;; *) echo "$0: Error: No command specified. See \`$0 help\` for more details." false ;; esac exit $?