From fc2ba496fd09ca68c7e6eeb2c11e7000d08ff099 Mon Sep 17 00:00:00 2001 From: Lesmiscore Date: Sat, 17 Sep 2022 01:04:23 +0900 Subject: [PATCH] Allow open ranges for time ranges (#4940) Authored by: Lesmiscore --- yt_dlp/YoutubeDL.py | 5 +++-- yt_dlp/__init__.py | 11 ++++++----- yt_dlp/options.py | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py index 3b6281066..0bfc47767 100644 --- a/yt_dlp/YoutubeDL.py +++ b/yt_dlp/YoutubeDL.py @@ -2711,17 +2711,18 @@ def to_screen(*msg): (f['format_id'] for f in formats_to_download)) if requested_ranges: to_screen(f'Downloading {len(requested_ranges)} time ranges:', - (f'{int(c["start_time"])}-{int(c["end_time"])}' for c in requested_ranges)) + (f'{c["start_time"]:.1f}-{c["end_time"]:.1f}' for c in requested_ranges)) max_downloads_reached = False for fmt, chapter in itertools.product(formats_to_download, requested_ranges or [{}]): new_info = self._copy_infodict(info_dict) new_info.update(fmt) offset, duration = info_dict.get('section_start') or 0, info_dict.get('duration') or float('inf') + end_time = offset + min(chapter.get('end_time', duration), duration) if chapter or offset: new_info.update({ 'section_start': offset + chapter.get('start_time', 0), - 'section_end': offset + min(chapter.get('end_time', duration), duration), + 'section_end': end_time if end_time < offset + duration else None, 'section_title': chapter.get('title'), 'section_number': chapter.get('index'), }) diff --git a/yt_dlp/__init__.py b/yt_dlp/__init__.py index 356155fcd..87d431c6e 100644 --- a/yt_dlp/__init__.py +++ b/yt_dlp/__init__.py @@ -326,14 +326,15 @@ def validate_outtmpl(tmpl, msg): def parse_chapters(name, value): chapters, ranges = [], [] + parse_timestamp = lambda x: float('inf') if x in ('inf', 'infinite') else parse_duration(x) for regex in value or []: if regex.startswith('*'): - for range in regex[1:].split(','): - dur = tuple(map(parse_duration, range.strip().split('-'))) - if len(dur) == 2 and all(t is not None for t in dur): - ranges.append(dur) - else: + for range_ in map(str.strip, regex[1:].split(',')): + mobj = range_ != '-' and re.fullmatch(r'([^-]+)?\s*-\s*([^-]+)?', range_) + dur = mobj and (parse_timestamp(mobj.group(1) or '0'), parse_timestamp(mobj.group(2) or 'inf')) + if None in (dur or [None]): raise ValueError(f'invalid {name} time range "{regex}". Must be of the form *start-end') + ranges.append(dur) continue try: chapters.append(re.compile(regex)) diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 26392f619..9ad48486e 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -964,7 +964,7 @@ def _alias_callback(option, opt_str, value, parser, opts, nargs): 'Download only chapters whose title matches the given regular expression. ' 'Time ranges prefixed by a "*" can also be used in place of chapters to download the specified range. ' 'Needs ffmpeg. This option can be used multiple times to download multiple sections, ' - 'e.g. --download-sections "*10:15-15:00" --download-sections "intro"')) + 'e.g. --download-sections "*10:15-inf" --download-sections "intro"')) downloader.add_option( '--downloader', '--external-downloader', dest='external_downloader', metavar='[PROTO:]NAME', default={}, type='str',