From 290f64dbaa3a8c187d47b72b3c808bd52d15a6e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergey=20M=E2=80=A4?= Date: Mon, 24 Apr 2017 23:50:20 +0700 Subject: [PATCH] [downloader/fragment] Improve .ytdl format and start documenting --- youtube_dl/downloader/fragment.py | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/youtube_dl/downloader/fragment.py b/youtube_dl/downloader/fragment.py index 25c8f18ec..50c8254a4 100644 --- a/youtube_dl/downloader/fragment.py +++ b/youtube_dl/downloader/fragment.py @@ -31,6 +31,24 @@ class FragmentFD(FileDownloader): Skip unavailable fragments (DASH and hlsnative only) keep_fragments: Keep downloaded fragments on disk after downloading is finished + + For each incomplete fragment download youtube-dl keeps on disk a special + bookkeeping file with download state and metadata (in future such files will + be used for any incomplete download handled by youtube-dl). This file is + used to properly handle resuming, check download file consistency and detect + potential errors. The file has a .ytdl extension and represents a standard + JSON file of the following format: + + extractor: + Dictionary of extractor related data. TBD. + + downloader: + Dictionary of downloader related data. May contain following data: + current_fragment: + Dictionary with current (being downloaded) fragment data: + index: Index of current fragment among all fragments + fragment_count: + Total count of fragments """ def report_retry_fragment(self, err, frag_index, count, retries): @@ -55,16 +73,19 @@ class FragmentFD(FileDownloader): def _read_ytdl_file(self, ctx): stream, _ = sanitize_open(self.ytdl_filename(ctx['filename']), 'r') - ctx['fragment_index'] = json.loads(stream.read())['download']['current_fragment_index'] + ctx['fragment_index'] = json.loads(stream.read())['downloader']['current_fragment']['index'] stream.close() def _write_ytdl_file(self, ctx): frag_index_stream, _ = sanitize_open(self.ytdl_filename(ctx['filename']), 'w') - frag_index_stream.write(json.dumps({ - 'download': { - 'current_fragment_index': ctx['fragment_index'] + downloader = { + 'current_fragment': { + 'index': ctx['fragment_index'], }, - })) + } + if ctx.get('fragment_count') is not None: + downloader['fragment_count'] = ctx['fragment_count'] + frag_index_stream.write(json.dumps({'downloader': downloader})) frag_index_stream.close() def _download_fragment(self, ctx, frag_url, info_dict, headers=None):