[FEATURE] Ability to write .info.json files (#201)

This commit is contained in:
Jesse Bannon 2022-08-29 22:50:42 -07:00 committed by GitHub
parent 99925836f3
commit ca0ac787b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 650 additions and 394 deletions

View file

@ -38,6 +38,7 @@ presets:
output_directory: "{music_video_directory}"
file_name: "{music_video_name}.{ext}"
thumbnail_name: "{music_video_name}-thumb.jpg"
info_json_name: "{music_video_name}.{info_json_ext}"
# 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

View file

@ -53,6 +53,7 @@ presets:
output_directory: "{youtube_tv_shows_directory}/{tv_show_name_sanitized}"
file_name: "{episode_name}.{ext}"
thumbnail_name: "{episode_name}-thumb.jpg"
info_json_name: "{episode_name}.{info_json_ext}"
maintain_download_archive: True
# For each video downloaded, add an episode NFO file for it. We give it

View file

@ -44,8 +44,9 @@ presets:
# them on a successive invocation.
output_options:
output_directory: "{music_directory}"
file_name: "{artist_sanitized}/{album_directory_name}/{track_number_padded} - {title_sanitized}.{ext}"
thumbnail_name: "{artist_sanitized}/{album_directory_name}/folder.jpg"
file_name: "{album_path}/{track_file_name}.{ext}"
thumbnail_name: "{album_path}/folder.{thumbnail_ext}"
info_json_name: "{album_path}/{track_file_name}.{info_json_ext}"
maintain_download_archive: True
# For each song downloaded, populate the audio file with music tags.
@ -67,4 +68,6 @@ presets:
# which gets reused above for the audio file name and album art path.
overrides:
album_directory_name: "[{album_year}] {album_sanitized}"
track_file_name: "{track_number_padded} - {title_sanitized}"
album_path: "{artist_sanitized}/{album_directory_name}"
music_directory: "/path/to/music"

View file

@ -10,6 +10,7 @@ presets:
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"

View file

@ -118,6 +118,7 @@ class OutputOptions(StrictDictValidator):
file_name: "{title_sanitized}.{ext}"
# optional
thumbnail_name: "{title_sanitized}.{thumbnail_ext}"
info_json_name: "{title_sanitized}.{info_json_ext}"
maintain_download_archive: True
keep_files_before: now
keep_files_after: 19000101
@ -126,6 +127,7 @@ class OutputOptions(StrictDictValidator):
_required_keys = {"output_directory", "file_name"}
_optional_keys = {
"thumbnail_name",
"info_json_name",
"subtitles_name",
"maintain_download_archive",
"keep_files_before",
@ -148,6 +150,9 @@ class OutputOptions(StrictDictValidator):
self._thumbnail_name = self._validate_key_if_present(
key="thumbnail_name", validator=StringFormatterValidator
)
self._info_json_name = self._validate_key_if_present(
key="info_json_name", validator=StringFormatterValidator
)
self._maintain_download_archive = self._validate_key_if_present(
key="maintain_download_archive", validator=BoolValidator, default=False
@ -191,6 +196,15 @@ class OutputOptions(StrictDictValidator):
"""
return self._thumbnail_name
@property
def info_json_name(self) -> Optional[StringFormatterValidator]:
"""
Optional. The file name for the media's info json file. This can include directories such
as ``"Season {upload_year}/{title}.{info_json_ext}"``, and will be placed in the output
directory.
"""
return self._info_json_name
@property
def maintain_download_archive(self) -> bool:
"""

View file

@ -1,3 +1,5 @@
import copy
import json
import os
from pathlib import Path
from typing import Dict
@ -59,6 +61,33 @@ class Entry(EntryVariables, BaseEntry):
return None
def get_download_info_json_name(self) -> str:
"""
Returns
-------
The download info json's file name
"""
return f"{self.uid}.{self.info_json_ext}"
def get_download_info_json_path(self) -> str:
"""
Returns
-------
Entry's downloaded info json file path
"""
return str(Path(self.working_directory()) / self.get_download_info_json_name())
def write_info_json(self) -> None:
"""
Write the entry's _kwargs back into the info.json file as well as its source variables
"""
kwargs_dict = copy.deepcopy(self._kwargs)
kwargs_dict["ytdl_sub_entry_variables"] = self.to_dict()
kwargs_json = json.dumps(kwargs_dict, ensure_ascii=False, sort_keys=True, indent=2)
with open(self.get_download_info_json_path(), "w", encoding="utf-8") as file:
file.write(kwargs_json)
@final
def is_downloaded(self) -> bool:
"""

View file

@ -304,3 +304,13 @@ class EntryVariables(SourceVariables):
The uploaded date formatted as YYYY-MM-DD
"""
return f"{self.upload_year}-{self.upload_month_padded}-{self.upload_day_padded}"
@property
def info_json_ext(self) -> str:
"""
Returns
-------
str
The "info.json" extension
"""
return "info.json"

View file

@ -0,0 +1,136 @@
from abc import ABC
from pathlib import Path
from typing import Type
from ytdl_sub.config.config_file import ConfigOptions
from ytdl_sub.config.preset import Preset
from ytdl_sub.config.preset import PresetPlugins
from ytdl_sub.config.preset_options import OutputOptions
from ytdl_sub.config.preset_options import Overrides
from ytdl_sub.config.preset_options import YTDLOptions
from ytdl_sub.downloaders.downloader import Downloader
from ytdl_sub.downloaders.downloader import DownloaderValidator
from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive
class BaseSubscription(ABC):
"""
Subscription classes are the 'controllers' that perform...
- Downloading via ytdlp
- Adding metadata
- Placing files in the output directory
while configuring each step with provided configs. Child classes are expected to
provide SourceValidator (SourceT), which defines the source and its configurable options.
In addition, they should provide in the init an Entry type (EntryT), which is the entry that
will be returned after downloading.
"""
def __init__(
self,
name: str,
config_options: ConfigOptions,
preset_options: Preset,
):
"""
Parameters
----------
name: str
Name of the subscription
config_options: ConfigOptions
preset_options: Preset
"""
self.name = name
self._config_options = config_options
self._preset_options = preset_options
self._enhanced_download_archive = EnhancedDownloadArchive(
subscription_name=name,
working_directory=self.working_directory,
output_directory=self.output_directory,
)
@property
def downloader_class(self) -> Type[Downloader]:
"""
Returns
-------
This subscription's downloader class
"""
return self._preset_options.downloader
@property
def downloader_options(self) -> DownloaderValidator:
"""
Returns
-------
The download options for this subscription's downloader
"""
return self._preset_options.downloader_options
@property
def plugins(self) -> PresetPlugins:
"""
Returns
-------
List of tuples containing (plugin class, plugin options)
"""
return self._preset_options.plugins
@property
def ytdl_options(self) -> YTDLOptions:
"""
Returns
-------
YTDL options for this subscription
"""
return self._preset_options.ytdl_options
@property
def output_options(self) -> OutputOptions:
"""
Returns
-------
The output options defined for this subscription
"""
return self._preset_options.output_options
@property
def overrides(self) -> Overrides:
"""
Returns
-------
The overrides defined for this subscription
"""
return self._preset_options.overrides
@property
def working_directory(self) -> str:
"""
Returns
-------
The directory that the downloader saves files to
"""
return str(Path(self._config_options.working_directory) / Path(self.name))
@property
def output_directory(self) -> str:
"""
Returns
-------
The formatted output directory
"""
return self.overrides.apply_formatter(formatter=self.output_options.output_directory)
@property
def maintain_download_archive(self) -> bool:
"""
Returns
-------
Whether to maintain a download archive
"""
return (
self.output_options.maintain_download_archive
and self.downloader_class.supports_download_archive
)

View file

@ -1,388 +1,11 @@
import contextlib
import os
import shutil
from pathlib import Path
from typing import Dict
from typing import List
from typing import Optional
from typing import Type
from ytdl_sub.config.config_file import ConfigFile
from ytdl_sub.config.config_file import ConfigOptions
from ytdl_sub.config.preset import Preset
from ytdl_sub.config.preset import PresetPlugins
from ytdl_sub.config.preset_options import OutputOptions
from ytdl_sub.config.preset_options import Overrides
from ytdl_sub.config.preset_options import YTDLOptions
from ytdl_sub.downloaders.downloader import Downloader
from ytdl_sub.downloaders.downloader import DownloaderValidator
from ytdl_sub.entries.entry import Entry
from ytdl_sub.plugins.plugin import Plugin
from ytdl_sub.subscriptions.subscription_ytdl_options import SubscriptionYTDLOptions
from ytdl_sub.utils.datetime import to_date_range
from ytdl_sub.utils.exceptions import ValidationException
from ytdl_sub.utils.file_handler import FileHandlerTransactionLog
from ytdl_sub.utils.file_handler import FileMetadata
from ytdl_sub.utils.thumbnail import convert_download_thumbnail
from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive
from ytdl_sub.subscriptions.subscription_download import SubscriptionDownload
def _get_split_plugin(plugins: List[Plugin]) -> Optional[Plugin]:
split_plugins = [plugin for plugin in plugins if plugin.is_split_plugin]
if len(split_plugins) == 1:
return split_plugins[0]
if len(split_plugins) > 1:
raise ValidationException("Can not use more than one split plugins at a time")
return None
class Subscription:
"""
Subscription classes are the 'controllers' that perform...
- Downloading via ytdlp
- Adding metadata
- Placing files in the output directory
while configuring each step with provided configs. Child classes are expected to
provide SourceValidator (SourceT), which defines the source and its configurable options.
In addition, they should provide in the init an Entry type (EntryT), which is the entry that
will be returned after downloading.
"""
def __init__(
self,
name: str,
config_options: ConfigOptions,
preset_options: Preset,
):
"""
Parameters
----------
name: str
Name of the subscription
config_options: ConfigOptions
preset_options: Preset
"""
self.name = name
self.__config_options = config_options
self.__preset_options = preset_options
self._enhanced_download_archive = EnhancedDownloadArchive(
subscription_name=name,
working_directory=self.working_directory,
output_directory=self.output_directory,
)
@property
def downloader_class(self) -> Type[Downloader]:
"""
Returns
-------
This subscription's downloader class
"""
return self.__preset_options.downloader
@property
def downloader_options(self) -> DownloaderValidator:
"""
Returns
-------
The download options for this subscription's downloader
"""
return self.__preset_options.downloader_options
@property
def plugins(self) -> PresetPlugins:
"""
Returns
-------
List of tuples containing (plugin class, plugin options)
"""
return self.__preset_options.plugins
@property
def ytdl_options(self) -> YTDLOptions:
"""
Returns
-------
YTDL options for this subscription
"""
return self.__preset_options.ytdl_options
@property
def output_options(self) -> OutputOptions:
"""
Returns
-------
The output options defined for this subscription
"""
return self.__preset_options.output_options
@property
def overrides(self) -> Overrides:
"""
Returns
-------
The overrides defined for this subscription
"""
return self.__preset_options.overrides
@property
def working_directory(self) -> str:
"""
Returns
-------
The directory that the downloader saves files to
"""
return str(Path(self.__config_options.working_directory) / Path(self.name))
@property
def output_directory(self) -> str:
"""
Returns
-------
The formatted output directory
"""
return self.overrides.apply_formatter(formatter=self.output_options.output_directory)
@property
def maintain_download_archive(self) -> bool:
"""
Returns
-------
Whether to maintain a download archive
"""
return (
self.output_options.maintain_download_archive
and self.downloader_class.supports_download_archive
)
def _move_entry_files_to_output_directory(
self,
dry_run: bool,
entry: Entry,
entry_metadata: Optional[FileMetadata] = None,
):
"""
Helper function to move the media file and optionally thumbnail file to the output directory
for a single entry.
Parameters
----------
dry_run
Whether this session is a dry-run or not
entry:
The entry with files to move
entry_metadata
Optional. Metadata to record to the transaction log for this entry
"""
# Move the file after all direct file modifications are complete
output_file_name = self.overrides.apply_formatter(
formatter=self.output_options.file_name, entry=entry
)
self._enhanced_download_archive.save_file_to_output_directory(
file_name=entry.get_download_file_name(),
file_metadata=entry_metadata,
output_file_name=output_file_name,
entry=entry,
)
# TODO: see if entry even has a thumbnail
if self.output_options.thumbnail_name:
output_thumbnail_name = self.overrides.apply_formatter(
formatter=self.output_options.thumbnail_name, entry=entry
)
# We always convert entry thumbnails to jpgs, and is performed here
if not dry_run:
convert_download_thumbnail(entry=entry)
self._enhanced_download_archive.save_file_to_output_directory(
file_name=entry.get_download_thumbnail_name(),
output_file_name=output_thumbnail_name,
entry=entry,
)
@contextlib.contextmanager
def _prepare_working_directory(self):
"""
Context manager to create all directories to the working directory. Deletes the entire
working directory when cleaning up.
"""
os.makedirs(self.working_directory, exist_ok=True)
try:
yield
finally:
shutil.rmtree(self.working_directory)
@contextlib.contextmanager
def _maintain_archive_file(self):
"""
Context manager to initialize the enhanced download archive
"""
if self.maintain_download_archive:
self._enhanced_download_archive.prepare_download_archive()
yield
# If output options maintains stale file deletion, perform the delete here prior to saving
# the download archive
if self.maintain_download_archive:
date_range_to_keep = to_date_range(
before=self.output_options.keep_files_before,
after=self.output_options.keep_files_after,
overrides=self.overrides,
)
if date_range_to_keep:
self._enhanced_download_archive.remove_stale_files(date_range=date_range_to_keep)
self._enhanced_download_archive.save_download_mappings()
@contextlib.contextmanager
def _subscription_download_context_managers(self) -> None:
with (
self._prepare_working_directory(),
self._maintain_archive_file(),
):
yield
def _initialize_plugins(self) -> List[Plugin]:
"""
Returns
-------
List of plugins defined in the subscription, initialized and ready to use.
"""
plugins: List[Plugin] = []
for plugin_type, plugin_options in self.plugins.zipped():
plugin = plugin_type(
plugin_options=plugin_options,
overrides=self.overrides,
enhanced_download_archive=self._enhanced_download_archive,
)
plugins.append(plugin)
return plugins
def _post_process_entry(
self, plugins: List[Plugin], dry_run: bool, entry: Entry, entry_metadata: FileMetadata
):
# Post-process the entry with all plugins
for plugin in sorted(plugins, key=lambda _plugin: _plugin.priority.post_process):
optional_plugin_entry_metadata = plugin.post_process_entry(entry)
if optional_plugin_entry_metadata:
entry_metadata.extend(optional_plugin_entry_metadata)
# Then, move it to the output directory
self._move_entry_files_to_output_directory(
dry_run=dry_run, entry=entry, entry_metadata=entry_metadata
)
# Re-save the download archive after each entry is moved to the output directory
if self.maintain_download_archive:
self._enhanced_download_archive.save_download_mappings()
def _process_entry(
self, plugins: List[Plugin], dry_run: bool, entry: Entry, entry_metadata: FileMetadata
) -> None:
# First, modify the entry with all plugins
for plugin in sorted(plugins, key=lambda _plugin: _plugin.priority.modify_entry):
# Return if it is None, it is indicated to not process any further
if (entry := plugin.modify_entry(entry)) is None:
return
self._post_process_entry(
plugins=plugins, dry_run=dry_run, entry=entry, entry_metadata=entry_metadata
)
def _process_split_entry(
self, split_plugin: Plugin, plugins: List[Plugin], dry_run: bool, entry: Entry
) -> None:
plugins_pre_split = sorted(
[plugin for plugin in plugins if not plugin.priority.modify_entry_after_split],
key=lambda _plugin: _plugin.priority.modify_entry,
)
plugins_post_split = sorted(
[plugin for plugin in plugins if plugin.priority.modify_entry_after_split],
key=lambda _plugin: _plugin.priority.modify_entry,
)
# First, modify the entry with pre_split plugins
for plugin in plugins_pre_split:
# Return if it is None, it is indicated to not process any further
if (entry := plugin.modify_entry(entry)) is None:
return
# Then, perform the split
for split_entry, split_entry_metadata in split_plugin.split(entry=entry):
for plugin in plugins_post_split:
# Return if it is None, it is indicated to not process any further.
# Break out of the plugin loop
if (split_entry := plugin.modify_entry(split_entry)) is None:
break
# If split_entry is None from modify_entry, do not post process
if split_entry:
self._process_entry(
plugins=plugins,
dry_run=dry_run,
entry=split_entry,
entry_metadata=split_entry_metadata,
)
def download(self, dry_run: bool = False) -> FileHandlerTransactionLog:
"""
Performs the subscription download
Parameters
----------
dry_run
If true, do not download any video/audio files or move anything to the output
directory.
"""
self._enhanced_download_archive.reinitialize(dry_run=dry_run)
plugins = self._initialize_plugins()
ytdl_options_builder = SubscriptionYTDLOptions(
preset=self.__preset_options,
plugins=plugins,
enhanced_download_archive=self._enhanced_download_archive,
working_directory=self.working_directory,
dry_run=dry_run,
).builder()
with self._subscription_download_context_managers():
downloader = self.downloader_class(
download_options=self.downloader_options,
enhanced_download_archive=self._enhanced_download_archive,
ytdl_options_builder=ytdl_options_builder,
)
for entry in downloader.download():
entry_metadata = FileMetadata()
if isinstance(entry, tuple):
entry, entry_metadata = entry
if split_plugin := _get_split_plugin(plugins):
self._process_split_entry(
split_plugin=split_plugin, plugins=plugins, dry_run=dry_run, entry=entry
)
else:
self._process_entry(
plugins=plugins, dry_run=dry_run, entry=entry, entry_metadata=entry_metadata
)
downloader.post_download(overrides=self.overrides)
for plugin in plugins:
plugin.post_process_subscription()
return self._enhanced_download_archive.get_file_handler_transaction_log()
class Subscription(SubscriptionDownload):
@classmethod
def from_preset(cls, preset: Preset, config: ConfigFile) -> "Subscription":
"""

View file

@ -0,0 +1,271 @@
import contextlib
import os
import shutil
from abc import ABC
from typing import List
from typing import Optional
from ytdl_sub.entries.entry import Entry
from ytdl_sub.plugins.plugin import Plugin
from ytdl_sub.subscriptions.base_subscription import BaseSubscription
from ytdl_sub.subscriptions.subscription_ytdl_options import SubscriptionYTDLOptions
from ytdl_sub.utils.datetime import to_date_range
from ytdl_sub.utils.exceptions import ValidationException
from ytdl_sub.utils.file_handler import FileHandlerTransactionLog
from ytdl_sub.utils.file_handler import FileMetadata
from ytdl_sub.utils.thumbnail import convert_download_thumbnail
def _get_split_plugin(plugins: List[Plugin]) -> Optional[Plugin]:
split_plugins = [plugin for plugin in plugins if plugin.is_split_plugin]
if len(split_plugins) == 1:
return split_plugins[0]
if len(split_plugins) > 1:
raise ValidationException("Can not use more than one split plugins at a time")
return None
class SubscriptionDownload(BaseSubscription, ABC):
"""
Handles the subscription download logic
"""
def _move_entry_files_to_output_directory(
self,
dry_run: bool,
entry: Entry,
entry_metadata: Optional[FileMetadata] = None,
):
"""
Helper function to move the media file and optionally thumbnail file to the output directory
for a single entry.
Parameters
----------
dry_run
Whether this session is a dry-run or not
entry:
The entry with files to move
entry_metadata
Optional. Metadata to record to the transaction log for this entry
"""
# Move the file after all direct file modifications are complete
output_file_name = self.overrides.apply_formatter(
formatter=self.output_options.file_name, entry=entry
)
self._enhanced_download_archive.save_file_to_output_directory(
file_name=entry.get_download_file_name(),
file_metadata=entry_metadata,
output_file_name=output_file_name,
entry=entry,
)
# TODO: see if entry even has a thumbnail
if self.output_options.thumbnail_name:
output_thumbnail_name = self.overrides.apply_formatter(
formatter=self.output_options.thumbnail_name, entry=entry
)
# We always convert entry thumbnails to jpgs, and is performed here
if not dry_run:
convert_download_thumbnail(entry=entry)
self._enhanced_download_archive.save_file_to_output_directory(
file_name=entry.get_download_thumbnail_name(),
output_file_name=output_thumbnail_name,
entry=entry,
)
if self.output_options.info_json_name:
output_info_json_name = self.overrides.apply_formatter(
formatter=self.output_options.info_json_name, entry=entry
)
# if not dry-run, write the info json
if not dry_run:
entry.write_info_json()
self._enhanced_download_archive.save_file_to_output_directory(
file_name=entry.get_download_info_json_name(),
output_file_name=output_info_json_name,
entry=entry,
)
@contextlib.contextmanager
def _prepare_working_directory(self):
"""
Context manager to create all directories to the working directory. Deletes the entire
working directory when cleaning up.
"""
os.makedirs(self.working_directory, exist_ok=True)
try:
yield
finally:
shutil.rmtree(self.working_directory)
@contextlib.contextmanager
def _maintain_archive_file(self):
"""
Context manager to initialize the enhanced download archive
"""
if self.maintain_download_archive:
self._enhanced_download_archive.prepare_download_archive()
yield
# If output options maintains stale file deletion, perform the delete here prior to saving
# the download archive
if self.maintain_download_archive:
date_range_to_keep = to_date_range(
before=self.output_options.keep_files_before,
after=self.output_options.keep_files_after,
overrides=self.overrides,
)
if date_range_to_keep:
self._enhanced_download_archive.remove_stale_files(date_range=date_range_to_keep)
self._enhanced_download_archive.save_download_mappings()
@contextlib.contextmanager
def _subscription_download_context_managers(self) -> None:
with (
self._prepare_working_directory(),
self._maintain_archive_file(),
):
yield
def _initialize_plugins(self) -> List[Plugin]:
"""
Returns
-------
List of plugins defined in the subscription, initialized and ready to use.
"""
plugins: List[Plugin] = []
for plugin_type, plugin_options in self.plugins.zipped():
plugin = plugin_type(
plugin_options=plugin_options,
overrides=self.overrides,
enhanced_download_archive=self._enhanced_download_archive,
)
plugins.append(plugin)
return plugins
def _post_process_entry(
self, plugins: List[Plugin], dry_run: bool, entry: Entry, entry_metadata: FileMetadata
):
# Post-process the entry with all plugins
for plugin in sorted(plugins, key=lambda _plugin: _plugin.priority.post_process):
optional_plugin_entry_metadata = plugin.post_process_entry(entry)
if optional_plugin_entry_metadata:
entry_metadata.extend(optional_plugin_entry_metadata)
# Then, move it to the output directory
self._move_entry_files_to_output_directory(
dry_run=dry_run, entry=entry, entry_metadata=entry_metadata
)
# Re-save the download archive after each entry is moved to the output directory
if self.maintain_download_archive:
self._enhanced_download_archive.save_download_mappings()
def _process_entry(
self, plugins: List[Plugin], dry_run: bool, entry: Entry, entry_metadata: FileMetadata
) -> None:
# First, modify the entry with all plugins
for plugin in sorted(plugins, key=lambda _plugin: _plugin.priority.modify_entry):
# Return if it is None, it is indicated to not process any further
if (entry := plugin.modify_entry(entry)) is None:
return
self._post_process_entry(
plugins=plugins, dry_run=dry_run, entry=entry, entry_metadata=entry_metadata
)
def _process_split_entry(
self, split_plugin: Plugin, plugins: List[Plugin], dry_run: bool, entry: Entry
) -> None:
plugins_pre_split = sorted(
[plugin for plugin in plugins if not plugin.priority.modify_entry_after_split],
key=lambda _plugin: _plugin.priority.modify_entry,
)
plugins_post_split = sorted(
[plugin for plugin in plugins if plugin.priority.modify_entry_after_split],
key=lambda _plugin: _plugin.priority.modify_entry,
)
# First, modify the entry with pre_split plugins
for plugin in plugins_pre_split:
# Return if it is None, it is indicated to not process any further
if (entry := plugin.modify_entry(entry)) is None:
return
# Then, perform the split
for split_entry, split_entry_metadata in split_plugin.split(entry=entry):
for plugin in plugins_post_split:
# Return if it is None, it is indicated to not process any further.
# Break out of the plugin loop
if (split_entry := plugin.modify_entry(split_entry)) is None:
break
# If split_entry is None from modify_entry, do not post process
if split_entry:
self._process_entry(
plugins=plugins,
dry_run=dry_run,
entry=split_entry,
entry_metadata=split_entry_metadata,
)
def download(self, dry_run: bool = False) -> FileHandlerTransactionLog:
"""
Performs the subscription download
Parameters
----------
dry_run
If true, do not download any video/audio files or move anything to the output
directory.
"""
self._enhanced_download_archive.reinitialize(dry_run=dry_run)
plugins = self._initialize_plugins()
ytdl_options_builder = SubscriptionYTDLOptions(
preset=self._preset_options,
plugins=plugins,
enhanced_download_archive=self._enhanced_download_archive,
working_directory=self.working_directory,
dry_run=dry_run,
).builder()
with self._subscription_download_context_managers():
downloader = self.downloader_class(
download_options=self.downloader_options,
enhanced_download_archive=self._enhanced_download_archive,
ytdl_options_builder=ytdl_options_builder,
)
for entry in downloader.download():
entry_metadata = FileMetadata()
if isinstance(entry, tuple):
entry, entry_metadata = entry
if split_plugin := _get_split_plugin(plugins):
self._process_split_entry(
split_plugin=split_plugin, plugins=plugins, dry_run=dry_run, entry=entry
)
else:
self._process_entry(
plugins=plugins, dry_run=dry_run, entry=entry, entry_metadata=entry_metadata
)
downloader.post_download(overrides=self.overrides)
for plugin in plugins:
plugin.post_process_subscription()
return self._enhanced_download_archive.get_file_handler_transaction_log()

View file

@ -54,6 +54,7 @@ class ExpectedDownloads:
):
"""
Assert each expected file exists and that its respective md5 hash matches.
Ignores .info.json files by default since metadata can easily change
"""
if ignore_md5_hashes_for is None:
ignore_md5_hashes_for = []
@ -66,12 +67,11 @@ class ExpectedDownloads:
assert len(relative_file_paths) == self.file_count, "Mismatch in number of created files"
for expected_download in self.expected_downloads:
full_path = Path(relative_directory) / expected_download.path
assert os.path.isfile(
full_path
), f"Expected {str(expected_download.path)} to be a file but it is not"
path = str(expected_download.path)
full_path = Path(relative_directory) / path
assert os.path.isfile(full_path), f"Expected {path} to be a file but it is not"
if str(expected_download.path) in ignore_md5_hashes_for:
if path in ignore_md5_hashes_for or path.endswith(".info.json"):
continue
md5_hash = _get_file_md5_hash(full_file_path=full_path)

View file

@ -1,10 +1,12 @@
{
".ytdl-sub-recent-download-archive.json": "756b60d7a6c47d8163e3283404493a8d",
".ytdl-sub-recent-download-archive.json": "23520634f7908081f3d1333a1441a578",
"Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer-thumb.jpg": "705ca4e0d99b37e9ecdf6bfe4b90c59b",
"Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.info.json": "ad68ce82c78f1a0a757fc1fbd4d6b531",
"Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.mp4": "82f6ee7253e1dbb83ae7215af08ffacc",
"Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.nfo": "368d68db0cbe9eb4f43ece0517445e82",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id-thumb.jpg": "28d852ede73b879b9ebf9a061cfc7d46",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.en.srt": "3d2c4e7f65d2ca5e96da38ce7eecfc4e",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.info.json": "b085dea1c06975464acc5bdc1b950e4c",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.mp4": "e733b4cc385b953b08c8eb0f47e03c1e",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.nfo": "d9114d43d87907b2afc06eb089a8ac0a",
"fanart.jpg": "129c6639b47299bc48062f0365e670ee",

View file

@ -1,7 +1,8 @@
{
".ytdl-sub-recent-download-archive.json": "68e164a35d1541ce761a6d7fef19ee08",
".ytdl-sub-recent-download-archive.json": "3bbf72c014d055ecf672c8ea603140f7",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id-thumb.jpg": "28d852ede73b879b9ebf9a061cfc7d46",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.en.srt": "3d2c4e7f65d2ca5e96da38ce7eecfc4e",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.info.json": "b085dea1c06975464acc5bdc1b950e4c",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.mp4": "e733b4cc385b953b08c8eb0f47e03c1e",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.nfo": "d9114d43d87907b2afc06eb089a8ac0a",
"fanart.jpg": "129c6639b47299bc48062f0365e670ee",

View file

@ -1,4 +1,15 @@
{
"01. Intro (Feat. Racheal Ofori & Barney Artist).info.json": "4ec926da9b74eee3f9bf9e1895d3af30",
"02. Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json": "ae183114899d0b7bac8bfa01a09f6b36",
"03. Blaze (Feat. Kaya Thomas - Dyke).info.json": "86bff845b087dfc240d63a65afed9117",
"04. What If (Interlude).info.json": "d2e92735fcb8eaccaf2e28c8f2a0ab1f",
"05. No Peace (Feat. Tom Misch).info.json": "ed2a9ec8a833dd90bb6681d62c68ff3a",
"06. Closer (Feat. Lester Duval).info.json": "aa29efd172bb6afd27e948761087d01e",
"07. Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json": "79c0626f28d0a02074f14eac90e0670e",
"08. Dreams (Feat. Carmody).info.json": "c7bb7c910c0d74492ef62e4a32922f17",
"09. Dreaming (Interlude) (Feat. Racheal Ofori).info.json": "077efa0aa1d25afb05fb3285f139b77b",
"10. Hopeful (Feat. Jordan Rakei).info.json": "4541ba99f9b683f34652a60bc3c34ff5",
"11. Sunrise (Pillows) (Feat. Emmavie).info.json": "41a7ceb520a7d9e6736cba3f4be6a9c4",
"Alfa Mist - Nocturne [Full Album]/01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3": "ddc24257729f24055bf1b8dc06f8224c",
"Alfa Mist - Nocturne [Full Album]/02 - 02. Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3": "10dd7f13c469bd51ffcf3f8ff3ed3d69",
"Alfa Mist - Nocturne [Full Album]/03 - 03. Blaze (Feat. Kaya Thomas - Dyke).mp3": "376722aaf08d1ef6dcba0aaf7a3b7a79",

View file

@ -1,4 +1,5 @@
{
"Oblivion Mod \"Falcor\" p.1.info.json": "358e43cb1c00e7f4c960690994092e9e",
"Oblivion Mod \"Falcor\" p.1/01 - Oblivion Mod \"Falcor\" p.1.mp3": "703ffb93964ac025ee66221b98ee4d49",
"Oblivion Mod \"Falcor\" p.1/folder.jpg": "fb95b510681676e81c321171fc23143e"
}

View file

@ -1,4 +1,13 @@
{
"Answers (Feat. Rick David & Kaya Thomas - Dyke).info.json": "b4d6ae81fd1313c5ce962e88ab027782",
"Blaze (Feat. Kaya Thomas - Dyke).info.json": "05857a128e229ac9b364e8f5f09ff4b4",
"Closer (Feat. Lester Duval).info.json": "00c3e84f0b5506051ed31071208ff33d",
"Delusions: Rumination (Interlude) (Feat. Racheal Ofori).info.json": "b360033980fda9bcc3056aed2c3265b1",
"Dreaming (Interlude) (Feat. Racheal Ofori).info.json": "fd3df9675d2b01ad88a6d12d75ab526e",
"Dreams (Feat. Carmody).info.json": "402fb9066d25db35f801a6b94524bb38",
"Hopeful (Feat. Jordan Rakei).info.json": "ab750e7c550aac184f3ef82c3cf64212",
"Intro (Feat. Racheal Ofori & Barney Artist).info.json": "0777ecaaac9ffb1c4df3989e618dedf7",
"No Peace (Feat. Tom Misch).info.json": "0de13987489e4a8f9a94dd91dcbc4cf5",
"Nocturne/01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3": "15157be58e0f72485de1e7e10961321f",
"Nocturne/02 - Answers (Feat. Rick David & Kaya Thomas - Dyke).mp3": "28ff5e2dda45771f1c6d5265dd03095e",
"Nocturne/03 - Blaze (Feat. Kaya Thomas - Dyke).mp3": "705d7fc1799c1a14aa0656bd6e2bf260",
@ -10,5 +19,7 @@
"Nocturne/09 - Dreaming (Interlude) (Feat. Racheal Ofori).mp3": "cd213379cf53a8c1e4eb9134da257cd8",
"Nocturne/10 - Hopeful (Feat. Jordan Rakei).mp3": "ef7e06690ac849e1dd35771936d6ddb6",
"Nocturne/11 - Sunrise (Pillows) (Feat. Emmavie).mp3": "56293fb70edc1ef7decc2d417d87ff1d",
"Nocturne/folder.jpg": "bd3685acc53072e591bae2505ecb0648"
"Nocturne/folder.jpg": "bd3685acc53072e591bae2505ecb0648",
"Sunrise (Pillows) (Feat. Emmavie).info.json": "09f9975e3355e2d5888c07900f54f895",
"What If (Interlude).info.json": "328c05aeb45892d7ad6368e81d0947a5"
}

View file

@ -1,5 +1,8 @@
{
"Jesse's Minecraft Server [Trailer - Feb.1].info.json": "0a484e88b6d37b20017615aa6df3b5d9",
"Jesse's Minecraft Server [Trailer - Feb.1].ogg": "16f66f1d81541a1f18b62bc08ad01d16",
"Jesse's Minecraft Server [Trailer - Feb.27].info.json": "807c9f35c97beac21d8b3ca64df50860",
"Jesse's Minecraft Server [Trailer - Feb.27].ogg": "6f322d842a1e43b4c9981b42423d9b4c",
"Jesse's Minecraft Server [Trailer - Mar.21].info.json": "b87e89258f04fb3acb669e5b1e0fa468",
"Jesse's Minecraft Server [Trailer - Mar.21].ogg": "fe1dc3361a102661c27020d5b95a2a81"
}

View file

@ -1,3 +1,4 @@
{
"YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json": "ebc30f897906fa0f04738089c7e7715d",
"YouTube Rewind 2019: For the Record | #YouTubeRewind.mp3": "3a156b122bd79c956cce5079d3530cc3"
}

View file

@ -1,5 +1,6 @@
{
"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": "89d611e4f61a72204b9658acd492468d",
"JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.mp4": "2d40822bf4c0527f9080f00357b26ce0",
"JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.nfo": "b9bd35e4f260c728774d8dd31f83637c"
}

View file

@ -1,5 +1,6 @@
{
"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": "c0ad8fd87d9a70bd66ce069ae0acd490",
"JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.mp4": "6f0bac1c364ff3bb13d3e8a955aaa002",
"JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.nfo": "b9bd35e4f260c728774d8dd31f83637c"
}

View file

@ -1,5 +1,6 @@
{
"JMC - YouTube Rewind 2019 For the Record #YouTubeRewind-thumb.jpg": "50ee47c80f679029f5d3503bb91b045a",
"JMC - YouTube Rewind 2019 For the Record #YouTubeRewind.info.json": "eedd73b78d8a9d3b129049e87eb17b6c",
"JMC - YouTube Rewind 2019 For the Record #YouTubeRewind.mp4": "8562853314b75c1e47abd4f5ba97315c",
"JMC - YouTube Rewind 2019 For the Record #YouTubeRewind.nfo": "c64964fab07574080e5da3242e3bfd48"
}

View file

@ -2,6 +2,7 @@
"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": "577038a7e5a9833ebbd33562f5d6b376",
"JMC - YouTube Rewind 2019 For the Record #YouTubeRewind.mp4": "8562853314b75c1e47abd4f5ba97315c",
"JMC - YouTube Rewind 2019 For the Record #YouTubeRewind.nfo": "c64964fab07574080e5da3242e3bfd48"
}

View file

@ -1,19 +1,32 @@
{
".ytdl-sub-jb-download-archive.json": "1a99156e9ece62539fb2608416a07200",
".ytdl-sub-jb-download-archive.json": "1114f07090dfb35eea6848efeaf9755a",
"j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.info.json": "8f736aac8bbaa732e89efdcb61c3bc3d",
"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": "da0a923a6d0272e4dc726ac997360b28",
"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": "f952fe0830f106fac031d18022213892",
"j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3": "e145f0a2f6012768280c38655ca58065",
"j_b/[2022] Acoustic Treats/02 - 20160502 123150.info.json": "63f5a211448f95c78b866f048e4f2fc9",
"j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3": "60c8b8817a197a13e4bb90903af612c5",
"j_b/[2022] Acoustic Treats/03 - 20160504 143832.info.json": "a363365339ad3ab5139a51a6a6ed256d",
"j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3": "8265b7e4f79878af877bc6ecd9757efe",
"j_b/[2022] Acoustic Treats/04 - 20160601 221234.info.json": "9a1901fbd9761e29173b0fda5654e908",
"j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3": "accf46b76891d2954b893d0f91d82816",
"j_b/[2022] Acoustic Treats/05 - 20160601 222440.info.json": "886716e85228d46ce981aa0ba7bc2947",
"j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3": "e1f584f523336160d5c1104a61de77f3",
"j_b/[2022] Acoustic Treats/06 - 20170604 190236.info.json": "d23e769c83bc3303709b64432400a60d",
"j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3": "f6885b25901177f0357649afe97328cc",
"j_b/[2022] Acoustic Treats/07 - 20170612 193646.info.json": "04f467b4903aa9f090dc705db432edf2",
"j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3": "fa057f221cbe4cf2442cd2fdb960743e",
"j_b/[2022] Acoustic Treats/08 - 20170628 215206.info.json": "92f027ec29f445566242a82c27ed76ad",
"j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3": "7794ae812c64580e2ac8fc457d5cc85f",
"j_b/[2022] Acoustic Treats/09 - Finding Home.info.json": "f7458eaab93903e1568734ea1b33ee21",
"j_b/[2022] Acoustic Treats/09 - Finding Home.mp3": "adbf02eddb2090c008eb497d13ff84b9",
"j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.info.json": "553e676f982b364493fd323e6d886e05",
"j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3": "65bb10c84366c71498161734f953e93d",
"j_b/[2022] Acoustic Treats/11 - Untold History.info.json": "8abbad5d0821ed6c64dc632b49a133ec",
"j_b/[2022] Acoustic Treats/11 - Untold History.mp3": "6904b2918e5dc38d9a9f72d967eb74bf",
"j_b/[2022] Acoustic Treats/folder.jpg": "967892be44b8c47e1be73f055a7c6f08"
}

View file

@ -1,40 +1,52 @@
{
".ytdl-sub-pz-download-archive.json": "f0f692ef29653ca8d0af556415bfb065",
".ytdl-sub-pz-download-archive.json": "70615451318cdb5e018e007c77893a39",
"Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1-thumb.jpg": "fb95b510681676e81c321171fc23143e",
"Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1.info.json": "5d16096bc4256239932db2c2d98161a3",
"Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1.mp4": "931a705864c57d21d6fedebed4af6bbc",
"Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1.nfo": "2d0738094d8e649eaebbab16fd647da1",
"Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2-thumb.jpg": "8b32ee9c037fa669e444a0ac181525a1",
"Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2.info.json": "514d2c3eab500f9541910d7573cb495e",
"Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2.mp4": "d3469b4dca7139cb3dbc38712b6796bf",
"Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2.nfo": "5c258f9e54854ef292ce3c58331da110",
"Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg": "b232d253df621aa770b780c1301d364d",
"Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].info.json": "f9ccc0b104551ecd7b737451051118aa",
"Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].mp4": "e66287b9832277b6a4d1554e29d9fdcc",
"Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].nfo": "abb3ac33366cc3b86d0467c8fb80a323",
"Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg": "d17c379ea8b362f5b97c6b213b0342cb",
"Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].info.json": "6ad149bea780198512d73f075722ef82",
"Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].mp4": "04ab5cb3cc12325d0c96a7cd04a8b91d",
"Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].nfo": "46190954652c9d9812e061fc0c9e1d92",
"Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530",
"Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].info.json": "d040165f8ebc346c202605b19ed8e46b",
"Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].mp4": "025de6099a5c98e6397153c7a62d517d",
"Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].nfo": "30993fa8e00a0e370b4db244f3da8f7d",
"Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net)-thumb.jpg": "c956192a379b3661595c9920972d4819",
"Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net).info.json": "331af1c81b1bfa1df62179067a5f06b0",
"Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net).mp4": "3d9c19835b03355d6fd5d00cd59dbe5b",
"Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net).nfo": "11a0e8754c414875bcd454358683da5f",
"Season 2011/s2011.e0630 - Project Zombie Fin-thumb.jpg": "00ed383591779ffe98291de60f198fe9",
"Season 2011/s2011.e0630 - Project Zombie Fin.info.json": "07d6b5e38b8e03cbe0f1ca795f266a43",
"Season 2011/s2011.e0630 - Project Zombie Fin.mp4": "4971cb2d4fa29460361031f3fa8e1ea9",
"Season 2011/s2011.e0630 - Project Zombie Fin.nfo": "a464b9c8c48a9a5d4776436d8108f8f5",
"Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC]-thumb.jpg": "1718599d5189c65f7d8cf6acfa5ea851",
"Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC].info.json": "e804c82258849767d5f006627e66ac8f",
"Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC].mp4": "55e9b0add08c48c9c66105da0def2426",
"Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC].nfo": "3562934ab9a5e802d955eda24ad355de",
"Season 2012/s2012.e0123 - Project Zombie Map Trailer-thumb.jpg": "54ebe9df801b278fdd17b21afa8373a6",
"Season 2012/s2012.e0123 - Project Zombie Map Trailer.info.json": "d81b260f37fbf8499d6ba716f5d1c42a",
"Season 2012/s2012.e0123 - Project Zombie Map Trailer.mp4": "65e4ce53ed5ec4139995469f99477a50",
"Season 2012/s2012.e0123 - Project Zombie Map Trailer.nfo": "5e810d839be90dab579400a6177f90b3",
"Season 2013/s2013.e0719 - Project Zombie Rewind Trailer-thumb.jpg": "e29d49433175de8a761af35c5307791f",
"Season 2013/s2013.e0719 - Project Zombie Rewind Trailer.info.json": "4e450b92e57f8c99033b49e3326cdf72",
"Season 2013/s2013.e0719 - Project Zombie Rewind Trailer.mp4": "18620a8257a686beda65e54add4d4cd1",
"Season 2013/s2013.e0719 - Project Zombie Rewind Trailer.nfo": "83772bec917bb5d71e1ca0c061c1ec78",
"Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer-thumb.jpg": "705ca4e0d99b37e9ecdf6bfe4b90c59b",
"Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.info.json": "01a181a123d1b92d016dced5615ca67a",
"Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.mp4": "82f6ee7253e1dbb83ae7215af08ffacc",
"Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.nfo": "368d68db0cbe9eb4f43ece0517445e82",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id-thumb.jpg": "28d852ede73b879b9ebf9a061cfc7d46",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.en.srt": "3d2c4e7f65d2ca5e96da38ce7eecfc4e",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.info.json": "2ca573a5eb58e92df951be0a05e8e49c",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.mp4": "e733b4cc385b953b08c8eb0f47e03c1e",
"Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.nfo": "d9114d43d87907b2afc06eb089a8ac0a",
"fanart.jpg": "129c6639b47299bc48062f0365e670ee",

View file

@ -1,5 +1,6 @@
{
"JMC - Jesse's Minecraft Server-thumb.jpg": "a3f1910f9c51f6442f845a528e190829",
"JMC - Jesse's Minecraft Server.info.json": "604a3e1f5b0f27524772a90869fbbe06",
"JMC - Jesse's Minecraft Server.mkv": "21f246b1c922e11add509ea26c43c53d",
"JMC - Jesse's Minecraft Server.nfo": "d16396c60b63c06a4f2c9239553bdf61"
}

View file

@ -1,12 +1,15 @@
{
".ytdl-sub-music_video_playlist_test-download-archive.json": "9f785c29194a6ecfba6a6b4018763ddc",
".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": "7c870aea7df6733ddac1adc190797d6a",
"JMC - Jesse's Minecraft Server [Trailer - Feb.1].mp4": "e66287b9832277b6a4d1554e29d9fdcc",
"JMC - Jesse's Minecraft Server [Trailer - Feb.1].nfo": "f8fd72bb97ed03938487494ad9094ca0",
"JMC - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg": "d17c379ea8b362f5b97c6b213b0342cb",
"JMC - Jesse's Minecraft Server [Trailer - Feb.27].info.json": "e1d9ce4f91d4657468bb10de829a76e8",
"JMC - Jesse's Minecraft Server [Trailer - Feb.27].mp4": "04ab5cb3cc12325d0c96a7cd04a8b91d",
"JMC - Jesse's Minecraft Server [Trailer - Feb.27].nfo": "6de4d997cfb300356072b4ebb09cbe38",
"JMC - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg": "e7830aa8a64b0cde65ba3f7e5fc56530",
"JMC - Jesse's Minecraft Server [Trailer - Mar.21].info.json": "c601d4f904e45c8cc73e78c5873eba08",
"JMC - Jesse's Minecraft Server [Trailer - Mar.21].mp4": "025de6099a5c98e6397153c7a62d517d",
"JMC - Jesse's Minecraft Server [Trailer - Mar.21].nfo": "f000a6ed8caacb62a134a6ca81e3f308"
}

View file

@ -6,15 +6,21 @@
"Project Zombie - 5-6.Part 4.mp4": "de9afd0b6fa5f845b086e2d4915f2f14",
"Project Zombie - 6-6.Part 5.mp4": "d485c2a5df9a2d5bf9037a7a96a04d10",
"Project Zombie - Intro-thumb.jpg": "fb95b510681676e81c321171fc23143e",
"Project Zombie - Intro.info.json": "0aa234ae04a218f18c9aa2eb605ff078",
"Project Zombie - Intro.nfo": "3a89bd4707e64b66a22d13bb7f81bf16",
"Project Zombie - Part 1-thumb.jpg": "fb95b510681676e81c321171fc23143e",
"Project Zombie - Part 1.info.json": "1d1a70bf1bd9753c7035c9069fb99859",
"Project Zombie - Part 1.nfo": "a57a3a98d0b9db655bc4a792953ab96e",
"Project Zombie - Part 2-thumb.jpg": "fb95b510681676e81c321171fc23143e",
"Project Zombie - Part 2.info.json": "2781ca7fae971ca7a2825a6f16f432aa",
"Project Zombie - Part 2.nfo": "68921dd5386fd90e2c0640127dda5dc2",
"Project Zombie - Part 3-thumb.jpg": "fb95b510681676e81c321171fc23143e",
"Project Zombie - Part 3.info.json": "2d79048f59070044e519ab68ef469d62",
"Project Zombie - Part 3.nfo": "4198aec2d4cd70e4cb3946f10be205a7",
"Project Zombie - Part 4-thumb.jpg": "fb95b510681676e81c321171fc23143e",
"Project Zombie - Part 4.info.json": "4074e8d1fa1c0fccf1fe55ba52cc46a1",
"Project Zombie - Part 4.nfo": "8a87fa99c5ba5b11cd14c592a0b97dbb",
"Project Zombie - Part 5-thumb.jpg": "fb95b510681676e81c321171fc23143e",
"Project Zombie - Part 5.info.json": "48b519b3867bafb51c8f463293f357c3",
"Project Zombie - Part 5.nfo": "73091166bd5bd3d65d7e481e317ed128"
}

View file

@ -1,5 +1,6 @@
{
"JMC - Oblivion Mod Falcor p.1-thumb.jpg": "fb95b510681676e81c321171fc23143e",
"JMC - Oblivion Mod Falcor p.1.info.json": "b7e3751fe749817392d2d69be71a391c",
"JMC - Oblivion Mod Falcor p.1.mp4": "28c14cdac05c803efe71abb9454ab306",
"JMC - Oblivion Mod Falcor p.1.nfo": "24cc4e17d2bebc89b2759ce5471d403e"
}

View file

@ -2,6 +2,7 @@ Files created in '{output_directory}'
----------------------------------------
.ytdl-sub-recent-download-archive.json
Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer-thumb.jpg
Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.info.json
Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.mp4
Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.nfo
NFO tags:
@ -23,6 +24,7 @@ Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.nfo
year: 2018
Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id-thumb.jpg
Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.en.srt
Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.info.json
Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.mp4
Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.nfo
NFO tags:

View file

@ -11,5 +11,6 @@ tvshow.nfo
Files removed from '{output_directory}'
----------------------------------------
Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer-thumb.jpg
Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.info.json
Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.mp4
Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.nfo

View file

@ -2,6 +2,7 @@ Files created in '{output_directory}'
----------------------------------------
Rick Beato - Can you hear the difference 🎸🔥 #shorts-thumb.jpg
Rick Beato - Can you hear the difference 🎸🔥 #shorts.3gp
Rick Beato - Can you hear the difference 🎸🔥 #shorts.info.json
Rick Beato - Can you hear the difference 🎸🔥 #shorts.nfo
NFO tags:
musicvideo:

View file

@ -2,6 +2,7 @@ Files created in '{output_directory}'
----------------------------------------
Rick Beato - Can you hear the difference 🎸🔥 #shorts-thumb.jpg
Rick Beato - Can you hear the difference 🎸🔥 #shorts.3gp
Rick Beato - Can you hear the difference 🎸🔥 #shorts.info.json
Rick Beato - Can you hear the difference 🎸🔥 #shorts.nfo
NFO tags:
musicvideo:

View file

@ -1,5 +1,16 @@
Files created in '{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
Alfa Mist - Nocturne [Full Album]/01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3
From Chapter Split:
Warning: Dry-run assumes embedded chapters with no modifications

View file

@ -1,5 +1,16 @@
Files created in '{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
Alfa Mist - Nocturne [Full Album]/01 - 01. Intro (Feat. Racheal Ofori & Barney Artist).mp3
From Chapter Split:
Source Title: Alfa Mist - Nocturne [Full Album]

View file

@ -1,5 +1,6 @@
Files created in '{output_directory}'
----------------------------------------
Oblivion Mod "Falcor" p.1.info.json
Oblivion Mod "Falcor" p.1/01 - Oblivion Mod "Falcor" p.1.mp3
Music Tags:
album: Oblivion Mod "Falcor" p.1

View file

@ -1,5 +1,14 @@
Files created in '{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
Nocturne/01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3
From Chapter Split:
Warning: Dry-run assumes embedded chapters with no modifications
@ -143,4 +152,6 @@ Nocturne/11 - Sunrise (Pillows) (Feat. Emmavie).mp3
title: Sunrise (Pillows) (Feat. Emmavie)
track: 11
year: 2017
Nocturne/folder.jpg
Nocturne/folder.jpg
Sunrise (Pillows) (Feat. Emmavie).info.json
What If (Interlude).info.json

View file

@ -1,5 +1,14 @@
Files created in '{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
Nocturne/01 - Intro (Feat. Racheal Ofori & Barney Artist).mp3
From Chapter Split:
Source Title: Alfa Mist - Nocturne [Full Album]
@ -132,4 +141,6 @@ Nocturne/11 - Sunrise (Pillows) (Feat. Emmavie).mp3
title: Sunrise (Pillows) (Feat. Emmavie)
track: 11
year: 2017
Nocturne/folder.jpg
Nocturne/folder.jpg
Sunrise (Pillows) (Feat. Emmavie).info.json
What If (Interlude).info.json

View file

@ -1,5 +1,6 @@
Files created in '{output_directory}'
----------------------------------------
Jesse's Minecraft Server [Trailer - Feb.1].info.json
Jesse's Minecraft Server [Trailer - Feb.1].ogg
Music Tags:
album: Singles
@ -9,6 +10,7 @@ Jesse's Minecraft Server [Trailer - Feb.1].ogg
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
@ -18,6 +20,7 @@ Jesse's Minecraft Server [Trailer - Feb.27].ogg
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

View file

@ -1,5 +1,6 @@
Files created in '{output_directory}'
----------------------------------------
YouTube Rewind 2019: For the Record | #YouTubeRewind.info.json
YouTube Rewind 2019: For the Record | #YouTubeRewind.mp3
Music Tags:
album: Singles

View file

@ -1,6 +1,7 @@
Files created in '{output_directory}'
----------------------------------------
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
Chapters embedded from timestamp file:
0:00: Intro

View file

@ -1,6 +1,7 @@
Files created in '{output_directory}'
----------------------------------------
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
Embedded Chapters
Removed Chapter(s): Intro, Outro

View file

@ -2,6 +2,7 @@ Files created in '{output_directory}'
----------------------------------------
.ytdl-sub-regex_capture_playlist_test-download-archive.json
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
Project Zombie - Jesse's Minecraft Server [Trailer - Feb.1].nfo
NFO tags:
@ -20,6 +21,7 @@ Project Zombie - Jesse's Minecraft Server [Trailer - Feb.1].nfo
upload_date_both_caps: First and Second containing in regex default
year: 2011
Project Zombie - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg
Project Zombie - Jesse's Minecraft Server [Trailer - Feb.27].info.json
Project Zombie - Jesse's Minecraft Server [Trailer - Feb.27].mp4
Project Zombie - Jesse's Minecraft Server [Trailer - Feb.27].nfo
NFO tags:

View file

@ -1,6 +1,7 @@
Files created in '{output_directory}'
----------------------------------------
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
Embedded subtitles with lang(s) en, de
JMC - YouTube Rewind 2019 For the Record #YouTubeRewind.nfo

View file

@ -3,6 +3,7 @@ Files created in '{output_directory}'
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
JMC - YouTube Rewind 2019 For the Record #YouTubeRewind.info.json
JMC - YouTube Rewind 2019 For the Record #YouTubeRewind.mp4
Embedded subtitles with lang(s) en, de
JMC - YouTube Rewind 2019 For the Record #YouTubeRewind.nfo

View file

@ -1,6 +1,7 @@
Files created in '{output_directory}'
----------------------------------------
.ytdl-sub-jb-download-archive.json
j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.info.json
j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.mp3
Music Tags:
album: Baby Santana's Dorian Groove
@ -11,6 +12,7 @@ j_b/[2021] Baby Santana's Dorian Groove/01 - Baby Santana's Dorian Groove.mp3
track: 1
year: 2021
j_b/[2021] Baby Santana's Dorian Groove/folder.jpg
j_b/[2021] Purple Clouds/01 - Purple Clouds.info.json
j_b/[2021] Purple Clouds/01 - Purple Clouds.mp3
Music Tags:
album: Purple Clouds
@ -21,6 +23,7 @@ j_b/[2021] Purple Clouds/01 - Purple Clouds.mp3
track: 1
year: 2021
j_b/[2021] Purple Clouds/folder.jpg
j_b/[2022] Acoustic Treats/01 - 20160426 184214.info.json
j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3
Music Tags:
album: Acoustic Treats
@ -30,6 +33,7 @@ j_b/[2022] Acoustic Treats/01 - 20160426 184214.mp3
title: 20160426 184214
track: 1
year: 2022
j_b/[2022] Acoustic Treats/02 - 20160502 123150.info.json
j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3
Music Tags:
album: Acoustic Treats
@ -39,6 +43,7 @@ j_b/[2022] Acoustic Treats/02 - 20160502 123150.mp3
title: 20160502 123150
track: 2
year: 2022
j_b/[2022] Acoustic Treats/03 - 20160504 143832.info.json
j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3
Music Tags:
album: Acoustic Treats
@ -48,6 +53,7 @@ j_b/[2022] Acoustic Treats/03 - 20160504 143832.mp3
title: 20160504 143832
track: 3
year: 2022
j_b/[2022] Acoustic Treats/04 - 20160601 221234.info.json
j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3
Music Tags:
album: Acoustic Treats
@ -57,6 +63,7 @@ j_b/[2022] Acoustic Treats/04 - 20160601 221234.mp3
title: 20160601 221234
track: 4
year: 2022
j_b/[2022] Acoustic Treats/05 - 20160601 222440.info.json
j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3
Music Tags:
album: Acoustic Treats
@ -66,6 +73,7 @@ j_b/[2022] Acoustic Treats/05 - 20160601 222440.mp3
title: 20160601 222440
track: 5
year: 2022
j_b/[2022] Acoustic Treats/06 - 20170604 190236.info.json
j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3
Music Tags:
album: Acoustic Treats
@ -75,6 +83,7 @@ j_b/[2022] Acoustic Treats/06 - 20170604 190236.mp3
title: 20170604 190236
track: 6
year: 2022
j_b/[2022] Acoustic Treats/07 - 20170612 193646.info.json
j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3
Music Tags:
album: Acoustic Treats
@ -84,6 +93,7 @@ j_b/[2022] Acoustic Treats/07 - 20170612 193646.mp3
title: 20170612 193646
track: 7
year: 2022
j_b/[2022] Acoustic Treats/08 - 20170628 215206.info.json
j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3
Music Tags:
album: Acoustic Treats
@ -93,6 +103,7 @@ j_b/[2022] Acoustic Treats/08 - 20170628 215206.mp3
title: 20170628 215206
track: 8
year: 2022
j_b/[2022] Acoustic Treats/09 - Finding Home.info.json
j_b/[2022] Acoustic Treats/09 - Finding Home.mp3
Music Tags:
album: Acoustic Treats
@ -102,6 +113,7 @@ j_b/[2022] Acoustic Treats/09 - Finding Home.mp3
title: Finding Home
track: 9
year: 2022
j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.info.json
j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3
Music Tags:
album: Acoustic Treats
@ -111,6 +123,7 @@ j_b/[2022] Acoustic Treats/10 - Shallow Water WIP.mp3
title: Shallow Water WIP
track: 10
year: 2022
j_b/[2022] Acoustic Treats/11 - Untold History.info.json
j_b/[2022] Acoustic Treats/11 - Untold History.mp3
Music Tags:
album: Acoustic Treats

View file

@ -2,6 +2,7 @@ Files created in '{output_directory}'
----------------------------------------
.ytdl-sub-pz-download-archive.json
Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1-thumb.jpg
Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1.info.json
Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1.mp4
Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1.nfo
NFO tags:
@ -19,6 +20,7 @@ Season 2010/s2010.e0813 - Oblivion Mod Falcor p.1.nfo
title: Oblivion Mod "Falcor" p.1
year: 2010
Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2-thumb.jpg
Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2.info.json
Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2.mp4
Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2.nfo
NFO tags:
@ -36,6 +38,7 @@ Season 2010/s2010.e1202 - Oblivion Mod Falcor p.2.nfo
title: Oblivion Mod "Falcor" p.2
year: 2010
Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1]-thumb.jpg
Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].info.json
Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].mp4
Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].nfo
NFO tags:
@ -54,6 +57,7 @@ Season 2011/s2011.e0201 - Jesse's Minecraft Server [Trailer - Feb.1].nfo
title: Jesse's Minecraft Server [Trailer - Feb.1]
year: 2011
Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg
Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].info.json
Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].mp4
Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].nfo
NFO tags:
@ -91,6 +95,7 @@ Season 2011/s2011.e0227 - Jesse's Minecraft Server [Trailer - Feb.27].nfo
title: Jesse's Minecraft Server [Trailer - Feb.27]
year: 2011
Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg
Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].info.json
Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].mp4
Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].nfo
NFO tags:
@ -128,6 +133,7 @@ Season 2011/s2011.e0321 - Jesse's Minecraft Server [Trailer - Mar.21].nfo
title: Jesse's Minecraft Server [Trailer - Mar.21]
year: 2011
Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net)-thumb.jpg
Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net).info.json
Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net).mp4
Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projectzombie.beastnode.net).nfo
NFO tags:
@ -155,6 +161,7 @@ Season 2011/s2011.e0529 - Project Zombie Official Trailer (IP mc.projec
title: Project Zombie |Official Trailer| (IP: mc.projectzombie.beastnode.net)
year: 2011
Season 2011/s2011.e0630 - Project Zombie Fin-thumb.jpg
Season 2011/s2011.e0630 - Project Zombie Fin.info.json
Season 2011/s2011.e0630 - Project Zombie Fin.mp4
Season 2011/s2011.e0630 - Project Zombie Fin.nfo
NFO tags:
@ -168,6 +175,7 @@ Season 2011/s2011.e0630 - Project Zombie Fin.nfo
title: Project Zombie |Fin|
year: 2011
Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC]-thumb.jpg
Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC].info.json
Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC].mp4
Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC].nfo
NFO tags:
@ -188,6 +196,7 @@ Season 2011/s2011.e1121 - Skyrim 'Ultra HD wMods' [PC].nfo
title: Skyrim 'Ultra HD w/Mods' [PC]
year: 2011
Season 2012/s2012.e0123 - Project Zombie Map Trailer-thumb.jpg
Season 2012/s2012.e0123 - Project Zombie Map Trailer.info.json
Season 2012/s2012.e0123 - Project Zombie Map Trailer.mp4
Season 2012/s2012.e0123 - Project Zombie Map Trailer.nfo
NFO tags:
@ -208,6 +217,7 @@ Season 2012/s2012.e0123 - Project Zombie Map Trailer.nfo
title: Project Zombie |Map Trailer|
year: 2012
Season 2013/s2013.e0719 - Project Zombie Rewind Trailer-thumb.jpg
Season 2013/s2013.e0719 - Project Zombie Rewind Trailer.info.json
Season 2013/s2013.e0719 - Project Zombie Rewind Trailer.mp4
Season 2013/s2013.e0719 - Project Zombie Rewind Trailer.nfo
NFO tags:
@ -223,6 +233,7 @@ Season 2013/s2013.e0719 - Project Zombie Rewind Trailer.nfo
title: Project Zombie Rewind |Trailer|
year: 2013
Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer-thumb.jpg
Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.info.json
Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.mp4
Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.nfo
NFO tags:
@ -244,6 +255,7 @@ Season 2018/s2018.e1029 - Jesse's Minecraft Server Teaser Trailer.nfo
year: 2018
Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id-thumb.jpg
Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.en.srt
Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.info.json
Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.mp4
Season 2018/s2018.e1102 - Jesse's Minecraft Server IP mc.jesse.id.nfo
NFO tags:

View file

@ -1,6 +1,7 @@
Files created in '{output_directory}'
----------------------------------------
JMC - Jesse's Minecraft Server-thumb.jpg
JMC - Jesse's Minecraft Server.info.json
JMC - Jesse's Minecraft Server.mkv
Timestamps of playlist videos in the merged file:
0:00: Jesse's Minecraft Server [Trailer - Mar.21]

View file

@ -2,6 +2,7 @@ Files created in '{output_directory}'
----------------------------------------
.ytdl-sub-music_video_playlist_test-download-archive.json
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
JMC - Jesse's Minecraft Server [Trailer - Feb.1].nfo
NFO tags:
@ -11,6 +12,7 @@ JMC - Jesse's Minecraft Server [Trailer - Feb.1].nfo
title: Jesse's Minecraft Server [Trailer - Feb.1]
year: 2011
JMC - Jesse's Minecraft Server [Trailer - Feb.27]-thumb.jpg
JMC - Jesse's Minecraft Server [Trailer - Feb.27].info.json
JMC - Jesse's Minecraft Server [Trailer - Feb.27].mp4
JMC - Jesse's Minecraft Server [Trailer - Feb.27].nfo
NFO tags:
@ -20,6 +22,7 @@ JMC - Jesse's Minecraft Server [Trailer - Feb.27].nfo
title: Jesse's Minecraft Server [Trailer - Feb.27]
year: 2011
JMC - Jesse's Minecraft Server [Trailer - Mar.21]-thumb.jpg
JMC - Jesse's Minecraft Server [Trailer - Mar.21].info.json
JMC - Jesse's Minecraft Server [Trailer - Mar.21].mp4
JMC - Jesse's Minecraft Server [Trailer - Mar.21].nfo
NFO tags:

View file

@ -13,6 +13,7 @@ Project Zombie - 5-6.Part 4.mp4
Project Zombie - 6-6.Part 5.mp4
1:01 - 1:28
Project Zombie - Intro-thumb.jpg
Project Zombie - Intro.info.json
Project Zombie - Intro.nfo
NFO tags:
musicvideo:
@ -21,6 +22,7 @@ Project Zombie - Intro.nfo
title: Intro
year: 2010
Project Zombie - Part 1-thumb.jpg
Project Zombie - Part 1.info.json
Project Zombie - Part 1.nfo
NFO tags:
musicvideo:
@ -29,6 +31,7 @@ Project Zombie - Part 1.nfo
title: Part 1
year: 2010
Project Zombie - Part 2-thumb.jpg
Project Zombie - Part 2.info.json
Project Zombie - Part 2.nfo
NFO tags:
musicvideo:
@ -37,6 +40,7 @@ Project Zombie - Part 2.nfo
title: Part 2
year: 2010
Project Zombie - Part 3-thumb.jpg
Project Zombie - Part 3.info.json
Project Zombie - Part 3.nfo
NFO tags:
musicvideo:
@ -45,6 +49,7 @@ Project Zombie - Part 3.nfo
title: Part 3
year: 2010
Project Zombie - Part 4-thumb.jpg
Project Zombie - Part 4.info.json
Project Zombie - Part 4.nfo
NFO tags:
musicvideo:
@ -53,6 +58,7 @@ Project Zombie - Part 4.nfo
title: Part 4
year: 2010
Project Zombie - Part 5-thumb.jpg
Project Zombie - Part 5.info.json
Project Zombie - Part 5.nfo
NFO tags:
musicvideo:

View file

@ -1,6 +1,7 @@
Files created in '{output_directory}'
----------------------------------------
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

View file

@ -77,6 +77,7 @@ def mock_entry_to_dict(
"upload_day_of_year_reversed": 354,
"upload_day_of_year_reversed_padded": "354",
"thumbnail_ext": thumbnail_ext,
"info_json_ext": "info.json",
}