mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-11-04 00:25:15 +00:00 
			
		
		
		
	@@ -2711,17 +2711,18 @@ class YoutubeDL:
 | 
				
			|||||||
                          (f['format_id'] for f in formats_to_download))
 | 
					                          (f['format_id'] for f in formats_to_download))
 | 
				
			||||||
                if requested_ranges:
 | 
					                if requested_ranges:
 | 
				
			||||||
                    to_screen(f'Downloading {len(requested_ranges)} time 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
 | 
					            max_downloads_reached = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for fmt, chapter in itertools.product(formats_to_download, requested_ranges or [{}]):
 | 
					            for fmt, chapter in itertools.product(formats_to_download, requested_ranges or [{}]):
 | 
				
			||||||
                new_info = self._copy_infodict(info_dict)
 | 
					                new_info = self._copy_infodict(info_dict)
 | 
				
			||||||
                new_info.update(fmt)
 | 
					                new_info.update(fmt)
 | 
				
			||||||
                offset, duration = info_dict.get('section_start') or 0, info_dict.get('duration') or float('inf')
 | 
					                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:
 | 
					                if chapter or offset:
 | 
				
			||||||
                    new_info.update({
 | 
					                    new_info.update({
 | 
				
			||||||
                        'section_start': offset + chapter.get('start_time', 0),
 | 
					                        '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_title': chapter.get('title'),
 | 
				
			||||||
                        'section_number': chapter.get('index'),
 | 
					                        'section_number': chapter.get('index'),
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -326,14 +326,15 @@ def validate_options(opts):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def parse_chapters(name, value):
 | 
					    def parse_chapters(name, value):
 | 
				
			||||||
        chapters, ranges = [], []
 | 
					        chapters, ranges = [], []
 | 
				
			||||||
 | 
					        parse_timestamp = lambda x: float('inf') if x in ('inf', 'infinite') else parse_duration(x)
 | 
				
			||||||
        for regex in value or []:
 | 
					        for regex in value or []:
 | 
				
			||||||
            if regex.startswith('*'):
 | 
					            if regex.startswith('*'):
 | 
				
			||||||
                for range in regex[1:].split(','):
 | 
					                for range_ in map(str.strip, regex[1:].split(',')):
 | 
				
			||||||
                    dur = tuple(map(parse_duration, range.strip().split('-')))
 | 
					                    mobj = range_ != '-' and re.fullmatch(r'([^-]+)?\s*-\s*([^-]+)?', range_)
 | 
				
			||||||
                    if len(dur) == 2 and all(t is not None for t in dur):
 | 
					                    dur = mobj and (parse_timestamp(mobj.group(1) or '0'), parse_timestamp(mobj.group(2) or 'inf'))
 | 
				
			||||||
                        ranges.append(dur)
 | 
					                    if None in (dur or [None]):
 | 
				
			||||||
                    else:
 | 
					 | 
				
			||||||
                        raise ValueError(f'invalid {name} time range "{regex}". Must be of the form *start-end')
 | 
					                        raise ValueError(f'invalid {name} time range "{regex}". Must be of the form *start-end')
 | 
				
			||||||
 | 
					                    ranges.append(dur)
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                chapters.append(re.compile(regex))
 | 
					                chapters.append(re.compile(regex))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -964,7 +964,7 @@ def create_parser():
 | 
				
			|||||||
            'Download only chapters whose title matches the given regular expression. '
 | 
					            '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. '
 | 
					            '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, '
 | 
					            '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.add_option(
 | 
				
			||||||
        '--downloader', '--external-downloader',
 | 
					        '--downloader', '--external-downloader',
 | 
				
			||||||
        dest='external_downloader', metavar='[PROTO:]NAME', default={}, type='str',
 | 
					        dest='external_downloader', metavar='[PROTO:]NAME', default={}, type='str',
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user