mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-21 20:46:36 -05:00
[SponsorBlock] Add Filler and Highlight categories (#1664)
Authored by: nihil-admirari, pukkandan
This commit is contained in:
parent
b1aaf1c07f
commit
8157a09d22
5 changed files with 42 additions and 23 deletions
18
README.md
18
README.md
|
@ -940,19 +940,21 @@ ## SponsorBlock Options:
|
||||||
|
|
||||||
--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.
|
||||||
|
|
|
@ -124,11 +124,11 @@ def test_remove_marked_arrange_sponsors_ChapterWithSponsors(self):
|
||||||
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):
|
||||||
|
|
|
@ -1465,20 +1465,29 @@ def _dict_from_options_callback(
|
||||||
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',
|
||||||
|
|
|
@ -24,7 +24,7 @@ def __init__(self, downloader, remove_chapters_patterns=None, remove_sponsor_seg
|
||||||
*, 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 @@ def _remove_tiny_rename_sponsors(self, chapters):
|
||||||
'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']):
|
||||||
|
|
|
@ -10,18 +10,23 @@
|
||||||
|
|
||||||
|
|
||||||
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 @@ def duration_filter(s):
|
||||||
# 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:
|
||||||
|
|
Loading…
Reference in a new issue