Created
April 27, 2018 18:55
-
-
Save Misko-2083/86dcb64ed2e22c7b7bc6785b5e02b3aa to your computer and use it in GitHub Desktop.
youtube-dl wrapper with yad paned dialog UI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
### Itchy video | |
### Downloads videos (with the best video + best audio or best option available) into ~/Videos | |
### If ffmpeg or avconv is installed, best video & best audio will be downloaded separately | |
### and combined into a single file | |
### Requires: xev (provided by "x11-utils" package), xdotool, yad, youtube-dl, wget | |
### Note: uses xev with -event option (so, should work in debian jessie or newer) | |
### Made by Misko_2083 | |
# *********************** | |
# DEPENDANCY CHECK | |
# *********************** | |
ERR(){ echo "ERROR: $1" 1>&2; } | |
declare -i DEPCOUNT=0 | |
for DEP in /usr/bin/{xev,xdotool,yad,youtube-dl,wget}; { | |
[ -x "$DEP" ] || { | |
ERR "$LINENO Dependency '$DEP' not met." | |
DEPCOUNT+=1 | |
} | |
} | |
[ $DEPCOUNT -eq 0 ] || exit 1 | |
# *********************** | |
# END DEPENDANCY CHECK | |
# *********************** | |
# *********************** | |
# INITIALIZATION | |
# *********************** | |
# Download location | |
export SAVEDIR="$HOME/Videos" | |
cd "${SAVEDIR}" | |
# Command for running download_video function | |
# Later will be used by yad | |
export ytdownload='@bash -c "download_video %1"' | |
# We need this to store the youtube Link | |
export ytlink=$(mktemp /tmp/ytlnk.XXXXXXXX) | |
# Temp files paths | |
export ytdpipe=$(mktemp -u /tmp/ytd.XXXXXXXX) | |
export ytdpipetwo=$(mktemp -u /tmp/ytd2.XXXXXXXX) | |
# Make named pipes | |
mkfifo "$ytdpipe" | |
mkfifo "$ytdpipetwo" | |
# Initialize the key for the paned dialog plugs | |
ytdkey=$(($RANDOM * $$)) | |
# *********************** | |
# END INITIALIZATION | |
# *********************** | |
# *********************** | |
# FUNCTIONS | |
# *********************** | |
# ------------------ | |
function on_exit { | |
# ------------------ | |
# Removes temorary files | |
rm -f "$ytdpipe" | |
rm -f "$ytdpipetwo" | |
rm -f "$ytlink" | |
} | |
trap "on_exit" EXIT | |
# ------------------ | |
function download_video () { | |
# ------------------ | |
# Disables fbtn in first yad plug tab | |
# fbtn is the second field | |
echo "2:@disabled@" | |
# Check if the URL is valid with the spider | |
if wget -q --spider "$1"; then | |
# Export url to a temp file for later use | |
echo "${1}" >> "$ytlink" | |
echo "#Preparing to download" >> "$ytdpipe" | |
# Loop that gets percentage and progress from the second named pipe ($ytdpipetwo), | |
# writes them to first named pipe ($ytdpipe) | |
while read line; do | |
# Filters lines with percentage | |
if [[ "$(echo $line | grep '[0-9]*%')" ]];then | |
percent=$(echo $line | awk '{print $2}') | |
echo "${percent%.*}" >> "$ytdpipe" | |
fi | |
# Filters lines with '[download\]' | |
if [[ "$(echo $line | grep '\[download\]')" ]];then | |
progress=$(echo $line | awk '{$1=""; print $0}') | |
echo "#$progress" >> "$ytdpipe" | |
fi | |
done < "$ytdpipetwo" & | |
LOOP_PID="$!" | |
# Downloads video | |
# output is redirected to the second named pipe ($ytdpipetwo) | |
youtube-dl -f 'bestvideo [ext = mp4] + bestaudio [ext = m4a] / bestvideo + bestaudio / best' --merge-output-format mp4 --newline -i -o "%(title)s.%(ext)s" "${1}" 2>&1 >> $ytdpipetwo & | |
ytproc_pid=$! | |
wait $ytproc_pid 2>/dev/null # supress message from kill command later, wait also returns exit status | |
if [[ "$?" = 0 ]] | |
then | |
echo "0" >> "$ytdpipe" | |
echo "#Download complete." >> "$ytdpipe" | |
kill "$LOOP_PID" | |
elif [[ ! -s "$ytdpid" ]]; then | |
echo "#Download canceled." >> "$ytdpipe" | |
echo "0" >> "$ytdpipe" | |
else | |
echo "#Download error" >> "$ytdpipe" | |
kill "$LOOP_PID" | |
fi | |
else | |
echo "#Invalid URL" >> "$ytdpipe" | |
fi | |
# Enables fbtn in the first yad plug tab | |
# fbtn is the second field | |
echo "2:$ytdownload" | |
} | |
export -f download_video | |
# ------------------ | |
function ytdl_version () { | |
# ------------------ | |
# This function checks for new youtube-dl version | |
# If youtube-dl is latest, writes "up-to-date" to the progress bar | |
# If tit isn't, writes "update is available" to the progress bar | |
echo "#Checking youtube-dl version" >> "$ytdpipe" | |
wget --spider --user-agent="Mozilla/5.0 Gecko/20100101" --timeout=30 -q "https://rg3.github.io/youtube-dl/" -O /dev/null | |
if [[ "$?" -ne "0" ]]; then | |
echo "#Can't connect to youtube-dl server site" >> "$ytdpipe" | |
fi | |
ytdlcv=$(youtube-dl --version) | |
ytdllv=$(wget -O- -q "https://rg3.github.io/youtube-dl/update/LATEST_VERSION") | |
if [[ "$ytdlcv" == "$ytdllv" ]]; then | |
echo "#youtube-dl is up-to-date" >> "$ytdpipe" | |
else | |
echo "#youtube-dl update is available" >> "$ytdpipe" | |
fi | |
} | |
export -f ytdl_version | |
# ------------------ | |
function stop_clicked () { | |
# ------------------ | |
# This function is executed when the stop button in the main yad dialog is clicked | |
# Finds youtube-dl process and kills it | |
if [[ ! -s "${ytlink}" ]]; then | |
echo "#Nothing to stop." >> "$ytdpipe" | |
else | |
YoutubeLink="$(tail -1 "${ytlink}")" | |
YtCommand="youtube-dl -f bestvideo [ext = mp4] + bestaudio [ext = m4a] / bestvideo + bestaudio / best --merge-output-format mp4 --newline -i -o %(title)s.%(ext)s $YoutubeLink" | |
YoutubePID="$(ps -eo pid,cmd | grep -F "$YtCommand" | grep -v "grep" | awk '{ print $1 }')" | |
if [[ "$YoutubePID" != "" ]]; then | |
kill -9 $YoutubePID | |
else | |
echo "#Nothing to stop." >> "$ytdpipe" | |
fi | |
fi | |
} | |
export -f stop_clicked | |
# *********************** | |
# END FUNCTIONS | |
# *********************** | |
# *********************** | |
# MAIN | |
# *********************** | |
# Open the name pipe on file descriptor 3 | |
exec 3<> $ytdpipe | |
# First paned tab | |
# Form with entrey and download button | |
yad --plug="$ytdkey" --tabnum=1 --form --field "Enter video url":CE "" \ | |
--image=browser-download --field="Download!browser-download:fbtn" "$ytdownload" & | |
# Second paned tab | |
# progress bar | |
yad --plug="$ytdkey" --tabnum=2 --window-icon="$ICON" \ | |
--progress --borders=6 --auto-close --auto-kill <&3 & | |
echo "#Enter video URL." >> "$ytdpipe" | |
#ytdl_version &)" | |
# main window | |
yad --class="Itchy" --paned --key="$ytdkey" \ | |
--button="Check yoututube-dl":'bash -c "ytdl_version" 2>/dev/null' \ | |
--button="Stop":'bash -c "stop_clicked" 2>/dev/null' --text="Enter the video or playlist URL and click Download" \ | |
--width=500 --height=200 --border=9 \ | |
--title=$"Itchy video" --window-icon="browser-download" --center & | |
YPID="$!" | |
# *********************** | |
# END MAIN | |
# *********************** | |
# Wait untill main window opens, that is until window name appears | |
until xdotool getwindowname "$(xdotool search --any --pid $YPID --class "Itchy" 2>/dev/null | tail -1 2>/dev/null)" &>/dev/null; do | |
# sleep until the window opens | |
sleep .1 | |
done | |
# Decimal window id | |
WindowID="$(xdotool search --any --pid $YPID --class "Itchy" 2>/dev/null | tail -1)" | |
# Hexadecimal | |
WindowIDHex=$(printf "0x%08x" ${WindowID}) | |
# Base seven | |
WindowBSeven=$(printf "0x%07x" ${WindowID}) | |
# This is needed because youtube-dl prevents one yad plug tab from closing | |
# We have to find out when the main dialog is closed | |
# Monitor for DestroyNotify event of the main yad window and kill youtube-dl | |
xev -event structure -id ${WindowIDHex} 2>/dev/null | | |
while IFS=$',' read -a A; do | |
# If main window is closed | |
if [[ "${A[0]}" =~ "DestroyNotify event" ]]; then | |
YoutubeLink="$(tail -1 "${ytlink}")" | |
YtCommand="youtube-dl -f bestvideo [ext = mp4] + bestaudio [ext = m4a] / bestvideo + bestaudio / best --merge-output-format mp4 --newline -i -o %(title)s.%(ext)s $YoutubeLink" | |
YoutubePID="$(ps -eo pid,cmd | grep -F "$YtCommand" | grep -v "grep" | awk '{ print $1 }')" | |
if [[ "$YoutubePID" != "" ]]; then | |
kill -9 $YoutubePID | |
fi | |
# xev has to be killed too or it will run forever | |
XevPID="$(ps -eo pid,cmd | grep "xev -event structure -id $WindowIDHex" | grep -v "grep" | awk '{ print $1 }')" | |
kill $XevPID | |
wait $XevPID 2> /dev/null | |
fi | |
A=() | |
done & xev_pid=$! | |
# Wait until yad window closes | |
wait $YPID | |
# Wait also returns exit status | |
# If we need exit status of the main window can get it here | |
# echo $? | |
# Wait until process with pid xev_pid finishes | |
# This is needed to properly remove temp files | |
wait $xev_pid | |
# Removing *.part file(s) | |
YoutubeLink="$(tail -1 "${ytlink}")" | |
if [[ "${YoutubeLink}" != "" ]]; then | |
# Offer cleanup | |
if yad --text="Do you want Itchy video to search and remove any *.part file(s) left?" \ | |
--button="Yes!gtk-yes:0" --button="No!gtk-no:1" --timeout=10 --timeout-indicator=right \ | |
--title=$"Itchy video" --window-icon="browser-download" --image=browser-download --border=9 | |
then | |
echo "Searching for any *.part file from the most recent download attempts" | |
OIFS="$IFS" # backup internal field separator | |
IFS=$'\n' | |
for LNK in $(<${ytlink}); do | |
Fname="$(youtube-dl --get-filename -o "%(title)s" "${LNK}")" | |
echo "${Fname}" | |
rm "$(find "${SAVEDIR}" -type f -name "*${Fname}.*" | grep part)" &>/dev/null # Finds & removes the part file | |
done | |
# restores internal field separator | |
IFS="$OIFS" | |
fi | |
fi | |
# Close file descriptor 3 | |
exec 3>&- | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment