mirror of
https://github.com/LukeHagar/ytdl-sub.git
synced 2025-12-06 04:22:12 +00:00
[BACKEND] Update music video example with url download strategy (#312)
* [DOCS] document file __preset__ * [REFACTOR] Use `download` type in examples * TODO: download strategy docs, validate fixtures, fix playlist test * playlist fixed, fixtures look good * download strategy docs, fix tests * better docs * lint * yt fixed * split chapters fixed * fix video * better docs * lint
This commit is contained in:
1
Makefile
1
Makefile
@@ -12,6 +12,7 @@ clean:
|
||||
build/ \
|
||||
dist/ \
|
||||
src/ytdl_sub.egg-info/ \
|
||||
docs/_html/ \
|
||||
.coverage \
|
||||
coverage.xml
|
||||
|
||||
|
||||
@@ -36,69 +36,18 @@ download_strategy
|
||||
Download strategies dictate what is getting downloaded from a source. Each
|
||||
download strategy has its own set of parameters.
|
||||
|
||||
youtube
|
||||
'''''''
|
||||
Download strategies for downloading videos (or audio if you configure `ytdl_options`_ correctly) from Youtube. See
|
||||
Download strategies for downloading music from Soundcloud. See
|
||||
:class:`Youtube Variables <ytdl_sub.entries.variables.youtube_variables>`
|
||||
for available source variables to use.
|
||||
.. _url:
|
||||
|
||||
channel
|
||||
_______
|
||||
.. autoclass:: ytdl_sub.downloaders.youtube.channel.YoutubeChannelDownloaderOptions()
|
||||
:members: channel_url, channel_avatar_path, channel_banner_path
|
||||
:member-order: bysource
|
||||
:exclude-members: get_date_range
|
||||
|
||||
.. autofunction:: ytdl_sub.downloaders.youtube.channel.YoutubeChannelDownloader.ytdl_option_defaults()
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
.. _YouTube Playlist:
|
||||
|
||||
playlist
|
||||
________
|
||||
.. autoclass:: ytdl_sub.downloaders.youtube.playlist.YoutubePlaylistDownloaderOptions()
|
||||
:members: playlist_url, playlist_thumbnail_name
|
||||
url
|
||||
'''
|
||||
.. autoclass:: ytdl_sub.downloaders.generic.url.UrlDownloadOptions()
|
||||
:members: url, playlist_thumbnails, source_thumbnails
|
||||
:member-order: bysource
|
||||
|
||||
.. autofunction:: ytdl_sub.downloaders.youtube.playlist.YoutubePlaylistDownloader.ytdl_option_defaults()
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
video
|
||||
_____
|
||||
.. autoclass:: ytdl_sub.downloaders.youtube.video.YoutubeVideoDownloaderOptions()
|
||||
:members: video_url
|
||||
:member-order: bysource
|
||||
|
||||
.. autofunction:: ytdl_sub.downloaders.youtube.video.YoutubeVideoDownloader.ytdl_option_defaults()
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
merge_playlist
|
||||
______________
|
||||
.. autoclass:: ytdl_sub.downloaders.youtube.merge_playlist.YoutubeMergePlaylistDownloaderOptions()
|
||||
:members: playlist_url, add_chapters
|
||||
:member-order: bysource
|
||||
|
||||
.. autofunction:: ytdl_sub.downloaders.youtube.merge_playlist.YoutubeMergePlaylistDownloader.ytdl_option_defaults()
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
soundcloud
|
||||
''''''''''
|
||||
Download strategies for downloading music from Soundcloud. See
|
||||
:class:`Soundcloud Variables <ytdl_sub.entries.variables.soundcloud_variables>`
|
||||
for available source variables to use.
|
||||
|
||||
albums_and_singles
|
||||
__________________
|
||||
.. autoclass:: ytdl_sub.downloaders.soundcloud.albums_and_singles.SoundcloudAlbumsAndSinglesDownloadOptions()
|
||||
:members: url, skip_premiere_tracks
|
||||
:member-order: bysource
|
||||
|
||||
.. autofunction:: ytdl_sub.downloaders.soundcloud.albums_and_singles.SoundcloudAlbumsAndSinglesDownloader.ytdl_option_defaults()
|
||||
multi_url
|
||||
'''''''''
|
||||
.. autoclass:: ytdl_sub.downloaders.generic.multi_url.MultiUrlDownloadOptions()
|
||||
:members: urls, variables
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -171,6 +120,7 @@ audio_extract
|
||||
.. autoclass:: ytdl_sub.plugins.audio_extract.AudioExtractOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -179,6 +129,7 @@ chapters
|
||||
.. autoclass:: ytdl_sub.plugins.chapters.ChaptersOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -187,12 +138,14 @@ date_range
|
||||
.. autoclass:: ytdl_sub.plugins.date_range.DateRangeOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
file_convert
|
||||
''''''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.file_convert.FileConvertOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -200,6 +153,7 @@ music_tags
|
||||
''''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.music_tags.MusicTagsOptions()
|
||||
:members:
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -208,6 +162,7 @@ nfo_tags
|
||||
.. autoclass:: ytdl_sub.plugins.nfo_tags.NfoTagsOptions()
|
||||
:members: nfo_name, nfo_root, tags, kodi_safe
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -216,6 +171,7 @@ output_directory_nfo_tags
|
||||
.. autoclass:: ytdl_sub.plugins.output_directory_nfo_tags.OutputDirectoryNfoTagsOptions()
|
||||
:members: nfo_name, nfo_root, tags, kodi_safe
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -227,6 +183,7 @@ regex
|
||||
.. autoclass:: ytdl_sub.plugins.regex.SourceVariableRegex()
|
||||
:members: match, capture_group_names, capture_group_defaults
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -235,6 +192,7 @@ split_by_chapters
|
||||
.. autoclass:: ytdl_sub.plugins.split_by_chapters.SplitByChaptersOptions()
|
||||
:members: when_no_chapters
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -243,6 +201,7 @@ subtitles
|
||||
.. autoclass:: ytdl_sub.plugins.subtitles.SubtitleOptions()
|
||||
:members: subtitles_name, subtitles_type, embed_subtitles, languages, allow_auto_generated_subtitles
|
||||
:member-order: bysource
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -250,6 +209,7 @@ video_tags
|
||||
''''''''''
|
||||
.. autoclass:: ytdl_sub.plugins.video_tags.VideoTagsOptions()
|
||||
:members:
|
||||
:exclude-members: partial_validate
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
# This example shows how we can use the `kodi_music_videos_config.yaml` preset
|
||||
# to download music videos in a few different ways. We will use made-up artists
|
||||
# in each example
|
||||
|
||||
###############################################################################
|
||||
# LEVEL 1 - DOWNLOAD MUSIC VIDEO PLAYLIST
|
||||
|
||||
# Subscription names are defined by you. We will call this one john_smith
|
||||
# for simplicity, and it will download every single video in john_smith's music
|
||||
# video playlist. Many artists maintain a playlist of all their music videos,
|
||||
# which makes this an easy way to grab all of them.
|
||||
john_smith:
|
||||
# We must define a preset to use from our config. We named the one in the
|
||||
# config example "yt_music_video", so set that here.
|
||||
preset: "yt_music_video_playlist"
|
||||
|
||||
# Since our preset download strategy is set to 'playlist', set the playlist url
|
||||
youtube:
|
||||
playlist_url: "https://youtube.com/playlist?list=UCsvn_Po0SmunchJYtttWpOxMg"
|
||||
|
||||
# Overrides can be defined per-subscription. If you noticed, we used {artist}
|
||||
# and {artist_sanitized} in our "yt_music_video" preset. We intended to reserve
|
||||
# that variable to be defined for each individual subscription. Each override
|
||||
# defined here will create a '_sanitized' version that is safe for file systems.
|
||||
#
|
||||
# A note for Kodi music videos, it is important to make sure your artist name
|
||||
# exactly matches how it is formatted in Kodi itself, otherwise it will be
|
||||
# read in as a new artist
|
||||
overrides:
|
||||
artist: "John Smith and the Instrument Players"
|
||||
|
||||
###############################################################################
|
||||
# LEVEL 2 - DOWNLOAD SINGLE MUSIC VIDEO
|
||||
|
||||
# It is not always ideal to download all of an artist's music videos.
|
||||
# Maybe you only like one song of theirs. We can reuse our preset
|
||||
# to download a single video instead.
|
||||
#
|
||||
# The only difference between this example and the one above is
|
||||
# - preset
|
||||
# Use the music video preset, not the playlist preset
|
||||
# - youtube.video_url
|
||||
# The video url to download
|
||||
#
|
||||
# Of course, defining yaml configuration to download a single video once
|
||||
# and never again seems weird. Instead, we can perform this download via
|
||||
# command:
|
||||
#
|
||||
# ytdl-sub dl \
|
||||
# --preset "yt_music_video" \
|
||||
# --youtube.video_url "https://youtube.com/watch?v=QhY6r6oAErg" \
|
||||
# --overrides.artist "John Smith and the Instrument Players"
|
||||
#
|
||||
john_smith_one_hit_wonder:
|
||||
preset: "yt_music_video"
|
||||
youtube:
|
||||
video_url: "https://youtube.com/watch?v=QhY6r6oAErg"
|
||||
overrides:
|
||||
artist: "John Smith and the Instrument Players"
|
||||
@@ -3,14 +3,14 @@ configuration:
|
||||
working_directory: '.ytdl-sub-downloads'
|
||||
|
||||
presets:
|
||||
yt_song:
|
||||
youtube:
|
||||
download_strategy: "video"
|
||||
song:
|
||||
download:
|
||||
download_strategy: "url"
|
||||
url: "{url}"
|
||||
|
||||
output_options:
|
||||
output_directory: "{music_directory}"
|
||||
file_name: "{custom_track_name_sanitized}.{ext}"
|
||||
info_json_name: "{custom_track_name_sanitized}.{info_json_ext}"
|
||||
|
||||
audio_extract:
|
||||
codec: "mp3"
|
||||
@@ -34,15 +34,13 @@ presets:
|
||||
custom_track_number: "1"
|
||||
|
||||
# TODO: make a playlist of individual songs into an album. Need playlist_title
|
||||
yt_song_playlist:
|
||||
preset: yt_song
|
||||
youtube:
|
||||
download_strategy: "playlist"
|
||||
song_playlist:
|
||||
preset: "song"
|
||||
overrides:
|
||||
custom_track_number: "{playlist_index}"
|
||||
|
||||
yt_album_as_chapters:
|
||||
preset: "yt_song"
|
||||
album_from_chapters:
|
||||
preset: "song"
|
||||
output_options:
|
||||
file_name: "{custom_album_name_sanitized}/{chapter_index_padded} - {custom_track_name_sanitized}.{ext}"
|
||||
thumbnail_name: "{custom_album_name_sanitized}/folder.{thumbnail_ext}"
|
||||
@@ -1,12 +1,13 @@
|
||||
# This example shows how to download and format a Youtube video OR playlist
|
||||
# to display in Kodi as a music video. Kodi requires music videos to be in
|
||||
# a shared directory, so we will configure this to make the output directory
|
||||
# formatted as:
|
||||
# This example shows how to download and format a music video OR playlist
|
||||
# of music videos to display in Kodi as a music video. The format will
|
||||
# look like:
|
||||
#
|
||||
# /path/to/Music Videos
|
||||
# Elton John/
|
||||
# Elton John - Rocketman-thumb.jpg
|
||||
# Elton John - Rocketman.mp4
|
||||
# Elton John - Rocketman.nfo
|
||||
# System of a Down/
|
||||
# System of a Down - Chop Suey-thumb.jpg
|
||||
# System of a Down - Chop Suey.mp4
|
||||
# System of a Down - Chop Suey.nfo
|
||||
@@ -16,20 +17,21 @@ configuration:
|
||||
working_directory: '.ytdl-sub-downloads'
|
||||
|
||||
presets:
|
||||
yt_music_video:
|
||||
# A single YouTube video is our source/download strategy. However, this
|
||||
# can be overwritten to download music videos from a "playlist", as we
|
||||
# will see in a preset below
|
||||
youtube:
|
||||
download_strategy: "video"
|
||||
music_video:
|
||||
# Set the download details
|
||||
download:
|
||||
# We will only use a single URL to download music video(s).
|
||||
# Make {url} an override variable to set later.
|
||||
download_strategy: "url"
|
||||
url: "{url}"
|
||||
|
||||
# For advanced YTDL users only; any YTDL parameter can be set here.
|
||||
# To download age-restricted videos, you will need to set your cookie
|
||||
# file here as a ytdl parameter. For more info, see
|
||||
# https://ytdl-sub.readthedocs.io/en/latest/faq.html#download-age-restricted-youtube-videos
|
||||
#
|
||||
# ytdl_options:
|
||||
# cookiefile: "path/to/cookie_file.txt
|
||||
ytdl_options:
|
||||
# cookiefile: "path/to/cookie_file.txt
|
||||
break_on_existing: True # Stop downloads if it already exists
|
||||
|
||||
# For each video downloaded, set the file and thumbnail name here.
|
||||
# We set both with {music_video_name}, which is a variable we define in
|
||||
@@ -39,6 +41,7 @@ presets:
|
||||
file_name: "{music_video_name}.{ext}"
|
||||
thumbnail_name: "{music_video_name}-thumb.jpg"
|
||||
info_json_name: "{music_video_name}.{info_json_ext}"
|
||||
maintain_download_archive: True
|
||||
|
||||
# For each video downloaded, add a music video NFO file for it. Populate it
|
||||
# with tags that Kodi will read and use to display it in the music or music
|
||||
@@ -55,23 +58,10 @@ presets:
|
||||
# Overrides is a section where we can define our own variables, and use them in
|
||||
# any other section. We define our music video directory and episode file name
|
||||
# here, which gets reused above for the video, thumbnail, and NFO file.
|
||||
# Recommended to override the artist variable.
|
||||
# Recommended to override the artist variable since {channel} is not always
|
||||
# the artist's exact name.
|
||||
overrides:
|
||||
music_video_directory: "path/to/Music Videos"
|
||||
music_video_name: "{artist_sanitized} - {title_sanitized}"
|
||||
music_video_name: "{artist_sanitized}/{artist_sanitized} - {title_sanitized}"
|
||||
artist: "{channel}"
|
||||
|
||||
# It is not always ideal to download all of an artist's music videos.
|
||||
# Maybe you only like one song of theirs. We can reuse our preset above
|
||||
# to download a single video instead.
|
||||
yt_music_video_playlist:
|
||||
preset: "yt_music_video"
|
||||
youtube:
|
||||
download_strategy: "playlist"
|
||||
|
||||
# Setting maintain_download_archive=True is generally a good thing to enable
|
||||
# with playlists and channels because it will store previously downloaded
|
||||
# video ids to tell YTDL not to re-download them on a successive invocation.
|
||||
output_options:
|
||||
maintain_download_archive: True
|
||||
|
||||
24
examples/music_videos_subscriptions.yaml
Normal file
24
examples/music_videos_subscriptions.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
###############################################################################
|
||||
# DOWNLOAD MUSIC VIDEO PLAYLIST
|
||||
john_smith:
|
||||
preset: "music_video"
|
||||
overrides:
|
||||
url: "https://youtube.com/playlist?list=UCsvn_Po0SmunchJYtttWpOxMg"
|
||||
artist: "John Smith and the Instrument Players"
|
||||
|
||||
###############################################################################
|
||||
# DOWNLOAD SINGLE MUSIC VIDEO VIA CLI
|
||||
|
||||
# It is not always ideal to download all of an artist's music videos.
|
||||
# Maybe you only like one song of theirs. We can reuse our preset
|
||||
# to download a single video instead.
|
||||
#
|
||||
# Of course, defining yaml configuration to download a single video once
|
||||
# and never again seems weird. Instead, we can perform this download via
|
||||
# command-line:
|
||||
#
|
||||
# ytdl-sub dl \
|
||||
# --preset "music_video" \
|
||||
# --override.url "https://youtube.com/watch?v=QhY6r6oAErg" \
|
||||
# --overrides.artist "John Smith and the Instrument Players"
|
||||
#
|
||||
@@ -134,6 +134,12 @@ class DownloadArgsParser:
|
||||
|
||||
next_dict[arg_name_split[-1]] = arg_value
|
||||
|
||||
# TODO: handle ints/floats
|
||||
if arg_value == "True":
|
||||
next_dict[arg_name_split[-1]] = True
|
||||
elif arg_value == "False":
|
||||
next_dict[arg_name_split[-1]] = False
|
||||
|
||||
return argument_dict
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -51,20 +51,20 @@ class ConfigOptions(StrictDictValidator):
|
||||
|
||||
configuration:
|
||||
dl_aliases:
|
||||
mv: "--preset yt_music_video"
|
||||
v: "--youtube.video_url"
|
||||
mv: "--preset music_video"
|
||||
u: "--download.url"
|
||||
|
||||
Simplifies
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
ytdl-sub dl --preset "yt_music_video" --youtube.video_url "youtube.com/watch?v=a1b2c3"
|
||||
ytdl-sub dl --preset "music_video" --download.url "youtube.com/watch?v=a1b2c3"
|
||||
|
||||
to
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
ytdl-sub dl --mv --v "youtube.com/watch?v=a1b2c3"
|
||||
ytdl-sub dl --mv --u "youtube.com/watch?v=a1b2c3"
|
||||
"""
|
||||
if self._dl_aliases:
|
||||
return self._dl_aliases.dict
|
||||
|
||||
@@ -550,7 +550,7 @@ class Downloader(DownloadArchiver, Generic[DownloaderOptionsT], ABC):
|
||||
) -> Iterable[Entry] | Iterable[Tuple[Entry, FileMetadata]]:
|
||||
"""The function to perform the download of all media entries"""
|
||||
# download the bottom-most urls first since they are top-priority
|
||||
for collection_url in reversed(self.collection.collection_urls.list):
|
||||
for collection_url in reversed(self.collection.urls.list):
|
||||
parents, orphan_entries = self._download_url_metadata(collection_url=collection_url)
|
||||
collection_url_entries: List[Entry] = []
|
||||
|
||||
|
||||
@@ -71,9 +71,9 @@ class UrlValidator(StrictDictValidator):
|
||||
@property
|
||||
def url(self) -> OverridesStringFormatterValidator:
|
||||
"""
|
||||
URL to download from, listed in priority from lowest (top) to highest (bottom). If a
|
||||
download exists in more than one URL, it will resolve to the bottom-most one and inherit
|
||||
those variables.
|
||||
Required. URL to download from, listed in priority from lowest (top) to highest (bottom).
|
||||
If a download exists in more than one URL, it will resolve to the bottom-most one and
|
||||
inherit those variables.
|
||||
"""
|
||||
return self._url
|
||||
|
||||
@@ -85,30 +85,13 @@ class UrlValidator(StrictDictValidator):
|
||||
"""
|
||||
return self._variables
|
||||
|
||||
@property
|
||||
def source_thumbnails(self) -> Optional[UrlThumbnailListValidator]:
|
||||
"""
|
||||
Thumbnails to download from the source, if any exist. The hierarchy is defined as
|
||||
source -> playlist -> entry.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
source_thumbnails:
|
||||
- name: "poster.jpg"
|
||||
uid: "avatar_uncropped"
|
||||
|
||||
UID is the yt-dlp thumbnail ID or can specify ``latest_entry`` to use the last entry's
|
||||
thumbnail that was downloaded.
|
||||
"""
|
||||
return self._source_thumbnails
|
||||
|
||||
@property
|
||||
def playlist_thumbnails(self) -> Optional[UrlThumbnailListValidator]:
|
||||
"""
|
||||
Thumbnails to download from the source, if any exist. The hierarchy is defined as
|
||||
source -> playlist -> entry.
|
||||
Thumbnails to download from the playlist, if any exist. Playlist is the ``yt-dlp`` naming
|
||||
convention for a set that contains multiple entries. For example, the URL
|
||||
``https://www.youtube.com/c/RickastleyCoUkOfficial`` would have ``playlist`` refer to the
|
||||
channel.
|
||||
|
||||
Usage:
|
||||
|
||||
@@ -117,12 +100,40 @@ class UrlValidator(StrictDictValidator):
|
||||
playlist_thumbnails:
|
||||
- name: "poster.jpg"
|
||||
uid: "avatar_uncropped"
|
||||
- name: "fanart.jpg"
|
||||
uid: "banner_uncropped"
|
||||
|
||||
UID is the yt-dlp thumbnail ID or can specify ``latest_entry`` to use the last entry's
|
||||
thumbnail that was downloaded.
|
||||
``name`` is the file name relative to the output directory to store the thumbnail.
|
||||
``uid`` is the yt-dlp thumbnail ID. Can specify ``latest_entry`` to use the latest entry's
|
||||
thumbnail.
|
||||
"""
|
||||
return self._playlist_thumbnails
|
||||
|
||||
@property
|
||||
def source_thumbnails(self) -> Optional[UrlThumbnailListValidator]:
|
||||
"""
|
||||
Thumbnails to download from the source, if any exist. Source in this context refers to the
|
||||
set of sets. For example, the URL
|
||||
``https://www.youtube.com/c/RickastleyCoUkOfficial/playlists``
|
||||
would have ``playlist`` refer to each individual playlist, whereas ``source`` refers
|
||||
to the channel.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
source_thumbnails:
|
||||
- name: "poster.jpg"
|
||||
uid: "avatar_uncropped"
|
||||
- name: "fanart.jpg"
|
||||
uid: "banner_uncropped"
|
||||
|
||||
``name`` is the file name relative to the output directory to store the thumbnail.
|
||||
``uid`` is the yt-dlp thumbnail ID. Can specify ``latest_entry`` to use the latest entry's
|
||||
thumbnail.
|
||||
"""
|
||||
return self._source_thumbnails
|
||||
|
||||
|
||||
class UrlListValidator(ListValidator[UrlValidator]):
|
||||
_inner_list_type = UrlValidator
|
||||
@@ -173,12 +184,22 @@ class MultiUrlValidator(StrictDictValidator, AddsVariablesMixin):
|
||||
self._urls = self._validate_key(key="urls", validator=UrlListValidator)
|
||||
|
||||
@property
|
||||
def collection_urls(self) -> UrlListValidator:
|
||||
def urls(self) -> UrlListValidator:
|
||||
"""
|
||||
Required. The Soundcloud user's url, i.e. ``soundcloud.com/the_username``
|
||||
Required. A list of :ref:`url` with the addition of the ``variables`` attribute.
|
||||
"""
|
||||
return self._urls
|
||||
|
||||
@property
|
||||
def variables(self) -> DictFormatterValidator:
|
||||
"""
|
||||
Optional. Source variables to add to each entry downloaded from its respective :ref:`url`.
|
||||
The top-most :ref:`url` must define all possible variables. Other :ref:`url` entries can
|
||||
redefine all of them or a subset of the top-most variables.
|
||||
"""
|
||||
# keep for readthedocs documentation
|
||||
return self._urls.list[0].variables
|
||||
|
||||
def added_source_variables(self) -> List[str]:
|
||||
"""
|
||||
Returns
|
||||
@@ -205,7 +226,7 @@ class MultiUrlValidator(StrictDictValidator, AddsVariablesMixin):
|
||||
)
|
||||
|
||||
# Apply formatting to each new source variable, ensure it resolves
|
||||
for collection_url in self.collection_urls.list:
|
||||
for collection_url in self.urls.list:
|
||||
for (
|
||||
source_var_name,
|
||||
source_var_formatter_str,
|
||||
|
||||
@@ -144,7 +144,7 @@ class YoutubeMergePlaylistDownloader(Downloader[YoutubeMergePlaylistDownloaderOp
|
||||
|
||||
def download(self) -> List[Tuple[Entry, FileMetadata]]:
|
||||
"""Download a single Youtube video, then split it into multiple videos"""
|
||||
url = self.overrides.apply_formatter(self.collection.collection_urls.list[0].url)
|
||||
url = self.overrides.apply_formatter(self.collection.urls.list[0].url)
|
||||
|
||||
entry_dict = self.extract_info(url=url)
|
||||
merged_video = self._to_merged_video(entry_dict=entry_dict)
|
||||
|
||||
@@ -63,7 +63,7 @@ def preset_dict_to_dl_args(preset_dict: Dict) -> str:
|
||||
def _recursive_preset_args(cli_key: str, current_value: Dict | Any) -> List[str]:
|
||||
if isinstance(current_value, dict):
|
||||
preset_args: List[str] = []
|
||||
for v_key, v_value in current_value.items():
|
||||
for v_key, v_value in sorted(current_value.items()):
|
||||
preset_args.extend(
|
||||
_recursive_preset_args(
|
||||
cli_key=f"{cli_key}.{v_key}" if cli_key else v_key, current_value=v_value
|
||||
|
||||
@@ -14,7 +14,7 @@ from ytdl_sub.utils.file_handler import FileHandlerTransactionLog
|
||||
|
||||
@pytest.fixture()
|
||||
def music_video_config_path():
|
||||
return "examples/kodi_music_videos_config.yaml"
|
||||
return "examples/music_videos_config.yaml"
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@@ -34,7 +34,7 @@ def soundcloud_discography_config():
|
||||
|
||||
@pytest.fixture()
|
||||
def youtube_audio_config_path():
|
||||
return "examples/youtube_extract_and_tag_audio.yaml"
|
||||
return "examples/music_audio_from_videos.yaml"
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
|
||||
@@ -8,8 +8,8 @@ from ytdl_sub.subscriptions.subscription import Subscription
|
||||
@pytest.fixture
|
||||
def single_song_preset_dict(output_directory):
|
||||
return {
|
||||
"preset": "yt_song",
|
||||
"youtube": {"video_url": "https://www.youtube.com/watch?v=2lAe1cqCOXo"},
|
||||
"preset": "song",
|
||||
"download": {"url": "https://www.youtube.com/watch?v=2lAe1cqCOXo"},
|
||||
"output_options": {"output_directory": output_directory},
|
||||
# download the worst format so it is fast
|
||||
"ytdl_options": {
|
||||
@@ -22,8 +22,8 @@ def single_song_preset_dict(output_directory):
|
||||
@pytest.fixture
|
||||
def multiple_songs_preset_dict(output_directory):
|
||||
return {
|
||||
"preset": "yt_song_playlist",
|
||||
"youtube": {"playlist_url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35"},
|
||||
"preset": "song_playlist",
|
||||
"download": {"url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35"},
|
||||
"output_options": {"output_directory": output_directory},
|
||||
"audio_extract": {"codec": "vorbis", "quality": 140},
|
||||
# download the worst format so it is fast
|
||||
@@ -34,6 +34,7 @@ def multiple_songs_preset_dict(output_directory):
|
||||
}
|
||||
|
||||
|
||||
# TODO: Test album from chapters
|
||||
class TestAudioExtract:
|
||||
@pytest.mark.parametrize("dry_run", [True, False])
|
||||
def test_audio_extract_single_song(
|
||||
|
||||
@@ -8,8 +8,8 @@ from ytdl_sub.subscriptions.subscription import Subscription
|
||||
@pytest.fixture
|
||||
def single_video_sponsorblock_and_embedded_subs_preset_dict(output_directory):
|
||||
return {
|
||||
"preset": "yt_music_video",
|
||||
"youtube": {"video_url": "https://www.youtube.com/watch?v=-wJOUAuKZm8"},
|
||||
"preset": "music_video",
|
||||
"download": {"url": "https://www.youtube.com/watch?v=-wJOUAuKZm8"},
|
||||
# override the output directory with our fixture-generated dir
|
||||
"output_options": {"output_directory": output_directory},
|
||||
"subtitles": {
|
||||
|
||||
@@ -8,8 +8,8 @@ from ytdl_sub.subscriptions.subscription import Subscription
|
||||
@pytest.fixture
|
||||
def preset_dict(output_directory):
|
||||
return {
|
||||
"preset": "yt_music_video",
|
||||
"youtube": {"video_url": "https://www.youtube.com/watch?v=2zYF9JLHDmA"},
|
||||
"preset": "music_video",
|
||||
"download": {"url": "https://www.youtube.com/watch?v=2zYF9JLHDmA"},
|
||||
"output_options": {"output_directory": output_directory},
|
||||
# download the worst format so it is fast
|
||||
"ytdl_options": {
|
||||
|
||||
@@ -7,8 +7,8 @@ from ytdl_sub.subscriptions.subscription import Subscription
|
||||
@pytest.fixture
|
||||
def subscription_dict(output_directory):
|
||||
return {
|
||||
"preset": "yt_music_video",
|
||||
"youtube": {"video_url": "https://www.youtube.com/shorts/ucYmEqmlhFw"},
|
||||
"preset": "music_video",
|
||||
"download": {"url": "https://www.youtube.com/shorts/ucYmEqmlhFw"},
|
||||
# override the output directory with our fixture-generated dir
|
||||
"output_options": {"output_directory": output_directory},
|
||||
# download the worst format so it is fast
|
||||
|
||||
@@ -13,8 +13,8 @@ from ytdl_sub.utils.exceptions import ValidationException
|
||||
@pytest.fixture
|
||||
def regex_subscription_dict(output_directory):
|
||||
return {
|
||||
"preset": "yt_music_video_playlist",
|
||||
"youtube": {"playlist_url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35"},
|
||||
"preset": "music_video",
|
||||
"download": {"url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35"},
|
||||
# override the output directory with our fixture-generated dir
|
||||
"output_options": {"output_directory": output_directory},
|
||||
# download the worst format so it is fast
|
||||
|
||||
@@ -12,8 +12,8 @@ from ytdl_sub.utils.exceptions import ValidationException
|
||||
@pytest.fixture
|
||||
def yt_album_as_chapters_preset_dict(output_directory):
|
||||
return {
|
||||
"preset": "yt_album_as_chapters",
|
||||
"youtube": {"video_url": "https://www.youtube.com/watch?v=zeR2_YjlXWA"},
|
||||
"preset": "album_from_chapters",
|
||||
"download": {"url": "https://www.youtube.com/watch?v=zeR2_YjlXWA"},
|
||||
# override the output directory with our fixture-generated dir
|
||||
"output_options": {"output_directory": output_directory},
|
||||
# download the worst format so it is fast
|
||||
@@ -128,7 +128,7 @@ class TestSplitByChapters:
|
||||
mergedeep.merge(
|
||||
yt_album_as_chapters_with_regex_preset_dict,
|
||||
{
|
||||
"youtube": {"video_url": "https://youtube.com/watch?v=HKTNxEqsN3Q"},
|
||||
"download": {"url": "https://youtube.com/watch?v=HKTNxEqsN3Q"},
|
||||
"split_by_chapters": {"when_no_chapters": when_no_chapters},
|
||||
},
|
||||
)
|
||||
|
||||
@@ -8,8 +8,8 @@ from ytdl_sub.subscriptions.subscription import Subscription
|
||||
@pytest.fixture
|
||||
def single_video_subs_embed_preset_dict(output_directory):
|
||||
return {
|
||||
"preset": "yt_music_video",
|
||||
"youtube": {"video_url": "https://www.youtube.com/watch?v=2lAe1cqCOXo"},
|
||||
"preset": "music_video",
|
||||
"download": {"url": "https://www.youtube.com/watch?v=2lAe1cqCOXo"},
|
||||
# override the output directory with our fixture-generated dir
|
||||
"output_options": {"output_directory": output_directory},
|
||||
"subtitles": {
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
import pytest
|
||||
from expected_download import assert_expected_downloads
|
||||
from expected_transaction_log import assert_transaction_log_matches
|
||||
|
||||
from ytdl_sub.config.config_file import ConfigFile
|
||||
from ytdl_sub.config.preset import Preset
|
||||
from ytdl_sub.subscriptions.subscription import Subscription
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def config_path():
|
||||
return "examples/kodi_music_videos_config.yaml"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def subscription_name():
|
||||
return "jmc"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def config(config_path):
|
||||
return ConfigFile.from_file_path(config_path=config_path)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def subscription_dict(output_directory, subscription_name):
|
||||
return {
|
||||
"preset": "yt_music_video_playlist",
|
||||
"youtube": {
|
||||
"download_strategy": "merge_playlist",
|
||||
"playlist_url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35",
|
||||
"add_chapters": True,
|
||||
},
|
||||
# override the output directory with our fixture-generated dir
|
||||
"output_options": {"output_directory": output_directory},
|
||||
# download the worst format so it is fast
|
||||
"ytdl_options": {
|
||||
"format": "best[height<=480]",
|
||||
"postprocessor_args": {"ffmpeg": ["-bitexact"]}, # Must add this for reproducibility
|
||||
},
|
||||
"overrides": {"artist": "JMC"},
|
||||
}
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# PLAYLIST FIXTURES
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def playlist_subscription(config, subscription_name, subscription_dict):
|
||||
playlist_preset = Preset.from_dict(
|
||||
config=config,
|
||||
preset_name=subscription_name,
|
||||
preset_dict=subscription_dict,
|
||||
)
|
||||
|
||||
return Subscription.from_preset(
|
||||
preset=playlist_preset,
|
||||
config=config,
|
||||
)
|
||||
|
||||
|
||||
# @pytest.fixture
|
||||
# def expected_playlist_download():
|
||||
# # fmt: off
|
||||
# return ExpectedDownloads(
|
||||
# expected_downloads=[
|
||||
# ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server-thumb.jpg"), md5="a3f1910f9c51f6442f845a528e190829"),
|
||||
# ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server.mkv")), # not bitexact TODO: check size
|
||||
# ExpectedDownloadFile(path=Path("JMC - Jesse's Minecraft Server.nfo"), md5="10df5dcdb65ab18ecf21b3503c77e48b"),
|
||||
# ]
|
||||
# )
|
||||
# # fmt: on
|
||||
|
||||
|
||||
class TestYoutubeMergePlaylist:
|
||||
"""
|
||||
Downloads my old minecraft youtube channel, pretends they are music videos. Ensure the above
|
||||
files exist and have the expected md5 file hashes.
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize("dry_run", [True, False])
|
||||
def test_merge_playlist_download(self, playlist_subscription, output_directory, dry_run):
|
||||
transaction_log = playlist_subscription.download(dry_run=dry_run)
|
||||
assert_transaction_log_matches(
|
||||
output_directory=output_directory,
|
||||
transaction_log=transaction_log,
|
||||
transaction_log_summary_file_name="youtube/test_merge_playlist.txt",
|
||||
)
|
||||
assert_expected_downloads(
|
||||
output_directory=output_directory,
|
||||
dry_run=dry_run,
|
||||
ignore_md5_hashes_for=["JMC - Jesse's Minecraft Server.mkv"], # TODO, better test here
|
||||
expected_download_summary_file_name="youtube/test_merge_playlist.json",
|
||||
)
|
||||
@@ -11,10 +11,10 @@ from ytdl_sub.subscriptions.subscription import Subscription
|
||||
@pytest.fixture
|
||||
def playlist_preset_dict(output_directory):
|
||||
return {
|
||||
"preset": "yt_music_video_playlist",
|
||||
"youtube": {
|
||||
"playlist_url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35",
|
||||
"playlist_thumbnail_name": "poster.jpg",
|
||||
"preset": "music_video",
|
||||
"download": {
|
||||
"url": "https://youtube.com/playlist?list=PL5BC0FC26BECA5A35",
|
||||
"playlist_thumbnails": {"name": "poster.jpg", "uid": "latest_entry"},
|
||||
},
|
||||
# override the output directory with our fixture-generated dir
|
||||
"output_options": {"output_directory": output_directory},
|
||||
|
||||
@@ -10,10 +10,13 @@ from ytdl_sub.subscriptions.subscription import Subscription
|
||||
@pytest.fixture
|
||||
def single_video_preset_dict(output_directory):
|
||||
return {
|
||||
"preset": "yt_music_video",
|
||||
"youtube": {"video_url": "https://youtube.com/watch?v=HKTNxEqsN3Q"},
|
||||
"preset": "music_video",
|
||||
"download": {"url": "https://youtube.com/watch?v=HKTNxEqsN3Q"},
|
||||
# override the output directory with our fixture-generated dir
|
||||
"output_options": {"output_directory": output_directory},
|
||||
"output_options": {
|
||||
"output_directory": output_directory,
|
||||
"maintain_download_archive": False,
|
||||
},
|
||||
# download the worst format so it is fast
|
||||
"ytdl_options": {
|
||||
"format": "worst[ext=mp4]",
|
||||
@@ -79,10 +82,10 @@ class TestYoutubeVideo:
|
||||
assert_transaction_log_matches(
|
||||
output_directory=output_directory,
|
||||
transaction_log=transaction_log,
|
||||
transaction_log_summary_file_name="youtube/test_video.txt",
|
||||
transaction_log_summary_file_name="youtube/test_video_cli.txt",
|
||||
)
|
||||
assert_expected_downloads(
|
||||
output_directory=output_directory,
|
||||
dry_run=dry_run,
|
||||
expected_download_summary_file_name="youtube/test_video.json",
|
||||
expected_download_summary_file_name="youtube/test_video_cli.json",
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3-thumb.jpg": "662fcaadf6e80d63591bac19a5fdffb0",
|
||||
"Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.info.json": "c5f4cdadcf89a60811e733f84edc8996",
|
||||
"Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.mp4": "390177bcc076e309d1534b8bb5afdcc7",
|
||||
"Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.nfo": "cacf09ab38f9b3085da9c5af516cf22a"
|
||||
".ytdl-sub-file_convert_test-download-archive.json": "65aa49c7345f9fc201e42ddc4a96b19b",
|
||||
"Beyond The Guitar/Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3-thumb.jpg": "662fcaadf6e80d63591bac19a5fdffb0",
|
||||
"Beyond The Guitar/Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.info.json": "30b444dbe693b1483904698ad1b19090",
|
||||
"Beyond The Guitar/Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.mp4": "390177bcc076e309d1534b8bb5afdcc7",
|
||||
"Beyond The Guitar/Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.nfo": "cacf09ab38f9b3085da9c5af516cf22a"
|
||||
}
|
||||
@@ -1,15 +1,4 @@
|
||||
{
|
||||
"01. Intro (Feat. Racheal Ofori & Barney Artist).info.json": "c13b562993dd1507e0be88ac003f36fe",
|
||||
"02. Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json": "d66fde52ecb4613f517db1546e9d866e",
|
||||
"03. Blaze (Feat. Kaya Thomas - Dyke).info.json": "ce72fff01376252cba06e6baa761c7db",
|
||||
"04. What If (Interlude).info.json": "d862af9c67c6433024cfb7f295f62718",
|
||||
"05. No Peace (Feat. Tom Misch).info.json": "aa779527de1e3d439d9abc3424b7f4c9",
|
||||
"06. Closer (Feat. Lester Duval).info.json": "35c99e4f14f8329fb77d6319f376f7ec",
|
||||
"07. Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json": "bd823154833b1389ed91154a2d734903",
|
||||
"08. Dreams (Feat. Carmody).info.json": "2b89e85a878cf81c7c480ab5b069f940",
|
||||
"09. Dreaming (Interlude) (Feat. Racheal Ofori).info.json": "126bd7301438748a77d94303d3ffec77",
|
||||
"10. Hopeful (Feat. Jordan Rakei).info.json": "3d13233826e965264ac2f8d28f2149f9",
|
||||
"11. Sunrise (Pillows) (Feat. Emmavie).info.json": "8671fee720b686eb9f79db63b8341eed",
|
||||
"Alfa Mist - Nocturne [Full Album]/01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3": "1ede8775719b99d05c89d6d0a2a74df5",
|
||||
"Alfa Mist - Nocturne [Full Album]/02 - 02. Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3": "2430b44a6c15050f7e2ee09274c26600",
|
||||
"Alfa Mist - Nocturne [Full Album]/03 - 03. Blaze (Feat. Kaya Thomas - Dyke).mp3": "8dbb8d15109955c4540dfe3c015157b8",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"Oblivion Mod "Falcor" p.1.info.json": "0819dc20f5803f8c91a8c8d2d9f7b211",
|
||||
"Oblivion Mod "Falcor" p.1/01 - Oblivion Mod "Falcor" p.1.mp3": "6d570f225f6c3a14de0ba4c912995641",
|
||||
"Oblivion Mod "Falcor" p.1/folder.jpg": "fb95b510681676e81c321171fc23143e"
|
||||
}
|
||||
@@ -1,13 +1,4 @@
|
||||
{
|
||||
"Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json": "fc16b2772425a226a6d4202c1f32968e",
|
||||
"Blaze (Feat. Kaya Thomas - Dyke).info.json": "5c7b118a2bd620bd8a2e9f3654bdbcf6",
|
||||
"Closer (Feat. Lester Duval).info.json": "3565218771e9366378a0b7d740ccc73c",
|
||||
"Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json": "a78f4db52e9d1c68b800d8714d209c9f",
|
||||
"Dreaming (Interlude) (Feat. Racheal Ofori).info.json": "2c66fdeabbc20599455da7e5cc26a269",
|
||||
"Dreams (Feat. Carmody).info.json": "ce220d509238eec57b2c48682a139643",
|
||||
"Hopeful (Feat. Jordan Rakei).info.json": "90ce01e9e8a3f4d4db71db0971cdd5f8",
|
||||
"Intro (Feat. Racheal Ofori & Barney Artist).info.json": "763400e50f187dad3260dcdac2b02542",
|
||||
"No Peace (Feat. Tom Misch).info.json": "f3991884b296795e048bd023b64d4b99",
|
||||
"Nocturne/01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3": "b2e2a9834f03d1928e0c8a0602899d4d",
|
||||
"Nocturne/02 - Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3": "8fe76edcc77c5d8db0f7b5b8577a4cf6",
|
||||
"Nocturne/03 - Blaze (Feat. Kaya Thomas - Dyke).mp3": "fd45453753a783ec4f26ef399a8ecece",
|
||||
@@ -19,7 +10,5 @@
|
||||
"Nocturne/09 - Dreaming (Interlude) (Feat. Racheal Ofori).mp3": "e50182fa81d56bb9261654e1906d18af",
|
||||
"Nocturne/10 - Hopeful (Feat. Jordan Rakei).mp3": "d2f9958553262c4bee4f82f98f1d42c7",
|
||||
"Nocturne/11 - Sunrise (Pillows) (Feat. Emmavie).mp3": "767dc4f27cc0a57d5391baf7b242d3f0",
|
||||
"Nocturne/folder.jpg": "bd3685acc53072e591bae2505ecb0648",
|
||||
"Sunrise (Pillows) (Feat. Emmavie).info.json": "9d01ca8f301334d118772f2b389fb9e4",
|
||||
"What If (Interlude).info.json": "848b11d8d6fa51defc4cbda6a7b3e218"
|
||||
"Nocturne/folder.jpg": "bd3685acc53072e591bae2505ecb0648"
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"Jesse's Minecraft Server [Trailer - Feb.1].info.json": "4214f8fac3333eb6baa73ea9648f86b4",
|
||||
"Jesse's Minecraft Server [Trailer - Feb.1].ogg": "afb2264e271e3c464d0fe9ba0db37f88",
|
||||
"Jesse's Minecraft Server [Trailer - Feb.27].info.json": "5dcc4ad1ccccb69c5054d497fad41884",
|
||||
"Jesse's Minecraft Server [Trailer - Feb.27].ogg": "6f322d842a1e43b4c9981b42423d9b4c",
|
||||
"Jesse's Minecraft Server [Trailer - Mar.21].info.json": "5a491a80875794abee3ee7da60b9d51b",
|
||||
"Jesse's Minecraft Server [Trailer - Mar.21].ogg": "fe1dc3361a102661c27020d5b95a2a81"
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
{
|
||||
"YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json": "de578129ce495c2ee4bf8f15212e1bb2",
|
||||
"YouTube Rewind 2019: For the Record | #YouTubeRewind.mp3": "d3687bf6c13a2a5f3a8a05fbce9be28c"
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case-thumb.jpg": "b5353a824a4800cc26f884e3025ed969",
|
||||
"JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.info.json": "d4ceb53039697fbb08a9479a4b1e97fd",
|
||||
"JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.mp4": "97f74f4796ba5a5977bbb4fb0b21ae93",
|
||||
"JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.nfo": "b9bd35e4f260c728774d8dd31f83637c"
|
||||
".ytdl-sub-chapters_from_timestamps_with_subs-download-archive.json": "40abc64a8fe93a10406bff1548a2cbe2",
|
||||
"JMC/JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case-thumb.jpg": "b5353a824a4800cc26f884e3025ed969",
|
||||
"JMC/JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.info.json": "c37c5f70f422a806eed1dd11a4c43d34",
|
||||
"JMC/JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.mp4": "97f74f4796ba5a5977bbb4fb0b21ae93",
|
||||
"JMC/JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.nfo": "b9bd35e4f260c728774d8dd31f83637c"
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case-thumb.jpg": "b5353a824a4800cc26f884e3025ed969",
|
||||
"JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.info.json": "f4ecde8a60ad02c83b02a951ef28f60f",
|
||||
"JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.mp4": "ba555c6a13869f3557b724b6ef2fbb6e",
|
||||
"JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.nfo": "b9bd35e4f260c728774d8dd31f83637c"
|
||||
".ytdl-sub-sponsorblock_with_embedded_subs_test-download-archive.json": "40abc64a8fe93a10406bff1548a2cbe2",
|
||||
"JMC/JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case-thumb.jpg": "b5353a824a4800cc26f884e3025ed969",
|
||||
"JMC/JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.info.json": "bc7bb4272d0d30edc87725f8aa64a25a",
|
||||
"JMC/JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.mp4": "ba555c6a13869f3557b724b6ef2fbb6e",
|
||||
"JMC/JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.nfo": "b9bd35e4f260c728774d8dd31f83637c"
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind-thumb.jpg": "50ee47c80f679029f5d3503bb91b045a",
|
||||
"JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json": "22585d06ef862a4b923db4e2665f0d79",
|
||||
"JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.mp4": "1f1f91f85b162c20596a2413e704b809",
|
||||
"JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.nfo": "c64964fab07574080e5da3242e3bfd48"
|
||||
".ytdl-sub-subtitles_embedded_test-download-archive.json": "1aa35c1d2663ac721f33f8374c00af1a",
|
||||
"JMC/JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind-thumb.jpg": "50ee47c80f679029f5d3503bb91b045a",
|
||||
"JMC/JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json": "fe08fcd1b68f00715e041bd98bec0570",
|
||||
"JMC/JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.mp4": "1f1f91f85b162c20596a2413e704b809",
|
||||
"JMC/JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.nfo": "c64964fab07574080e5da3242e3bfd48"
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind-thumb.jpg": "50ee47c80f679029f5d3503bb91b045a",
|
||||
"JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.de.srt": "b343c3bb9257b7ee7ba38f570a115b37",
|
||||
"JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.en.srt": "fe8c6ee92cae6e059fd80fd61691adbe",
|
||||
"JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json": "089845553911c366198932b30bca5d00",
|
||||
"JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.mp4": "1f1f91f85b162c20596a2413e704b809",
|
||||
"JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.nfo": "c64964fab07574080e5da3242e3bfd48"
|
||||
".ytdl-sub-subtitles_embedded_and_file_test-download-archive.json": "fb48a287b1af0c78d7f79749c0cec9d7",
|
||||
"JMC/JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind-thumb.jpg": "50ee47c80f679029f5d3503bb91b045a",
|
||||
"JMC/JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.de.srt": "b343c3bb9257b7ee7ba38f570a115b37",
|
||||
"JMC/JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.en.srt": "fe8c6ee92cae6e059fd80fd61691adbe",
|
||||
"JMC/JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json": "759e958c5911de5df6ac25887f8e1c6a",
|
||||
"JMC/JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.mp4": "1f1f91f85b162c20596a2413e704b809",
|
||||
"JMC/JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.nfo": "c64964fab07574080e5da3242e3bfd48"
|
||||
}
|
||||
@@ -1,32 +1,32 @@
|
||||
{
|
||||
".ytdl-sub-jb-download-archive.json": "1114f07090dfb35eea6848efeaf9755a",
|
||||
"j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.info.json": "5b1cd3c76846b216eeb5cc3566b0f0a8",
|
||||
"j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.info.json": "b95796948d30558e057a3f2c794c650c",
|
||||
"j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.mp3": "bffbd558e12c6a9e029dc136a88342c4",
|
||||
"j_b/[2021] Baby Santana's Dorian Groove/folder.jpg": "967892be44b8c47e1be73f055a7c6f08",
|
||||
"j_b/[2021] Purple Clouds/01 - Purple Clouds.info.json": "2207ed41f248ce72ffe6263df804dd24",
|
||||
"j_b/[2021] Purple Clouds/01 - Purple Clouds.info.json": "e4d6f7da57a8bc18f82332778ac9b1f0",
|
||||
"j_b/[2021] Purple Clouds/01 - Purple Clouds.mp3": "038db58aebe2ba875b733932b42a94d6",
|
||||
"j_b/[2021] Purple Clouds/folder.jpg": "967892be44b8c47e1be73f055a7c6f08",
|
||||
"j_b/[2022] Acoustic Treats/01 - 20160426 184214.info.json": "d90d8a19209fd3ef9f441c5e9c75a32f",
|
||||
"j_b/[2022] Acoustic Treats/01 - 20160426 184214.info.json": "4294a791c9e295dcbcb536528215ab2e",
|
||||
"j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3": "e145f0a2f6012768280c38655ca58065",
|
||||
"j_b/[2022] Acoustic Treats/02 - 20160502 123150.info.json": "c4df2eb9a4eecb06f425c73f8dfb98f3",
|
||||
"j_b/[2022] Acoustic Treats/02 - 20160502 123150.info.json": "9fcdd8984dd286b03d07900240325468",
|
||||
"j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3": "60c8b8817a197a13e4bb90903af612c5",
|
||||
"j_b/[2022] Acoustic Treats/03 - 20160504 143832.info.json": "a4943268aa5a534548c21873f1ed17b8",
|
||||
"j_b/[2022] Acoustic Treats/03 - 20160504 143832.info.json": "6a3ca21f1cb2f43227fc95355dcaf7ab",
|
||||
"j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3": "8265b7e4f79878af877bc6ecd9757efe",
|
||||
"j_b/[2022] Acoustic Treats/04 - 20160601 221234.info.json": "c5a3e933fef9f041946e3fd58cc40cc5",
|
||||
"j_b/[2022] Acoustic Treats/04 - 20160601 221234.info.json": "accc54dbf191095e7bf39ab954fc5fa4",
|
||||
"j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3": "accf46b76891d2954b893d0f91d82816",
|
||||
"j_b/[2022] Acoustic Treats/05 - 20160601 222440.info.json": "a46f108c700f577392145a6e58d3766a",
|
||||
"j_b/[2022] Acoustic Treats/05 - 20160601 222440.info.json": "6c3dff44838b403d67a1229879edd51a",
|
||||
"j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3": "e1f584f523336160d5c1104a61de77f3",
|
||||
"j_b/[2022] Acoustic Treats/06 - 20170604 190236.info.json": "6a78bdb0ed2958f0083ace1c166a363f",
|
||||
"j_b/[2022] Acoustic Treats/06 - 20170604 190236.info.json": "b37323719f632e5a607e3fe93a220c9b",
|
||||
"j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3": "f6885b25901177f0357649afe97328cc",
|
||||
"j_b/[2022] Acoustic Treats/07 - 20170612 193646.info.json": "84cd8697d8d6876b19ceb35f4b60bcf0",
|
||||
"j_b/[2022] Acoustic Treats/07 - 20170612 193646.info.json": "af3b911d3d24adfa11810676d50c055c",
|
||||
"j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3": "fa057f221cbe4cf2442cd2fdb960743e",
|
||||
"j_b/[2022] Acoustic Treats/08 - 20170628 215206.info.json": "e5669e3802c0d35ab14435b34929d61a",
|
||||
"j_b/[2022] Acoustic Treats/08 - 20170628 215206.info.json": "208280c591da9bcc4570b58c36452e23",
|
||||
"j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3": "7794ae812c64580e2ac8fc457d5cc85f",
|
||||
"j_b/[2022] Acoustic Treats/09 - Finding Home.info.json": "5de4bd28ba1f4e67e895f1e4a37fccdd",
|
||||
"j_b/[2022] Acoustic Treats/09 - Finding Home.info.json": "23ebe28b09ceaac0a8ef64a324d86f76",
|
||||
"j_b/[2022] Acoustic Treats/09 - Finding Home.mp3": "adbf02eddb2090c008eb497d13ff84b9",
|
||||
"j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.info.json": "ddb35f4fc41551b68d58b5df62d73bf4",
|
||||
"j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.info.json": "d1c383d73b067ac6f7888dbb39393263",
|
||||
"j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3": "65bb10c84366c71498161734f953e93d",
|
||||
"j_b/[2022] Acoustic Treats/11 - Untold History.info.json": "489da77a730183b0185d262ad4639085",
|
||||
"j_b/[2022] Acoustic Treats/11 - Untold History.info.json": "edc39b25c8eb95807ab5523272d8c2d6",
|
||||
"j_b/[2022] Acoustic Treats/11 - Untold History.mp3": "6904b2918e5dc38d9a9f72d967eb74bf",
|
||||
"j_b/[2022] Acoustic Treats/folder.jpg": "967892be44b8c47e1be73f055a7c6f08"
|
||||
}
|
||||
@@ -1,17 +1,17 @@
|
||||
{
|
||||
".ytdl-sub-music_video_playlist_test-download-archive.json": "25b8e44961343116436584e341c7fe9b",
|
||||
"JMC - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg": "b232d253df621aa770b780c1301d364d",
|
||||
"JMC - Jesse's Minecraft Server [Trailer - Feb.1].info.json": "c73232e03c9e14b62145917cca3a242c",
|
||||
"JMC - Jesse's Minecraft Server [Trailer - Feb.1].mp4": "7bfa1475504a7c8a4aaa8c89f9306331",
|
||||
"JMC - Jesse's Minecraft Server [Trailer - Feb.1].nfo": "de6f9a17a5ebf92aa02b14f7342b8d36",
|
||||
"JMC - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg": "d17c379ea8b362f5b97c6b213b0342cb",
|
||||
"JMC - Jesse's Minecraft Server [Trailer - Feb.27].info.json": "56ab3eddea58572ffdc33d0945f083b2",
|
||||
"JMC - Jesse's Minecraft Server [Trailer - Feb.27].mp4": "04ab5cb3cc12325d0c96a7cd04a8b91d",
|
||||
"JMC - Jesse's Minecraft Server [Trailer - Feb.27].nfo": "9a4a57bb91f1ac97b588fdf66bac4c9b",
|
||||
"JMC - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530",
|
||||
"JMC - Jesse's Minecraft Server [Trailer - Mar.21].info.json": "f45f60467a0d7a82282ad7e1a481ede2",
|
||||
"JMC - Jesse's Minecraft Server [Trailer - Mar.21].mp4": "025de6099a5c98e6397153c7a62d517d",
|
||||
"JMC - Jesse's Minecraft Server [Trailer - Mar.21].nfo": "b98f1fa3e76b4592aeeaed4f6e220809",
|
||||
".ytdl-sub-music_video_playlist_test-download-archive.json": "e7f7c35e33c132a96d1f12b18f388b35",
|
||||
"JMC/JMC - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg": "b232d253df621aa770b780c1301d364d",
|
||||
"JMC/JMC - Jesse's Minecraft Server [Trailer - Feb.1].info.json": "0cfc2ecee75f6f33efac020d0fab44fa",
|
||||
"JMC/JMC - Jesse's Minecraft Server [Trailer - Feb.1].mp4": "7bfa1475504a7c8a4aaa8c89f9306331",
|
||||
"JMC/JMC - Jesse's Minecraft Server [Trailer - Feb.1].nfo": "de6f9a17a5ebf92aa02b14f7342b8d36",
|
||||
"JMC/JMC - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg": "d17c379ea8b362f5b97c6b213b0342cb",
|
||||
"JMC/JMC - Jesse's Minecraft Server [Trailer - Feb.27].info.json": "6d3d49a3ba25746f786678838a64b485",
|
||||
"JMC/JMC - Jesse's Minecraft Server [Trailer - Feb.27].mp4": "04ab5cb3cc12325d0c96a7cd04a8b91d",
|
||||
"JMC/JMC - Jesse's Minecraft Server [Trailer - Feb.27].nfo": "9a4a57bb91f1ac97b588fdf66bac4c9b",
|
||||
"JMC/JMC - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530",
|
||||
"JMC/JMC - Jesse's Minecraft Server [Trailer - Mar.21].info.json": "19c04838f1aac493ba1eb2b9e933ba1f",
|
||||
"JMC/JMC - Jesse's Minecraft Server [Trailer - Mar.21].mp4": "025de6099a5c98e6397153c7a62d517d",
|
||||
"JMC/JMC - Jesse's Minecraft Server [Trailer - Mar.21].nfo": "b98f1fa3e76b4592aeeaed4f6e220809",
|
||||
"poster.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530",
|
||||
"tvshow.nfo": "e4123860532466ed5e0ebf2c9e44eb18"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"JMC - Oblivion Mod "Falcor" p.1-thumb.jpg": "fb95b510681676e81c321171fc23143e",
|
||||
"JMC - Oblivion Mod "Falcor" p.1.info.json": "7e370795027d99f4db007d84d45cbc43",
|
||||
"JMC - Oblivion Mod "Falcor" p.1.mp4": "3744c49f2e447bd7712a5aad5ed36be2",
|
||||
"JMC - Oblivion Mod "Falcor" p.1.nfo": "24cc4e17d2bebc89b2759ce5471d403e"
|
||||
"JMC/JMC - Oblivion Mod "Falcor" p.1-thumb.jpg": "fb95b510681676e81c321171fc23143e",
|
||||
"JMC/JMC - Oblivion Mod "Falcor" p.1.info.json": "1651175b28db7c315df2758e6b66d353",
|
||||
"JMC/JMC - Oblivion Mod "Falcor" p.1.mp4": "3744c49f2e447bd7712a5aad5ed36be2",
|
||||
"JMC/JMC - Oblivion Mod "Falcor" p.1.nfo": "24cc4e17d2bebc89b2759ce5471d403e"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"JMC/JMC - Oblivion Mod "Falcor" p.1-thumb.jpg": "fb95b510681676e81c321171fc23143e",
|
||||
"JMC/JMC - Oblivion Mod "Falcor" p.1.info.json": "8d1bfe968d6eae87462850be79abe13a",
|
||||
"JMC/JMC - Oblivion Mod "Falcor" p.1.mp4": "3744c49f2e447bd7712a5aad5ed36be2",
|
||||
"JMC/JMC - Oblivion Mod "Falcor" p.1.nfo": "24cc4e17d2bebc89b2759ce5471d403e"
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
.ytdl-sub-file_convert_test-download-archive.json
|
||||
{output_directory}/Beyond The Guitar
|
||||
Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3-thumb.jpg
|
||||
Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.info.json
|
||||
Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.mp4
|
||||
|
||||
@@ -1,6 +1,40 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
.ytdl-sub-kodi_safe_xml-download-archive.json
|
||||
test.nfo
|
||||
NFO tags:
|
||||
kodi_safe_root 🎸:
|
||||
kodi_safe_multi_title 🎸:
|
||||
- value 1 🎸
|
||||
- value 2 🎸
|
||||
kodi_safe_multi_title_with_attrs:
|
||||
-
|
||||
attributes:
|
||||
🎸?:
|
||||
value
|
||||
newlines 🎸
|
||||
tag:
|
||||
the
|
||||
tag 1 🎸🎸
|
||||
-
|
||||
attributes:
|
||||
🎸?:
|
||||
value
|
||||
newlines 🎸
|
||||
tag:
|
||||
the
|
||||
tag 2 🎸🎸
|
||||
kodi_safe_title 🎸: kodi_safe_value 🎸
|
||||
kodi_safe_title_with_attrs:
|
||||
attributes:
|
||||
🎸?:
|
||||
value
|
||||
newlines 🎸
|
||||
tag:
|
||||
the
|
||||
tag 🎸🎸
|
||||
{output_directory}/Rick Beato
|
||||
Rick Beato - Can you hear the difference? 🎸🔥 #shorts-thumb.jpg
|
||||
Rick Beato - Can you hear the difference? 🎸🔥 #shorts.info.json
|
||||
Rick Beato - Can you hear the difference? 🎸🔥 #shorts.mp4
|
||||
@@ -39,36 +73,4 @@ Files created:
|
||||
the
|
||||
tag 🎸🎸
|
||||
title: Can you hear the difference? 🎸🔥 #shorts
|
||||
year: 2022
|
||||
test.nfo
|
||||
NFO tags:
|
||||
kodi_safe_root 🎸:
|
||||
kodi_safe_multi_title 🎸:
|
||||
- value 1 🎸
|
||||
- value 2 🎸
|
||||
kodi_safe_multi_title_with_attrs:
|
||||
-
|
||||
attributes:
|
||||
🎸?:
|
||||
value
|
||||
newlines 🎸
|
||||
tag:
|
||||
the
|
||||
tag 1 🎸🎸
|
||||
-
|
||||
attributes:
|
||||
🎸?:
|
||||
value
|
||||
newlines 🎸
|
||||
tag:
|
||||
the
|
||||
tag 2 🎸🎸
|
||||
kodi_safe_title 🎸: kodi_safe_value 🎸
|
||||
kodi_safe_title_with_attrs:
|
||||
attributes:
|
||||
🎸?:
|
||||
value
|
||||
newlines 🎸
|
||||
tag:
|
||||
the
|
||||
tag 🎸🎸
|
||||
year: 2022
|
||||
@@ -1,6 +1,40 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
.ytdl-sub-kodi_safe_xml-download-archive.json
|
||||
test.nfo
|
||||
NFO tags:
|
||||
kodi_safe_root □:
|
||||
kodi_safe_multi_title □:
|
||||
- value 1 □
|
||||
- value 2 □
|
||||
kodi_safe_multi_title_with_attrs:
|
||||
-
|
||||
attributes:
|
||||
□?:
|
||||
value
|
||||
newlines □
|
||||
tag:
|
||||
the
|
||||
tag 1 □□
|
||||
-
|
||||
attributes:
|
||||
□?:
|
||||
value
|
||||
newlines □
|
||||
tag:
|
||||
the
|
||||
tag 2 □□
|
||||
kodi_safe_title □: kodi_safe_value □
|
||||
kodi_safe_title_with_attrs:
|
||||
attributes:
|
||||
□?:
|
||||
value
|
||||
newlines □
|
||||
tag:
|
||||
the
|
||||
tag □□
|
||||
{output_directory}/Rick Beato
|
||||
Rick Beato - Can you hear the difference? 🎸🔥 #shorts-thumb.jpg
|
||||
Rick Beato - Can you hear the difference? 🎸🔥 #shorts.info.json
|
||||
Rick Beato - Can you hear the difference? 🎸🔥 #shorts.mp4
|
||||
@@ -39,36 +73,4 @@ Files created:
|
||||
the
|
||||
tag □□
|
||||
title: Can you hear the difference? □□ #shorts
|
||||
year: 2022
|
||||
test.nfo
|
||||
NFO tags:
|
||||
kodi_safe_root □:
|
||||
kodi_safe_multi_title □:
|
||||
- value 1 □
|
||||
- value 2 □
|
||||
kodi_safe_multi_title_with_attrs:
|
||||
-
|
||||
attributes:
|
||||
□?:
|
||||
value
|
||||
newlines □
|
||||
tag:
|
||||
the
|
||||
tag 1 □□
|
||||
-
|
||||
attributes:
|
||||
□?:
|
||||
value
|
||||
newlines □
|
||||
tag:
|
||||
the
|
||||
tag 2 □□
|
||||
kodi_safe_title □: kodi_safe_value □
|
||||
kodi_safe_title_with_attrs:
|
||||
attributes:
|
||||
□?:
|
||||
value
|
||||
newlines □
|
||||
tag:
|
||||
the
|
||||
tag □□
|
||||
year: 2022
|
||||
@@ -1,17 +1,5 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
01. Intro (Feat. Racheal Ofori & Barney Artist).info.json
|
||||
02. Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json
|
||||
03. Blaze (Feat. Kaya Thomas - Dyke).info.json
|
||||
04. What If (Interlude).info.json
|
||||
05. No Peace (Feat. Tom Misch).info.json
|
||||
06. Closer (Feat. Lester Duval).info.json
|
||||
07. Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json
|
||||
08. Dreams (Feat. Carmody).info.json
|
||||
09. Dreaming (Interlude) (Feat. Racheal Ofori).info.json
|
||||
10. Hopeful (Feat. Jordan Rakei).info.json
|
||||
11. Sunrise (Pillows) (Feat. Emmavie).info.json
|
||||
{output_directory}/Alfa Mist - Nocturne [Full Album]
|
||||
01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3
|
||||
From Chapter Split:
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
01. Intro (Feat. Racheal Ofori & Barney Artist).info.json
|
||||
02. Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json
|
||||
03. Blaze (Feat. Kaya Thomas - Dyke).info.json
|
||||
04. What If (Interlude).info.json
|
||||
05. No Peace (Feat. Tom Misch).info.json
|
||||
06. Closer (Feat. Lester Duval).info.json
|
||||
07. Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json
|
||||
08. Dreams (Feat. Carmody).info.json
|
||||
09. Dreaming (Interlude) (Feat. Racheal Ofori).info.json
|
||||
10. Hopeful (Feat. Jordan Rakei).info.json
|
||||
11. Sunrise (Pillows) (Feat. Emmavie).info.json
|
||||
{output_directory}/Alfa Mist - Nocturne [Full Album]
|
||||
01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3
|
||||
From Chapter Split:
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
Oblivion Mod "Falcor" p.1.info.json
|
||||
{output_directory}/Oblivion Mod "Falcor" p.1
|
||||
01 - Oblivion Mod "Falcor" p.1.mp3
|
||||
Music Tags:
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json
|
||||
Blaze (Feat. Kaya Thomas - Dyke).info.json
|
||||
Closer (Feat. Lester Duval).info.json
|
||||
Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json
|
||||
Dreaming (Interlude) (Feat. Racheal Ofori).info.json
|
||||
Dreams (Feat. Carmody).info.json
|
||||
Hopeful (Feat. Jordan Rakei).info.json
|
||||
Intro (Feat. Racheal Ofori & Barney Artist).info.json
|
||||
No Peace (Feat. Tom Misch).info.json
|
||||
Sunrise (Pillows) (Feat. Emmavie).info.json
|
||||
What If (Interlude).info.json
|
||||
{output_directory}/Nocturne
|
||||
01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3
|
||||
From Chapter Split:
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json
|
||||
Blaze (Feat. Kaya Thomas - Dyke).info.json
|
||||
Closer (Feat. Lester Duval).info.json
|
||||
Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json
|
||||
Dreaming (Interlude) (Feat. Racheal Ofori).info.json
|
||||
Dreams (Feat. Carmody).info.json
|
||||
Hopeful (Feat. Jordan Rakei).info.json
|
||||
Intro (Feat. Racheal Ofori & Barney Artist).info.json
|
||||
No Peace (Feat. Tom Misch).info.json
|
||||
Sunrise (Pillows) (Feat. Emmavie).info.json
|
||||
What If (Interlude).info.json
|
||||
{output_directory}/Nocturne
|
||||
01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3
|
||||
From Chapter Split:
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
Jesse's Minecraft Server [Trailer - Feb.1].info.json
|
||||
Jesse's Minecraft Server [Trailer - Feb.1].ogg
|
||||
Music Tags:
|
||||
album: Singles
|
||||
@@ -11,7 +10,6 @@ Files created:
|
||||
title: Jesse's Minecraft Server [Trailer - Feb.1]
|
||||
track: 3
|
||||
year: 2011
|
||||
Jesse's Minecraft Server [Trailer - Feb.27].info.json
|
||||
Jesse's Minecraft Server [Trailer - Feb.27].ogg
|
||||
Music Tags:
|
||||
album: Singles
|
||||
@@ -21,7 +19,6 @@ Files created:
|
||||
title: Jesse's Minecraft Server [Trailer - Feb.27]
|
||||
track: 2
|
||||
year: 2011
|
||||
Jesse's Minecraft Server [Trailer - Mar.21].info.json
|
||||
Jesse's Minecraft Server [Trailer - Mar.21].ogg
|
||||
Music Tags:
|
||||
album: Singles
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json
|
||||
YouTube Rewind 2019: For the Record | #YouTubeRewind.mp3
|
||||
Music Tags:
|
||||
album: Singles
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
.ytdl-sub-chapters_from_timestamps_with_subs-download-archive.json
|
||||
{output_directory}/JMC
|
||||
JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case-thumb.jpg
|
||||
JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.info.json
|
||||
JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.mp4
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
.ytdl-sub-sponsorblock_with_embedded_subs_test-download-archive.json
|
||||
{output_directory}/JMC
|
||||
JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case-thumb.jpg
|
||||
JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.info.json
|
||||
JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.mp4
|
||||
|
||||
@@ -2,6 +2,7 @@ Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
.ytdl-sub-regex_capture_playlist_test-download-archive.json
|
||||
{output_directory}/Project Zombie
|
||||
Project Zombie - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg
|
||||
Project Zombie - Jesse's Minecraft Server [Trailer - Feb.1].info.json
|
||||
Project Zombie - Jesse's Minecraft Server [Trailer - Feb.1].mp4
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
.ytdl-sub-subtitles_embedded_test-download-archive.json
|
||||
{output_directory}/JMC
|
||||
JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind-thumb.jpg
|
||||
JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json
|
||||
JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.mp4
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
.ytdl-sub-subtitles_embedded_and_file_test-download-archive.json
|
||||
{output_directory}/JMC
|
||||
JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind-thumb.jpg
|
||||
JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.de.srt
|
||||
JMC - YouTube Rewind 2019: For the Record | #YouTubeRewind.en.srt
|
||||
|
||||
@@ -2,6 +2,14 @@ Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
.ytdl-sub-music_video_playlist_test-download-archive.json
|
||||
poster.jpg
|
||||
tvshow.nfo
|
||||
NFO tags:
|
||||
test:
|
||||
playlist_description: Trailers, Updates, etc
|
||||
playlist_title: Jesse's Minecraft Server
|
||||
playlist_uploader: Project Zombie
|
||||
{output_directory}/JMC
|
||||
JMC - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg
|
||||
JMC - Jesse's Minecraft Server [Trailer - Feb.1].info.json
|
||||
JMC - Jesse's Minecraft Server [Trailer - Feb.1].mp4
|
||||
@@ -37,11 +45,4 @@ Files created:
|
||||
playlist_count: 3
|
||||
playlist_index: 1
|
||||
title: Jesse's Minecraft Server [Trailer - Mar.21]
|
||||
year: 2011
|
||||
poster.jpg
|
||||
tvshow.nfo
|
||||
NFO tags:
|
||||
test:
|
||||
playlist_description: Trailers, Updates, etc
|
||||
playlist_title: Jesse's Minecraft Server
|
||||
playlist_uploader: Project Zombie
|
||||
year: 2011
|
||||
@@ -1,6 +1,6 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}
|
||||
{output_directory}/JMC
|
||||
JMC - Oblivion Mod "Falcor" p.1-thumb.jpg
|
||||
JMC - Oblivion Mod "Falcor" p.1.info.json
|
||||
JMC - Oblivion Mod "Falcor" p.1.mp4
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
Files created:
|
||||
----------------------------------------
|
||||
{output_directory}/JMC
|
||||
JMC - Oblivion Mod "Falcor" p.1-thumb.jpg
|
||||
JMC - Oblivion Mod "Falcor" p.1.info.json
|
||||
JMC - Oblivion Mod "Falcor" p.1.mp4
|
||||
Video Tags:
|
||||
title: Oblivion Mod "Falcor" p.1
|
||||
JMC - Oblivion Mod "Falcor" p.1.nfo
|
||||
NFO tags:
|
||||
musicvideo:
|
||||
album: Music Videos
|
||||
artist: JMC
|
||||
title: Oblivion Mod "Falcor" p.1
|
||||
year: 2010
|
||||
@@ -44,9 +44,9 @@ class TestDownloadArgsParser:
|
||||
"aliases, cmd, expected_sub_dict",
|
||||
[
|
||||
(
|
||||
{"mv": "--preset yt_music_video", "v": "--youtube.video_url"},
|
||||
{"mv": "--preset music_video", "v": "--download.url"},
|
||||
"dl --mv --v 123abc",
|
||||
{"preset": "yt_music_video", "youtube": {"video_url": "123abc"}},
|
||||
{"preset": "music_video", "download": {"url": "123abc"}},
|
||||
),
|
||||
(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user