|
|
@ -295,16 +295,23 @@ class FragmentFD(FileDownloader):
|
|
|
|
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 filetime:
|
|
|
|
if self.params.get('updatetime', True) and 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 @@ class FragmentFD(FileDownloader):
|
|
|
|
'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 @@ class FragmentFD(FileDownloader):
|
|
|
|
|
|
|
|
|
|
|
|
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 @@ class FragmentFD(FileDownloader):
|
|
|
|
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 @@ class FragmentFD(FileDownloader):
|
|
|
|
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 @@ class FragmentFD(FileDownloader):
|
|
|
|
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 = (
|
|
|
|
|
|
|
|
((lambda _: False) if info_dict.get('is_live') else (lambda idx: idx == 0))
|
|
|
|
|
|
|
|
if self.params.get('skip_unavailable_fragments', True) else (lambda _: True))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not pack_func:
|
|
|
|
if not self.params.get('skip_unavailable_fragments', True):
|
|
|
|
pack_func = lambda frag_content, _: frag_content
|
|
|
|
is_fatal = lambda _: True
|
|
|
|
|
|
|
|
|
|
|
|
def download_fragment(fragment, ctx):
|
|
|
|
def download_fragment(fragment, ctx):
|
|
|
|
if not interrupt_trigger[0]:
|
|
|
|
if not interrupt_trigger[0]:
|
|
|
@ -527,5 +529,4 @@ class FragmentFD(FileDownloader):
|
|
|
|
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
|
|
|
|
|
|
|
|