Skip to content

Instantly share code, notes, and snippets.

@pdkl95
Created May 27, 2019 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pdkl95/0f963eae3612ecb104f233ca9eed435d to your computer and use it in GitHub Desktop.
Save pdkl95/0f963eae3612ecb104f233ca9eed435d to your computer and use it in GitHub Desktop.
GUI track selector front end for youtube-dl
#!/bin/bash
#
# ytdltracks - GUI track selector front end for youtube-dl
#
# Author: pdkl95 (2819)
#
# Requires: https://github.com/v1cont/yad
#
: ${YOUTUBE_DL:=youtube-dl}
: ${YAD:=yad}
declare self="$(basename "$@")"
declare pretend=false
errecho() {
echo "$*" 1>&2
}
die() {
errecho "${self}: error - $*"
exit 1
}
warn() {
errecho "${self}: $*"
}
##################################################################
# youtube-dl commands
get_url_title() {
"${YOUTUBE_DL}" --get-title "$1"
}
declare auto_audio_track=""
declare auto_video_track=""
declare all_formats_text=""
declare url_title=""
get_format_data() {
local url="$1" ; shift
auto_audio_track=""
auto_video_track=""
errecho ">>> URL \"${url}\""
errecho " Downloading format list.,,,"
all_formats_text="$("${YOUTUBE_DL}" --list-formats "${url}")"
errecho " Downloading title,,,"
url_title="$("${YOUTUBE_DL}" --get-title "${url}")"
}
raw_all_formats() {
echo -n "${all_formats_text}"
}
filter_non_format_header() {
sed -e '1,/format code/ d'
}
declare WS='[[:space:]]\+'
declare GRP_CODE='\([[:digit:]]\+\)'
declare GRP_EXT='\(\w\+\)'
declare GRP_RES='\(\w\+\( only\)\?\)'
declare GRP_NOTE='\(.*\)'
declare TSV_MATCH="^${GRP_CODE}${WS}${GRP_EXT}${WS}${GRP_RES}${WS}${GRP_NOTE}"
declare TSV_REPLACE="\1\t\2\t\3\t\"\5\""
declare TSV_CMD="s|${TSV_MATCH}|${TSV_REPLACE}|"
filter_into_tsv() {
sed -e "${TSV_CMD}"
}
all_formats() {
raw_all_formats | filter_non_format_header | filter_into_tsv
}
##################################################################
# temp dl script management
declare DLSH="$(mktemp --tmpdir=${TMPDIR:-/tmp} --suffix=.sh "${self}-XXXXXX")"
trap "rm -f ${DLSH}" EXIT
dlshecho() {
echo -n "$@" >> "${DLSH}"
}
dlsheoln() {
echo >> "${DLSH}"
}
####################################
each_row() {
local action="$1" ; shift
all_formats | (
IFS=$'\t\n'
while read code ext res note ; do
case "${action}" in
prepare_row)
prepare_row "${code}" "${ext}" "${res}" "${note}"
;;
echo_code)
echo "${code}"
;;
esac
done
)
}
guess_video_track() {
while read code ; do
case "${code}" in
140)
auto_audio_track=140
;;
299 | 298 | 137 | 136 | 135 | 134 | 133)
if [[ -n "${auto_video_track}" ]] ; then
if (( code>auto_video_track )) ; then
auto_video_track="${code}"
fi
else
auto_video_track="${code}"
fi
;;
esac
done < <(each_row echo_code)
}
code_is_autoselected() {
if [[ -z "${code}" ]] ; then
return 1
fi
if [[ "${code}" == "${auto_audio_track}" ]] ; then
return 0
fi
if [[ "${code}" == "${auto_video_track}" ]] ; then
return 0
fi
return 1
}
prepare_row() {
local code="$1" ext="$2" res="$3" note="$4"
note="${note#\"}"
note="${note%\"}"
if code_is_autoselected "$@" ; then
echo TRUE
else
echo FALSE
fi
echo "${code}"
echo "${ext}"
echo "${res}"
echo "${note}"
}
prepare_rows() {
each_row prepare_row
}
declare pick_title="Select Tracks"
pick_text() {
echo "<span size='large' weight='bold'>${pick_title}</span>"
echo "<span>\"${url_title}\"</span>"
echo "<span size='large'>All selected tracks will be included in the media file.</span>"
}
yad_picktracks() {
local -a opts=()
opts+=( --title="${pick_title}" )
opts+=( --width=640 --height=620 )
opts+=( --center )
opts+=( --borders=5 )
opts+=( --on-top )
opts+=( --button=gtk-cancel:1 )
opts+=( --button=gtk-ok:0 )
opts+=( --buttons-layout=spread )
opts+=( --text="$(pick_text)" )
opts+=( --list --checklist --multiple )
opts+=( --separator="" )
opts+=( --print-column=2 )
opts+=( --search-column=0 )
opts+=( --column="DL?" )
opts+=( --column="Code" )
opts+=( --column="Fmt" )
opts+=( --column="Res" )
opts+=( --column="Note" )
"${YAD}" "${opts[@]}"
}
picktracks() {
prepare_rows | yad_picktracks
}
is_code_audio() {
case "$1" in
140) return 0 ;;
*) return 1 ;;
esac
}
pick_ordered_tracks() {
local -a codes=( $(picktracks) )
for code in "${codes[@]}" ; do
if ! is_code_audio "${code}" ; then
echo "${code}"
fi
done
for code in "${codes[@]}" ; do
if is_code_audio "${code}" ; then
echo "${code}"
fi
done
}
prepare_dl() {
local url="$1" ; shift
local track
get_format_data "${url}"
guess_video_track
local -a tracks=( $(pick_ordered_tracks) )
local -i ntracks=${#tracks[@]}
if (( ntracks < 1 )) ; then
warn "No tracks selected for \"${url}\""
return 0
fi
if $pretend ; then
dlshecho "echo "
fi
dlshecho "${YOUTUBE_DL} "
dlshecho "-f ${tracks[0]}"
if (( ntracks > 1 )) ; then
for track in "${tracks[@]:1:${#tracks[@]}-1}" ; do
dlshecho "+${track}"
done
fi
dlshecho " \"${url}\""
dlsheoln
}
dltracks() {
if ! [[ -e "${DLSH}" ]] ; then
return 0
fi
"${SHELL}" "${DLSH}"
}
for url in "$@" ; do
prepare_dl "${url}"
done
dltracks
# Local Variables:
# mode: sh
# sh-basic-offset: 4
# sh-shell: bash
# coding: unix
# End:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment