1
mirror of https://github.com/yt-dlp/yt-dlp synced 2024-11-22 19:02:45 +01:00

[SponsorBlock] Add Filler and Highlight categories (#1664)

Authored by: nihil-admirari, pukkandan
This commit is contained in:
Nil Admirari 2021-12-09 12:40:31 +00:00 committed by GitHub
parent b1aaf1c07f
commit 8157a09d22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 23 deletions

View File

@ -940,19 +940,21 @@ Make chapter entries for, or remove various segments (sponsor,
--sponsorblock-mark CATS SponsorBlock categories to create chapters --sponsorblock-mark CATS SponsorBlock categories to create chapters
for, separated by commas. Available for, separated by commas. Available
categories are all, sponsor, intro, outro, categories are all, default(=all), sponsor,
selfpromo, interaction, preview, intro, outro, selfpromo, preview, filler,
music_offtopic. You can prefix the category interaction, music_offtopic, poi_highlight.
with a "-" to exempt it. See You can prefix the category with a "-" to
https://wiki.sponsor.ajay.app/index.php/Segment_Categories exempt it. See [1] for description of the
for description of the categories. Eg: categories. Eg: --sponsorblock-mark all,-preview
--sponsorblock-query all,-preview [1] https://wiki.sponsor.ajay.app/w/Segment_Categories
--sponsorblock-remove CATS SponsorBlock categories to be removed from --sponsorblock-remove CATS SponsorBlock categories to be removed from
the video file, separated by commas. If a the video file, separated by commas. If a
category is present in both mark and category is present in both mark and
remove, remove takes precedence. The syntax remove, remove takes precedence. The syntax
and available categories are the same as 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 --sponsorblock-chapter-title TEMPLATE
The title template for SponsorBlock The title template for SponsorBlock
chapters created by --sponsorblock-mark. chapters created by --sponsorblock-mark.

View File

@ -124,11 +124,11 @@ class TestModifyChaptersPP(unittest.TestCase):
chapters = self._chapters([70], ['c']) + [ chapters = self._chapters([70], ['c']) + [
self._sponsor_chapter(10, 20, 'sponsor'), self._sponsor_chapter(10, 20, 'sponsor'),
self._sponsor_chapter(30, 40, 'preview'), self._sponsor_chapter(30, 40, 'preview'),
self._sponsor_chapter(50, 60, 'sponsor')] self._sponsor_chapter(50, 60, 'filler')]
expected = self._chapters( expected = self._chapters(
[10, 20, 30, 40, 50, 60, 70], [10, 20, 30, 40, 50, 60, 70],
['c', '[SponsorBlock]: Sponsor', 'c', '[SponsorBlock]: Preview/Recap', ['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, []) self._remove_marked_arrange_sponsors_test_impl(chapters, expected, [])
def test_remove_marked_arrange_sponsors_UniqueNamesForOverlappingSponsors(self): def test_remove_marked_arrange_sponsors_UniqueNamesForOverlappingSponsors(self):

View File

@ -1465,20 +1465,29 @@ def parseOpts(overrideArguments=None):
sponsorblock.add_option( sponsorblock.add_option(
'--sponsorblock-mark', metavar='CATS', '--sponsorblock-mark', metavar='CATS',
dest='sponsorblock_mark', default=set(), action='callback', type='str', dest='sponsorblock_mark', default=set(), action='callback', type='str',
callback=_set_from_options_callback, callback_kwargs={'allowed_values': SponsorBlockPP.CATEGORIES.keys()}, callback=_set_from_options_callback, callback_kwargs={
help=( 'allowed_values': SponsorBlockPP.CATEGORIES.keys(),
'aliases': {'default': ['all']}
}, help=(
'SponsorBlock categories to create chapters for, separated by commas. ' 'SponsorBlock categories to create chapters for, separated by commas. '
'Available categories are all, %s. You can prefix the category with a "-" to exempt it. ' f'Available categories are all, default(=all), {", ".join(SponsorBlockPP.CATEGORIES.keys())}. '
'See https://wiki.sponsor.ajay.app/index.php/Segment_Categories for description of the categories. ' 'You can prefix the category with a "-" to exempt it. See [1] for description of the categories. '
'Eg: --sponsorblock-mark all,-preview' % ', '.join(SponsorBlockPP.CATEGORIES.keys()))) 'Eg: --sponsorblock-mark all,-preview [1] https://wiki.sponsor.ajay.app/w/Segment_Categories'))
sponsorblock.add_option( sponsorblock.add_option(
'--sponsorblock-remove', metavar='CATS', '--sponsorblock-remove', metavar='CATS',
dest='sponsorblock_remove', default=set(), action='callback', type='str', dest='sponsorblock_remove', default=set(), action='callback', type='str',
callback=_set_from_options_callback, callback_kwargs={'allowed_values': SponsorBlockPP.CATEGORIES.keys()}, callback=_set_from_options_callback, callback_kwargs={
help=( '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. ' '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. ' '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.add_option(
'--sponsorblock-chapter-title', metavar='TEMPLATE', '--sponsorblock-chapter-title', metavar='TEMPLATE',
default=DEFAULT_SPONSORBLOCK_CHAPTER_TITLE, dest='sponsorblock_chapter_title', default=DEFAULT_SPONSORBLOCK_CHAPTER_TITLE, dest='sponsorblock_chapter_title',

View File

@ -24,7 +24,7 @@ class ModifyChaptersPP(FFmpegPostProcessor):
*, sponsorblock_chapter_title=DEFAULT_SPONSORBLOCK_CHAPTER_TITLE, force_keyframes=False): *, sponsorblock_chapter_title=DEFAULT_SPONSORBLOCK_CHAPTER_TITLE, force_keyframes=False):
FFmpegPostProcessor.__init__(self, downloader) FFmpegPostProcessor.__init__(self, downloader)
self._remove_chapters_patterns = set(remove_chapters_patterns or []) 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._ranges_to_remove = set(remove_ranges or [])
self._sponsorblock_chapter_title = sponsorblock_chapter_title self._sponsorblock_chapter_title = sponsorblock_chapter_title
self._force_keyframes = force_keyframes self._force_keyframes = force_keyframes
@ -302,7 +302,7 @@ class ModifyChaptersPP(FFmpegPostProcessor):
'name': SponsorBlockPP.CATEGORIES[category], 'name': SponsorBlockPP.CATEGORIES[category],
'category_names': [SponsorBlockPP.CATEGORIES[c] for c in cats] '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. # Merge identically named sponsors.
if (new_chapters and 'categories' in new_chapters[-1] if (new_chapters and 'categories' in new_chapters[-1]
and new_chapters[-1]['title'] == c['title']): and new_chapters[-1]['title'] == c['title']):

View File

@ -10,18 +10,23 @@ from ..utils import PostProcessingError, network_exceptions, sanitized_Request
class SponsorBlockPP(FFmpegPostProcessor): class SponsorBlockPP(FFmpegPostProcessor):
# https://wiki.sponsor.ajay.app/w/Types
EXTRACTORS = { EXTRACTORS = {
'Youtube': 'YouTube', 'Youtube': 'YouTube',
} }
POI_CATEGORIES = {
'poi_highlight': 'Highlight',
}
CATEGORIES = { CATEGORIES = {
'sponsor': 'Sponsor', 'sponsor': 'Sponsor',
'intro': 'Intermission/Intro Animation', 'intro': 'Intermission/Intro Animation',
'outro': 'Endcards/Credits', 'outro': 'Endcards/Credits',
'selfpromo': 'Unpaid/Self Promotion', 'selfpromo': 'Unpaid/Self Promotion',
'interaction': 'Interaction Reminder',
'preview': 'Preview/Recap', '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'): def __init__(self, downloader, categories=None, api='https://sponsor.ajay.app'):
@ -47,6 +52,9 @@ class SponsorBlockPP(FFmpegPostProcessor):
# Ignore milliseconds difference at the start. # Ignore milliseconds difference at the start.
if start_end[0] <= 1: if start_end[0] <= 1:
start_end[0] = 0 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. # Ignore milliseconds difference at the end.
# Never allow the segment to exceed the video. # Never allow the segment to exceed the video.
if duration and duration - start_end[1] <= 1: if duration and duration - start_end[1] <= 1: