remove timestamps file
This commit is contained in:
parent
61287af12d
commit
75cfeb9c57
3 changed files with 1 additions and 129 deletions
|
|
@ -18,7 +18,6 @@ from ytdl_sub.validators.regex_validator import RegexListValidator
|
||||||
from ytdl_sub.validators.string_select_validator import StringSelectValidator
|
from ytdl_sub.validators.string_select_validator import StringSelectValidator
|
||||||
from ytdl_sub.validators.validators import BoolValidator
|
from ytdl_sub.validators.validators import BoolValidator
|
||||||
from ytdl_sub.validators.validators import ListValidator
|
from ytdl_sub.validators.validators import ListValidator
|
||||||
from ytdl_sub.validators.validators import StringValidator
|
|
||||||
|
|
||||||
SPONSORBLOCK_HIGHLIGHT_CATEGORIES: Set[str] = {"poi_highlight"}
|
SPONSORBLOCK_HIGHLIGHT_CATEGORIES: Set[str] = {"poi_highlight"}
|
||||||
SPONSORBLOCK_CATEGORIES: Set[str] = SPONSORBLOCK_HIGHLIGHT_CATEGORIES | {
|
SPONSORBLOCK_CATEGORIES: Set[str] = SPONSORBLOCK_HIGHLIGHT_CATEGORIES | {
|
||||||
|
|
@ -95,7 +94,6 @@ class ChaptersOptions(PluginOptions):
|
||||||
_optional_keys = {
|
_optional_keys = {
|
||||||
"embed_chapters",
|
"embed_chapters",
|
||||||
"allow_chapters_from_comments",
|
"allow_chapters_from_comments",
|
||||||
"embed_chapter_timestamps",
|
|
||||||
"sponsorblock_categories",
|
"sponsorblock_categories",
|
||||||
"remove_sponsorblock_categories",
|
"remove_sponsorblock_categories",
|
||||||
"remove_chapters_regex",
|
"remove_chapters_regex",
|
||||||
|
|
@ -119,9 +117,6 @@ class ChaptersOptions(PluginOptions):
|
||||||
self._force_key_frames = self._validate_key_if_present(
|
self._force_key_frames = self._validate_key_if_present(
|
||||||
key="force_key_frames", validator=BoolValidator, default=False
|
key="force_key_frames", validator=BoolValidator, default=False
|
||||||
).value
|
).value
|
||||||
self._embed_chapter_timestamps = self._validate_key_if_present(
|
|
||||||
"embed_chapter_timestamps", StringValidator
|
|
||||||
)
|
|
||||||
self._allow_chapters_from_comments = self._validate_key_if_present(
|
self._allow_chapters_from_comments = self._validate_key_if_present(
|
||||||
key="allow_chapters_from_comments", validator=BoolValidator, default=False
|
key="allow_chapters_from_comments", validator=BoolValidator, default=False
|
||||||
).value
|
).value
|
||||||
|
|
@ -136,11 +131,6 @@ class ChaptersOptions(PluginOptions):
|
||||||
"Cannot remove sponsorblock categories and embed chapters from comments"
|
"Cannot remove sponsorblock categories and embed chapters from comments"
|
||||||
)
|
)
|
||||||
|
|
||||||
if self._embed_chapters and self._embed_chapter_timestamps:
|
|
||||||
raise self._validation_exception(
|
|
||||||
"Cannot embed chapters from the source and from a timestamp file"
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def embed_chapters(self) -> Optional[bool]:
|
def embed_chapters(self) -> Optional[bool]:
|
||||||
"""
|
"""
|
||||||
|
|
@ -197,27 +187,6 @@ class ChaptersOptions(PluginOptions):
|
||||||
"""
|
"""
|
||||||
return self._force_key_frames
|
return self._force_key_frames
|
||||||
|
|
||||||
@property
|
|
||||||
def embed_chapter_timestamps(self) -> Optional[str]:
|
|
||||||
"""
|
|
||||||
Optional. The path to the file containing the timestamps to embed into the file as
|
|
||||||
chapters. Should be formatted as:
|
|
||||||
|
|
||||||
.. code-block:: markdown
|
|
||||||
|
|
||||||
0:00 Intro
|
|
||||||
0:24 Blackwater Park
|
|
||||||
10:23 Bleak
|
|
||||||
16:39 Jokes
|
|
||||||
1:02:23 Ending
|
|
||||||
|
|
||||||
This should only be used with single entity download strategies. Otherwise, an entire
|
|
||||||
playlist or channel would all the same embedded chapters.
|
|
||||||
"""
|
|
||||||
if self._embed_chapter_timestamps:
|
|
||||||
return self._embed_chapter_timestamps.value
|
|
||||||
return None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def allow_chapters_from_comments(self) -> bool:
|
def allow_chapters_from_comments(self) -> bool:
|
||||||
"""
|
"""
|
||||||
|
|
@ -333,11 +302,6 @@ class ChaptersPlugin(Plugin[ChaptersOptions]):
|
||||||
"""
|
"""
|
||||||
chapters = Chapters.from_empty()
|
chapters = Chapters.from_empty()
|
||||||
|
|
||||||
if self.plugin_options.embed_chapter_timestamps and not self.is_dry_run:
|
|
||||||
chapters = Chapters.from_timestamps_file(
|
|
||||||
chapters_file_path=self.plugin_options.embed_chapter_timestamps
|
|
||||||
)
|
|
||||||
|
|
||||||
if not _contains_any_chapters(entry) and self.plugin_options.allow_chapters_from_comments:
|
if not _contains_any_chapters(entry) and self.plugin_options.allow_chapters_from_comments:
|
||||||
for comment in entry.kwargs_get(COMMENTS, []):
|
for comment in entry.kwargs_get(COMMENTS, []):
|
||||||
chapters = Chapters.from_string(comment.get("text", ""))
|
chapters = Chapters.from_string(comment.get("text", ""))
|
||||||
|
|
@ -368,14 +332,7 @@ class ChaptersPlugin(Plugin[ChaptersOptions]):
|
||||||
FileMetadata outlining which chapters/SponsorBlock segments got removed
|
FileMetadata outlining which chapters/SponsorBlock segments got removed
|
||||||
"""
|
"""
|
||||||
if custom_chapters_metadata := entry.kwargs_get(YTDL_SUB_CUSTOM_CHAPTERS):
|
if custom_chapters_metadata := entry.kwargs_get(YTDL_SUB_CUSTOM_CHAPTERS):
|
||||||
title: str = ""
|
title: str = "Chapters from comments"
|
||||||
|
|
||||||
if self.plugin_options.embed_chapter_timestamps:
|
|
||||||
title = "Chapters embedded from timestamp file"
|
|
||||||
elif self.plugin_options.allow_chapters_from_comments:
|
|
||||||
title = "Chapters from comments"
|
|
||||||
|
|
||||||
assert title, "title should not be empty"
|
|
||||||
return FileMetadata.from_dict(
|
return FileMetadata.from_dict(
|
||||||
value_dict=custom_chapters_metadata,
|
value_dict=custom_chapters_metadata,
|
||||||
title=title,
|
title=title,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import json
|
import json
|
||||||
import os
|
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
@ -8,7 +7,6 @@ from typing import Optional
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
from ytdl_sub.entries.entry import Entry
|
from ytdl_sub.entries.entry import Entry
|
||||||
from ytdl_sub.utils.exceptions import ValidationException
|
|
||||||
from ytdl_sub.utils.file_handler import FileMetadata
|
from ytdl_sub.utils.file_handler import FileMetadata
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -184,50 +182,6 @@ class Chapters:
|
||||||
sort_dict=False, # timestamps + titles are already sorted
|
sort_dict=False, # timestamps + titles are already sorted
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_timestamps_file(cls, chapters_file_path: str) -> "Chapters":
|
|
||||||
"""
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
chapters_file_path
|
|
||||||
Path to file containing chapters
|
|
||||||
|
|
||||||
Raises
|
|
||||||
------
|
|
||||||
ValidationException
|
|
||||||
File path does not exist or contains invalid formatting
|
|
||||||
"""
|
|
||||||
if not os.path.isfile(chapters_file_path):
|
|
||||||
raise ValidationException(
|
|
||||||
f"chapter/timestamp file path '{chapters_file_path}' does not exist."
|
|
||||||
)
|
|
||||||
|
|
||||||
with open(chapters_file_path, "r", encoding="utf-8") as file:
|
|
||||||
lines = file.readlines()
|
|
||||||
|
|
||||||
timestamps: List[Timestamp] = []
|
|
||||||
titles: List[str] = []
|
|
||||||
|
|
||||||
for idx, line in enumerate(lines):
|
|
||||||
line_split = line.strip().split(maxsplit=1)
|
|
||||||
|
|
||||||
# Allow the last line to be blank
|
|
||||||
if idx == len(lines) - 1 and not line.strip():
|
|
||||||
break
|
|
||||||
|
|
||||||
if len(line_split) != 2:
|
|
||||||
raise ValidationException(
|
|
||||||
f"Chapter/Timestamp file '{chapters_file_path}' could not parse '{line}': "
|
|
||||||
f"must be in the format of 'HH:MM:SS title"
|
|
||||||
)
|
|
||||||
|
|
||||||
timestamp_str, title = tuple(x for x in line_split)
|
|
||||||
|
|
||||||
timestamps.append(Timestamp.from_str(timestamp_str))
|
|
||||||
titles.append(title)
|
|
||||||
|
|
||||||
return cls(timestamps=timestamps, titles=titles)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_string(cls, input_str: str) -> "Chapters":
|
def from_string(cls, input_str: str) -> "Chapters":
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -86,45 +86,6 @@ class TestChapters:
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@pytest.mark.parametrize("dry_run", [True, False])
|
|
||||||
def test_chapters_from_timestamp_file_with_subs(
|
|
||||||
self,
|
|
||||||
music_video_config,
|
|
||||||
sponsorblock_and_subs_preset_dict,
|
|
||||||
timestamps_file_path,
|
|
||||||
output_directory,
|
|
||||||
dry_run,
|
|
||||||
):
|
|
||||||
# Test chapters and video tags, throw in a video tag with special chars while we are at it
|
|
||||||
sponsorblock_and_subs_preset_dict["chapters"] = {
|
|
||||||
"embed_chapters": False,
|
|
||||||
"embed_chapter_timestamps": timestamps_file_path,
|
|
||||||
}
|
|
||||||
sponsorblock_and_subs_preset_dict["video_tags"] = {
|
|
||||||
"tags": {"description": "🎸 / ' \" \n newline?"}
|
|
||||||
}
|
|
||||||
|
|
||||||
subscription = Subscription.from_dict(
|
|
||||||
config=music_video_config,
|
|
||||||
preset_name="chapters_from_timestamps_with_subs",
|
|
||||||
preset_dict=sponsorblock_and_subs_preset_dict,
|
|
||||||
)
|
|
||||||
|
|
||||||
transaction_log = subscription.download(dry_run=dry_run)
|
|
||||||
assert_transaction_log_matches(
|
|
||||||
output_directory=output_directory,
|
|
||||||
transaction_log=transaction_log,
|
|
||||||
transaction_log_summary_file_name="plugins/test_chapters_from_ts_with_subs.txt",
|
|
||||||
)
|
|
||||||
assert_expected_downloads(
|
|
||||||
output_directory=output_directory,
|
|
||||||
dry_run=dry_run,
|
|
||||||
expected_download_summary_file_name="plugins/test_chapters_from_ts_with_subs.json",
|
|
||||||
ignore_md5_hashes_for=[
|
|
||||||
"JMC/JMC - This GPU SLIDES into this Case! - Silverstone SUGO 16 ITX Case.mp4"
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("dry_run", [True, False])
|
@pytest.mark.parametrize("dry_run", [True, False])
|
||||||
def test_chapters_from_comments(
|
def test_chapters_from_comments(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue