From 8157a09d22f6f4310427a7155e737c2c1bc3aef9 Mon Sep 17 00:00:00 2001 From: Nil Admirari <50202386+nihil-admirari@users.noreply.github.com> Date: Thu, 9 Dec 2021 12:40:31 +0000 Subject: [PATCH] [SponsorBlock] Add Filler and Highlight categories (#1664) Authored by: nihil-admirari, pukkandan --- README.md | 18 ++++++++++-------- test/test_postprocessors.py | 4 ++-- yt_dlp/options.py | 25 +++++++++++++++++-------- yt_dlp/postprocessor/modify_chapters.py | 4 ++-- yt_dlp/postprocessor/sponsorblock.py | 14 +++++++++++--- 5 files changed, 42 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 65d8aa5827..0eecb55367 100644 --- a/README.md +++ b/README.md @@ -940,19 +940,21 @@ Make chapter entries for, or remove various segments (sponsor, --sponsorblock-mark CATS SponsorBlock categories to create chapters for, separated by commas. Available - categories are all, sponsor, intro, outro, - selfpromo, interaction, preview, - music_offtopic. You can prefix the category - with a "-" to exempt it. See - https://wiki.sponsor.ajay.app/index.php/Segment_Categories - for description of the categories. Eg: - --sponsorblock-query all,-preview + categories are all, default(=all), sponsor, + intro, outro, selfpromo, preview, filler, + interaction, music_offtopic, poi_highlight. + You can prefix the category with a "-" to + exempt it. See [1] for description of the + categories. Eg: --sponsorblock-mark all,-preview + [1] https://wiki.sponsor.ajay.app/w/Segment_Categories --sponsorblock-remove CATS SponsorBlock categories to be removed from the video file, separated by commas. If a category is present in both mark and remove, remove takes precedence. The syntax and available categories are the same as - for --sponsorblock-mark + for --sponsorblock-mark except that + "default" refers to "all,-filler" and + poi_highlight is not available --sponsorblock-chapter-title TEMPLATE The title template for SponsorBlock chapters created by --sponsorblock-mark. diff --git a/test/test_postprocessors.py b/test/test_postprocessors.py index 090c7b47b0..bbe998993f 100644 --- a/test/test_postprocessors.py +++ b/test/test_postprocessors.py @@ -124,11 +124,11 @@ class TestModifyChaptersPP(unittest.TestCase): chapters = self._chapters([70], ['c']) + [ self._sponsor_chapter(10, 20, 'sponsor'), self._sponsor_chapter(30, 40, 'preview'), - self._sponsor_chapter(50, 60, 'sponsor')] + self._sponsor_chapter(50, 60, 'filler')] expected = self._chapters( [10, 20, 30, 40, 50, 60, 70], ['c', '[SponsorBlock]: Sponsor', 'c', '[SponsorBlock]: Preview/Recap', - 'c', '[SponsorBlock]: Sponsor', 'c']) + 'c', '[SponsorBlock]: Filler Tangent', 'c']) self._remove_marked_arrange_sponsors_test_impl(chapters, expected, []) def test_remove_marked_arrange_sponsors_UniqueNamesForOverlappingSponsors(self): diff --git a/yt_dlp/options.py b/yt_dlp/options.py index bb421e0f81..82088638bc 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1465,20 +1465,29 @@ def parseOpts(overrideArguments=None): sponsorblock.add_option( '--sponsorblock-mark', metavar='CATS', dest='sponsorblock_mark', default=set(), action='callback', type='str', - callback=_set_from_options_callback, callback_kwargs={'allowed_values': SponsorBlockPP.CATEGORIES.keys()}, - help=( + callback=_set_from_options_callback, callback_kwargs={ + 'allowed_values': SponsorBlockPP.CATEGORIES.keys(), + 'aliases': {'default': ['all']} + }, help=( 'SponsorBlock categories to create chapters for, separated by commas. ' - 'Available categories are all, %s. You can prefix the category with a "-" to exempt it. ' - 'See https://wiki.sponsor.ajay.app/index.php/Segment_Categories for description of the categories. ' - 'Eg: --sponsorblock-mark all,-preview' % ', '.join(SponsorBlockPP.CATEGORIES.keys()))) + f'Available categories are all, default(=all), {", ".join(SponsorBlockPP.CATEGORIES.keys())}. ' + 'You can prefix the category with a "-" to exempt it. See [1] for description of the categories. ' + 'Eg: --sponsorblock-mark all,-preview [1] https://wiki.sponsor.ajay.app/w/Segment_Categories')) sponsorblock.add_option( '--sponsorblock-remove', metavar='CATS', dest='sponsorblock_remove', default=set(), action='callback', type='str', - callback=_set_from_options_callback, callback_kwargs={'allowed_values': SponsorBlockPP.CATEGORIES.keys()}, - help=( + callback=_set_from_options_callback, callback_kwargs={ + 'allowed_values': set(SponsorBlockPP.CATEGORIES.keys()) - set(SponsorBlockPP.POI_CATEGORIES.keys()), + # Note: From https://wiki.sponsor.ajay.app/w/Types: + # The filler category is very aggressive. + # It is strongly recommended to not use this in a client by default. + 'aliases': {'default': ['all', '-filler']} + }, help=( 'SponsorBlock categories to be removed from the video file, separated by commas. ' 'If a category is present in both mark and remove, remove takes precedence. ' - 'The syntax and available categories are the same as for --sponsorblock-mark')) + 'The syntax and available categories are the same as for --sponsorblock-mark ' + 'except that "default" refers to "all,-filler" ' + f'and {", ".join(SponsorBlockPP.POI_CATEGORIES.keys())} is not available')) sponsorblock.add_option( '--sponsorblock-chapter-title', metavar='TEMPLATE', default=DEFAULT_SPONSORBLOCK_CHAPTER_TITLE, dest='sponsorblock_chapter_title', diff --git a/yt_dlp/postprocessor/modify_chapters.py b/yt_dlp/postprocessor/modify_chapters.py index 0728bdcf55..91433c364b 100644 --- a/yt_dlp/postprocessor/modify_chapters.py +++ b/yt_dlp/postprocessor/modify_chapters.py @@ -24,7 +24,7 @@ class ModifyChaptersPP(FFmpegPostProcessor): *, sponsorblock_chapter_title=DEFAULT_SPONSORBLOCK_CHAPTER_TITLE, force_keyframes=False): FFmpegPostProcessor.__init__(self, downloader) self._remove_chapters_patterns = set(remove_chapters_patterns or []) - self._remove_sponsor_segments = set(remove_sponsor_segments or []) + self._remove_sponsor_segments = set(remove_sponsor_segments or []) - set(SponsorBlockPP.POI_CATEGORIES.keys()) self._ranges_to_remove = set(remove_ranges or []) self._sponsorblock_chapter_title = sponsorblock_chapter_title self._force_keyframes = force_keyframes @@ -302,7 +302,7 @@ class ModifyChaptersPP(FFmpegPostProcessor): 'name': SponsorBlockPP.CATEGORIES[category], 'category_names': [SponsorBlockPP.CATEGORIES[c] for c in cats] }) - c['title'] = self._downloader.evaluate_outtmpl(self._sponsorblock_chapter_title, c) + c['title'] = self._downloader.evaluate_outtmpl(self._sponsorblock_chapter_title, c.copy()) # Merge identically named sponsors. if (new_chapters and 'categories' in new_chapters[-1] and new_chapters[-1]['title'] == c['title']): diff --git a/yt_dlp/postprocessor/sponsorblock.py b/yt_dlp/postprocessor/sponsorblock.py index 70c5462d14..cd48b15ae6 100644 --- a/yt_dlp/postprocessor/sponsorblock.py +++ b/yt_dlp/postprocessor/sponsorblock.py @@ -10,18 +10,23 @@ from ..utils import PostProcessingError, network_exceptions, sanitized_Request class SponsorBlockPP(FFmpegPostProcessor): - + # https://wiki.sponsor.ajay.app/w/Types EXTRACTORS = { 'Youtube': 'YouTube', } + POI_CATEGORIES = { + 'poi_highlight': 'Highlight', + } CATEGORIES = { 'sponsor': 'Sponsor', 'intro': 'Intermission/Intro Animation', 'outro': 'Endcards/Credits', 'selfpromo': 'Unpaid/Self Promotion', - 'interaction': 'Interaction Reminder', 'preview': 'Preview/Recap', - 'music_offtopic': 'Non-Music Section' + 'filler': 'Filler Tangent', + 'interaction': 'Interaction Reminder', + 'music_offtopic': 'Non-Music Section', + **POI_CATEGORIES, } def __init__(self, downloader, categories=None, api='https://sponsor.ajay.app'): @@ -47,6 +52,9 @@ class SponsorBlockPP(FFmpegPostProcessor): # Ignore milliseconds difference at the start. if start_end[0] <= 1: start_end[0] = 0 + # Make POI chapters 1 sec so that we can properly mark them + if s['category'] in self.POI_CATEGORIES.keys(): + start_end[1] += 1 # Ignore milliseconds difference at the end. # Never allow the segment to exceed the video. if duration and duration - start_end[1] <= 1: