# 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