From 0a8e95ce81af733614987a01085a77ac7d798a3b Mon Sep 17 00:00:00 2001 From: tcely Date: Wed, 29 Jan 2025 14:13:05 -0500 Subject: [PATCH 01/13] Create hooks.py --- tubesync/sync/hooks.py | 53 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tubesync/sync/hooks.py diff --git a/tubesync/sync/hooks.py b/tubesync/sync/hooks.py new file mode 100644 index 00000000..4e1aee8c --- /dev/null +++ b/tubesync/sync/hooks.py @@ -0,0 +1,53 @@ +import os +import yt_dlp + +from common.logger import log +from django.conf import settings + + +class ProgressHookStatus: + def __init__(self): + self.download_progress = 0 + + +def yt_dlp_progress_hook(event): + hook = progress_hook.get('status', hook) + filename = os.path.basename(event['filename']) + + if event.get('downloaded_bytes') is None or event.get('total_bytes') is None: + return None + + if event['status'] == 'error': + log.error(f'[youtube-dl] error occured downloading: {filename}') + elif event['status'] == 'downloading': + downloaded_bytes = event.get('downloaded_bytes', 0) + total_bytes = event.get('total_bytes', 0) + eta = event.get('_eta_str', '?').strip() + percent_done = event.get('_percent_str', '?').strip() + speed = event.get('_speed_str', '?').strip() + total = event.get('_total_bytes_str', '?').strip() + if downloaded_bytes > 0 and total_bytes > 0: + p = round((event['downloaded_bytes'] / event['total_bytes']) * 100) + if (p % 5 == 0) and p > hook.download_progress: + hook.download_progress = p + log.info(f'[youtube-dl] downloading: {filename} - {percent_done} ' + f'of {total} at {speed}, {eta} remaining') + else: + # No progress to monitor, just spam every 10 download messages instead + hook.download_progress += 1 + if hook.download_progress % 10 == 0: + log.info(f'[youtube-dl] downloading: {filename} - {percent_done} ' + f'of {total} at {speed}, {eta} remaining') + elif event['status'] == 'finished': + total_size_str = event.get('_total_bytes_str', '?').strip() + elapsed_str = event.get('_elapsed_str', '?').strip() + log.info(f'[youtube-dl] finished downloading: {filename} - ' + f'{total_size_str} in {elapsed_str}') + else: + log.warn(f'[youtube-dl] unknown event: {str(event)}') + +progress_hook = { + 'status': ProgressHookStatus(), + 'function': yt_dlp_progress_hook, +} + From f59946e874ae9b61dd9198aaeff05fcbe91bc40b Mon Sep 17 00:00:00 2001 From: tcely Date: Wed, 29 Jan 2025 14:42:34 -0500 Subject: [PATCH 02/13] Cleanup youtube.py --- tubesync/sync/youtube.py | 55 +++++++++------------------------------- 1 file changed, 12 insertions(+), 43 deletions(-) diff --git a/tubesync/sync/youtube.py b/tubesync/sync/youtube.py index c0360ca9..54a8a56e 100644 --- a/tubesync/sync/youtube.py +++ b/tubesync/sync/youtube.py @@ -14,6 +14,7 @@ from tempfile import TemporaryDirectory from urllib.parse import urlsplit, parse_qs from django.conf import settings +from .hooks import progress_hook from .utils import mkdir_p import yt_dlp @@ -177,42 +178,6 @@ def download_media(url, media_format, extension, output_file, info_json, Downloads a YouTube URL to a file on disk. ''' - def hook(event): - filename = os.path.basename(event['filename']) - - if event.get('downloaded_bytes') is None or event.get('total_bytes') is None: - return None - - if event['status'] == 'error': - log.error(f'[youtube-dl] error occured downloading: {filename}') - elif event['status'] == 'downloading': - downloaded_bytes = event.get('downloaded_bytes', 0) - total_bytes = event.get('total_bytes', 0) - eta = event.get('_eta_str', '?').strip() - percent_done = event.get('_percent_str', '?').strip() - speed = event.get('_speed_str', '?').strip() - total = event.get('_total_bytes_str', '?').strip() - if downloaded_bytes > 0 and total_bytes > 0: - p = round((event['downloaded_bytes'] / event['total_bytes']) * 100) - if (p % 5 == 0) and p > hook.download_progress: - hook.download_progress = p - log.info(f'[youtube-dl] downloading: {filename} - {percent_done} ' - f'of {total} at {speed}, {eta} remaining') - else: - # No progress to monitor, just spam every 10 download messages instead - hook.download_progress += 1 - if hook.download_progress % 10 == 0: - log.info(f'[youtube-dl] downloading: {filename} - {percent_done} ' - f'of {total} at {speed}, {eta} remaining') - elif event['status'] == 'finished': - total_size_str = event.get('_total_bytes_str', '?').strip() - elapsed_str = event.get('_elapsed_str', '?').strip() - log.info(f'[youtube-dl] finished downloading: {filename} - ' - f'{total_size_str} in {elapsed_str}') - else: - log.warn(f'[youtube-dl] unknown event: {str(event)}') - - hook.download_progress = 0 default_opts = yt_dlp.parse_options([]).options pp_opts = deepcopy(default_opts) @@ -230,6 +195,7 @@ def download_media(url, media_format, extension, output_file, info_json, pp_opts.sponsorblock_mark.update('all,-chapter'.split(',')) pp_opts.sponsorblock_remove.update(sponsor_categories or {}) + opts = get_yt_opts() ytopts = { 'format': media_format, 'merge_output_format': extension, @@ -237,15 +203,15 @@ def download_media(url, media_format, extension, output_file, info_json, 'quiet': False if settings.DEBUG else True, 'verbose': True if settings.DEBUG else False, 'noprogress': None if settings.DEBUG else True, - 'progress_hooks': [hook], 'writeinfojson': info_json, - 'postprocessors': [], 'writesubtitles': write_subtitles, 'writeautomaticsub': auto_subtitles, 'subtitleslangs': sub_langs.split(','), + 'paths': opts.get('paths', dict()), + 'postprocessors': opts.get('postprocessors', list()), + 'postprocessor_args': opts.get('postprocessor_args', dict()) + 'progress_hooks': opts.get('progress_hooks', list()), } - opts = get_yt_opts() - ytopts['paths'] = opts.get('paths', {}) output_dir = os.path.dirname(output_file) temp_dir_parent = output_dir temp_dir_prefix = '.yt_dlp-' @@ -260,13 +226,16 @@ def download_media(url, media_format, extension, output_file, info_json, 'temp': temp_dir.name, }) - codec_options = [] + progress_hook_func = progress_hook.get('function', None) + if progress_hook_func: + ytopts['progress_hooks'].append(progress_hook_func) + + codec_options = list() ofn = ytopts['outtmpl'] if 'av1-' in ofn: codec_options = ['-c:v', 'libsvtav1', '-preset', '8', '-crf', '35'] elif 'vp9-' in ofn: codec_options = ['-c:v', 'libvpx-vp9', '-b:v', '0', '-crf', '31'] - ytopts['postprocessor_args'] = opts.get('postprocessor_args', {}) set_ffmpeg_codec = not ( ytopts['postprocessor_args'] and ytopts['postprocessor_args']['modifychapters+ffmpeg'] @@ -277,7 +246,7 @@ def download_media(url, media_format, extension, output_file, info_json, }) # create the post processors list - ytopts['postprocessors'] = list(yt_dlp.get_postprocessors(pp_opts)) + ytopts['postprocessors'].extend(list(yt_dlp.get_postprocessors(pp_opts))) opts.update(ytopts) From 7a9ab47d9b99ad7e43951149e7c61b009efb7848 Mon Sep 17 00:00:00 2001 From: tcely Date: Wed, 29 Jan 2025 14:50:39 -0500 Subject: [PATCH 03/13] fixup: missed a comma --- tubesync/sync/youtube.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tubesync/sync/youtube.py b/tubesync/sync/youtube.py index 54a8a56e..7c308f36 100644 --- a/tubesync/sync/youtube.py +++ b/tubesync/sync/youtube.py @@ -209,7 +209,7 @@ def download_media(url, media_format, extension, output_file, info_json, 'subtitleslangs': sub_langs.split(','), 'paths': opts.get('paths', dict()), 'postprocessors': opts.get('postprocessors', list()), - 'postprocessor_args': opts.get('postprocessor_args', dict()) + 'postprocessor_args': opts.get('postprocessor_args', dict()), 'progress_hooks': opts.get('progress_hooks', list()), } output_dir = os.path.dirname(output_file) From 8019a94c468c843c55b4ec4d32e6fbd953c8793d Mon Sep 17 00:00:00 2001 From: tcely Date: Wed, 29 Jan 2025 18:45:45 -0500 Subject: [PATCH 04/13] Log failure to get hook status object --- tubesync/sync/hooks.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tubesync/sync/hooks.py b/tubesync/sync/hooks.py index 4e1aee8c..3379ee68 100644 --- a/tubesync/sync/hooks.py +++ b/tubesync/sync/hooks.py @@ -11,8 +11,11 @@ class ProgressHookStatus: def yt_dlp_progress_hook(event): - hook = progress_hook.get('status', hook) + hook = progress_hook.get('status', None) filename = os.path.basename(event['filename']) + if hook is None: + log.error('yt_dlp_progress_hook: failed to get hook status object') + return None if event.get('downloaded_bytes') is None or event.get('total_bytes') is None: return None From eaaa4365f65ffc4b2d87b323f027ada7a8bd3396 Mon Sep 17 00:00:00 2001 From: tcely Date: Thu, 30 Jan 2025 13:08:48 -0500 Subject: [PATCH 05/13] Better handling of user specified post processors --- tubesync/sync/youtube.py | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/tubesync/sync/youtube.py b/tubesync/sync/youtube.py index 7c308f36..24f63f73 100644 --- a/tubesync/sync/youtube.py +++ b/tubesync/sync/youtube.py @@ -35,7 +35,6 @@ if _youtubedl_tempdir: _defaults['paths'] = _paths - class YouTubeError(yt_dlp.utils.DownloadError): ''' Generic wrapped error for all errors that could be raised by youtube-dl. @@ -170,18 +169,35 @@ def get_media_info(url): return response -def download_media(url, media_format, extension, output_file, info_json, - sponsor_categories=None, - embed_thumbnail=False, embed_metadata=False, skip_sponsors=True, - write_subtitles=False, auto_subtitles=False, sub_langs='en'): +# Yes, this looks odd. But, it works. +# It works without also causing indentation problems. +# I'll take ease of editing, thanks. +def download_media( + url, media_format, extension, output_file, + info_json, sponsor_categories=None, + embed_thumbnail=False, embed_metadata=False, + skip_sponsors=True, write_subtitles=False, + auto_subtitles=False, sub_langs='en' +): ''' Downloads a YouTube URL to a file on disk. ''' - + opts = get_yt_opts() default_opts = yt_dlp.parse_options([]).options pp_opts = deepcopy(default_opts) + + # We fake up this option to make it easier for the user to add post processors. + postprocessors = opts.get('add_postprocessors', pp_opts.add_postprocessors) + if isinstance(postprocessors, str): + postprocessors = postprocessors.split(',') + if not isinstance(postprocessors, list): + postprocessors = list() + # Add any post processors configured the 'hard' way also. + postprocessors.extend( opts.get('postprocessors', list()) ) + pp_opts.__dict__.update({ + 'add_postprocessors': postprocessors, 'embedthumbnail': embed_thumbnail, 'addmetadata': embed_metadata, 'addchapters': True, @@ -195,7 +211,6 @@ def download_media(url, media_format, extension, output_file, info_json, pp_opts.sponsorblock_mark.update('all,-chapter'.split(',')) pp_opts.sponsorblock_remove.update(sponsor_categories or {}) - opts = get_yt_opts() ytopts = { 'format': media_format, 'merge_output_format': extension, @@ -208,7 +223,6 @@ def download_media(url, media_format, extension, output_file, info_json, 'writeautomaticsub': auto_subtitles, 'subtitleslangs': sub_langs.split(','), 'paths': opts.get('paths', dict()), - 'postprocessors': opts.get('postprocessors', list()), 'postprocessor_args': opts.get('postprocessor_args', dict()), 'progress_hooks': opts.get('progress_hooks', list()), } @@ -245,8 +259,9 @@ def download_media(url, media_format, extension, output_file, info_json, 'modifychapters+ffmpeg': codec_options, }) - # create the post processors list - ytopts['postprocessors'].extend(list(yt_dlp.get_postprocessors(pp_opts))) + # Create the post processors list. + # It already included user configured post processors as well. + ytopts['postprocessors'] = list(yt_dlp.get_postprocessors(pp_opts)) opts.update(ytopts) From 470dbf426e52cee5048e057afa4fe34e7d682235 Mon Sep 17 00:00:00 2001 From: tcely Date: Thu, 30 Jan 2025 14:29:52 -0500 Subject: [PATCH 06/13] Parse the post processors strings already in use --- tubesync/sync/youtube.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tubesync/sync/youtube.py b/tubesync/sync/youtube.py index 487dc84f..f6a83b61 100644 --- a/tubesync/sync/youtube.py +++ b/tubesync/sync/youtube.py @@ -17,6 +17,7 @@ from django.conf import settings from .hooks import progress_hook from .utils import mkdir_p import yt_dlp +from yt_dlp.utils import remove_end _defaults = getattr(settings, 'YOUTUBE_DEFAULTS', {}) @@ -190,7 +191,23 @@ def download_media( # We fake up this option to make it easier for the user to add post processors. postprocessors = opts.get('add_postprocessors', pp_opts.add_postprocessors) if isinstance(postprocessors, str): - postprocessors = postprocessors.split(',') + # NAME1[:ARGS],NAME2[:ARGS] + # ARGS are a semicolon ";" delimited list of NAME=VALUE + # + # This means that "," cannot be present in NAME or VALUE. + # If you need to support that, then use the 'postprocessors' key, + # in your settings dictionary instead. + _postprocessor_opts_parser = lambda key, val='': ( + *( + item.split('=', 1) for item in (val.split(';') if val else []) + ), + ( 'key', remove_end(key, 'PP'), ) + ) + postprocessors = list( + dict( + _postprocessor_opts_parser( *val.split(':', 1) ) + ) for val in postprocessors.split(',') + ) if not isinstance(postprocessors, list): postprocessors = list() # Add any post processors configured the 'hard' way also. From 1bbfed8e4d3abaf3d09e21bdfa017f44904ce7ce Mon Sep 17 00:00:00 2001 From: tcely Date: Thu, 30 Jan 2025 14:40:03 -0500 Subject: [PATCH 07/13] Don't embed spaces in keys --- tubesync/sync/youtube.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tubesync/sync/youtube.py b/tubesync/sync/youtube.py index f6a83b61..9a81093a 100644 --- a/tubesync/sync/youtube.py +++ b/tubesync/sync/youtube.py @@ -191,7 +191,7 @@ def download_media( # We fake up this option to make it easier for the user to add post processors. postprocessors = opts.get('add_postprocessors', pp_opts.add_postprocessors) if isinstance(postprocessors, str): - # NAME1[:ARGS],NAME2[:ARGS] + # NAME1[:ARGS], NAME2[:ARGS] # ARGS are a semicolon ";" delimited list of NAME=VALUE # # This means that "," cannot be present in NAME or VALUE. @@ -206,7 +206,7 @@ def download_media( postprocessors = list( dict( _postprocessor_opts_parser( *val.split(':', 1) ) - ) for val in postprocessors.split(',') + ) for val in map(str.strip, postprocessors.split(',')) ) if not isinstance(postprocessors, list): postprocessors = list() From 005cd37fa7ec09d9b7d30e0cfca5c72864011d4e Mon Sep 17 00:00:00 2001 From: tcely Date: Thu, 30 Jan 2025 15:29:30 -0500 Subject: [PATCH 08/13] Convert `--sponsorblock-mark` using `yt-dlp` I shouldn't have tried this myself. It's much more complicated than I originally thought. --- tubesync/sync/youtube.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tubesync/sync/youtube.py b/tubesync/sync/youtube.py index 9a81093a..7d5f82a2 100644 --- a/tubesync/sync/youtube.py +++ b/tubesync/sync/youtube.py @@ -225,7 +225,10 @@ def download_media( }) if skip_sponsors: - pp_opts.sponsorblock_mark.update('all,-chapter'.split(',')) + # Let yt_dlp convert from human for us. + pp_opts.sponsorblock_mark = yt_dlp.parse_options( + ['--sponsorblock-mark=all,-chapter'] + ).options.sponsorblock_mark pp_opts.sponsorblock_remove.update(sponsor_categories or {}) ytopts = { From 0a39d96fc6014bdf2e48ddb9a6ee39fa5b2b7596 Mon Sep 17 00:00:00 2001 From: tcely Date: Thu, 30 Jan 2025 17:44:39 -0500 Subject: [PATCH 09/13] Add & use `postprocessor_hook` --- tubesync/sync/hooks.py | 38 +++++++++++++++++++++++++++++++++++++- tubesync/sync/youtube.py | 7 ++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/tubesync/sync/hooks.py b/tubesync/sync/hooks.py index 3379ee68..fc94b137 100644 --- a/tubesync/sync/hooks.py +++ b/tubesync/sync/hooks.py @@ -6,9 +6,27 @@ from django.conf import settings class ProgressHookStatus: + valid = frozenset(( + 'downloading', + 'finished', + 'error', + )) + def __init__(self): self.download_progress = 0 +class PPHookStatus: + valid = frozenset(( + 'started', + 'processing', + 'finished', + )) + + def __init__(self, *args, status=None, postprocessor=None, info_dict={}, **kwargs): + self.info = info_dict + self.name = postprocessor + self.status = status + def yt_dlp_progress_hook(event): hook = progress_hook.get('status', None) @@ -17,6 +35,10 @@ def yt_dlp_progress_hook(event): log.error('yt_dlp_progress_hook: failed to get hook status object') return None + if event['status'] not in ProgressHookStatus.valid: + log.warn(f'[youtube-dl] unknown event: {str(event)}') + return None + if event.get('downloaded_bytes') is None or event.get('total_bytes') is None: return None @@ -46,11 +68,25 @@ def yt_dlp_progress_hook(event): elapsed_str = event.get('_elapsed_str', '?').strip() log.info(f'[youtube-dl] finished downloading: {filename} - ' f'{total_size_str} in {elapsed_str}') - else: + +def yt_dlp_postprocessor_hook(event): + if event['status'] not in PPHookStatus.valid: log.warn(f'[youtube-dl] unknown event: {str(event)}') + return None + + postprocessor_hook['status'] = PPHookStatus(*event) + if 'started' == event['status']: + log.debug(repr(event['info_dict'])) + log.info(f'[{event['postprocessor']}] {event['status']}') + progress_hook = { 'status': ProgressHookStatus(), 'function': yt_dlp_progress_hook, } +postprocessor_hook = { + 'status': PPHookStatus(), + 'function': yt_dlp_postprocessor_hook, +} + diff --git a/tubesync/sync/youtube.py b/tubesync/sync/youtube.py index 7d5f82a2..ece08ffe 100644 --- a/tubesync/sync/youtube.py +++ b/tubesync/sync/youtube.py @@ -14,7 +14,7 @@ from tempfile import TemporaryDirectory from urllib.parse import urlsplit, parse_qs from django.conf import settings -from .hooks import progress_hook +from .hooks import postprocessor_hook, progress_hook from .utils import mkdir_p import yt_dlp from yt_dlp.utils import remove_end @@ -250,6 +250,7 @@ def download_media( 'sleep_interval_requests': 30, 'paths': opts.get('paths', dict()), 'postprocessor_args': opts.get('postprocessor_args', dict()), + 'postprocessor_hooks': opts.get('postprocessor_hooks', list()), 'progress_hooks': opts.get('progress_hooks', list()), } output_dir = os.path.dirname(output_file) @@ -266,6 +267,10 @@ def download_media( 'temp': temp_dir.name, }) + postprocessor_hook_func = postprocessor_hook.get('function', None) + if postprocessor_hook_func: + ytopts['postprocessor_hooks'].append(postprocessor_hook_func) + progress_hook_func = progress_hook.get('function', None) if progress_hook_func: ytopts['progress_hooks'].append(progress_hook_func) From 36814ddfcd560312d5e9094edfe73a88659388ea Mon Sep 17 00:00:00 2001 From: tcely Date: Thu, 30 Jan 2025 18:02:42 -0500 Subject: [PATCH 10/13] fixup: quoting fun --- tubesync/sync/hooks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tubesync/sync/hooks.py b/tubesync/sync/hooks.py index fc94b137..2819c6bb 100644 --- a/tubesync/sync/hooks.py +++ b/tubesync/sync/hooks.py @@ -77,7 +77,7 @@ def yt_dlp_postprocessor_hook(event): postprocessor_hook['status'] = PPHookStatus(*event) if 'started' == event['status']: log.debug(repr(event['info_dict'])) - log.info(f'[{event['postprocessor']}] {event['status']}') + log.info(f'[{event["postprocessor"]}] {event["status"]}') progress_hook = { From cda3a485db9b440de6aef941420b1f9d2183f0f7 Mon Sep 17 00:00:00 2001 From: tcely Date: Thu, 30 Jan 2025 20:51:22 -0500 Subject: [PATCH 11/13] Prettier logged messages --- tubesync/sync/hooks.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tubesync/sync/hooks.py b/tubesync/sync/hooks.py index 2819c6bb..3d397a13 100644 --- a/tubesync/sync/hooks.py +++ b/tubesync/sync/hooks.py @@ -76,8 +76,19 @@ def yt_dlp_postprocessor_hook(event): postprocessor_hook['status'] = PPHookStatus(*event) if 'started' == event['status']: + if 'formats' in event['info_dict']: + del event['info_dict']['formats'] log.debug(repr(event['info_dict'])) - log.info(f'[{event["postprocessor"]}] {event["status"]}') + key = 'Unknown' + name = key + if 'id' in event['info_dict']: + key = event['info_dict']['id'] + title = None + if 'title' in event['info_dict']: + title = event['info_dict']['title'] + name = f'{key}: {title}' + + log.info(f'[{event["postprocessor"]}] {event["status"]} for: {name}') progress_hook = { From 2b8fea103e3ca9171386f67e59a550cd37cdd531 Mon Sep 17 00:00:00 2001 From: tcely Date: Thu, 30 Jan 2025 20:57:32 -0500 Subject: [PATCH 12/13] Remove `automatic_captions` from debug log too --- tubesync/sync/hooks.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tubesync/sync/hooks.py b/tubesync/sync/hooks.py index 3d397a13..9679e014 100644 --- a/tubesync/sync/hooks.py +++ b/tubesync/sync/hooks.py @@ -78,6 +78,8 @@ def yt_dlp_postprocessor_hook(event): if 'started' == event['status']: if 'formats' in event['info_dict']: del event['info_dict']['formats'] + if 'automatic_captions' in event['info_dict']: + del event['info_dict']['automatic_captions'] log.debug(repr(event['info_dict'])) key = 'Unknown' name = key From 60ee227caa6aa8ad9d2e79a97d4e186be62eca8b Mon Sep 17 00:00:00 2001 From: tcely Date: Thu, 30 Jan 2025 21:22:10 -0500 Subject: [PATCH 13/13] Prefer `display_id` and `fulltitle` for logs --- tubesync/sync/hooks.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/tubesync/sync/hooks.py b/tubesync/sync/hooks.py index 9679e014..cd0f208f 100644 --- a/tubesync/sync/hooks.py +++ b/tubesync/sync/hooks.py @@ -75,20 +75,28 @@ def yt_dlp_postprocessor_hook(event): return None postprocessor_hook['status'] = PPHookStatus(*event) + + name = key = 'Unknown' + if 'display_id' in event['info_dict']: + key = event['info_dict']['display_id'] + elif 'id' in event['info_dict']: + key = event['info_dict']['id'] + + title = None + if 'fulltitle' in event['info_dict']: + title = event['info_dict']['fulltitle'] + elif 'title' in event['info_dict']: + title = event['info_dict']['title'] + + if title: + name = f'{key}: {title}' + if 'started' == event['status']: if 'formats' in event['info_dict']: del event['info_dict']['formats'] if 'automatic_captions' in event['info_dict']: del event['info_dict']['automatic_captions'] log.debug(repr(event['info_dict'])) - key = 'Unknown' - name = key - if 'id' in event['info_dict']: - key = event['info_dict']['id'] - title = None - if 'title' in event['info_dict']: - title = event['info_dict']['title'] - name = f'{key}: {title}' log.info(f'[{event["postprocessor"]}] {event["status"]} for: {name}')