Compare commits

...

2 Commits

Author SHA1 Message Date
Paul Storkman
a23be8bba2 Add generated README.md 2024-12-30 16:39:23 +01:00
Paul Storkman
1bd564ddab Integrate the retry count into the wait-for-video option. 2024-12-29 21:10:46 +01:00
4 changed files with 44 additions and 31 deletions

View File

@ -352,14 +352,14 @@ If you fork the project on GitHub, you can run your fork's [build workflow](.git
(Experimental)
--no-live-from-start Download livestreams from the current time
(default)
--wait-for-video MIN[-MAX] Wait for scheduled streams to become
--wait-for-video MIN[-MAX][:RETRIES]
Wait for scheduled streams to become
available. Pass the minimum number of
seconds (or range) to wait between retries
seconds (or range) to wait between retries.
RETRIES is the maximum number of additional
attempts if the video is still unavailable
after waiting (default is infinite)
--no-wait-for-video Do not wait for scheduled streams (default)
--wait-retries RETRIES Number of retries while waiting for
scheduled streams to become available
(default is infinite). --wait-for-video must
also be set
--mark-watched Mark videos watched (even with --simulate)
--no-mark-watched Do not mark videos watched (default)
--color [STREAM:]POLICY Whether to emit color codes in output,

View File

@ -1621,7 +1621,10 @@ class YoutubeDL:
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
wait_retries = 0
max_retries = self.params.get('wait_retries')
wait_range = self.params.get('wait_for_video')
max_retries = float('inf')
if wait_range and wait_range[2] is not None:
max_retries = wait_range[2]
while True:
try:
return func(self, *args, **kwargs)
@ -1699,7 +1702,7 @@ class YoutubeDL:
or ie_result.get('formats') or ie_result.get('url')):
return
min_wait, max_wait = self.params.get('wait_for_video')
min_wait, max_wait, _ = self.params.get('wait_for_video')
diff = try_get(ie_result, lambda x: x['release_timestamp'] - time.time())
if diff is None and ie_result.get('live_status') == 'is_upcoming':
diff = round(random.uniform(min_wait, max_wait) if (max_wait and min_wait) else (max_wait or min_wait), 0)

View File

@ -225,12 +225,36 @@ def validate_options(opts):
else:
validate_minmax(opts.sleep_interval, opts.max_sleep_interval, 'sleep interval')
def parse_retries(name, value):
if value is None:
return None
elif value in ('inf', 'infinite'):
return float('inf')
try:
return int(value)
except (TypeError, ValueError):
validate(False, f'{name} retry count', value)
def parse_range_with_arg(name, arg_name, value,
parse_limits=parse_duration, parse_arg=parse_retries):
# syntax: MIN[-MAX][:N]
m = re.fullmatch(r'([^-:]+)(-[^:]+)?(:.+)?', value)
validate(m, name, value)
min_val, max_val, arg_val = m.groups()
min_lim, max_lim = map(parse_limits, [min_val, (max_val and max_val[1:])])
validate(min_lim is not None, name, value)
validate(max_val is None or max_lim is not None, name, value)
validate_minmax(min_lim, max_lim, name)
parsed_arg = parse_arg(arg_name, arg_val and arg_val[1:])
return (min_lim, max_lim, parsed_arg)
if opts.wait_for_video is not None:
min_wait, max_wait, *_ = map(parse_duration, [*opts.wait_for_video.split('-', 1), None])
validate(min_wait is not None and not (max_wait is None and '-' in opts.wait_for_video),
'time range to wait for video', opts.wait_for_video)
validate_minmax(min_wait, max_wait, 'time range to wait for video')
opts.wait_for_video = (min_wait, max_wait)
min_wait, max_wait, wait_retries = parse_range_with_arg(
'time range to wait for video', 'waiting', opts.wait_for_video)
validate_positive('waiting retry count', wait_retries)
opts.wait_for_video = (min_wait, max_wait, wait_retries)
# Format sort
for f in opts.format_sort:
@ -255,19 +279,8 @@ def validate_options(opts):
validate_positive('audio quality', int_or_none(float_or_none(opts.audioquality), default=0))
# Retries
def parse_retries(name, value):
if value is None:
return None
elif value in ('inf', 'infinite'):
return float('inf')
try:
return int(value)
except (TypeError, ValueError):
validate(False, f'{name} retry count', value)
opts.retries = parse_retries('download', opts.retries)
opts.fragment_retries = parse_retries('fragment', opts.fragment_retries)
opts.wait_retries = parse_retries('waiting', opts.wait_retries)
opts.extractor_retries = parse_retries('extractor', opts.extractor_retries)
opts.file_access_retries = parse_retries('file access', opts.file_access_retries)
@ -928,7 +941,6 @@ def parse_options(argv=None):
'extract_flat': opts.extract_flat,
'live_from_start': opts.live_from_start,
'wait_for_video': opts.wait_for_video,
'wait_retries': opts.wait_retries,
'mark_watched': opts.mark_watched,
'merge_output_format': opts.merge_output_format,
'final_ext': final_ext,

View File

@ -436,18 +436,16 @@ def create_parser():
help='Download livestreams from the current time (default)')
general.add_option(
'--wait-for-video',
dest='wait_for_video', metavar='MIN[-MAX]', default=None,
dest='wait_for_video', metavar='MIN[-MAX][:RETRIES]', default=None,
help=(
'Wait for scheduled streams to become available. '
'Pass the minimum number of seconds (or range) to wait between retries'))
'Pass the minimum number of seconds (or range) to wait between retries. '
'RETRIES is the maximum number of additional attempts if the video '
'is still unavailable after waiting (default is infinite)'))
general.add_option(
'--no-wait-for-video',
dest='wait_for_video', action='store_const', const=None,
help='Do not wait for scheduled streams (default)')
general.add_option(
'--wait-retries',
dest='wait_retries', metavar='RETRIES', default='infinite',
help='Number of retries while waiting for scheduled streams to become available (default is %default). --wait-for-video must also be set')
general.add_option(
'--mark-watched',
action='store_true', dest='mark_watched', default=False,