Add pre-processor stage `video`

Related: #456, #5808
pull/5732/merge
pukkandan 1 year ago
parent 4455918e7f
commit 119e40ef64
No known key found for this signature in database
GPG Key ID: 7EEE9E1E817D0A39

@ -725,7 +725,7 @@ You can also fork the project on GitHub and run your fork's [build workflow](.gi
screen, optionally prefixed with when to screen, optionally prefixed with when to
print it, separated by a ":". Supported print it, separated by a ":". Supported
values of "WHEN" are the same as that of values of "WHEN" are the same as that of
--use-postprocessor, and "video" (default). --use-postprocessor (default: video).
Implies --quiet. Implies --simulate unless Implies --quiet. Implies --simulate unless
--no-simulate or later stages of WHEN are --no-simulate or later stages of WHEN are
used. This option can be used multiple times used. This option can be used multiple times
@ -979,18 +979,18 @@ You can also fork the project on GitHub and run your fork's [build workflow](.gi
--ffmpeg-location PATH Location of the ffmpeg binary; either the --ffmpeg-location PATH Location of the ffmpeg binary; either the
path to the binary or its containing directory path to the binary or its containing directory
--exec [WHEN:]CMD Execute a command, optionally prefixed with --exec [WHEN:]CMD Execute a command, optionally prefixed with
when to execute it (after_move if when to execute it, separated by a ":".
unspecified), separated by a ":". Supported Supported values of "WHEN" are the same as
values of "WHEN" are the same as that of that of --use-postprocessor (default:
--use-postprocessor. Same syntax as the after_move). Same syntax as the output
output template can be used to pass any template can be used to pass any field as
field as arguments to the command. After arguments to the command. After download, an
download, an additional field "filepath" additional field "filepath" that contains
that contains the final path of the the final path of the downloaded file is
downloaded file is also available, and if no also available, and if no fields are passed,
fields are passed, %(filepath)q is appended %(filepath)q is appended to the end of the
to the end of the command. This option can command. This option can be used multiple
be used multiple times times
--no-exec Remove any previously defined --exec --no-exec Remove any previously defined --exec
--convert-subs FORMAT Convert the subtitles to another format --convert-subs FORMAT Convert the subtitles to another format
(currently supported: ass, lrc, srt, vtt) (currently supported: ass, lrc, srt, vtt)
@ -1028,14 +1028,16 @@ You can also fork the project on GitHub and run your fork's [build workflow](.gi
postprocessor is invoked. It can be one of postprocessor is invoked. It can be one of
"pre_process" (after video extraction), "pre_process" (after video extraction),
"after_filter" (after video passes filter), "after_filter" (after video passes filter),
"before_dl" (before each video download), "video" (after --format; before
"post_process" (after each video download; --print/--output), "before_dl" (before each
default), "after_move" (after moving video video download), "post_process" (after each
file to it's final locations), "after_video" video download; default), "after_move"
(after downloading and processing all (after moving video file to it's final
formats of a video), or "playlist" (at end locations), "after_video" (after downloading
of playlist). This option can be used and processing all formats of a video), or
multiple times to add different postprocessors "playlist" (at end of playlist). This option
can be used multiple times to add different
postprocessors
## SponsorBlock Options: ## SponsorBlock Options:
Make chapter entries for, or remove various segments (sponsor, Make chapter entries for, or remove various segments (sponsor,

@ -2977,6 +2977,16 @@ class YoutubeDL:
# Does nothing under normal operation - for backward compatibility of process_info # Does nothing under normal operation - for backward compatibility of process_info
self.post_extract(info_dict) self.post_extract(info_dict)
def replace_info_dict(new_info):
nonlocal info_dict
if new_info == info_dict:
return
info_dict.clear()
info_dict.update(new_info)
new_info, _ = self.pre_process(info_dict, 'video')
replace_info_dict(new_info)
self._num_downloads += 1 self._num_downloads += 1
# info_dict['_filename'] needs to be set for backward compatibility # info_dict['_filename'] needs to be set for backward compatibility
@ -3090,13 +3100,6 @@ class YoutubeDL:
for link_type, should_write in write_links.items()): for link_type, should_write in write_links.items()):
return return
def replace_info_dict(new_info):
nonlocal info_dict
if new_info == info_dict:
return
info_dict.clear()
info_dict.update(new_info)
new_info, files_to_move = self.pre_process(info_dict, 'before_dl', files_to_move) new_info, files_to_move = self.pre_process(info_dict, 'before_dl', files_to_move)
replace_info_dict(new_info) replace_info_dict(new_info)

@ -277,6 +277,20 @@ def create_parser():
out_dict[key] = out_dict.get(key, []) + [val] if append else val out_dict[key] = out_dict.get(key, []) + [val] if append else val
setattr(parser.values, option.dest, out_dict) setattr(parser.values, option.dest, out_dict)
def when_prefix(default):
return {
'default': {},
'type': 'str',
'action': 'callback',
'callback': _dict_from_options_callback,
'callback_kwargs': {
'allowed_keys': '|'.join(map(re.escape, POSTPROCESS_WHEN)),
'default_key': default,
'multiple_keys': False,
'append': True,
},
}
parser = _YoutubeDLOptionParser() parser = _YoutubeDLOptionParser()
alias_group = optparse.OptionGroup(parser, 'Aliases') alias_group = optparse.OptionGroup(parser, 'Aliases')
Formatter = string.Formatter() Formatter = string.Formatter()
@ -1086,28 +1100,16 @@ def create_parser():
help='Do not download the video but write all related files (Alias: --no-download)') help='Do not download the video but write all related files (Alias: --no-download)')
verbosity.add_option( verbosity.add_option(
'-O', '--print', '-O', '--print',
metavar='[WHEN:]TEMPLATE', dest='forceprint', default={}, type='str', metavar='[WHEN:]TEMPLATE', dest='forceprint', **when_prefix('video'),
action='callback', callback=_dict_from_options_callback, help=(
callback_kwargs={
'allowed_keys': 'video|' + '|'.join(map(re.escape, POSTPROCESS_WHEN)),
'default_key': 'video',
'multiple_keys': False,
'append': True,
}, help=(
'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 (default: video). '
'Implies --quiet. Implies --simulate unless --no-simulate or later stages of WHEN are used. ' 'Implies --quiet. Implies --simulate unless --no-simulate or later stages of WHEN are used. '
'This option can be used multiple times')) 'This option can be used multiple times'))
verbosity.add_option( verbosity.add_option(
'--print-to-file', '--print-to-file',
metavar='[WHEN:]TEMPLATE FILE', dest='print_to_file', default={}, type='str', nargs=2, metavar='[WHEN:]TEMPLATE FILE', dest='print_to_file', nargs=2, **when_prefix('video'),
action='callback', callback=_dict_from_options_callback, help=(
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. ' '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')) 'FILE uses the same syntax as the output template. This option can be used multiple times'))
verbosity.add_option( verbosity.add_option(
@ -1629,16 +1631,10 @@ def create_parser():
help='Location of the ffmpeg binary; either the path to the binary or its containing directory') help='Location of the ffmpeg binary; either the path to the binary or its containing directory')
postproc.add_option( postproc.add_option(
'--exec', '--exec',
metavar='[WHEN:]CMD', dest='exec_cmd', default={}, type='str', metavar='[WHEN:]CMD', dest='exec_cmd', **when_prefix('after_move'),
action='callback', callback=_dict_from_options_callback, help=(
callback_kwargs={ 'Execute a command, optionally prefixed with when to execute it, separated by a ":". '
'allowed_keys': '|'.join(map(re.escape, POSTPROCESS_WHEN)), 'Supported values of "WHEN" are the same as that of --use-postprocessor (default: after_move). '
'default_key': 'after_move',
'multiple_keys': False,
'append': True,
}, help=(
'Execute a command, optionally prefixed with when to execute it (after_move if unspecified), separated by a ":". '
'Supported values of "WHEN" are the same as that of --use-postprocessor. '
'Same syntax as the output template can be used to pass any field as arguments to the command. ' 'Same syntax as the output template can be used to pass any field as arguments to the command. '
'After download, an additional field "filepath" that contains the final path of the downloaded file ' 'After download, an additional field "filepath" that contains the final path of the downloaded file '
'is also available, and if no fields are passed, %(filepath)q is appended to the end of the command. ' 'is also available, and if no fields are passed, %(filepath)q is appended to the end of the command. '
@ -1714,7 +1710,8 @@ def create_parser():
'ARGS are a semicolon ";" delimited list of NAME=VALUE. ' 'ARGS are a semicolon ";" delimited list of NAME=VALUE. '
'The "when" argument determines when the postprocessor is invoked. ' 'The "when" argument determines when the postprocessor is invoked. '
'It can be one of "pre_process" (after video extraction), "after_filter" (after video passes filter), ' 'It can be one of "pre_process" (after video extraction), "after_filter" (after video passes filter), '
'"before_dl" (before each video download), "post_process" (after each video download; default), ' '"video" (after --format; before --print/--output), "before_dl" (before each video download), '
'"post_process" (after each video download; default), '
'"after_move" (after moving video file to it\'s final locations), ' '"after_move" (after moving video file to it\'s final locations), '
'"after_video" (after downloading and processing all formats of a video), ' '"after_video" (after downloading and processing all formats of a video), '
'or "playlist" (at end of playlist). ' 'or "playlist" (at end of playlist). '

@ -3395,7 +3395,7 @@ def qualities(quality_ids):
return q return q
POSTPROCESS_WHEN = ('pre_process', 'after_filter', 'before_dl', 'post_process', 'after_move', 'after_video', 'playlist') POSTPROCESS_WHEN = ('pre_process', 'after_filter', 'video', 'before_dl', 'post_process', 'after_move', 'after_video', 'playlist')
DEFAULT_OUTTMPL = { DEFAULT_OUTTMPL = {

Loading…
Cancel
Save