mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-27 03:03:01 +00:00
[fragment] Generalize fragmented media file downloader
This commit is contained in:
parent
289bbb350e
commit
95d8f7ea12
1 changed files with 110 additions and 0 deletions
110
youtube_dl/downloader/fragment.py
Normal file
110
youtube_dl/downloader/fragment.py
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
from __future__ import division, unicode_literals
|
||||||
|
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
from .common import FileDownloader
|
||||||
|
from .http import HttpFD
|
||||||
|
from ..utils import (
|
||||||
|
encodeFilename,
|
||||||
|
sanitize_open,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class HttpQuietDownloader(HttpFD):
|
||||||
|
def to_screen(self, *args, **kargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FragmentFD(FileDownloader):
|
||||||
|
"""
|
||||||
|
A base file downloader class for fragmented media (e.g. f4m/m3u8 manifests).
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _prepare_and_start_frag_download(self, ctx):
|
||||||
|
self._prepare_frag_download(ctx)
|
||||||
|
self._start_frag_download(ctx)
|
||||||
|
|
||||||
|
def _prepare_frag_download(self, ctx):
|
||||||
|
self.to_screen('[%s] Total fragments: %d' % (self.FD_NAME, ctx['total_frags']))
|
||||||
|
self.report_destination(ctx['filename'])
|
||||||
|
dl = HttpQuietDownloader(
|
||||||
|
self.ydl,
|
||||||
|
{
|
||||||
|
'continuedl': True,
|
||||||
|
'quiet': True,
|
||||||
|
'noprogress': True,
|
||||||
|
'ratelimit': self.params.get('ratelimit', None),
|
||||||
|
'test': self.params.get('test', False),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
tmpfilename = self.temp_name(ctx['filename'])
|
||||||
|
dest_stream, tmpfilename = sanitize_open(tmpfilename, 'wb')
|
||||||
|
ctx.update({
|
||||||
|
'dl': dl,
|
||||||
|
'dest_stream': dest_stream,
|
||||||
|
'tmpfilename': tmpfilename,
|
||||||
|
})
|
||||||
|
|
||||||
|
def _start_frag_download(self, ctx):
|
||||||
|
total_frags = ctx['total_frags']
|
||||||
|
# This dict stores the download progress, it's updated by the progress
|
||||||
|
# hook
|
||||||
|
state = {
|
||||||
|
'status': 'downloading',
|
||||||
|
'downloaded_bytes': 0,
|
||||||
|
'frag_index': 0,
|
||||||
|
'frag_count': total_frags,
|
||||||
|
'filename': ctx['filename'],
|
||||||
|
'tmpfilename': ctx['tmpfilename'],
|
||||||
|
}
|
||||||
|
start = time.time()
|
||||||
|
ctx['started'] = start
|
||||||
|
|
||||||
|
def frag_progress_hook(s):
|
||||||
|
if s['status'] not in ('downloading', 'finished'):
|
||||||
|
return
|
||||||
|
|
||||||
|
frag_total_bytes = s.get('total_bytes', 0)
|
||||||
|
if s['status'] == 'finished':
|
||||||
|
state['downloaded_bytes'] += frag_total_bytes
|
||||||
|
state['frag_index'] += 1
|
||||||
|
|
||||||
|
estimated_size = (
|
||||||
|
(state['downloaded_bytes'] + frag_total_bytes) /
|
||||||
|
(state['frag_index'] + 1) * total_frags)
|
||||||
|
time_now = time.time()
|
||||||
|
state['total_bytes_estimate'] = estimated_size
|
||||||
|
state['elapsed'] = time_now - start
|
||||||
|
|
||||||
|
if s['status'] == 'finished':
|
||||||
|
progress = self.calc_percent(state['frag_index'], total_frags)
|
||||||
|
else:
|
||||||
|
frag_downloaded_bytes = s['downloaded_bytes']
|
||||||
|
frag_progress = self.calc_percent(frag_downloaded_bytes,
|
||||||
|
frag_total_bytes)
|
||||||
|
progress = self.calc_percent(state['frag_index'], total_frags)
|
||||||
|
progress += frag_progress / float(total_frags)
|
||||||
|
|
||||||
|
state['eta'] = self.calc_eta(
|
||||||
|
start, time_now, estimated_size, state['downloaded_bytes'] + frag_downloaded_bytes)
|
||||||
|
state['speed'] = s.get('speed')
|
||||||
|
self._hook_progress(state)
|
||||||
|
|
||||||
|
ctx['dl'].add_progress_hook(frag_progress_hook)
|
||||||
|
|
||||||
|
return start
|
||||||
|
|
||||||
|
def _finish_frag_download(self, ctx):
|
||||||
|
ctx['dest_stream'].close()
|
||||||
|
elapsed = time.time() - ctx['started']
|
||||||
|
self.try_rename(ctx['tmpfilename'], ctx['filename'])
|
||||||
|
fsize = os.path.getsize(encodeFilename(ctx['filename']))
|
||||||
|
|
||||||
|
self._hook_progress({
|
||||||
|
'downloaded_bytes': fsize,
|
||||||
|
'total_bytes': fsize,
|
||||||
|
'filename': ctx['filename'],
|
||||||
|
'status': 'finished',
|
||||||
|
'elapsed': elapsed,
|
||||||
|
})
|
Loading…
Reference in a new issue