]> jfr.im git - yt-dlp.git/commitdiff
Allow `--print` to be run at any post-processing stage
authorpukkandan <redacted>
Mon, 10 Jan 2022 18:27:59 +0000 (23:57 +0530)
committerpukkandan <redacted>
Mon, 10 Jan 2022 18:58:01 +0000 (00:28 +0530)
README.md
yt_dlp/YoutubeDL.py
yt_dlp/options.py

index b40f5c693356e28260263722253c2a16b4e3c649..31e5aad3ae07ad81afbed09601e5be83f45315d5 100644 (file)
--- a/README.md
+++ b/README.md
@@ -667,11 +667,13 @@ ## Verbosity and Simulation Options:
     --skip-download                  Do not download the video but write all
                                      related files (Alias: --no-download)
     -O, --print [WHEN:]TEMPLATE      Field name or output template to print to
-                                     screen per video. Prefix the template with
-                                     "playlist:" to print it once per playlist
-                                     instead. Implies --quiet and --simulate
-                                     (unless --no-simulate is used). This option
-                                     can be used multiple times
+                                     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).
+                                     Implies --quiet and --simulate (unless
+                                     --no-simulate is used). This option can be
+                                     used multiple times
     -j, --dump-json                  Quiet, but print JSON information for each
                                      video. Simulate unless --no-simulate is
                                      used. See "OUTPUT TEMPLATE" for a
@@ -1221,6 +1223,11 @@ # OUTPUT TEMPLATE
 
  - `urls` (string): The URLs of all requested formats, one in each line
  - `filename` (string): Name of the video file. Note that the actual filename may be different due to post-processing. Use `--exec echo` to get the name after all postprocessing is complete
+ - `formats_table` (table): The video format table as printed by `--list-formats`
+ - `thumbnails_table` (table): The thumbnail format table as printed by `--list-thumbnails`
+ - `subtitles_table` (table): The subtitle format table as printed by `--list-subs`
+ - `automatic_captions_table` (table): The automatic subtitle format table as printed by `--list-subs`
  
 Available only in `--sponsorblock-chapter-title`:
 
index dff4b17b3096406c19c94d8edfcb338aa13a99e5..a239f1c3cdbb145a8daf8233057bd57bd4189893 100644 (file)
@@ -1772,13 +1772,8 @@ def get_entry(i):
                 self.prepare_filename(ie_copy, 'pl_infojson'), overwrite=True) is None:
             return
 
-        for tmpl in self.params['forceprint'].get('playlist', []):
-            self._forceprint(tmpl, ie_result)
-
-        for pp in self._pps['playlist']:
-            ie_result = self.run_pp(pp, ie_result)
-
-        self.to_screen('[download] Finished downloading playlist: %s' % playlist)
+        ie_result = self.run_all_pps('playlist', ie_result)
+        self.to_screen(f'[download] Finished downloading playlist: {playlist}')
         return ie_result
 
     @__handle_extraction_exceptions
@@ -2600,8 +2595,7 @@ def is_wellformed(f):
                 self.record_download_archive(info_dict)
 
             info_dict['requested_downloads'] = formats_to_download
-            for pp in self._pps['after_video']:
-                info_dict = self.run_pp(pp, info_dict)
+            info_dict = self.run_all_pps('after_video', info_dict)
             if max_downloads_reached:
                 raise MaxDownloadsReached()
 
@@ -3228,6 +3222,26 @@ def filter_requested_info(info_dict, actually_filter=True):
         ''' Alias of sanitize_info for backward compatibility '''
         return YoutubeDL.sanitize_info(info_dict, actually_filter)
 
+    @staticmethod
+    def post_extract(info_dict):
+        def actual_post_extract(info_dict):
+            if info_dict.get('_type') in ('playlist', 'multi_video'):
+                for video_dict in info_dict.get('entries', {}):
+                    actual_post_extract(video_dict or {})
+                return
+
+            post_extractor = info_dict.get('__post_extractor') or (lambda: {})
+            extra = post_extractor().items()
+            info_dict.update(extra)
+            info_dict.pop('__post_extractor', None)
+
+            original_infodict = info_dict.get('__original_infodict') or {}
+            original_infodict.update(extra)
+            original_infodict.pop('__post_extractor', None)
+
+        actual_post_extract(info_dict or {})
+
+
     def run_pp(self, pp, infodict):
         files_to_delete = []
         if '__files_to_move' not in infodict:
@@ -3257,44 +3271,27 @@ def run_pp(self, pp, infodict):
                     del infodict['__files_to_move'][old_filename]
         return infodict
 
-    @staticmethod
-    def post_extract(info_dict):
-        def actual_post_extract(info_dict):
-            if info_dict.get('_type') in ('playlist', 'multi_video'):
-                for video_dict in info_dict.get('entries', {}):
-                    actual_post_extract(video_dict or {})
-                return
-
-            post_extractor = info_dict.get('__post_extractor') or (lambda: {})
-            extra = post_extractor().items()
-            info_dict.update(extra)
-            info_dict.pop('__post_extractor', None)
-
-            original_infodict = info_dict.get('__original_infodict') or {}
-            original_infodict.update(extra)
-            original_infodict.pop('__post_extractor', None)
-
-        actual_post_extract(info_dict or {})
+    def run_all_pps(self, key, info, *, additional_pps=None):
+        for tmpl in self.params['forceprint'].get(key, []):
+            self._forceprint(tmpl, info)
+        for pp in (additional_pps or []) + self._pps[key]:
+            info = self.run_pp(info)
+        return info
 
     def pre_process(self, ie_info, key='pre_process', files_to_move=None):
         info = dict(ie_info)
         info['__files_to_move'] = files_to_move or {}
-        for pp in self._pps[key]:
-            info = self.run_pp(pp, info)
+        info = self.run_all_pps(key, info)
         return info, info.pop('__files_to_move', None)
 
     def post_process(self, filename, info, files_to_move=None):
         """Run all the postprocessors on the given file."""
         info['filepath'] = filename
         info['__files_to_move'] = files_to_move or {}
-
-        for pp in info.get('__postprocessors', []) + self._pps['post_process']:
-            info = self.run_pp(pp, info)
+        info = self.run_all_pps('post_process', info, additional_pps=info.get('__postprocessors'))
         info = self.run_pp(MoveFilesAfterDownloadPP(self), info)
         del info['__files_to_move']
-        for pp in self._pps['after_move']:
-            info = self.run_pp(pp, info)
-        return info
+        return self.run_all_pps('after_move', info)
 
     def _make_archive_id(self, info_dict):
         video_id = info_dict.get('id')
index 15c480e6d1a9ad5a35bd8f66187c75f8da23f1f6..4dd7c6dbd8d5c7cfca9f49762c3e59c2dde7e413 100644 (file)
@@ -910,13 +910,13 @@ def _dict_from_options_callback(
         metavar='[WHEN:]TEMPLATE', dest='forceprint', default={}, type='str',
         action='callback', callback=_dict_from_options_callback,
         callback_kwargs={
-            'allowed_keys': 'video|playlist',
+            '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 per video. '
-            'Prefix the template with "playlist:" to print it once per playlist instead. '
+            '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). '
             'Implies --quiet and --simulate (unless --no-simulate is used). This option can be used multiple times'))
     verbosity.add_option(
         '-g', '--get-url',