You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							266 lines
						
					
					
						
							5.3 KiB
						
					
					
				
			
		
		
	
	
							266 lines
						
					
					
						
							5.3 KiB
						
					
					
				| #!/bin/sh | |
|  | |
| # Depends: GNU getopt, mpv, socat, streamlink, xclip | |
|  | |
| SOCK="/tmp/umpv-fifo" | |
|  | |
| help() { | |
| 	B=$(tput bold) | |
| 	U=$(tput smul) | |
| 	N=$(tput sgr0) | |
|  | |
| 	cat << EOF | |
| ${B}NAME${N} | |
| 	play - mpv playback functions | |
|  | |
| ${B}SYNOPSIS${N} | |
| 	${B}play${N} [${U}OPTION${N}] [${U}ARGS${N}...] | |
|  | |
| ${B}DESCRIPTION${N} | |
| 	play is a script to manage different mpv viewing bahavior. | |
| 	If no ${U}URLS${N} argument is provided, it is read from the clipboard instead. | |
| 	The queue option starts a mpv window with a playlist, which all videos of | |
| 	subsequent queue calls get added to. | |
|  | |
| ${B}OPTIONS${N} | |
| 	${B}-h${N}, ${B}--help${N} | |
| 		Display usage message and exit. | |
|  | |
| 	${B}-q${N}, ${B}--quality${N} ${U}QUALITY${N} | |
| 		Set the video quality, example: ${U}720p60${N}. | |
|  | |
| 	${B}-f${N}, ${B}--shuffle${N} [${U}URLS${N}...] | |
| 		Shuffle audio playlist (disables video playback). | |
|  | |
| 	${B}-u${N}, ${B}--queue${N} [${U}URLS${N}...] | |
| 		Add multiple videos to the unique mpv's queue. | |
|  | |
| 	${B}-s${N}, ${B}--stream${N} [${U}URLS${N}...] | |
| 		Play video(s) using streamlink. | |
|  | |
| 	${B}-l${N}, ${B}--low-latency${N} | |
| 		Enable twitch low-latency mode in streamlink. | |
| EOF | |
| } | |
|  | |
| # -------------------------------------- | |
|  | |
| qualityFormat() { | |
| 	url="$1" | |
|  | |
| 	# Twitch urls dont support fancy matching | |
| 	if echo "$url" | grep -q "twitch\.tv"; then | |
| 		if [ -z "$quality" ]; then | |
| 			echo "Source" | |
| 		else | |
| 			echo "$quality" | |
| 		fi | |
| 		return | |
| 	fi | |
|  | |
| 	# , separator = download several formats | |
| 	# + separator = merge several formats into a single file | |
| 	# / separator = or | |
| 	if [ -z "$quality" ]; then | |
| 		echo "bestvideo[height<=?1080]+bestaudio/best" | |
| 	else | |
| 		height="$(echo "$quality" | awk -F 'p' '{ print $1 }')" | |
| 		fps="$(echo "$quality" | awk -F 'p' '{ print $2 }')" | |
|  | |
| 		format="bestvideo[height<=?$height]" | |
| 		if [ -n "$fps" ]; then | |
| 			format="${format}[fps<=?$fps]" | |
| 		fi | |
| 		format="$format+bestaudio/best" | |
|  | |
| 		echo "$format" | |
| 	fi | |
| } | |
|  | |
| play() { | |
| 	url="$1" | |
|  | |
| 	notify-send -t 2500 "Loading video: $url" | |
| 	setsid -f mpv --no-terminal \ | |
| 		   --ytdl-format="$(qualityFormat "$url")" \ | |
| 		   --ytdl-raw-options=add-metadata=,external-downloader=aria2c \ | |
| 		   "$url" | |
| } | |
|  | |
| shuffle() { | |
| 	urls="$*" | |
|  | |
| 	mpv --no-video --shuffle \ | |
| 		--ytdl-format='bestaudio[ext=m4a]' \ | |
| 		--ytdl-raw-options=add-metadata=,external-downloader=aria2c \ | |
| 		"$urls" | |
| } | |
|  | |
| queue() { | |
| 	urls="$*" | |
|  | |
| 	options="--no-terminal --force-window --input-ipc-server=$SOCK" | |
|  | |
| 	# Create mpv cache directory | |
| 	dir="$(dirname "$SOCK")" | |
| 	[ ! -d "$dir" ] && mkdir -p "$dir" | |
|  | |
| 	# Delete socket if no umpv is running | |
| 	if ! pgrep -f "mpv $options" > /dev/null; then | |
| 		rm -f "$SOCK" | |
| 	fi | |
|  | |
| 	if [ -S "$SOCK" ]; then | |
| 		notify-send -t 2500 "Added video to queue.." | |
| 		# Add video to named pipe | |
| 		echo "$urls" | awk -v RS=' ' '{ print "raw loadfile "$1" append" }' \ | |
| 			| socat UNIX-CONNECT:"$SOCK" - | |
| 	else | |
| 		# Play video | |
| 		notify-send -t 2500 "Loading video: $urls" | |
| 		# shellcheck disable=2086 | |
| 		setsid -f mpv $options \ | |
| 			   --ytdl-format="$(qualityFormat $urls)" \ | |
| 			   --ytdl-raw-options=add-metadata=,external-downloader=aria2c \ | |
| 			   $urls | |
| 	fi | |
| } | |
|  | |
| stream() { | |
| 	channel="$1" | |
| 	quality="$2" | |
| 	lowLatency="$3" | |
|  | |
| 	if [ -z "$quality" ]; then | |
| 		if ! streamlink --quiet --config /dev/null "$channel"; then | |
| 			return 1 | |
| 		fi | |
|  | |
| 		printf "Select stream quality: " | |
| 		read -r quality | |
| 	fi | |
|  | |
| 	if [ -z "$lowLatency" ]; then | |
| 		arguments="\ | |
| 			--player-args '--force-window'" | |
| 	else | |
| 		arguments="\ | |
| 			--twitch-low-latency \ | |
| 			--player-args '--force-window --cache=yes --demuxer-max-bytes=750k'" | |
| 	fi | |
|  | |
| 	echo "Starting stream $channel @ $quality" | |
| 	command="setsid -f streamlink \ | |
| 		--twitch-disable-hosting \ | |
| 		--twitch-disable-reruns \ | |
| 		--player mpv \ | |
| 		--stream-sorting-excludes '<480p,>=1080p' \ | |
| 		$arguments \ | |
| 		$channel $quality > /dev/null 2>&1" | |
| 	eval "$command" | |
| } | |
|  | |
| # Option parsing | |
| # -------------------------------------- | |
|  | |
| script="$(basename "$0")" | |
| parsed="$(getopt --options "hslquf" \ | |
| 				 --longoptions "help,stream,quality,queue,shuffle" \ | |
| 				 -n "$script" -- "$@" 2>&1)" | |
| result="$?" | |
|  | |
| # Exit if invalid option is provided | |
| if [ "$result" -ne 0 ]; then | |
| 	echo "$parsed" | head -n 1 >&2 | |
| 	echo "Try './$script --help' for more information." >&2 | |
| 	exit 1 | |
| fi | |
|  | |
| eval set -- "$parsed" | |
|  | |
| streamOption=0 | |
| qualityOption=0 | |
| lowLatencyOption=0 | |
| queueOption=0 | |
| shuffleOption=0 | |
| while true; do | |
| 	case "$1" in | |
| 		-h | --help) | |
| 			help | |
| 			exit | |
| 			;; | |
| 		-s | --stream) | |
| 			streamOption=1 | |
| 			shift | |
| 			;; | |
| 		-l | --low-latency) | |
| 			lowLatencyOption=1 | |
| 			shift | |
| 			;; | |
| 		-q | --quality) | |
| 			qualityOption=1 | |
| 			shift | |
| 			;; | |
| 		-u | --queue) | |
| 			queueOption=1 | |
| 			shift | |
| 			;; | |
| 		-f | --shuffle) | |
| 			shuffleOption=1 | |
| 			shift | |
| 			;; | |
| 		--) | |
| 			shift | |
| 			break | |
| 			;; | |
| 		*) | |
| 			break | |
| 			;; | |
| 	esac | |
| done | |
|  | |
| # Target parsing | |
| # -------------------------------------- | |
|  | |
| # Incompatible flags | |
| result=$((streamOption + queueOption + shuffleOption)) | |
| if [ $result -gt 1 ]; then | |
| 	echo "Incompatible flags." >&2 | |
| 	echo "Try './$script --help' for more information." >&2 | |
| 	exit 1; | |
| fi | |
|  | |
| # Get quality | |
| if [ $qualityOption -eq 1 ]; then | |
| 	quality="$1" | |
| 	shift | |
| fi | |
|  | |
| # Set url to clipboard if none provided | |
| clip="$(xclip -selection clipboard -out)" | |
| if [ "$#" -eq 0 ]; then | |
| 	eval set -- "$clip" | |
| fi | |
|  | |
| [ $lowLatencyOption -eq 1 ] && lowLatency="1" | |
|  | |
| # Execute | |
| # -------------------------------------- | |
|  | |
| if [ $streamOption -eq 1 ]; then | |
| 	for url in "$@"; do | |
| 		stream "$url" "$quality" "$lowLatency" | |
| 	done | |
| elif [ $shuffleOption -eq 1 ]; then | |
| 	shuffle "$*" | |
| elif [ $queueOption -eq 1 ]; then | |
| 	queue "$*" | |
| else | |
| 	if [ "$*" = "" ]; then | |
| 		play "$(xclip -o)" | |
| 	else | |
| 		for url in "$@"; do | |
| 			play "$url" | |
| 		done | |
| 	fi | |
| fi
 | |
| 
 |