123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- #!/bin/bash
- usage() {
- echo "
- Search Youtube.
- Usage: youtube-search [OPTIONS] [\"SEARCH STRING\"]
- Requires jshon and youtube-dl to be in PATH (or a youtube-dl compatible
- executable, see -e option). Requires perl and HTML::Entities.
- You can provide a search string in double quotes on the command line,
- or enter it interactively.
- It helps if xclip and/or tput are available, but the script works without those.
- OPTIONS
- -l List more detail for each result (slower, larger download).
- -f Full width - don't cut long strings to terminal width.
- -m int Maximum number of results shown Default: $max_results.
- We suspect that only the values 3 or 10 should be used.
- -t int Timeout for URL retrieval. Default: $timeout.
- -e str Use this executable instead of youtbe-dl.
- -M str Use this application to open the selected Youtube URL.
- Tested with youtube-dl and also mpv.
- -D Debug: dump complete json result and more.
- -h This help.
- "
- exit 1
- }
- base_url='https://m.youtube.com'
- minlen=3 # minimum length for search term
- # character for separator line
- sepchar="-"
- # Colors
- RED='\033[31m'
- BLUE='\033[34m'
- CYAN='\033[36m'
- GREEN='\033[32m'
- YELLOW='\033[33m'
- END='\033[0;0m'
- BOLD='\033[1m'
- #Set number of video results here.
- max_results=3
- timeout=10
- fullwidth=False
- debug=0
- uts=''
- mpv=()
- YTDL="${YTDL:-youtube-dl}"
- ytdlopts=( --flat-playlist --sub-lang en )
- options=( title description duration view_count id )
- # Parsing the command line
- while getopts "lfm:t:e:M:Dh" opt; do
- case $opt in
- l)
- options=( "${options[@]}" uploader_id like_count dislike_count thumbnail )
- ytdlopts=( --sub-lang en )
- ;;
- f)
- fullwidth=True
- ;;
- m)
- max_results="$OPTARG"
- ;;
- t)
- timeout="$OPTARG"
- ;;
- e)
- which "$OPTARG" >/dev/null && YTDL="$OPTARG" || exit 1
- ;;
- M)
- mpv=( $OPTARG )
- which "${mpv[0]}" >/dev/null || exit 1
- ;;
- D)
- debug=1
- ;;
- h|*)
- usage
- ;;
- esac
- done
- shift $((OPTIND-1))
- # quick dependency check
- for dep in "$YTDL" jshon; do
- type "$dep" >/dev/null || exit 1
- done
- perl -MHTML::Entities -e 1 || exit 1
- sep=''
- columns="$(tput cols)"
- [ -z "$columns" ] && columns=80
- # adjust separator width to terminal width
- for ((i=0;i<columns;i++)); do sep="$sep$sepchar"; done
- unset sepchar
- # Interactively obtain search term
- uts="${1%%$'\n'*}" # cut before first newline
- read -r -e -i "$uts" -p "Enter search term: " uts
- xclip -selection clipboard <<<"$uts";xclip -selection primary <<<"$uts"
- uts="$(perl -CS -MHTML::Entities -pe 'encode_entities($_);' <<<"$uts")"
- [ -z "$uts" ] && exit 1
- [[ "$debug" == 1 ]] && { echo "$sep"; echo "Encoded search term: $uts"; echo "Manual search: https://www.youtube.com/results?search_query=$uts"; echo "$sep"; }
- # adjust tabstops to longest key, cut strings to terminal width - tabstop
- longest=0
- for i in "${options[@]}"; do ((${#i} > longest)) && longest=${#i}; done
- longest=$((longest+3)); tabs $longest
- #### AND ACTION! ####
- mapfile -n "$max_results" -t results <<<"$("$YTDL" "${ytdlopts[@]}" --socket-timeout "$timeout" --dump-json "ytsearch$max_results:$uts")"
- #### AND ACTION! ####
- i=0
- url=()
- for line in "${results[@]}"; do
- echo -e "$YELLOW$i ${sep::-$(( ${#i} + 1 ))}$END"
- [ -z "$line" ] && echo "Empty line" && continue
- [[ "$debug" == 1 ]] && jshon <<<"$line" && echo -e "$YELLOW$sep$END"
- for o in "${options[@]}"; do
- res="$(jshon -e $o -u <<<"$line")"
- reswidth="$((columns-longest))"
- [[ "$fullwidth" == False ]] && (( reswidth > 15 )) && res="${res:0:$reswidth}"
- case "$o" in
- id) res="$base_url/watch?v=$res"
- url[$i]="$res"
- o="URL"
- ;;
- duration)
- res="${res%%.*}"
- ((h=${res}/3600))
- ((m=(${res}%3600)/60))
- ((s=${res}%60))
- res="$(printf "%02d:%02d:%02d\n" $h $m $s)"
- ;;
- esac
- echo -e "$GREEN$o:$END\t$res"
- done
- ((i++))
- done
- echo
- while :; do
- answer="-1"
- until [[ "$answer" =~ ^[0-9]+$ ]] && (( answer >= 0 )) && (( answer < i )); do
- read -p "Select URL no. (q to quit): " answer
- [[ "$answer" == q ]] && exit
- done
- url="${url[answer]}"
- if which xclip >/dev/null 2>&1; then
- xclip -selection clipboard <<<"$url"
- xclip -selection primary <<<"$url"
- echo "Copied $url to clipboard and primary."
- else
- echo "$url"
- fi
- [[ "${mpv[0]}" != '' ]] && echo "Launching ${mpv[@]} $url" && "${mpv[@]}" "$url"
- done
|