[downloader/fragment] HLS download can continue without first fragment

Closes #5274
This commit is contained in:
pukkandan 2022-10-18 18:33:00 +05:30
parent 2576d53a31
commit 814bba3933
No known key found for this signature in database
GPG key ID: 7EEE9E1E817D0A39
6 changed files with 30 additions and 34 deletions

View file

@ -51,7 +51,7 @@ def real_download(self, filename, info_dict):
args.append([ctx, fragments_to_download, fmt]) args.append([ctx, fragments_to_download, fmt])
return self.download_and_append_fragments_multiple(*args) return self.download_and_append_fragments_multiple(*args, is_fatal=lambda idx: idx == 0)
def _resolve_fragments(self, fragments, ctx): def _resolve_fragments(self, fragments, ctx):
fragments = fragments(ctx) if callable(fragments) else fragments fragments = fragments(ctx) if callable(fragments) else fragments

View file

@ -424,6 +424,4 @@ def real_download(self, filename, info_dict):
msg = 'Missed %d fragments' % (fragments_list[0][1] - (frag_i + 1)) msg = 'Missed %d fragments' % (fragments_list[0][1] - (frag_i + 1))
self.report_warning(msg) self.report_warning(msg)
self._finish_frag_download(ctx, info_dict) return self._finish_frag_download(ctx, info_dict)
return True

View file

@ -295,16 +295,23 @@ def _finish_frag_download(self, ctx, info_dict):
self.try_remove(ytdl_filename) self.try_remove(ytdl_filename)
elapsed = time.time() - ctx['started'] elapsed = time.time() - ctx['started']
if ctx['tmpfilename'] == '-': to_file = ctx['tmpfilename'] != '-'
downloaded_bytes = ctx['complete_frags_downloaded_bytes'] if to_file:
downloaded_bytes = os.path.getsize(encodeFilename(ctx['tmpfilename']))
else: else:
downloaded_bytes = ctx['complete_frags_downloaded_bytes']
if not downloaded_bytes:
if to_file:
self.try_remove(ctx['tmpfilename'])
self.report_error('The downloaded file is empty')
return False
elif to_file:
self.try_rename(ctx['tmpfilename'], ctx['filename']) self.try_rename(ctx['tmpfilename'], ctx['filename'])
if self.params.get('updatetime', True): filetime = ctx.get('fragment_filetime')
filetime = ctx.get('fragment_filetime') if self.params.get('updatetime', True) and filetime:
if filetime: with contextlib.suppress(Exception):
with contextlib.suppress(Exception): os.utime(ctx['filename'], (time.time(), filetime))
os.utime(ctx['filename'], (time.time(), filetime))
downloaded_bytes = os.path.getsize(encodeFilename(ctx['filename']))
self._hook_progress({ self._hook_progress({
'downloaded_bytes': downloaded_bytes, 'downloaded_bytes': downloaded_bytes,
@ -316,6 +323,7 @@ def _finish_frag_download(self, ctx, info_dict):
'max_progress': ctx.get('max_progress'), 'max_progress': ctx.get('max_progress'),
'progress_idx': ctx.get('progress_idx'), 'progress_idx': ctx.get('progress_idx'),
}, info_dict) }, info_dict)
return True
def _prepare_external_frag_download(self, ctx): def _prepare_external_frag_download(self, ctx):
if 'live' not in ctx: if 'live' not in ctx:
@ -362,7 +370,7 @@ def decrypt_fragment(fragment, frag_content):
return decrypt_fragment return decrypt_fragment
def download_and_append_fragments_multiple(self, *args, pack_func=None, finish_func=None): def download_and_append_fragments_multiple(self, *args, **kwargs):
''' '''
@params (ctx1, fragments1, info_dict1), (ctx2, fragments2, info_dict2), ... @params (ctx1, fragments1, info_dict1), (ctx2, fragments2, info_dict2), ...
all args must be either tuple or list all args must be either tuple or list
@ -370,7 +378,7 @@ def download_and_append_fragments_multiple(self, *args, pack_func=None, finish_f
interrupt_trigger = [True] interrupt_trigger = [True]
max_progress = len(args) max_progress = len(args)
if max_progress == 1: if max_progress == 1:
return self.download_and_append_fragments(*args[0], pack_func=pack_func, finish_func=finish_func) return self.download_and_append_fragments(*args[0], **kwargs)
max_workers = self.params.get('concurrent_fragment_downloads', 1) max_workers = self.params.get('concurrent_fragment_downloads', 1)
if max_progress > 1: if max_progress > 1:
self._prepare_multiline_status(max_progress) self._prepare_multiline_status(max_progress)
@ -380,8 +388,7 @@ def thread_func(idx, ctx, fragments, info_dict, tpe):
ctx['max_progress'] = max_progress ctx['max_progress'] = max_progress
ctx['progress_idx'] = idx ctx['progress_idx'] = idx
return self.download_and_append_fragments( return self.download_and_append_fragments(
ctx, fragments, info_dict, pack_func=pack_func, finish_func=finish_func, ctx, fragments, info_dict, **kwargs, tpe=tpe, interrupt_trigger=interrupt_trigger)
tpe=tpe, interrupt_trigger=interrupt_trigger)
class FTPE(concurrent.futures.ThreadPoolExecutor): class FTPE(concurrent.futures.ThreadPoolExecutor):
# has to stop this or it's going to wait on the worker thread itself # has to stop this or it's going to wait on the worker thread itself
@ -428,17 +435,12 @@ def interrupt_trigger_iter(fg):
return result return result
def download_and_append_fragments( def download_and_append_fragments(
self, ctx, fragments, info_dict, *, pack_func=None, finish_func=None, self, ctx, fragments, info_dict, *, is_fatal=(lambda idx: False),
tpe=None, interrupt_trigger=None): pack_func=(lambda content, idx: content), finish_func=None,
if not interrupt_trigger: tpe=None, interrupt_trigger=(True, )):
interrupt_trigger = (True, )
is_fatal = ( if not self.params.get('skip_unavailable_fragments', True):
((lambda _: False) if info_dict.get('is_live') else (lambda idx: idx == 0)) is_fatal = lambda _: True
if self.params.get('skip_unavailable_fragments', True) else (lambda _: True))
if not pack_func:
pack_func = lambda frag_content, _: frag_content
def download_fragment(fragment, ctx): def download_fragment(fragment, ctx):
if not interrupt_trigger[0]: if not interrupt_trigger[0]:
@ -527,5 +529,4 @@ def _download_fragment(fragment):
if finish_func is not None: if finish_func is not None:
ctx['dest_stream'].write(finish_func()) ctx['dest_stream'].write(finish_func())
ctx['dest_stream'].flush() ctx['dest_stream'].flush()
self._finish_frag_download(ctx, info_dict) return self._finish_frag_download(ctx, info_dict)
return True

View file

@ -280,5 +280,4 @@ def real_download(self, filename, info_dict):
return False return False
self.report_skip_fragment(frag_index) self.report_skip_fragment(frag_index)
self._finish_frag_download(ctx, info_dict) return self._finish_frag_download(ctx, info_dict)
return True

View file

@ -186,5 +186,4 @@ def real_download(self, filename, info_dict):
ctx['dest_stream'].write( ctx['dest_stream'].write(
b'--%b--\r\n\r\n' % frag_boundary.encode('us-ascii')) b'--%b--\r\n\r\n' % frag_boundary.encode('us-ascii'))
self._finish_frag_download(ctx, info_dict) return self._finish_frag_download(ctx, info_dict)
return True

View file

@ -191,8 +191,7 @@ def download_and_parse_fragment(url, frag_index, request_data=None, headers=None
if test: if test:
break break
self._finish_frag_download(ctx, info_dict) return self._finish_frag_download(ctx, info_dict)
return True
@staticmethod @staticmethod
def parse_live_timestamp(action): def parse_live_timestamp(action):