123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- #!/bin/bash
- shopt -s extglob
- #~ echo "$@" > /tmp/mpv-clip.log # ytfzf url_handler_opts='assdadasdasda' # doesn't work
- usage() {
- if [[ "$@" != "" ]]; then
- notify "$@" "Help text in terminal: $x11name -h"
- fi
- echo "
- Play URLs with mpv/youtube-dl/yt-dlp:
- mpv-clip [options] URL
- + copy URL back to clipboard or primary selection, formatted with media title.
- Options:
- -a Play only audio, but open a small controllable window with elapsed/total
- time, and don't disable the screensaver.
- -p Advance in playlist - does not seem to work with youtube currently.
- Does work with e.g. bandcamp.
- -Y str Options to add to mpv --ytdl-raw-options, after a comma. No quality
- control! See 'man mpv' for details.
- -y str Alternate domain that replaces youtube, e.g. \"invidious.snopyta.org\".
- Testing the domain requires 'ping'.
- -s str Override list of subtitle languages to embed. The default is to use
- your locale + English (2 letter ISO 639-1 codes): \"${slang}\". Pass empty
- string \"\" for ALL subtitles, which can be a lot for e.g. youtube.
- -c str How to copy URL+title back to the clipboard - this string must contain
- exactly two letters:
- 1. c|p|b for clipboard, primary selection, or both
- 2. b|m|t for BBCode, markdown or plain text
- Default: 'cb'.
- -t int Network timeout in seconds. With '-y', this is applied twice
- Default: $timeout
- -n Send desktop notifications.
- -i str Path to icon for notifications.
- Default: ${icon/$HOME/\~}
- -E str Comma separated list of variables and their values. This option exists
- to read ytfzf's values passed to URL handlers, namely \$video_pref,
- \$is_detach and \$is_audio_only
- -h This text.
- "
- exit 1
- }
- notify() {
- ((notify>0)) && notify-send -i $icon -- "$@" || \
- echo "$@"
- }
- clipboard() {
- [[ "$clipboard" == "" ]] && return
- # variables URL and title must be defined
- case $markup in
- b) out="[url=${URL}]${title}[/url]"
- ;;
- m) out="[${title}](${URL})"
- ;;
- t) out="$title
- $URL"
- ;;
- esac
- case $clipboard in
- c) echo -n "$out" | xsel -b
- ;;
- p) echo -n "$out" | xsel -p
- ;;
- b) echo -n "$out" | xsel -b
- echo -n "$out" | xsel -p
- ;;
- esac
- }
- x11name="mpv-clip" # xprop class name to be used by xdotool and optionally window manager
- icon="/usr/share/icons/Papirus/48x48/apps/multimedia-video-player.svg"
- bbcode=0 # fill clipboard with BBcode instead of plain text
- notify=0
- ytmirror=""
- timeout=5 # network timeout in seconds
- ytdlrawopts='write-info-json='
- clipboard='c'
- cbtext="clipboard"
- markup='t'
- for dep in mpv; do
- type "$dep" >/dev/null || usage
- done
- slang="${LANG%%_*}"
- slang="${slang,,}";
- [[ "$slang" == en ]] || slang="${slang},en"
- # Just to initialize the array...
- #~ opts=( --force-window=yes --ytdl=yes --ytdl-format=ytdl --script-opts=ytdl_hook-try_ytdl_first=yes --script-opts=ytdl_hook-all_formats=yes --script-opts=ytdl_hook-thumbnails=best --script-opts=ytdl_hook-use_manifests=yes ) # mpv options for all use cases
- opts=( --force-window=yes --ytdl=yes --ytdl-format=ytdl --script-opts=ytdl_hook-try_ytdl_first=yes ) # mpv options for all use cases
- while getopts apY:y:s:c:t:i:hnE: opt; do
- case $opt in
- a) geometry="33%x30+0+0"
- opts=( ${opts[@]} --vid=no --sub=no
- --osd-scale-by-window=no --no-osd-bar --no-osc
- --osd-msg1=\${time-pos}/\${duration}
- --osd-font-size=28 --osd-font=monospace --background=.1/.1/.1
- --osd-color=.9/.9/.9 --osd-border-size=0
- --osd-margin-y=0 --osd-margin-x=5 --no-stop-screensaver )
- x11name="${x11name}-audioonly"
- ;;
- p) opts=( ${opts[@]} --ytdl-raw-options=ignore-errors=,yes-playlist= ) # as of 2020-10-19, this does not seem to work at all with youtube (or invidious mirrors)
- x11name="${x11name}-playlist"
- ;;
- Y)
- ytdlrawopts=",$OPTARG"
- ;;
- y) ytmirror="$OPTARG" # will use "$ytmirror" instead of "www.youtube.com" or "youtu.be"
- for dep in host ping; do type $dep >/dev/null || usage; done
- ;;
- s) slang="$OPTARG" # comma separated list of subtitle languages - pass empty string '' or "" to get ALL subtitles
- ;;
- c) (( "${#OPTARG}" != 2 )) && usage "Invalid argument -$opt $OPTARG"
- clipboard="${OPTARG:0:1}"
- markup="${OPTARG:1:1}"
- [[ "$clipboard" =~ ^(c|p|b)$ ]] && [[ "$markup" =~ ^(b|m|t)$ ]] || usage "Invalid argument -$opt $OPTARG"
- type xsel >/dev/null || usage
- case $clipboard in
- c) cbtext="clipboard" ;;
- p) cbtext="primary selection" ;;
- b) cbtext="clipboard and primary selection" ;;
- esac
- ;;
- t) timeout="$OPTARG"
- [[ "$OPTARG" =~ ^[1-9][0-9]*$ ]] || usage "-$opt: Invalid number: $OPTARG (must be a positive integer)"
- ;;
- i) icon="$OPTARG"
- [ -r "$OPTARG" ] || usage "-$opt: Cannot read $OPTARG"
- ;;
- n) notify=1
- ;;
- E)
- echo "$OPTARG" >> /tmp/mpv-clip.log
- ;;
- h|*) usage
- ;;
- esac
- done
- shift $((OPTIND-1))
- cbtext="(copied URL+title to $cbtext)"
- # first things first...
- URL="$1"
- # remove leading/trailing whitespace:
- URL="${URL#[[:space:]]*}"
- URL="${URL%[[:space:]]*}"
- # replace the rest with %20 (urlencode for dummies)
- URL="${URL//[[:space:]]/%20}"
- # check if it's actually an http URL
- [[ "$URL" =~ ^(https?|ftp|file)://* ]] || URL="https://$URL" # try to fix it
- [[ "$URL" == ?*\.?* ]] || usage "$URL is not a valid URL" # must contain at least one dot
- # silently drop notifications if this is not available
- type notify-send >/dev/null 2>&1 || [[ "$notify" == 0 ]]
- if [[ "$ytmirror" != "" ]]; then
- ytdomains=( www.youtube.com youtube.com m.youtube.com youtu.be )
- for domain in "${ytdomains[@]}"; do
- if [[ "$URL" =~ ^(https?)://$domain/* ]]; then
- if ping -c1 -n -w"$timeout" "$ytmirror" >/dev/null; then
- URL="${URL/$domain/$ytmirror}" && break
- else
- ytmirror=''
- fi
- break
- fi
- done
- fi
- # introducing raw options passed to youtube-dl
- if [[ "$x11name" == *"-audioonly" ]]; then
- ytdlrawopts="${ytdlrawopts},format=bestaudio"
- fi
- #~ ytdlrawopts="${ytdlrawopts},socket-timeout=$timeout"
- [[ "$slang" == "" ]] || ytdlrawopts="${ytdlrawopts},sub-lang=\"$slang\""
- # for indentifying windows (and notifications)
- x11name="$x11name-$(printf '%(%H:%M:%S)T')"
- # Building the command line
- opts=( ${opts[@]}
- --network-timeout=$timeout
- --ytdl-raw-options="${ytdlrawopts#,}"
- --x11-name="$x11name"
- --quiet
- --no-msg-color
- --no-input-terminal --term-playing-msg='media-title: ${media-title}'
- --no-resume-playback
- --watch-later-directory=/dev/null
- )
- ((notify>1)) && notify "Trying: $URL" "$x11name"
- echo "Trying: $URL"
- coproc mpv "${opts[@]}" "$URL"
- error=0
- while read -r -u "${COPROC[0]}" line; do
- echo "$line"
- if [[ "$line" == *"media-title: "* ]]; then
- title="${line#*media-title: }"
- notify "$title" "$x11name $cbtext"
- clipboard
- #~ often there are http errors, but playback continues regardless. so let's drop it.
- #~ elif [[ "$line" == *"HTTP error"* ]] || [[ "$line" == *"ytdl_hook: ERROR:"* ]]; then
- elif [[ "$line" == *"ytdl_hook: ERROR:"* ]]; then
- line="${line%%; please report this issue*}"
- notify=1; error=1
- notify "$line" "$x11name"
- fi
- done
- [[ "$error" == 1 ]] && exit 1
- notify "That was: $title" "Exiting $x11name $cbtext"
|