使用 youtube-dl 下载播放列表。将每个视频的所有数据(包括存档文件)保存到上传者的文件夹中

使用 youtube-dl 下载播放列表。将每个视频的所有数据(包括存档文件)保存到上传者的文件夹中

这不能仅通过参数来完成,如下所示:使用 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-dlpyoutube-dl命令行实用程序从 YouTube(或其他支持的网站)下载视频。它提供了多种功能来处理下载视频和播放列表的不同场景。以下是该脚本功能的详细说明:

  1. 常用选项yt-dlp:它为/定义了一组常用选项youtube-dl,例如继续部分下载的文件、避免覆盖、启用详细输出以及将文件名限制为 ASCII 字符。

  2. 检测 yt-dlp/youtube-dl:该脚本尝试通过检查特定位置或使用命令来查找系统上的yt-dlp或可执行文件。youtube-dlwhich

  3. 配置粘贴命令:根据操作系统(macOS 或 Linux),脚本配置适当的命令来粘贴剪贴板内容(pbpastexselxclip)。

  4. get_log_filename 函数:此函数根据输入生成日志文件名,用下划线替换非字母数字字符,并将输入截断为 200 个字符。

  5. get_uploader 函数yt-dlp:此函数使用/检索给定视频 URL 的上传者名称youtube-dl

  6. download_video_into_uploaders_folder 函数:此函数将视频从提供的 URL(或剪贴板内容)下载到以上传者命名的文件夹中。它为每个上传者创建一个子文件夹,并存储一个存档文件来跟踪下载的视频。视频文件名包括上传者姓名、上传日期、标题和视频 ID。

  7. ytdlvu 函数:该函数是一个包装器download_video_into_uploaders_folder并在后台运行。

  8. download_video_with_metadata_into_uploaders_folder 函数:与类似download_video_into_uploaders_folder,但它还下载视频的元数据(信息 JSON、评论和缩略图)。

  9. ytdlvmu 函数:该函数是一个包装器download_video_with_metadata_into_uploaders_folder并在后台运行。

  10. download_video_playlist_with_metadata_into_uploaders_folder 函数:此函数下载整个播放列表,从提供的播放列表 URL 中提取视频 URL 并调用ytdlvmu每个视频。

  11. ytdlvpmu 函数:该函数是一个包装器download_video_playlist_with_metadata_into_uploaders_folder并在后台运行。

总之,该脚本提供了一组从 YouTube(或其他支持的网站)下载视频和播放列表的函数,同时按上传者组织它们并包含元数据。它支持yt-dlpyoutube-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 &
}

相关内容