mirror of https://github.com/yt-dlp/yt-dlp.git
[ModifyChapters] fixes (See desc)
* [docs] Fix typo * Do not enable `sponskrub` by default * Fix `--force-keyframes-at-cuts` * Don't embed subtitles if the video has been cut. Previously, running `--remove-chapters` with `--embed-subs` multiple times caused repeated cuts and out-of-sync subtitles * Store `_real_duration` to prevent running ffprobe multiple times
This commit is contained in:
parent
dd594deb2a
commit
165efb823b
|
@ -1394,7 +1394,7 @@ def parseOpts(overrideArguments=None):
|
||||||
'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. '
|
'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. '
|
'See https://wiki.sponsor.ajay.app/index.php/Segment_Categories for description of the categories. '
|
||||||
'Eg: --sponsorblock-query all,-preview' % ', '.join(SponsorBlockPP.CATEGORIES.keys())))
|
'Eg: --sponsorblock-mark all,-preview' % ', '.join(SponsorBlockPP.CATEGORIES.keys())))
|
||||||
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',
|
||||||
|
@ -1421,7 +1421,7 @@ def parseOpts(overrideArguments=None):
|
||||||
|
|
||||||
sponsorblock.add_option(
|
sponsorblock.add_option(
|
||||||
'--sponskrub',
|
'--sponskrub',
|
||||||
action='store_true', dest='sponskrub', default=None,
|
action='store_true', dest='sponskrub', default=False,
|
||||||
help=optparse.SUPPRESS_HELP)
|
help=optparse.SUPPRESS_HELP)
|
||||||
sponsorblock.add_option(
|
sponsorblock.add_option(
|
||||||
'--no-sponskrub',
|
'--no-sponskrub',
|
||||||
|
|
|
@ -15,6 +15,7 @@ from ..utils import (
|
||||||
dfxp2srt,
|
dfxp2srt,
|
||||||
encodeArgument,
|
encodeArgument,
|
||||||
encodeFilename,
|
encodeFilename,
|
||||||
|
float_or_none,
|
||||||
get_exe_version,
|
get_exe_version,
|
||||||
is_outdated_version,
|
is_outdated_version,
|
||||||
ISO639Utils,
|
ISO639Utils,
|
||||||
|
@ -233,6 +234,23 @@ class FFmpegPostProcessor(PostProcessor):
|
||||||
None)
|
None)
|
||||||
return num, len(streams)
|
return num, len(streams)
|
||||||
|
|
||||||
|
def _get_real_video_duration(self, info, fatal=True):
|
||||||
|
try:
|
||||||
|
if '_real_duration' not in info:
|
||||||
|
info['_real_duration'] = float_or_none(
|
||||||
|
traverse_obj(self.get_metadata_object(info['filepath']), ('format', 'duration')))
|
||||||
|
if not info['_real_duration']:
|
||||||
|
raise PostProcessingError('ffprobe returned empty duration')
|
||||||
|
except PostProcessingError as e:
|
||||||
|
if fatal:
|
||||||
|
raise PostProcessingError(f'Unable to determine video duration; {e}')
|
||||||
|
return info.setdefault('_real_duration', None)
|
||||||
|
|
||||||
|
def _duration_mismatch(self, d1, d2):
|
||||||
|
if not d1 or not d2:
|
||||||
|
return None
|
||||||
|
return abs(d1 - d2) > 1
|
||||||
|
|
||||||
def run_ffmpeg_multiple_files(self, input_paths, out_path, opts, **kwargs):
|
def run_ffmpeg_multiple_files(self, input_paths, out_path, opts, **kwargs):
|
||||||
return self.real_run_ffmpeg(
|
return self.real_run_ffmpeg(
|
||||||
[(path, []) for path in input_paths],
|
[(path, []) for path in input_paths],
|
||||||
|
@ -528,6 +546,10 @@ class FFmpegEmbedSubtitlePP(FFmpegPostProcessor):
|
||||||
return [], information
|
return [], information
|
||||||
|
|
||||||
filename = information['filepath']
|
filename = information['filepath']
|
||||||
|
if self._duration_mismatch(
|
||||||
|
self._get_real_video_duration(information, False), information['duration']):
|
||||||
|
self.to_screen(f'Skipping {self.pp_key()} since the real and expected durations mismatch')
|
||||||
|
return [], information
|
||||||
|
|
||||||
ext = information['ext']
|
ext = information['ext']
|
||||||
sub_langs, sub_names, sub_filenames = [], [], []
|
sub_langs, sub_names, sub_filenames = [], [], []
|
||||||
|
|
|
@ -9,11 +9,9 @@ from .ffmpeg import (
|
||||||
)
|
)
|
||||||
from .sponsorblock import SponsorBlockPP
|
from .sponsorblock import SponsorBlockPP
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
float_or_none,
|
|
||||||
orderedSet,
|
orderedSet,
|
||||||
PostProcessingError,
|
PostProcessingError,
|
||||||
prepend_extension,
|
prepend_extension,
|
||||||
traverse_obj,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,7 +35,7 @@ class ModifyChaptersPP(FFmpegPostProcessor):
|
||||||
if not chapters and not sponsor_chapters:
|
if not chapters and not sponsor_chapters:
|
||||||
return [], info
|
return [], info
|
||||||
|
|
||||||
real_duration = self._get_real_video_duration(info['filepath'])
|
real_duration = self._get_real_video_duration(info)
|
||||||
if not chapters:
|
if not chapters:
|
||||||
chapters = [{'start_time': 0, 'end_time': real_duration, 'title': info['title']}]
|
chapters = [{'start_time': 0, 'end_time': real_duration, 'title': info['title']}]
|
||||||
|
|
||||||
|
@ -45,8 +43,8 @@ class ModifyChaptersPP(FFmpegPostProcessor):
|
||||||
if not cuts:
|
if not cuts:
|
||||||
return [], info
|
return [], info
|
||||||
|
|
||||||
if abs(real_duration - info['duration']) > 1:
|
if self._duration_mismatch(real_duration, info.get('duration')):
|
||||||
if abs(real_duration - info['chapters'][-1]['end_time']) < 1:
|
if not self._duration_mismatch(real_duration, info['chapters'][-1]['end_time']):
|
||||||
self.to_screen(f'Skipping {self.pp_key()} since the video appears to be already cut')
|
self.to_screen(f'Skipping {self.pp_key()} since the video appears to be already cut')
|
||||||
return [], info
|
return [], info
|
||||||
if not info.get('__real_download'):
|
if not info.get('__real_download'):
|
||||||
|
@ -72,6 +70,7 @@ class ModifyChaptersPP(FFmpegPostProcessor):
|
||||||
os.replace(out_file, in_file)
|
os.replace(out_file, in_file)
|
||||||
files_to_remove.append(uncut_file)
|
files_to_remove.append(uncut_file)
|
||||||
|
|
||||||
|
info['_real_duration'] = info['chapters'][-1]['end_time']
|
||||||
return files_to_remove, info
|
return files_to_remove, info
|
||||||
|
|
||||||
def _mark_chapters_to_remove(self, chapters, sponsor_chapters):
|
def _mark_chapters_to_remove(self, chapters, sponsor_chapters):
|
||||||
|
@ -101,13 +100,6 @@ class ModifyChaptersPP(FFmpegPostProcessor):
|
||||||
|
|
||||||
return chapters, sponsor_chapters
|
return chapters, sponsor_chapters
|
||||||
|
|
||||||
def _get_real_video_duration(self, filename):
|
|
||||||
duration = float_or_none(
|
|
||||||
traverse_obj(self.get_metadata_object(filename), ('format', 'duration')))
|
|
||||||
if duration is None:
|
|
||||||
raise PostProcessingError('ffprobe returned empty duration')
|
|
||||||
return duration
|
|
||||||
|
|
||||||
def _get_supported_subs(self, info):
|
def _get_supported_subs(self, info):
|
||||||
for sub in (info.get('requested_subtitles') or {}).values():
|
for sub in (info.get('requested_subtitles') or {}).values():
|
||||||
sub_file = sub.get('filepath')
|
sub_file = sub.get('filepath')
|
||||||
|
@ -311,7 +303,7 @@ class ModifyChaptersPP(FFmpegPostProcessor):
|
||||||
in_file = filename
|
in_file = filename
|
||||||
out_file = prepend_extension(in_file, 'temp')
|
out_file = prepend_extension(in_file, 'temp')
|
||||||
if force_keyframes:
|
if force_keyframes:
|
||||||
in_file = self.force_keyframes(in_file, (t for r in ranges_to_cut for t in r))
|
in_file = self.force_keyframes(in_file, (t for c in ranges_to_cut for t in (c['start_time'], c['end_time'])))
|
||||||
self.to_screen(f'Removing chapters from {filename}')
|
self.to_screen(f'Removing chapters from {filename}')
|
||||||
self.concat_files([in_file] * len(concat_opts), out_file, concat_opts)
|
self.concat_files([in_file] * len(concat_opts), out_file, concat_opts)
|
||||||
if in_file != filename:
|
if in_file != filename:
|
||||||
|
|
Loading…
Reference in New Issue