]> jfr.im git - yt-dlp.git/commitdiff
Refactor (See desc)
authorpukkandan <redacted>
Tue, 9 Mar 2021 02:17:21 +0000 (07:47 +0530)
committerpukkandan <redacted>
Sun, 14 Mar 2021 14:32:55 +0000 (20:02 +0530)
* Create `FFmpegPostProcessor.real_run_ffmpeg` that can accept multiple input/output files along with switches for each
* Rewrite `cli_configuration_args` and related functions
* Create `YoutubeDL._ensure_dir_exists` - this was previously defined in multiple places

yt_dlp/YoutubeDL.py
yt_dlp/downloader/external.py
yt_dlp/postprocessor/common.py
yt_dlp/postprocessor/embedthumbnail.py
yt_dlp/postprocessor/ffmpeg.py
yt_dlp/postprocessor/sponskrub.py
yt_dlp/utils.py

index 7e0a69528262f55287db62ef5a436b2dbf7a1f82..397d405033725960487777279c57d40ee76d9692 100644 (file)
@@ -1171,6 +1171,9 @@ def _fixup(r):
         else:
             raise Exception('Invalid result type: %s' % result_type)
 
+    def _ensure_dir_exists(self, path):
+        return make_dir(path, self.report_error)
+
     def __process_playlist(self, ie_result, download):
         # We process each entry in the playlist
         playlist = ie_result.get('title') or ie_result.get('id')
@@ -1187,12 +1190,9 @@ def __process_playlist(self, ie_result, download):
             }
             ie_copy.update(dict(ie_result))
 
-            def ensure_dir_exists(path):
-                return make_dir(path, self.report_error)
-
             if self.params.get('writeinfojson', False):
                 infofn = self.prepare_filename(ie_copy, 'pl_infojson')
-                if not ensure_dir_exists(encodeFilename(infofn)):
+                if not self._ensure_dir_exists(encodeFilename(infofn)):
                     return
                 if not self.params.get('overwrites', True) and os.path.exists(encodeFilename(infofn)):
                     self.to_screen('[info] Playlist metadata is already present')
@@ -1208,7 +1208,7 @@ def ensure_dir_exists(path):
 
             if self.params.get('writedescription', False):
                 descfn = self.prepare_filename(ie_copy, 'pl_description')
-                if not ensure_dir_exists(encodeFilename(descfn)):
+                if not self._ensure_dir_exists(encodeFilename(descfn)):
                     return
                 if not self.params.get('overwrites', True) and os.path.exists(encodeFilename(descfn)):
                     self.to_screen('[info] Playlist description is already present')
@@ -2089,17 +2089,14 @@ def process_info(self, info_dict):
         if full_filename is None:
             return
 
-        def ensure_dir_exists(path):
-            return make_dir(path, self.report_error)
-
-        if not ensure_dir_exists(encodeFilename(full_filename)):
+        if not self._ensure_dir_exists(encodeFilename(full_filename)):
             return
-        if not ensure_dir_exists(encodeFilename(temp_filename)):
+        if not self._ensure_dir_exists(encodeFilename(temp_filename)):
             return
 
         if self.params.get('writedescription', False):
             descfn = self.prepare_filename(info_dict, 'description')
-            if not ensure_dir_exists(encodeFilename(descfn)):
+            if not self._ensure_dir_exists(encodeFilename(descfn)):
                 return
             if not self.params.get('overwrites', True) and os.path.exists(encodeFilename(descfn)):
                 self.to_screen('[info] Video description is already present')
@@ -2116,7 +2113,7 @@ def ensure_dir_exists(path):
 
         if self.params.get('writeannotations', False):
             annofn = self.prepare_filename(info_dict, 'annotation')
-            if not ensure_dir_exists(encodeFilename(annofn)):
+            if not self._ensure_dir_exists(encodeFilename(annofn)):
                 return
             if not self.params.get('overwrites', True) and os.path.exists(encodeFilename(annofn)):
                 self.to_screen('[info] Video annotations are already present')
@@ -2204,7 +2201,7 @@ def dl(name, info, subtitle=False):
 
         if self.params.get('writeinfojson', False):
             infofn = self.prepare_filename(info_dict, 'infojson')
-            if not ensure_dir_exists(encodeFilename(infofn)):
+            if not self._ensure_dir_exists(encodeFilename(infofn)):
                 return
             if not self.params.get('overwrites', True) and os.path.exists(encodeFilename(infofn)):
                 self.to_screen('[info] Video metadata is already present')
@@ -2360,7 +2357,7 @@ def correct_ext(filename):
                             fname = prepend_extension(
                                 self.prepare_filename(new_info, 'temp'),
                                 'f%s' % f['format_id'], new_info['ext'])
-                            if not ensure_dir_exists(fname):
+                            if not self._ensure_dir_exists(fname):
                                 return
                             downloaded.append(fname)
                             partial_success, real_download = dl(fname, new_info)
index 7c2d56d9c9058e08ef0ed410548c71f919c160c0..2c37860affa7d8c5b55c25a55dbcd27012c3d418 100644 (file)
@@ -108,7 +108,8 @@ def _valueless_option(self, command_option, param, expected_value=True):
     def _configuration_args(self, *args, **kwargs):
         return cli_configuration_args(
             self.params.get('external_downloader_args'),
-            self.get_basename(), *args, **kwargs)
+            [self.get_basename(), 'default'],
+            *args, **kwargs)
 
     def _call_downloader(self, tmpfilename, info_dict):
         """ Either overwrite this or implement _make_cmd """
index f8f4e7693f2175700a63ef9a0e3187b15bcdc869..3c316b34952bf6da93aa47b7a2ec7f10bac4e755 100644 (file)
@@ -91,10 +91,18 @@ def try_utime(self, path, atime, mtime, errnote='Cannot update utime of file'):
         except Exception:
             self.report_warning(errnote)
 
-    def _configuration_args(self, *args, **kwargs):
+    def _configuration_args(self, exe, keys=None, default=[], use_compat=True):
+        pp_key = self.pp_key().lower()
+        exe = exe.lower()
+        root_key = exe if pp_key == exe else '%s+%s' % (pp_key, exe)
+        keys = ['%s%s' % (root_key, k) for k in (keys or [''])]
+        if root_key in keys:
+            keys += [root_key] + ([] if pp_key == exe else [(self.pp_key(), exe)]) + ['default']
+        else:
+            use_compat = False
         return cli_configuration_args(
             self._downloader.params.get('postprocessor_args'),
-            self.pp_key().lower(), *args, **kwargs)
+            keys, default, use_compat)
 
 
 class AudioConversionError(PostProcessingError):
index cc6cd1c8ecd0526f52cd3817ff6659c4a6224aa6..3c68e0298478c60f83e738d5a0c24e45611f430c 100644 (file)
@@ -139,7 +139,7 @@ def is_webp(path):
                        encodeFilename(thumbnail_filename, True),
                        encodeArgument('-o'),
                        encodeFilename(temp_filename, True)]
-                cmd += [encodeArgument(o) for o in self._configuration_args(exe='AtomicParsley')]
+                cmd += [encodeArgument(o) for o in self._configuration_args('AtomicParsley')]
 
                 self.to_screen('Adding thumbnail to "%s"' % filename)
                 self.write_debug('AtomicParsley command line: %s' % shell_quote(cmd))
index 944a4bc17729cf789bb78e3b7a4fa81111cae5ac..a8635c1d11472fe4210afb318605f45a37c50556 100644 (file)
@@ -234,25 +234,35 @@ def get_stream_number(self, path, keys, value):
         return num, len(streams)
 
     def run_ffmpeg_multiple_files(self, input_paths, out_path, opts):
+        return self.real_run_ffmpeg(
+            [(path, []) for path in input_paths],
+            [(out_path, opts)])
+
+    def real_run_ffmpeg(self, input_path_opts, output_path_opts):
         self.check_version()
 
         oldest_mtime = min(
-            os.stat(encodeFilename(path)).st_mtime for path in input_paths)
+            os.stat(encodeFilename(path)).st_mtime for path, _ in input_path_opts)
 
         cmd = [encodeFilename(self.executable, True), encodeArgument('-y')]
         # avconv does not have repeat option
         if self.basename == 'ffmpeg':
             cmd += [encodeArgument('-loglevel'), encodeArgument('repeat+info')]
 
-        def make_args(file, pre=[], post=[], *args, **kwargs):
-            args = pre + self._configuration_args(*args, **kwargs) + post
+        def make_args(file, args, name, number):
+            keys = ['_%s%d' % (name, number), '_%s' % name]
+            if name == 'o' and number == 1:
+                keys.append('')
+            args += self._configuration_args(self.basename, keys)
+            if name == 'i':
+                args.append('-i')
             return (
-                [encodeArgument(o) for o in args]
+                [encodeArgument(arg) for arg in args]
                 + [encodeFilename(self._ffmpeg_filename_argument(file), True)])
 
-        for i, path in enumerate(input_paths):
-            cmd += make_args(path, post=['-i'], exe='%s_i%d' % (self.basename, i + 1), use_default_arg=False)
-        cmd += make_args(out_path, pre=opts, exe=self.basename)
+        for arg_type, path_opts in (('i', input_path_opts), ('o', output_path_opts)):
+            cmd += [arg for i, o in enumerate(path_opts)
+                    for arg in make_args(o[0], o[1], arg_type, i + 1)]
 
         self.write_debug('ffmpeg command line: %s' % shell_quote(cmd))
         p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
@@ -262,7 +272,8 @@ def make_args(file, pre=[], post=[], *args, **kwargs):
             if self.get_param('verbose', False):
                 self.report_error(stderr)
             raise FFmpegPostProcessorError(stderr.split('\n')[-1])
-        self.try_utime(out_path, oldest_mtime, oldest_mtime)
+        for out_path, _ in output_path_opts:
+            self.try_utime(out_path, oldest_mtime, oldest_mtime)
         return stderr.decode('utf-8', 'replace')
 
     def run_ffmpeg(self, path, out_path, opts):
index 2f30acc8e52b43af0204b680a22ab813cb5a614a..4ba33398ea3ecf2fed89d24ad5de0d28d888aae5 100644 (file)
@@ -71,7 +71,7 @@ def run(self, information):
         if not self.cutout:
             cmd += ['-chapter']
         cmd += compat_shlex_split(self.args)  # For backward compatibility
-        cmd += self._configuration_args(exe=self._exe_name, use_default_arg='no_compat')
+        cmd += self._configuration_args(self._exe_name, use_compat=False)
         cmd += ['--', information['id'], filename, temp_filename]
         cmd = [encodeArgument(i) for i in cmd]
 
index 12bc637f853c9ba8f9c5038609176a11218e3187..77f8c0f4d454017b6f4ad0076bcbbb1ec53f29ef 100644 (file)
@@ -4692,36 +4692,26 @@ def cli_valueless_option(params, command_option, param, expected_value=True):
     return [command_option] if param == expected_value else []
 
 
-def cli_configuration_args(argdict, key, default=[], exe=None, use_default_arg=True):
-    # use_default_arg can be True, False, or 'no_compat'
+def cli_configuration_args(argdict, keys, default=[], use_compat=True):
     if isinstance(argdict, (list, tuple)):  # for backward compatibility
-        if use_default_arg is True:
+        if use_compat:
             return argdict
         else:
             argdict = None
-
     if argdict is None:
         return default
     assert isinstance(argdict, dict)
 
-    key = key.lower()
-    args = exe_args = None
-    if exe is not None:
-        assert isinstance(exe, compat_str)
-        exe = exe.lower()
-        args = argdict.get('%s+%s' % (key, exe))
-        if args is None:
-            exe_args = argdict.get(exe)
-
-    if args is None:
-        args = argdict.get(key) if key != exe else None
-    if args is None and exe_args is None:
-        args = argdict.get('default', default) if use_default_arg else default
-
-    args, exe_args = args or [], exe_args or []
-    assert isinstance(args, (list, tuple))
-    assert isinstance(exe_args, (list, tuple))
-    return args + exe_args
+    assert isinstance(keys, (list, tuple))
+    for key_list in keys:
+        if isinstance(key_list, compat_str):
+            key_list = (key_list,)
+        arg_list = list(filter(
+            lambda x: x is not None,
+            [argdict.get(key.lower()) for key in key_list]))
+        if arg_list:
+            return [arg for args in arg_list for arg in args]
+    return default
 
 
 class ISO639Utils(object):