2 # Desc: Download YouTube videos
3 # Usage: $ ./bkytpldl-generic
6 declare -a args
; # array for yt-dlp arguments
7 declare -a urls urls_rand
; # array for YouTube playlist URLs
11 urls
+=("https://www.youtube.com/playlist?list=PLxxx"); # adjust me
12 urls
+=("https://www.youtube.com/playlist?list=PLxxx"); # adjust me
13 urls
+=("https://www.youtube.com/playlist?list=PLxxx"); # adjust me
15 yell
() { echo "$0: $*" >&2; } # print script path and all args to stderr
16 die
() { yell
"$*"; exit 111; } # same as yell() but non-zero exit status
17 must
() { "$@" || die
"cannot $*"; } # runs args as command, reports args if command fails
20 if ! command -v yt-dlp
1>/dev
/random
2>&1; then die
"FATAL:yt-dlp not found."; fi;
22 # Donʼt run multiple yt-dlp instances
23 if pgrep
"^yt-dlp$" 1>/dev
/random
2>&1; then die
"FATAL:yt-dlp already running."; fi;
26 if [[ ! -d $dir_out ]]; then mkdir
-p "$dir_out"; fi;
28 # == Assemble options ==
30 # yt-dlp output options
31 ## Restrict file name character set
32 #args+=("--restrict-filenames"); # Remove non-ASCII characters
33 args
+=("--trim-filenames=120"); # Use in tandem with `%(title).120B`
35 ## Request to write accompanying files
36 args
+=("--write-subs"); # Write subtitles file
37 args
+=("--write-auto-subs"); # Write subtitles file
38 #args+=("--all-subs"); # Download all available subtitles (causes many requests)
39 #subLangs="en.*,ja.*,id.*,es.*,zh-Hans.*,zh-Hant.*,sv.*,el.*,hi.*,ru.*,bn.*,fr.*,ko.*,ar.*,nv.*"; # custom language list
40 subLangs
="en,en-orig,en.*"; # custom language list
41 args
+=("--sub-langs" "$subLangs");
42 args
+=("--write-info-json"); # Write accompanying json file
43 args
+=("--no-overwrites"); # Don't overwrite files
44 args
+=("--write-thumbnail"); # Write thumbnail
46 ## Only download metadata
47 #args+=("--no-download"); # Don't download video file.
50 args
+=("--write-comments"); # Get comments
52 ### comment_sort values:
53 ### top : use YouTube top comment algorithm
54 ### new : get newest comments (default)
55 ### max_comments values:
56 ### max-comments : max number of parent comments or replies
57 ### max-parents : max number of comment threads
58 ### max-replies : max number of replies across all threads
59 ### max-replies-per-thread : max number of replies per thread
60 args
+=("--extractor-args" "youtube:comment_sort=top;max_comments=10000,100,10000,100");
62 ## Randomize order in which playlist items are downloaded
63 args
+=("--playlist-random");
65 ## Delay between downloads
67 maxSleep
="$(( minSleep + (RANDOM + RANDOM + RANDOM) / ( 3 * 400) ))"; # roughly 60 seconds
68 args
+=("--min-sleep-interval" "$minSleep");
69 args
+=("--max-sleep-interval" "$maxSleep");
70 args
+=("--sleep-requests" "2"); # delay on metadata requests
71 args
+=("--sleep-subtitles" "10"); # delay for subtitles
73 ## Remember downloaded videos to avoid redownload attempts
74 pathDA
="$dir_out"/.bkytpldl_history.txt
;
75 args
+=("--download-archive" "$pathDA");
77 ## Use firefox 'default-release' profile cookies
78 ## Example: Linux: from ~/.mozilla/firefox/deadbeef.default-release/
79 #args+=("--cookies-from-browser");
80 #args+=("firefox:deadbeef.default-release"); Default Firefox profile name
82 ## Specify output filename format
83 ## Note: `$(title).120B` shortens title to 120 bytes (useful for
84 ## titles with UTF-8 characters.
86 args
+=("%(playlist)s/%(upload_date)s.%(channel)s.%(channel_id)s.%(title).120B.%(id)s.%(ext)s");
88 ## Limit download resolution to 1080p
89 args
+=("-S" "res:1080");
91 ## Specify playlist URLs to download
92 ### Shuffle playlist download order
93 mapfile
-t urls_rand
< <(printf "%s\n" "${urls[@]}" | shuf
);
94 for url
in "${urls_rand[@]}"; do
98 # Change working directory to output dir
99 pushd "$dir_out" || die
"FATAL:Failed to change pwd to:dir_out:$dir_out";
101 # == Download videos ==
103 #yell "DEBUG:args:$(declare -p args)"; # debug command
104 must yt-dlp
"${args[@]}"; # execute command
105 popd || die
"FATAL:Failed to return from dir_out:$dir_out";
107 # Author: Steven Baltakatei Sandoval