mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-12-22 01:56:30 -05:00
parent
2edb38e8ca
commit
bb66c24797
@ -686,6 +686,12 @@ You can also fork the project on github and run your fork's [build workflow](.gi
|
|||||||
Implies --quiet and --simulate (unless
|
Implies --quiet and --simulate (unless
|
||||||
--no-simulate is used). This option can be
|
--no-simulate is used). This option can be
|
||||||
used multiple times
|
used multiple times
|
||||||
|
--print-to-file [WHEN:]TEMPLATE FILE
|
||||||
|
Append given template to the file. The
|
||||||
|
values of WHEN and TEMPLATE are same as
|
||||||
|
that of --print. FILE uses the same syntax
|
||||||
|
as the output template. This option can be
|
||||||
|
used multiple times
|
||||||
-j, --dump-json Quiet, but print JSON information for each
|
-j, --dump-json Quiet, but print JSON information for each
|
||||||
video. Simulate unless --no-simulate is
|
video. Simulate unless --no-simulate is
|
||||||
used. See "OUTPUT TEMPLATE" for a
|
used. See "OUTPUT TEMPLATE" for a
|
||||||
|
@ -201,9 +201,12 @@ class YoutubeDL(object):
|
|||||||
verbose: Print additional info to stdout.
|
verbose: Print additional info to stdout.
|
||||||
quiet: Do not print messages to stdout.
|
quiet: Do not print messages to stdout.
|
||||||
no_warnings: Do not print out anything for warnings.
|
no_warnings: Do not print out anything for warnings.
|
||||||
forceprint: A dict with keys video/playlist mapped to
|
forceprint: A dict with keys WHEN mapped to a list of templates to
|
||||||
a list of templates to force print to stdout
|
print to stdout. The allowed keys are video or any of the
|
||||||
|
items in utils.POSTPROCESS_WHEN.
|
||||||
For compatibility, a single list is also accepted
|
For compatibility, a single list is also accepted
|
||||||
|
print_to_file: A dict with keys WHEN (same as forceprint) mapped to
|
||||||
|
a list of tuples with (template, filename)
|
||||||
forceurl: Force printing final URL. (Deprecated)
|
forceurl: Force printing final URL. (Deprecated)
|
||||||
forcetitle: Force printing title. (Deprecated)
|
forcetitle: Force printing title. (Deprecated)
|
||||||
forceid: Force printing ID. (Deprecated)
|
forceid: Force printing ID. (Deprecated)
|
||||||
@ -349,8 +352,8 @@ class YoutubeDL(object):
|
|||||||
postprocessors: A list of dictionaries, each with an entry
|
postprocessors: A list of dictionaries, each with an entry
|
||||||
* key: The name of the postprocessor. See
|
* key: The name of the postprocessor. See
|
||||||
yt_dlp/postprocessor/__init__.py for a list.
|
yt_dlp/postprocessor/__init__.py for a list.
|
||||||
* when: When to run the postprocessor. Can be one of
|
* when: When to run the postprocessor. Allowed values are
|
||||||
pre_process|before_dl|post_process|after_move.
|
the entries of utils.POSTPROCESS_WHEN
|
||||||
Assumed to be 'post_process' if not given
|
Assumed to be 'post_process' if not given
|
||||||
post_hooks: Deprecated - Register a custom postprocessor instead
|
post_hooks: Deprecated - Register a custom postprocessor instead
|
||||||
A list of functions that get called as the final step
|
A list of functions that get called as the final step
|
||||||
@ -592,8 +595,10 @@ class YoutubeDL(object):
|
|||||||
else:
|
else:
|
||||||
self.params['nooverwrites'] = not self.params['overwrites']
|
self.params['nooverwrites'] = not self.params['overwrites']
|
||||||
|
|
||||||
# Compatibility with older syntax
|
|
||||||
params.setdefault('forceprint', {})
|
params.setdefault('forceprint', {})
|
||||||
|
params.setdefault('print_to_file', {})
|
||||||
|
|
||||||
|
# Compatibility with older syntax
|
||||||
if not isinstance(params['forceprint'], dict):
|
if not isinstance(params['forceprint'], dict):
|
||||||
params['forceprint'] = {'video': params['forceprint']}
|
params['forceprint'] = {'video': params['forceprint']}
|
||||||
|
|
||||||
@ -2683,19 +2688,32 @@ class YoutubeDL(object):
|
|||||||
subs[lang] = f
|
subs[lang] = f
|
||||||
return subs
|
return subs
|
||||||
|
|
||||||
def _forceprint(self, tmpl, info_dict):
|
def _forceprint(self, key, info_dict):
|
||||||
mobj = re.match(r'\w+(=?)$', tmpl)
|
if info_dict is None:
|
||||||
if mobj and mobj.group(1):
|
return
|
||||||
tmpl = f'{tmpl[:-1]} = %({tmpl[:-1]})r'
|
info_copy = info_dict.copy()
|
||||||
elif mobj:
|
info_copy['formats_table'] = self.render_formats_table(info_dict)
|
||||||
tmpl = '%({})s'.format(tmpl)
|
info_copy['thumbnails_table'] = self.render_thumbnails_table(info_dict)
|
||||||
|
info_copy['subtitles_table'] = self.render_subtitles_table(info_dict.get('id'), info_dict.get('subtitles'))
|
||||||
|
info_copy['automatic_captions_table'] = self.render_subtitles_table(info_dict.get('id'), info_dict.get('automatic_captions'))
|
||||||
|
|
||||||
info_dict = info_dict.copy()
|
def format_tmpl(tmpl):
|
||||||
info_dict['formats_table'] = self.render_formats_table(info_dict)
|
mobj = re.match(r'\w+(=?)$', tmpl)
|
||||||
info_dict['thumbnails_table'] = self.render_thumbnails_table(info_dict)
|
if mobj and mobj.group(1):
|
||||||
info_dict['subtitles_table'] = self.render_subtitles_table(info_dict.get('id'), info_dict.get('subtitles'))
|
return f'{tmpl[:-1]} = %({tmpl[:-1]})r'
|
||||||
info_dict['automatic_captions_table'] = self.render_subtitles_table(info_dict.get('id'), info_dict.get('automatic_captions'))
|
elif mobj:
|
||||||
self.to_stdout(self.evaluate_outtmpl(tmpl, info_dict))
|
return f'%({tmpl})s'
|
||||||
|
return tmpl
|
||||||
|
|
||||||
|
for tmpl in self.params['forceprint'].get(key, []):
|
||||||
|
self.to_stdout(self.evaluate_outtmpl(format_tmpl(tmpl), info_copy))
|
||||||
|
|
||||||
|
for tmpl, file_tmpl in self.params['print_to_file'].get(key, []):
|
||||||
|
filename = self.evaluate_outtmpl(file_tmpl, info_dict)
|
||||||
|
tmpl = format_tmpl(tmpl)
|
||||||
|
self.to_screen(f'[info] Writing {tmpl!r} to: {filename}')
|
||||||
|
with io.open(filename, 'a', encoding='utf-8') as f:
|
||||||
|
f.write(self.evaluate_outtmpl(tmpl, info_copy) + '\n')
|
||||||
|
|
||||||
def __forced_printings(self, info_dict, filename, incomplete):
|
def __forced_printings(self, info_dict, filename, incomplete):
|
||||||
def print_mandatory(field, actual_field=None):
|
def print_mandatory(field, actual_field=None):
|
||||||
@ -2719,10 +2737,11 @@ class YoutubeDL(object):
|
|||||||
elif 'url' in info_dict:
|
elif 'url' in info_dict:
|
||||||
info_dict['urls'] = info_dict['url'] + info_dict.get('play_path', '')
|
info_dict['urls'] = info_dict['url'] + info_dict.get('play_path', '')
|
||||||
|
|
||||||
if self.params['forceprint'].get('video') or self.params.get('forcejson'):
|
if (self.params.get('forcejson')
|
||||||
|
or self.params['forceprint'].get('video')
|
||||||
|
or self.params['print_to_file'].get('video')):
|
||||||
self.post_extract(info_dict)
|
self.post_extract(info_dict)
|
||||||
for tmpl in self.params['forceprint'].get('video', []):
|
self._forceprint('video', info_dict)
|
||||||
self._forceprint(tmpl, info_dict)
|
|
||||||
|
|
||||||
print_mandatory('title')
|
print_mandatory('title')
|
||||||
print_mandatory('id')
|
print_mandatory('id')
|
||||||
@ -3290,8 +3309,7 @@ class YoutubeDL(object):
|
|||||||
return infodict
|
return infodict
|
||||||
|
|
||||||
def run_all_pps(self, key, info, *, additional_pps=None):
|
def run_all_pps(self, key, info, *, additional_pps=None):
|
||||||
for tmpl in self.params['forceprint'].get(key, []):
|
self._forceprint(key, info)
|
||||||
self._forceprint(tmpl, info)
|
|
||||||
for pp in (additional_pps or []) + self._pps[key]:
|
for pp in (additional_pps or []) + self._pps[key]:
|
||||||
info = self.run_pp(pp, info)
|
info = self.run_pp(pp, info)
|
||||||
return info
|
return info
|
||||||
|
@ -356,6 +356,10 @@ def _real_main(argv=None):
|
|||||||
for type_, tmpl_list in opts.forceprint.items():
|
for type_, tmpl_list in opts.forceprint.items():
|
||||||
for tmpl in tmpl_list:
|
for tmpl in tmpl_list:
|
||||||
validate_outtmpl(tmpl, f'{type_} print template')
|
validate_outtmpl(tmpl, f'{type_} print template')
|
||||||
|
for type_, tmpl_list in opts.print_to_file.items():
|
||||||
|
for tmpl, file in tmpl_list:
|
||||||
|
validate_outtmpl(tmpl, f'{type_} print-to-file template')
|
||||||
|
validate_outtmpl(file, f'{type_} print-to-file filename')
|
||||||
validate_outtmpl(opts.sponsorblock_chapter_title, 'SponsorBlock chapter title')
|
validate_outtmpl(opts.sponsorblock_chapter_title, 'SponsorBlock chapter title')
|
||||||
for k, tmpl in opts.progress_template.items():
|
for k, tmpl in opts.progress_template.items():
|
||||||
k = f'{k[:-6]} console title' if '-title' in k else f'{k} progress'
|
k = f'{k[:-6]} console title' if '-title' in k else f'{k} progress'
|
||||||
@ -663,6 +667,7 @@ def _real_main(argv=None):
|
|||||||
'forcefilename': opts.getfilename,
|
'forcefilename': opts.getfilename,
|
||||||
'forceformat': opts.getformat,
|
'forceformat': opts.getformat,
|
||||||
'forceprint': opts.forceprint,
|
'forceprint': opts.forceprint,
|
||||||
|
'print_to_file': opts.print_to_file,
|
||||||
'forcejson': opts.dumpjson or opts.print_json,
|
'forcejson': opts.dumpjson or opts.print_json,
|
||||||
'dump_single_json': opts.dump_single_json,
|
'dump_single_json': opts.dump_single_json,
|
||||||
'force_write_download_archive': opts.force_write_download_archive,
|
'force_write_download_archive': opts.force_write_download_archive,
|
||||||
|
@ -173,11 +173,16 @@ def create_parser():
|
|||||||
process_key=str.lower, append=False):
|
process_key=str.lower, append=False):
|
||||||
|
|
||||||
out_dict = dict(getattr(parser.values, option.dest))
|
out_dict = dict(getattr(parser.values, option.dest))
|
||||||
|
multiple_args = not isinstance(value, str)
|
||||||
if multiple_keys:
|
if multiple_keys:
|
||||||
allowed_keys = r'(%s)(,(%s))*' % (allowed_keys, allowed_keys)
|
allowed_keys = r'(%s)(,(%s))*' % (allowed_keys, allowed_keys)
|
||||||
mobj = re.match(r'(?i)(?P<keys>%s)%s(?P<val>.*)$' % (allowed_keys, delimiter), value)
|
mobj = re.match(
|
||||||
|
r'(?i)(?P<keys>%s)%s(?P<val>.*)$' % (allowed_keys, delimiter),
|
||||||
|
value[0] if multiple_args else value)
|
||||||
if mobj is not None:
|
if mobj is not None:
|
||||||
keys, val = mobj.group('keys').split(','), mobj.group('val')
|
keys, val = mobj.group('keys').split(','), mobj.group('val')
|
||||||
|
if multiple_args:
|
||||||
|
val = [val, *value[1:]]
|
||||||
elif default_key is not None:
|
elif default_key is not None:
|
||||||
keys, val = [default_key], value
|
keys, val = [default_key], value
|
||||||
else:
|
else:
|
||||||
@ -923,6 +928,18 @@ def create_parser():
|
|||||||
'Field name or output template to print to screen, optionally prefixed with when to print it, separated by a ":". '
|
'Field name or output template to print to screen, optionally prefixed with when to print it, separated by a ":". '
|
||||||
'Supported values of "WHEN" are the same as that of --use-postprocessor, and "video" (default). '
|
'Supported values of "WHEN" are the same as that of --use-postprocessor, and "video" (default). '
|
||||||
'Implies --quiet and --simulate (unless --no-simulate is used). This option can be used multiple times'))
|
'Implies --quiet and --simulate (unless --no-simulate is used). This option can be used multiple times'))
|
||||||
|
verbosity.add_option(
|
||||||
|
'--print-to-file',
|
||||||
|
metavar='[WHEN:]TEMPLATE FILE', dest='print_to_file', default={}, type='str', nargs=2,
|
||||||
|
action='callback', callback=_dict_from_options_callback,
|
||||||
|
callback_kwargs={
|
||||||
|
'allowed_keys': 'video|' + '|'.join(map(re.escape, POSTPROCESS_WHEN)),
|
||||||
|
'default_key': 'video',
|
||||||
|
'multiple_keys': False,
|
||||||
|
'append': True,
|
||||||
|
}, help=(
|
||||||
|
'Append given template to the file. The values of WHEN and TEMPLATE are same as that of --print. '
|
||||||
|
'FILE uses the same syntax as the output template. This option can be used multiple times'))
|
||||||
verbosity.add_option(
|
verbosity.add_option(
|
||||||
'-g', '--get-url',
|
'-g', '--get-url',
|
||||||
action='store_true', dest='geturl', default=False,
|
action='store_true', dest='geturl', default=False,
|
||||||
|
Loading…
Reference in New Issue
Block a user