vd

来自Tsetien’s Wiki
跳转到导航 跳转到搜索

A very personal Windows Batch script for the downloading of videos from YouTube, Twitter (and maybe some other sources) to a local place (here in this case is D:\_WMD\) using a locally stored up-to-date Netscape-styled cookies.txt (here in this case, it is located at D:\Omnigena\cookies.txt) that automatically produced by yt-dlp. It requires the following software to be properly set up in %PATH% (here in my case is C:\_c\):

By default, the script takes the input URL and tries to download the best matching video track of a resolution up to but not more than 4K with the best audio track it finds, merges them into one file using the suitable container that yt-dlp deems, and names the final output as ‘[yymmdd] title of the video (ID of the video).ext’, where ‘yymmdd’ in the square brackets of the beginning of the filename stands for a 6-digit date string converted from the timestamp, upload date, release date, or modified date of the video—whichever the source has defined and comes first, followed by the title of the video and then ends with the video’s ID wrapped in brackets. For most of the YouTube videos these days, this means it will return a filename similar to the one exampled below:

[241008] Visit the Falkland Islands—Stanley from the Skies (9gqvkyF-CDA).webm

The ID of the video saved in the brackets of the ending part of the filename is pretty useful when it comes to videos downloaded from YouTube sources, where it can be put at the end of the following incomplete URL to recreate its source link; I cannot be certain, however, that this little trick is equally applicable on videos downloaded from other websites.

https://www.youtube.com/watch?v=

The script accepts switches listed as follows to control the maximum desired resolution of the video to be downloaded:

  • -l: if applied, the script will remove all the resolution restrictions and try to download the best (highest) resolution of video it finds;
  • -m: if applied, the script will try to download the video with the highest resolution that is under 4K;
  • -s: if applied, the script will try to download the video with the highest resolution that is under 2K, which normally means ‘1080p’; and
  • -ss: if applied, the script will try to download the video with the highest resolution that is under 1080p, which normally means ‘720p’.

Apart from these quality control switches, there is a special -t switch that is dedicated to Twitter video downloading, which, when applied:

  • the naming pattern will change into ‘[yymmdd] display name of the Twitter user (UID of the Twitter user) Tweet ID.ext’, similar to the example shown below:
    [241115] Sky News (SkyNews) 1857335821038211072.mp4
  • a text file bearing the same name as the video will be saved alongside, in which the link to the Tweet, the full content of the Tweet, the timestamp of the Tweet’ publication, and the timestamp of the downloading of the Tweet’s video are recorded in the format of the example shown below:
https://twitter.com/SkyNews/status/1857335996020367814
The UK economy grew by just 0.1% during the first three months of the Labour government, according to official figures The figures are down from the 0.5% growth in the second quarter of 2024. Sky's @gurpreetnarwan has the details ⬇️ 📺 Sky 501
Originally posted at: 20241115GMT081303, Retrieved at: 20241115GMT082239
  • the saving location (of the video and the text) will be changed to a subfolder named _twitter; and
  • the quality switches will be ignored since the resolutions of the videos on Twitter are normally low enough.

The script also accepts the following switches to append the main download command with their corresponding patches if applied:

  • -ws: appends --write-subs to the main command;
  • -was: appends --write-auto-subs to the main command;
  • -en: appends --sub-langs "en.*" to the main command; and
  • -srt: appends --convert-subs srt to the main command.

Lastly, if -k is applied, then the script will extract the video’s audio track and save it alongside in its original format, provided the current directory is writable—yes, the current path, not the save location prewritten in the script, as an intermediate random file will first be written there and then be deleted shortly after.

When extracting the audio track using -k, its metadata will be stripped by default, unless the double k switch (-kk) is applied instead of the single one.

A translated bash version is enclosed at the end.

The batch

vd.bat
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
set "a="
set "c=%AppData%\yt-dlp\config-d"
set "e="
set "k="
set "kk="
set "n="
set "t="
set "u="
set "x="
set "int="
set "r32="
set "str=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"
for /l %%i in (1,1,32) do (
	set /a int=!random!%%63
	for %%j in (!int!) do set "r32=!r32!!str:~%%j,1!"
)
:a
if /i "%~1"=="" goto p
if /i "%~1"=="-ss" set "c=%AppData%\yt-dlp\config-ss"
if /i "%~1"=="-s" set "c=%AppData%\yt-dlp\config-s"
if /i "%~1"=="-m" set "c=%AppData%\yt-dlp\config-m"
if /i "%~1"=="-l" set "c=%AppData%\yt-dlp\config-l"
if /i "%~1"=="-t" set "c=%AppData%\yt-dlp\config-t"
if /i "%~1"=="-ws" set "a=%a% --write-subs"
if /i "%~1"=="-was" set "a=%a% --write-auto-subs"
if /i "%~1"=="-en" set "a=%a% --sub-langs "en.*""
if /i "%~1"=="-srt" set "a=%a% --convert-subs srt"
if /i "%~1"=="-k" set "k=1"
if /i "%~1"=="-kk" set "kk=1"
if /i not "%~1"=="-l" if /i not "%~1"=="-m" if /i not "%~1"=="-s" if /i not "%~1"=="-ss" if /i not "%~1"=="-t" if /i not "%~1"=="-ws" if /i not "%~1"=="-was" if /i not "%~1"=="-en" if /i not "%~1"=="-srt" if /i not "%~1"=="-k" if /i not "%~1"=="-kk" if not defined u set "u=%~1"
shift
goto a
:p
if not defined u goto e
yt-dlp "%u%" --config-location "%c%"%a%
if not defined k if not defined kk goto e
if /i "%c%"=="%AppData%\yt-dlp\config-t" (
	for /f "delims=" %%a in ('yt-dlp "%u%" --config-location "%AppData%\yt-dlp\config-tvn"') do set "n=%%a"
) else (
	for /f "delims=" %%a in ('yt-dlp "%u%" --config-location "%AppData%\yt-dlp\config-vn"') do set "n=%%a"
)
if exist "!n!.webm" (
	set "t=.webm"
) else if exist "!n!.mkv" (
	set "t=.mkv"
) else if exist "!n!.mp4" (
	set "t=.mp4"
) else if exist "!n!.flv" (
	set "t=.flv"
) else goto e
ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "!n!!t!" > %r32%.txt
for /f "delims=" %%b in (%r32%.txt) do set "e=%%b"
del /q %r32%.txt
if /i "!e!"=="opus" set "x=.opus"
if /i "!e!"=="aac" set "x=.m4a"
if /i "!e!"=="mp3" set "x=.mp3"
if /i "!e!"=="vorbis" set "x=.ogg"
if not defined x goto e
if not defined kk (
	ffmpeg -i "!n!!t!" -vn -c:a copy -map_metadata -1 -map_chapters -1 -metadata:s handler_name= -metadata:s vendor_id= -disposition 0 "!n!!x!"
) else (
	ffmpeg -i "!n!!t!" -vn -c:a copy "!n!!x!"
)
:e
endlocal

The yt-dlp configuration files

These files shall be put into %AppData%\yt-dlp with no extension attached to their filenames.

NB
Please note that the second space in line 5 of the following config file—the one preceding %(title)s—is turned into a non-breaking space, which is not intended; and yet this is due to an internal error made by either SyntaxHighlight or MediaWiki and hence not controllable by this site. Therefore, it is advised to manually replace it with a regular space before practical application.
config
--write-subs
--write-auto-subs
-f "bv*+ba/b"
--cookies "D:\Omnigena\cookies.txt"
-o "D:\_WMD\[%(timestamp>%y%m%d,upload_date>%y%m%d,release_date>%y%m%d,modified_date>%y%m%d)s] %(title)s (%(id)s).%(ext)s"
--replace-in-metadata "title" "\: " "—"
--replace-in-metadata "title" "\?" ""
--replace-in-metadata "title" "\:" "-"
--replace-in-metadata "title" "[\"]" "'"
--replace-in-metadata "title" "[\|]" " · "
--replace-in-metadata "title" "  " " "
--extractor-args youtubetab:skip=authcheck
NB
Please note that the second space in line 2 of the following config file—the one preceding %(title)s—is turned into a non-breaking space, which is not intended; and yet this is due to an internal error made by either SyntaxHighlight or MediaWiki and hence not controllable by this site. Therefore, it is advised to manually replace it with a regular space before practical application.
config-vn
--print filename
-o "D:\_WMD\[%(timestamp>%y%m%d,upload_date>%y%m%d,release_date>%y%m%d,modified_date>%y%m%d)s] %(title)s (%(id)s)"
NB
Please note that the second space (the one preceding %(uploader)s) and the fourth (the one preceding %(display_id,id)s) in line 2 of the following config file are turned into non-breaking spaces, which is not intended; and yet this is due to an internal error made by either SyntaxHighlight or MediaWiki and hence not controllable by this site. Therefore, it is advised to manually replace them with regular spaces before practical application.
config-tvn
--print filename
-o "D:\_WMD\_twitter\[%(timestamp>%y%m%d,upload_date>%y%m%d,release_date>%y%m%d,modified_date>%y%m%d)s] %(uploader)s (%(uploader_id,channel_id)s) %(display_id,id)s%(playlist_index& [|)s%(playlist_index|)s%(playlist_index&]|)s"
config-d
--no-write-subs
--no-write-auto-subs
-f "bv*[height<=?4200][width<=?4200]+ba/b"
-S "res:2900"
config-l
--no-write-subs
--no-write-auto-subs
config-m
--no-write-subs
--no-write-auto-subs
-f "bv*[height<=?3600][width<=?3600]+ba/b"
-S "res:2700"
config-s
--no-write-subs
--no-write-auto-subs
-f "bv*[height<=?2520][width<=?2520]+ba/b"
-S "res:1400"
config-ss
--no-write-subs
--no-write-auto-subs
-f "bv*[height<=?1890][width<=?1890]+ba/b"
-S "res:1050"
NB
Please note that there are many space characters in lines 3 and 4 of the following config file (highlit) are turned into non-breaking spaces, which is not intended; and yet this is due to an internal error made by either SyntaxHighlight or MediaWiki and hence not controllable by this site. Therefore, it is advised to manually replace them with regular spaces before practical application.
config-t
--no-write-subs
--no-write-auto-subs
--print-to-file "%(webpage_url)s%(description)s%(timestamp>%Y%m%dGMT%H%M%S)s, Retrieved at: %(epoch>%Y%m%dGMT%H%M%S)s" "D:\_WMD\_twitter\[%(timestamp>%y%m%d,upload_date>%y%m%d,release_date>%y%m%d,modified_date>%y%m%d)s] %(uploader)s (%(uploader_id,channel_id)s) %(display_id,id)s.txt"
-o "D:\_WMD\_twitter\[%(timestamp>%y%m%d,upload_date>%y%m%d,release_date>%y%m%d,modified_date>%y%m%d)s] %(uploader)s (%(uploader_id,channel_id)s) %(display_id,id)s%(playlist_index& [|)s%(playlist_index|)s%(playlist_index&]|)s.%(ext)s"
--replace-in-metadata "description" "(^.+?)( https\:\/\/t\.co\/.{1,20}?\Z)" "\n\1\nOriginally posted at: "
--replace-in-metadata "webpage_url" "https://x.com" "https://twitter.com"

And a bash translation

The following bash script is translated by ChatGPT 5.1. And since it is to be used on Linux, the configuration files above shall, then of course, be modified first (the paths, obviously) and then put into ~/.config/yt-dlp/.

There are some trivial differences between the following bash script and the above batch one; they are intended by design, and will therefore not be aligned in the future.

Both scripts use -k to extract the audio track, but on Linux, the metadata of the extracted audio track will be kept by default. Only when another switch, -c, is separately applied, will the script cleanse the metadata from the audio track. And, there is an added switch, -a, exclusive to the bash script, independent of and prioritised over -k, that, when applied, the original video will be deleted, leaving only the extracted audio track. (Still, -c is needed for the removal of metadata.)

vd
#!/bin/bash
set -euo pipefail
a=""
c="$HOME/.config/yt-dlp/config-d"
d=""
e=""
k=""
n=""
t=""
u=""
x=""
z=""
while [ $# -gt 0 ]; do
	if [ "$1" = "-ss" ]; then c="$HOME/.config/yt-dlp/config-ss"
	elif [ "$1" = "-s" ]; then c="$HOME/.config/yt-dlp/config-s"
	elif [ "$1" = "-m" ]; then c="$HOME/.config/yt-dlp/config-m"
	elif [ "$1" = "-l" ]; then c="$HOME/.config/yt-dlp/config-l"
	elif [ "$1" = "-t" ]; then c="$HOME/.config/yt-dlp/config-t"
	elif [ "$1" = "-ws" ]; then a="$a --write-subs"
	elif [ "$1" = "-was" ]; then a="$a --write-auto-subs"
	elif [ "$1" = "-en" ]; then a="$a --sub-langs en.*"
	elif [ "$1" = "-srt" ]; then a="$a --convert-subs srt"
	elif [ "$1" = "-k" ]; then k="1"
	elif [ "$1" = "-a" ]; then d="1"
	elif [ "$1" = "-c" ]; then z="-map_metadata -1 -map_chapters -1 -metadata:s handler_name= -metadata:s vendor_id= -disposition 0"
	elif [ -z "$u" ]; then u="$1"
	fi
	shift
done
if [ -z "$u" ]; then exit 0; fi
yt-dlp "$u" --config-location "$c" $a
if [ -z "$k" ] && [ -z "$d" ]; then exit 0; fi
if [ "$c" = "$HOME/.config/yt-dlp/config-t" ]; then
	n="$(yt-dlp "$u" --config-location "$HOME/.config/yt-dlp/config-tvn")"
else
	n="$(yt-dlp "$u" --config-location "$HOME/.config/yt-dlp/config-vn")"
fi
if [ -f "$n.webm" ]; then t=".webm"
elif [ -f "$n.mkv" ]; then t=".mkv"
elif [ -f "$n.mp4" ]; then t=".mp4"
elif [ -f "$n.flv" ]; then t=".flv"
else exit 0
fi
e="$(ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "$n$t")"
if [ "$e" = "opus" ]; then x=".opus"
elif [ "$e" = "aac" ]; then x=".m4a"
elif [ "$e" = "mp3" ]; then x=".mp3"
elif [ "$e" = "vorbis" ]; then x=".ogg"
else exit 0
fi
if [ -z "$z" ]; then
	ffmpeg -i "$n$t" -vn -c:a copy "$n$x"
else
	ffmpeg -i "$n$t" -vn -c:a copy $z "$n$x"
fi
if [ -z "$d" ]; then exit 0; fi
rm -f "$n$t"