#!/usr/bin/env bash # # Copyright (C) 2023 Skylar Widulski # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . # RUNTIME="${XDG_RUNTIME_DIR:-/run}/wf-shadow" MONITOR=1 AUDIO_DEV="" VIDEO_DEV="" VERBOSE="" trap 'kill $(jobs -p) 2>/dev/null' EXIT trap 'exit' INT set -m if [ ! -d "$RUNTIME" ]; then mkdir -p "$RUNTIME" 2>/dev/null fi if [ ! -d /tmp/wf-shadow ]; then mkdir -p /tmp/wf-shadow 2>/dev/null fi if [ ! -d "$HOME"/Videos/wf-shadow ]; then mkdir -p "$HOME"/Videos/wf-shadow 2>/dev/null fi if ! command -v wf-recorder &>/dev/null; then printf "Need wf-recorder\n" exit 1 fi if ! command -v wofi &>/dev/null; then printf "Need wofi\n" exit 1 fi print_help() { cat << EOF wf-shadow: A Wayland shadow recorder using wf-recorder and wofi USAGE: wf-shadow OPTION [OPTIONS...] OPTIONS: -s MONITOR, --start MONITOR Start a wf-shadow instance with display number MONITOR -r MONITOR, --record MONITOR Record the last few moments of video using a wofi menu -e MONITOR, --end MONITOR End wf-shadow instance with display number MONITOR -a DEVICE, --audio DEVICE Use DEVICE for audio recording. Passed to wf-recorder -a -V DEVICE, --video DEVICE Use DEVICE for video encoding. Passed to wf-recorder -d -v, --verbose Verbose output -h, --help Show this menu VARIABLES: \$WF_SHADOW_SAVE The directory to save clips in \$WF_SHADOW_FORMAT The date format to save clips in EOF exit $1 } record() { local FILE="${WF_SHADOW_SAVE:-"$HOME"/Videos/wf-shadow/}""$(date +"${WF_SHADOW_FORMAT:-%Y%m%d_%H:%M:%S}")__$2".mp4 if [ $VERBOSE ]; then if ffmpeg -nostdin -y -sseof -"$2" -i "$1" "$FILE" &>/dev/null; then notify-send "Clip saved" "$2 second clip saved to $FILE" else notify-send "Error saving clip" "Start a new session with --verbose to see ffmpeg output" fi else if ffmpeg -nostdin -y -sseof -"$2" -i "$1" "$FILE"; then notify-send "Clip saved" "$2 second clip saved to $FILE" else notify-send "Error saving clip" "Start a new session with --verbose to see ffmpeg output" fi fi } start() { local WOFI_STRING="5 seconds\n10 seconds\n15 seconds\n30 seconds\n1 minute\n5 minutes\n10 minutes\nCancel\n" while true; do for i in /tmp/wf-shadow/tmp{00..10}.mp4; do touch "$i" if [ $VERBOSE ]; then wf-recorder ${VIDEO_DEV:+-d "$VIDEO_DEV"} -a $AUDIO_DEV -f "$i" <<< y$'\n'$MONITOR & else wf-recorder ${VIDEO_DEV:+-d "$VIDEO_DEV"} -a $AUDIO_DEV -f "$i" <<< y$'\n'$MONITOR &>/dev/null & fi printf "%s" "$!" > "$RUNTIME"/"$MONITOR".pid fg || exit case "$(if [ $VERBOSE ]; then printf "$WOFI_STRING" | wofi --dmenu -i -H 500 -W 250 -x 0 -y 0; else printf "$WOFI_STRING" | wofi --dmenu -i -H 500 -W 250 -x 0 -y 0 &> /dev/null; fi)" in '5 seconds') record "$i" 5 ;; '10 seconds') record "$i" 10 ;; '15 seconds') record "$i" 15 ;; '30 seconds') record "$i" 30 ;; '1 minute') record "$i" 60 ;; '5 minutes') record "$i" 300 ;; '10 minutes') record "$I" 600 ;; *) ;; esac & done done } until [ -z "$1" ]; do case "$1" in '-h' | '--help') print_help ;; '-e' | '--end') END=1 MONITOR="$2" shift 2 ;; '-r' | '--record') RECORD=1 MONITOR="$2" shift 2 ;; '-s' | '--start') START=1 MONITOR="$2" shift 2 ;; '-a' | '--audio') AUDIO_DEV="$2" shift 2 ;; '-V' | '--video') VIDEO_DEV="$2" shift 2 ;; '-v' | '--verbose') VERBOSE="1" shift 1 ;; *) print_help ;; esac done if [ "$START" == 1 ]; then if [ "$MONITOR" ]; then if [ ! -e "$RUNTIME"/"$MONITOR"_host.pid ]; then printf "%s" "$$" > "$RUNTIME"/"$MONITOR"_host.pid start else printf "A wf-shadow instance is already running on display %d\n" "$MONITOR" fi else print_help 1 fi fi if [ "$RECORD" == 1 ]; then if [ "$MONITOR" ]; then kill -2 "$(<"$RUNTIME"/"$MONITOR".pid)" else print_help 1 fi fi if [ "$END" == 1 ]; then if [ "$MONITOR" ]; then kill "$(<"$RUNTIME"/"$MONITOR"_host.pid)" && rm -f "$RUNTIME"/"$MONITOR"_host.pid else print_help 1 fi fi