scripts: Add queue functionality to vidl

When adding new links to vidl, it will now put them in a queue (file)
from which it then begins downloading links one after the other. Only
one downloading instance of vidl will ever be running, but you can still
add more links by invoking it again while it is.

Added one new command line option `-c` to quickly empty the queue and
start over.

Fixes #8.
This commit is contained in:
Marty Oehme 2022-03-12 09:21:44 +01:00
parent 08d246272a
commit 3e00e84319
Signed by: Marty
GPG Key ID: B7538B8F50A1C800
1 changed files with 126 additions and 41 deletions

View File

@ -2,13 +2,6 @@
# download a file if it does not exist in the archive alread
# otherwise just re-link it from the archive
DL_FOLDER="${DL_FOLDER:-${XDG_VIDEOS_DIR:-$HOME/videos}}/inbox"
ARCHIVE_FOLDER="${ARCHIVE_FOLDER:-${XDG_VIDEOS_DIR:-$HOME/videos}}/archive"
YT_DL_CMD="${YT_DL_CMD:-yt-dlp}"
yt_default_opts=(-f "best[height\<=1080]" --retries 15 --embed-subs --sub-lang "en,de,es,fr")
declare -a YT_DL_OPTS=${YT_DL_OPTS:-( "${yt_default_opts[@]}" )}
YT_DL_TITLE="""${YT_DL_TITLE:-%(channel)s_%(title)s_%(id)s}"""
show_help() {
printf """
archive.sh: Hard linking your stuff.
@ -22,19 +15,24 @@ Point it to a link you want downloaded.
Options:
-h Display this help.
-h Display this help.
-d Directory to check for existence of file and archive to if needed.
-d Directory to check for existence of file and archive to if needed.
If this is passed will not download existing archived files again.
-f Directory to download to.
-f Directory to download to.
-c Clear existing download queue.
-t Point to youtube-dl command to use. Can be command or absolute link.
By default will use \`yt-dlp\` which is a more up to date fork of the
program.
youtube-dl program.
"""
}
while getopts "t:f:d:h" opt; do
urls=("$@")
while getopts "t:f:d:hc" opt; do
case "$opt" in
# v) verbose=1
# ;;
@ -47,6 +45,9 @@ while getopts "t:f:d:h" opt; do
d)
ARCHIVE_FOLDER="$OPTARG"
;;
c)
ONLY_DO=clear
;;
h | \? | *)
show_help
exit 0
@ -55,7 +56,15 @@ while getopts "t:f:d:h" opt; do
done
shift $((OPTIND - 1))
_call_archive() {
get_ytdl_fname() {
yt_dl_fname=$("$YT_DL_CMD" --get-filename -o "$YT_DL_TITLE" "$*")
if [ -z "$yt_dl_fname" ]; then
echo Could not get video filename, error with youtube-dl.
exit 1
fi
}
_call_archive() { # 1=new_file, 2=archive_location
command -v archive >/dev/null 2>&1 || {
echo "archive command not found."
exit 1
@ -64,43 +73,119 @@ _call_archive() {
}
vid_ext="\(mp4\|avi\|webm\|mkv\|mpe?g\|3gp\|m4a\)"
_findfile() {
dir="$1"
fname="$2"
find "$dir" -type f -name "$fname.*" | sed -ne "/$fname\.$vid_ext$/Ip"
_findfile() { # 1=directory, 2=file
find "$1" -type f -name "$2.*" | sed -ne "/$2\.$vid_ext$/Ip"
}
YT_DL_TITLE="%(channel)s_%(title)s_%(id)s"
_download() {
_alreadyexists() { # 1=video_regex
if [ ! -d "$ARCHIVE_FOLDER" ]; then return 0; fi
local found
found=$(_findfile "$ARCHIVE_FOLDER" "$1")
if [ -n "$found" ]; then
return 0
else
return 1
fi
}
_download_cmd() {
"$YT_DL_CMD" \
-o "$DL_FOLDER/$YT_DL_TITLE.%(ext)s" \
"${YT_DL_OPTS[@]}" \
"$url"
"$*"
}
url="$*"
dl_fn=$("$YT_DL_CMD" --get-filename -o "$YT_DL_TITLE" "$url")
video_file_regex="${dl_fn}"
download() { # 1=url
# # download the video to download folder
if ! _alreadyexists "$yt_dl_fname"; then
_download_cmd "$*"
if [ -z "$dl_fn" ]; then
echo Could not get video filename, error with youtube-dl.
exit 1
fi
# yt-dl never knows the exact filename in advance
file=$(_findfile "$DL_FOLDER" "$yt_dl_fname")
if [ -z "$file" ]; then exit 1; fi
_call_archive "$file" "$ARCHIVE_FOLDER"
# only link old file if one exists
else
archive_file=$(_findfile "$ARCHIVE_FOLDER" "$yt_dl_fname")
echo "$archive_file" | while read -r file; do
echo "file $file exists, not downloading duplicate"
_call_archive "$file" "$DL_FOLDER"
done
fi
}
alreadyexists=$(_findfile "$ARCHIVE_FOLDER" "$video_file_regex")
setup() {
DL_FOLDER="${DL_FOLDER:-${XDG_VIDEOS_DIR:-$HOME/videos}}/inbox"
ARCHIVE_FOLDER="${ARCHIVE_FOLDER:-${XDG_VIDEOS_DIR:-$HOME/videos}}/archive"
YT_DL_CMD="${YT_DL_CMD:-yt-dlp}"
yt_default_opts=(-f "best[height\<=1080]" --retries 15 --embed-subs --sub-lang "en,de,es,fr")
declare -a YT_DL_OPTS=${YT_DL_OPTS:-( "${yt_default_opts[@]}" )}
YT_DL_TITLE="${YT_DL_TITLE:-%(channel)s_%(title)s_%(id)s}" # this title needs to be without extension
# # download the video to download folder
if [ "$alreadyexists" = "" ] || [ -z "$alreadyexists" ]; then
_download
queue_file="${XDG_CACHE_HOME:-$HOME/.cache}/vidl_queue"
if [ ! -f "$queue_file" ]; then
mkdir -p $(dirname "$queue_file")
touch "$queue_file"
fi
lock_dir="${XDG_CACHE_HOME:-$HOME/.cache}/vidl_lock"
}
# yt-dl never knows the exact filename in advance
file=$(_findfile "$DL_FOLDER" "$video_file_regex")
if [ -z "$file" ]; then exit 1; fi
_call_archive "$file" "$ARCHIVE_FOLDER"
# only link old file if one exists
else
echo "$alreadyexists" | while read -r file; do
echo "file $file exists, not downloading duplicate"
_call_archive "$file" "$DL_FOLDER"
is_in_queue() { # 1=url
[ -f "$queue_file" ] || return 1
grep -q "$1" "$queue_file"
}
add_to_queue() { # 1=url
if is_in_queue "$1"; then return; fi
echo "$1" >>"$queue_file"
echo "added $url to queue."
}
remove_from_queue() { # 1=url
sed -i.bak -e "\|$1|d" "$queue_file"
}
clear_queue() {
rm "$queue_file"
}
remove_lock() {
if ! rmdir $lock_dir; then
echo "Failed to remove lock '$lock_dir'. Please remove manually before next run."
exit 1
fi
}
is_only_instance() {
if mkdir $lock_dir 2>/dev/null; then
trap "remove_lock" EXIT
return 0
else
return 1
fi
}
main() {
setup
if [ "$ONLY_DO" = "clear" ]; then
clear_queue
exit
fi
for url in $*; do
add_to_queue "$url"
done
fi
if is_only_instance; then
echo "Download starting..."
while read -r line; do
get_ytdl_fname "$line"
download "$line"
remove_from_queue "$line"
done <"$queue_file"
else
echo "Download already running, only adding to queue."
fi
echo "Download done..."
}
main "${urls[@]}"