#!/bin/bash # BTV 1.11 -- BTA 2025 -- LostGeek.NET # MPV Wrapper for minimal CLI-based video playback over SSH AUDIO_DEV="hdmi:CARD=vc4hdmi0,DEV=0" IPC_SOCKET="/tmp/mpvsocket" MPV_OPTS="--vo=drm --ao=alsa --audio-device=$AUDIO_DEV --no-terminal --fs --input-ipc-server=$IPC_SOCKET" LOGFILE="$HOME/mpv-playback.log" PID_FILE="$HOME/mpv.pid" # Kill existing mpv process kill_existing_mpv() { if pgrep -x mpv > /dev/null; then echo "Stopping existing mpv process..." pkill -9 mpv sleep 1 rm -f "$PID_FILE" echo "mpv stopped." else echo "No mpv process running to stop." fi } # Format seconds to HH:MM:SS format_time() { local secs=$1 printf "%02d:%02d:%02d" $((secs / 3600)) $(( (secs % 3600) / 60 )) $((secs % 60)) } print_playback_info() { if [ ! -S "$IPC_SOCKET" ]; then echo "No IPC socket found. Is MPV running with --input-ipc-server?" return fi local time_pos duration remaining time_pos=$(echo '{ "command": ["get_property", "time-pos"] }' | socat - "$IPC_SOCKET" 2>/dev/null | jq -r '.data') duration=$(echo '{ "command": ["get_property", "duration"] }' | socat - "$IPC_SOCKET" 2>/dev/null | jq -r '.data') if [[ -z "$time_pos" || "$time_pos" == "null" || -z "$duration" || "$duration" == "null" ]]; then echo "Playback info not available yet." return fi # Now we know both are numeric remaining=$(echo "$duration - $time_pos" | bc 2>/dev/null) echo "Elapsed: $(format_time ${time_pos%.*}) / Remaining: $(format_time ${remaining%.*})" } # Check if mpv is running check_status() { if pgrep -x mpv > /dev/null; then echo "mpv is running." print_playback_info else echo "mpv is not running." fi } # Pause mpv playback pause_playback() { local pid pid=$(cat "$PID_FILE") if [[ -z "$pid" || ! -d "/proc/$pid" ]]; then echo "No active mpv process to pause." exit 1 fi echo "Getting playback info before pausing (PID: $pid)..." print_playback_info echo "Pausing playback..." kill -SIGSTOP "$pid" echo "Playback paused." } # Resume mpv playback resume_playback() { local pid pid=$(cat "$PID_FILE") if [[ -z "$pid" || ! -d "/proc/$pid" ]]; then echo "No active mpv process to resume." exit 1 fi echo "Attempting to resume playback (PID: $pid)..." kill -SIGCONT "$pid" echo "Playback resumed." print_playback_info } # Play a file (detached) play_file() { local file="$1" if [[ ! -f "$file" ]]; then echo "File not found: $file" exit 1 fi echo "Starting playback in background: $file" nohup mpv $MPV_OPTS "$file" > "$LOGFILE" 2>&1 & pid=$! echo $pid > "$PID_FILE" disown echo "Playback started. Log: $LOGFILE" } # Show video file selection menu select_and_play() { echo "Listing video files in: $PWD" mapfile -t files < <(ls -1v | grep -Ei '\.(mp4|mkv|avi|mov|flv|webm)$') if [ ${#files[@]} -eq 0 ]; then echo "No video files found." exit 1 fi echo for i in "${!files[@]}"; do printf "%2d: %s\n" $((i+1)) "${files[$i]}" done echo read -p "Which video would you like to play? [1-${#files[@]}]: " choice if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le ${#files[@]} ]; then play_file "${files[$((choice-1))]}" else echo "Invalid selection." exit 1 fi } # Handle command-line args case "$1" in --stop|stop) kill_existing_mpv ;; --pause|pause) pause_playback ;; --resume|resume) resume_playback ;; --status|status) check_status ;; --play|play) shift if [ -z "$1" ]; then echo "Usage: $0 --play " exit 1 fi play_file "$1" ;; *) if [ $# -eq 0 ]; then # Toggle pause/resume if already running if [ -f "$PID_FILE" ] && pgrep -x mpv > /dev/null; then if ps -p $(cat "$PID_FILE") -o stat= | grep -q 'T'; then resume_playback else pause_playback fi else # No playback running, show video selection select_and_play fi else echo "Unknown option: $1" echo "Usage:" echo " $0 # interactive file chooser" echo " $0 --play # play file in background" echo " $0 --pause # pause playback" echo " $0 --resume # resume playback" echo " $0 --stop # stop and kill mpv playback" echo " $0 --status # check if mpv is running" exit 1 fi ;; esac