这不能仅通过参数来完成,如下所示:使用 args 设置下载存档路径
我想制作两个类似的脚本。下载视频并将每个视频的存档文件保存到上传者的文件夹中。另一个脚本也下载元数据。
我想在下载之前检查一下存档。
我希望能够并行多次使用该函数,并将它们放在后台。
我能想到的获取上传器的唯一方法是下载带有输出的元数据%(uploader)s
。
然后使用上传者的名称创建一个文件夹,删除文件,然后从创建的文件夹中再次下载具有正确名称的文件。
我有一些功能已经定义可能对此有所帮助。
这是我尝试过的,但它不起作用
# Video Playlist saving archive file to uploader's folder
ytp() {
# Dl opts=(
${opts[@]}
--skownload metadata
--skip-download
--write-info-json
)
# Get ten random characters
local rand=$( cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 10 | head -n 1 )
LOG_NAME=$( get_log_name "$(${paste[@]})" )
$yt_dl ${opts[@]} --output "%(uploader|Anon-%(id)s)s.%(ext)s" "$(${paste[@]})" >> "/tmp/$LOG_NAME" 2>&1
for f in *.info.json; do
local name="${f%.*}"
if [[ $name == Anon* ]]; then
name="Anon"
fi
mkdir -p "$name"
rm "$f"
cd "$name" || exit
# Download media
ytv
cd .. || exit
done
}
答案1
有一个悬而未决的问题可以提供更优雅的解决方案。
[功能请求] 文件名模板支持 --download-archive
#!/usr/bin/env bash
# Common options for yt-dlp/youtube-dl
COMMON_OPTIONS=(
--continue # Resume partially downloaded files
--no-overwrites # Do not overwrite any files
--no-post-overwrites # Do not overwrite post-processed files
--verbose # Print various debugging information
--restrict-filenames # Restrict filenames to only ASCII characters, and avoid "&" and spaces in filenames
--retry-sleep fragment:exp=2:64 # Time to sleep between retries in seconds
)
# Determine the location of either 'yt-dlp' or 'youtube-dl' executable
if [ -f /usr/local/bin/yt-dlp ]; then
YT_DL="/usr/local/bin/yt-dlp"
elif [ -f /usr/local/bin/youtube-dl ]; then
YT_DL="/usr/local/bin/youtube-dl"
else
if command -v yt-dlp >/dev/null 2>&1; then
YT_DL="$(which yt-dlp)"
elif command -v youtube-dl >/dev/null 2>&1; then
YT_DL="$(which youtube-dl)"
else
echo "ERROR: Neither yt-dlp nor youtube-dl found in PATH"
return 1
fi
fi
# Configure paste command based on the operating system
# For macOS (Darwin), use 'pbpaste' and set the ffmpeg location.
if [[ $OSTYPE == darwin* ]]; then
if ! command -v pbpaste >/dev/null 2>&1; then
echo "ERROR: 'pbpaste' is not found on macOS."
exit 1
fi
PASTE_COMMAND=(pbpaste)
COMMON_OPTIONS+=("--ffmpeg-location" "/usr/local/bin/ffmpeg")
# For Linux, use 'xsel' or 'xclip' for clipboard access or display an error message if none is executable.
else
if [[ -x "$(command -v xsel)" ]]; then
PASTE_COMMAND=(xsel -ob)
elif [[ -x "$(command -v xclip)" ]]; then
PASTE_COMMAND=(xclip -selection clipboard -o)
else
echo "ERROR: Neither xsel nor xclip is executable."
exit 1
fi
fi
# Get the log filename based on the input
get_log_filename() {
local input="${1//[^[:alnum:].-]/_}" # Replace non-alphanumeric characters with underscores
input="${input:0:200}" # Truncate the input to 200 characters
echo "yt-dlp_$(date +%y%m%d%H%M%S)_${input}.log"
}
# Get the uploader of a video
get_uploader() {
"${YT_DL}" --print '%(uploader|Unknown)s' "$1"
}
download_video_into_uploaders_folder() {
local input="${1:-$(${PASTE_COMMAND[@]})}"
local log_filename="$(get_log_filename "$input")"
local uploader="$(get_uploader "$input")"
local options=(
${COMMON_OPTIONS[@]}
--format '(bv+(wa[abr>=64]/ba))/b'
--format-sort res:720,tbr~2000
--download-archive "$uploader/archive.txt"
)
# Deal with long filenames
if ! "${YT_DL}" "${options[@]}" --output "%(uploader|Unknown)s/%(upload_date>%Y-%m-%d|)s%(upload_date& |)s%(title)s-%(id)s.%(ext)s" "${input}" >> "/tmp/${log_filename}" 2>&1; then
echo "Long filename ERROR: ${input}"
"${YT_DL}" "${options[@]}" --output "%(uploader|Unknown)s/%(upload_date>%Y-%m-%d|)s%(upload_date& |)s%(webpage_url_domain)s-%(id)s.%(ext)s" "${input}" >> "/tmp/${log_filename}" 2>&1
fi
}
ytdlvu() {
local input="${1:-$(${PASTE_COMMAND[@]})}"
download_video_into_uploaders_folder "$input" &
}
download_video_with_metadata_into_uploaders_folder() {
local input="${1:-$(${PASTE_COMMAND[@]})}"
local log_filename="$(get_log_filename "$input")"
local uploader="$(get_uploader "$input")"
local options=(
${COMMON_OPTIONS[@]}
--format '(bv+(wa[abr>=64]/ba))/b'
--format-sort res:720,tbr~2000
--download-archive "$uploader/archive.txt"
--write-info-json
--write-comments
--write-thumbnail
)
# Deal with long filenames
if ! "${YT_DL}" "${options[@]}" --output "%(uploader|Unknown)s/%(upload_date>%Y-%m-%d|)s%(upload_date& |)s%(title)s-%(id)s.%(ext)s" "${input}" >> "/tmp/${log_filename}" 2>&1; then
echo "Long filename ERROR: ${input}"
"${YT_DL}" "${options[@]}" --output "%(uploader|Unknown)s/%(upload_date>%Y-%m-%d|)s%(upload_date& |)s%(webpage_url_domain)s-%(id)s.%(ext)s" "${input}" >> "/tmp/${log_filename}" 2>&1
fi
}
ytdlvmu() {
local input="${1:-$(${PASTE_COMMAND[@]})}"
download_video_with_metadata_into_uploaders_folder "$input" &
}
download_video_playlist_with_metadata_into_uploaders_folder() {
local input="${1:-$(${PASTE_COMMAND[@]})}"
local video_urls=$(get_playlist_urls "$playlist")
for url in $video_urls; do
ytdlvmu "$url"
done
}
ytdlvpmu() {
local input="${1:-$(${PASTE_COMMAND[@]})}"
download_video_playlist_with_metadata_into_uploaders_folder "$input" &
}
此 Bash 脚本旨在使用yt-dlp
或youtube-dl
命令行实用程序从 YouTube(或其他支持的网站)下载视频。它提供了多种功能来处理下载视频和播放列表的不同场景。以下是该脚本功能的详细说明:
常用选项
yt-dlp
:它为/定义了一组常用选项youtube-dl
,例如继续部分下载的文件、避免覆盖、启用详细输出以及将文件名限制为 ASCII 字符。检测 yt-dlp/youtube-dl:该脚本尝试通过检查特定位置或使用命令来查找系统上的
yt-dlp
或可执行文件。youtube-dl
which
配置粘贴命令:根据操作系统(macOS 或 Linux),脚本配置适当的命令来粘贴剪贴板内容(
pbpaste
、xsel
或xclip
)。get_log_filename 函数:此函数根据输入生成日志文件名,用下划线替换非字母数字字符,并将输入截断为 200 个字符。
get_uploader 函数
yt-dlp
:此函数使用/检索给定视频 URL 的上传者名称youtube-dl
。download_video_into_uploaders_folder 函数:此函数将视频从提供的 URL(或剪贴板内容)下载到以上传者命名的文件夹中。它为每个上传者创建一个子文件夹,并存储一个存档文件来跟踪下载的视频。视频文件名包括上传者姓名、上传日期、标题和视频 ID。
ytdlvu 函数:该函数是一个包装器
download_video_into_uploaders_folder
并在后台运行。download_video_with_metadata_into_uploaders_folder 函数:与类似
download_video_into_uploaders_folder
,但它还下载视频的元数据(信息 JSON、评论和缩略图)。ytdlvmu 函数:该函数是一个包装器
download_video_with_metadata_into_uploaders_folder
并在后台运行。download_video_playlist_with_metadata_into_uploaders_folder 函数:此函数下载整个播放列表,从提供的播放列表 URL 中提取视频 URL 并调用
ytdlvmu
每个视频。ytdlvpmu 函数:该函数是一个包装器
download_video_playlist_with_metadata_into_uploaders_folder
并在后台运行。
总之,该脚本提供了一组从 YouTube(或其他支持的网站)下载视频和播放列表的函数,同时按上传者组织它们并包含元数据。它支持yt-dlp
和youtube-dl
实用程序,并处理不同操作系统的剪贴板访问。
答案2
如果你使用 sh/bash/zsh 类型的 shell,你可以这样做
touch temp_archive.txt; yt-dlp --write-info-json --download-archive temp_archive.txt -o "%(uploader)s/%(title)s-[%(id)s].%(ext)s" --exec after_video:'cat temp_archive.txt >> "%(uploader)s/archive.txt"; printf "" > temp_archive.txt' "URL"
在一个函数中:
opts=(
--continue
--no-overwrites
--no-post-overwrites
--verbose
--restrict-filenames
--retry-sleep fragment:exp=2:64
)
get_log_name() {
TIMESTAMP=$( date +%y%m%d%H%M%S )
NAME=${1//[^[:alnum:].-]/_}
echo "yt-dlp_${TIMESTAMP}_${NAME}.log"
}
deal_with_long_filename_playlist() {
LOG_NAME=$( get_log_name "$(${paste[@]})" )
if ! $yt_dl ${opts[@]} --output "%(uploader|Anon)s/%(upload_date>%Y-%m-%d|)s%(upload_date& |)s%(title)s-%(id)s.%(ext)s" "$(${paste[@]})" >> "/tmp/$LOG_NAME" 2>&1; then
$yt_dl ${opts[@]} --output "%(uploader|Anon)s/%(upload_date>%Y-%m-%d|)s%(upload_date& |)s%(webpage_url_domain)s-%(id)s.%(ext)s" "$(${paste[@]})" >> "/tmp/$LOG_NAME" 2>&1
fi
rm temp_archive.txt
}
# Video Playlist saving archive file to uploader's folder
ytvp() {
local opts=(
${opts[@]}
--format '(bv+(wa[abr>=64]/ba))/b'
--format-sort res:720,tbr~2000
--download-archive temp_archive.txt
--exec after_video:'cat temp_archive.txt >> "%(uploader)s/archive.txt"; printf "" > temp_archive.txt'
)
deal_with_long_filename_playlist &
}
# Video playlist with metadata
ytvpm() {
local opts=(
${opts[@]}
--format '(bv+(wa[abr>=64]/ba))/b'
--format-sort res:720,tbr~2000
--download-archive temp_archive.txt
--exec after_video:'cat temp_archive.txt >> "%(uploader)s/archive.txt"; printf "" > temp_archive.txt'
--write-info-json
--write-comments
--write-thumbnail
)
deal_with_long_filename_playlist &
}