chapters and split by chapters plugins WIP

This commit is contained in:
jbannon 2022-08-15 05:23:58 +00:00
parent 871c051aa8
commit 653681040d
5 changed files with 179 additions and 7 deletions

View file

@ -0,0 +1,107 @@
import re
from typing import Dict
from typing import List
from typing import Optional
from typing import Set
from ytdl_sub.entries.entry import Entry
from ytdl_sub.plugins.plugin import Plugin
from ytdl_sub.plugins.plugin import PluginOptions
from ytdl_sub.validators.regex_validator import RegexListValidator
from ytdl_sub.validators.string_select_validator import StringSelectValidator
from ytdl_sub.validators.validators import ListValidator
SPONSORBLOCK_HIGHLIGHT_CATEGORIES: Set[str] = {"poi_highlight"}
SPONSORBLOCK_CATEGORIES: Set[str] = SPONSORBLOCK_HIGHLIGHT_CATEGORIES | {
"sponsor",
"intro",
"outro",
"selfpromo",
"preview",
"filler",
"interaction",
"music_offtopic",
}
class SponsorBlockCategoriesValidator(StringSelectValidator):
_expected_value_type = "sponsorblock category"
_select_values = {"all"} | SPONSORBLOCK_CATEGORIES
class SponsorBlockCategoryListValidator(ListValidator[SponsorBlockCategoriesValidator]):
_expected_value_type = "sponsorblock category"
_inner_list_type = SponsorBlockCategoriesValidator
class ChaptersOptions(PluginOptions):
"""
Add chapters to video files if they are present. Options to add SponsorBlock chapters and
remove them or existing chapters.
Usage:
.. code-block:: yaml
presets:
my_example_preset:
chapters:
sponsorblock_categories:
- "outro"
- "selfpromo"
- "preview"
- "interaction"
- "sponsor"
- "music_offtopic"
- "intro"
remove_sponsorblock_categories: "all"
remove_chapters_regex:
- "sponsor"
"""
_optional_keys = {
"sponsorblock_categories",
"remove_sponsorblock_categories",
"remove_chapters_regex",
}
def __init__(self, name, value):
super().__init__(name, value)
self._sponsorblock_categories = self._validate_key_if_present(
key="sponsorblock_categories", validator=SponsorBlockCategoryListValidator
)
self._remove_sponsorblock_categories = self._validate_key_if_present(
key="remove_sponsorblock_categories", validator=SponsorBlockCategoryListValidator
)
self._remove_chapters_regex = self._validate_key_if_present(
key="remove_chapters_regex", validator=RegexListValidator
)
@property
def sponsorblock_categories(self) -> Optional[List[str]]:
if self._sponsorblock_categories:
return [validator.value for validator in self._sponsorblock_categories.list]
return None
@property
def remove_sponsorblock_categories(self) -> Optional[List[str]]:
if self._remove_sponsorblock_categories:
return [validator.value for validator in self._remove_sponsorblock_categories.list]
return None
@property
def remove_chapters_regex(self) -> Optional[List[re.Pattern]]:
if self._remove_chapters_regex:
return [validator.compiled_regex for validator in self._remove_chapters_regex.list]
return None
class ChaptersPlugin(Plugin[ChaptersOptions]):
plugin_options_type = ChaptersOptions
def modify_entry(self, entry: Entry) -> Optional[Entry]:
"""
Tags the entry's audio file using values defined in the metadata options
"""
return entry

View file

@ -0,0 +1,54 @@
from typing import Dict
from typing import Optional
from ytdl_sub.entries.entry import Entry
from ytdl_sub.plugins.plugin import Plugin
from ytdl_sub.plugins.plugin import PluginOptions
from ytdl_sub.validators.string_select_validator import StringSelectValidator
class WhenNoChaptersValidator(StringSelectValidator):
_expected_value_type = "when no chapters option"
_select_values = {"pass", "drop", "error"}
class SplitByChaptersOptions(PluginOptions):
"""
Splits a file by chapters into multiple files. Each file becomes its own entry with ``title``
set to its chapter name, and is processed separately by other plugins.
Usage:
.. code-block:: yaml
presets:
my_example_preset:
split_by_chapters:
when_no_chapters: "pass" # "drop"/"error"
"""
_required_keys = {"when_no_chapters"}
def __init__(self, name, value):
super().__init__(name, value)
self._when_no_chapters = self._validate_key(
key="when_no_chapters", validator=WhenNoChaptersValidator
).value
@property
def when_no_chapters(self) -> str:
"""
Behavior to perform when no chapters are present. Supports "pass" (continue processing),
"drop" (exclude it from output), and "error" (stop processing for everything).
"""
return self._when_no_chapters
class SplitByChaptersPlugin(Plugin[SplitByChaptersOptions]):
plugin_options_type = SplitByChaptersOptions
def modify_entry(self, entry: Entry) -> Optional[Entry]:
"""
Tags the entry's audio file using values defined in the metadata options
"""
return entry

View file

@ -28,6 +28,15 @@ class RegexValidator(StringValidator):
"""
return self._compiled_regex.groups
@property
def compiled_regex(self) -> re.Pattern:
"""
Returns
-------
The regex compiled
"""
return self._compiled_regex
def match(self, input_str: str) -> Optional[List[str]]:
"""
Parameters

View file

@ -7,10 +7,12 @@ from ytdl_sub.subscriptions.subscription import Subscription
@pytest.fixture
def single_song_preset_dict(output_directory):
def single_song_preset_dict(output_directory, timestamps_file_path):
return {
"preset": "yt_song",
"youtube": {"video_url": "https://www.youtube.com/watch?v=2lAe1cqCOXo"},
"youtube": {
"video_url": "https://www.youtube.com/watch?v=gr0XWmEbiMQ",
},
"output_options": {"output_directory": output_directory},
# download the worst format so it is fast
"ytdl_options": {

View file

@ -1,11 +1,11 @@
Files created in '{output_directory}'
----------------------------------------
YouTube Rewind 2019 For the Record #YouTubeRewind.mp3
Gabor Szabo - Dreams (1968) [full album].mp3
Music Tags:
album: Singles
albumartist: YouTube
artist: YouTube
albumartist: Cubensis Records
artist: Cubensis Records
genre: Unset
title: YouTube Rewind 2019: For the Record | #YouTubeRewind
title: Gabor Szabo - Dreams (1968) [full album]
track: 1
year: 2019
year: 2015