# creator -- content creation aliases and functions (recording, streaming, editing) # Sources: BreadOnPenguins, LukeSmithxyz, mochou-p, NapoleonWils0n, community # ============================================================================ # RECORDING # ============================================================================ alias recstatus='cat /tmp/recordingicon 2>/dev/null || echo "not recording"' # ============================================================================ # OBS CLI (requires obs-cli / obs-websocket) # ============================================================================ alias obs-stream-start='obs-cli stream start' alias obs-stream-stop='obs-cli stream stop' alias obs-stream-toggle='obs-cli stream toggle' alias obs-stream-status='obs-cli stream status' alias obs-rec-start='obs-cli recording start' alias obs-rec-stop='obs-cli recording stop' alias obs-rec-toggle='obs-cli recording toggle' alias obs-rec-status='obs-cli recording status' # ============================================================================ # YT-DLP ARCHIVING # ============================================================================ alias ytbest='yt-dlp -f "bestvideo+bestaudio" --merge-output-format mkv' alias ytarchive='yt-dlp -f "bestvideo+bestaudio" --merge-output-format mkv --embed-subs --embed-thumbnail --embed-metadata --embed-chapters --write-info-json' alias ytsubs='yt-dlp --write-sub --write-auto-sub --sub-lang en --convert-subs srt' # ============================================================================ # GIF / SOCIAL # ============================================================================ alias togif='f() { palette="/tmp/palette.png"; ffmpeg -v warning -i "$1" -vf "fps=7,scale=480:-1:flags=lanczos,palettegen" -y "$palette" && ffmpeg -v warning -i "$1" -i "$palette" -lavfi "fps=7,scale=480:-1:flags=lanczos [x]; [x][1:v] paletteuse" -y "${2:-output.gif}"; }; f' # ============================================================================ # TWITCH # ============================================================================ alias twitchdl='twitch-dl download' alias twitchclips='twitch-dl clips' alias twitchvods='twitch-dl videos' # ============================================================================ # AUDIO QUICK # ============================================================================ alias normalize='ffmpeg-normalize' # ============================================================================ # FUNCTIONS # ============================================================================ # toggle screen+audio recording with statusbar indicator record_toggle() { if [ -f /tmp/recpid ]; then kill -15 "$(cat /tmp/recpid)" "$(cat /tmp/audpid 2>/dev/null)" 2>/dev/null rm -f /tmp/recpid /tmp/audpid echo "" > /tmp/recordingicon pkill -RTMIN+3 dwmblocks 2>/dev/null notify-send "Recording ended" 2>/dev/null else res=$(xdpyinfo 2>/dev/null | awk '/dimensions/{print $2}') [ -z "$res" ] && res="1920x1080" ffmpeg -s "$res" -f x11grab -r 30 -i :0.0 \ -c:v h264 -qp 0 "$HOME/video_$(date '+%Y%m%d_%H%M%S').mkv" & echo $! > /tmp/recpid ffmpeg -f alsa -i default -af "afftdn=nf=-75" \ "$HOME/audio_$(date '+%Y%m%d_%H%M%S').wav" & echo $! > /tmp/audpid echo "REC" > /tmp/recordingicon pkill -RTMIN+3 dwmblocks 2>/dev/null notify-send "Recording started" 2>/dev/null fi } # dmenu-driven recording mode selector record_menu() { getdim() { xdpyinfo | awk '/dimensions/{print $2}'; } choice=$(printf "screencast\nvideo\nvideo selected\naudio\nwebcam" \ | dmenu -i -p "Record:") case "$choice" in screencast) ffmpeg -y -f x11grab -framerate 30 -s "$(getdim)" -i "$DISPLAY" \ -r 24 -f alsa -thread_queue_size 1024 -i default \ -c:v h264 -crf 0 -preset ultrafast -c:a aac \ "$HOME/screencast-$(date '+%y%m%d-%H%M-%S').mp4" & echo $! > /tmp/recordingpid ;; video) ffmpeg -f x11grab -framerate 30 -s "$(getdim)" -i "$DISPLAY" \ -c:v libx264 -qp 0 -r 30 \ "$HOME/video-$(date '+%y%m%d-%H%M-%S').mkv" & echo $! > /tmp/recordingpid ;; "video selected") slop -f "%x %y %w %h" > /tmp/slop read X Y W H < /tmp/slop ffmpeg -f x11grab -framerate 30 -video_size "${W}x${H}" -i :0.0+"$X,$Y" \ -c:v libx264 -qp 0 -r 30 "$HOME/box-$(date '+%y%m%d-%H%M-%S').mkv" & echo $! > /tmp/recordingpid ;; audio) ffmpeg -f alsa -i default -c:a flac \ "$HOME/audio-$(date '+%y%m%d-%H%M-%S').flac" & echo $! > /tmp/recordingpid ;; webcam) ffmpeg -f v4l2 -i /dev/video0 -video_size 640x480 \ "$HOME/webcam-$(date '+%y%m%d-%H%M-%S').mkv" & echo $! > /tmp/recordingpid ;; esac } # stop any active recording record_stop() { [ -f /tmp/recordingpid ] && kill -15 "$(cat /tmp/recordingpid)" && rm /tmp/recordingpid [ -f /tmp/recpid ] && kill -15 "$(cat /tmp/recpid)" && rm /tmp/recpid /tmp/audpid 2>/dev/null echo "" > /tmp/recordingicon pkill -RTMIN+3 dwmblocks 2>/dev/null } # trim video by start time and duration trimvid() { input="$1"; ss="$2"; dur="$3"; output="${4:-${input%.*}_trimmed.${input##*.}}" [ -z "$dur" ] && { echo "Usage: trimvid [output]"; return 1; } ffmpeg -ss "$ss" -t "$dur" -i "$input" -c copy "$output" } # concatenate videos from a list concatvids() { listfile="$1"; output="${2:-concat_output.mkv}" [ -z "$listfile" ] && { echo "Usage: concatvids [output]"; return 1; } ffmpeg -f concat -safe 0 -i "$listfile" -c copy "$output" } # picture-in-picture overlay pip_overlay() { bg="$1"; fg="$2"; output="${3:-pip_output.mkv}"; pos="${4:-br}"; width="${5:-480}" [ -z "$fg" ] && { echo "Usage: pip_overlay [output] [tl|tr|bl|br] [width]"; return 1; } case "$pos" in tl) x="10"; y="10" ;; tr) x="main_w-overlay_w-10"; y="10" ;; bl) x="10"; y="main_h-overlay_h-10" ;; br) x="main_w-overlay_w-10"; y="main_h-overlay_h-10" ;; esac ffmpeg -i "$bg" -i "$fg" -filter_complex \ "[1:v]scale=$width:-1[pip];[0:v][pip]overlay=$x:$y" \ -c:a copy "$output" } # fade video in/out fadevid() { input="$1"; duration="${2:-0.5}"; output="${3:-${input%.*}_faded.${input##*.}}" [ -z "$input" ] && { echo "Usage: fadevid [duration] [output]"; return 1; } total=$(ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 "$input" | cut -d. -f1) fadeout=$((total - ${duration%.*})) ffmpeg -i "$input" -vf "fade=t=in:st=0:d=$duration,fade=t=out:st=$fadeout:d=$duration" \ -af "afade=t=in:st=0:d=$duration,afade=t=out:st=$fadeout:d=$duration" "$output" } # split video for YouTube 15-min limit split_for_yt() { input="$1"; chunk="${2:-900}" [ -z "$input" ] && { echo "Usage: split_for_yt