From b9b5ecc61ccb1ba9df3a2ccaf0987fba34d4f84a Mon Sep 17 00:00:00 2001 From: vermont Date: Sat, 13 Jan 2024 13:02:43 -0500 Subject: [PATCH 1/5] Fix decorator performance. --- moviepy/decorators.py | 61 +++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/moviepy/decorators.py b/moviepy/decorators.py index 621e35853..c33edb006 100644 --- a/moviepy/decorators.py +++ b/moviepy/decorators.py @@ -78,22 +78,28 @@ def audio_video_fx(func, clip, *args, **kwargs): return func(clip, *args, **kwargs) -def preprocess_args(fun, varnames): - """Applies fun to variables in varnames before launching the function.""" +def preprocess_args(preprocess_func, varnames): + """Applies preprocess_func to variables in varnames before launching + the function. + """ - def wrapper(func, *args, **kwargs): - names = inspect.getfullargspec(func).args - new_args = [ - fun(arg) if (name in varnames) and (arg is not None) else arg - for (arg, name) in zip(args, names) - ] - new_kwargs = { - kwarg: fun(value) if kwarg in varnames else value - for (kwarg, value) in kwargs.items() - } - return func(*new_args, **new_kwargs) + def decor(func): + argnames = inspect.getfullargspec(func).args + + def wrapper(func, *args, **kwargs): + new_args = [ + preprocess_func(arg) if (name in varnames) and (arg is not None) else arg + for (arg, name) in zip(args, argnames) + ] + new_kwargs = { + kwarg: preprocess_func(value) if kwarg in varnames else value + for (kwarg, value) in kwargs.items() + } + return func(*new_args, **new_kwargs) + + return decorator.decorate(func, wrapper) - return decorator.decorator(wrapper) + return decor def convert_parameter_to_seconds(varnames): @@ -114,11 +120,12 @@ def add_mask_if_none(func, clip, *args, **kwargs): return func(clip, *args, **kwargs) -@decorator.decorator -def use_clip_fps_by_default(func, clip, *args, **kwargs): +def use_clip_fps_by_default(func): """Will use ``clip.fps`` if no ``fps=...`` is provided in **kwargs**.""" - def find_fps(fps): + argnames = inspect.getfullargspec(func).args[1:] + + def find_fps(clip, fps): if fps is not None: return fps elif getattr(clip, "fps", None): @@ -130,14 +137,16 @@ def find_fps(fps): " the clip's fps with `clip.fps=24`" % func.__name__ ) - names = inspect.getfullargspec(func).args[1:] + def wrapper(func, clip, *args, **kwargs): + new_args = [ + find_fps(clip, arg) if name == "fps" else arg + for (arg, name) in zip(args, argnames) + ] + new_kwargs = { + kwarg: find_fps(clip, kwarg) if kwarg == "fps" else value + for (kwarg, value) in kwargs.items() + } - new_args = [ - find_fps(arg) if (name == "fps") else arg for (arg, name) in zip(args, names) - ] - new_kwargs = { - kwarg: find_fps(value) if kwarg == "fps" else value - for (kwarg, value) in kwargs.items() - } + return func(clip, *new_args, **new_kwargs) - return func(clip, *new_args, **new_kwargs) + return decorator.decorate(func, wrapper) From c507dad341306b21c83a1bbfd4cd44c69c1cebde Mon Sep 17 00:00:00 2001 From: vermont Date: Sat, 9 Mar 2024 14:01:18 -0500 Subject: [PATCH 2/5] Fix formatting. --- moviepy/audio/fx/all/__init__.py | 1 + moviepy/decorators.py | 7 ++++++- moviepy/tools.py | 1 + moviepy/video/fx/all/__init__.py | 1 + moviepy/video/io/ffmpeg_reader.py | 13 +++++++------ moviepy/video/tools/credits.py | 1 + moviepy/video/tools/cuts.py | 6 +++--- 7 files changed, 20 insertions(+), 10 deletions(-) diff --git a/moviepy/audio/fx/all/__init__.py b/moviepy/audio/fx/all/__init__.py index c6cadf1c6..d51e65959 100644 --- a/moviepy/audio/fx/all/__init__.py +++ b/moviepy/audio/fx/all/__init__.py @@ -4,6 +4,7 @@ Use the fx method directly from the clip instance (e.g. ``clip.audio_normalize(...)``) or import the function from moviepy.audio.fx instead. """ + import warnings from .. import * # noqa 401,F403 diff --git a/moviepy/decorators.py b/moviepy/decorators.py index c33edb006..1177f214c 100644 --- a/moviepy/decorators.py +++ b/moviepy/decorators.py @@ -1,4 +1,5 @@ """Decorators used by moviepy.""" + import inspect import os @@ -88,7 +89,11 @@ def decor(func): def wrapper(func, *args, **kwargs): new_args = [ - preprocess_func(arg) if (name in varnames) and (arg is not None) else arg + ( + preprocess_func(arg) + if (name in varnames) and (arg is not None) + else arg + ) for (arg, name) in zip(args, argnames) ] new_kwargs = { diff --git a/moviepy/tools.py b/moviepy/tools.py index 8817c2d95..2778cd2d5 100644 --- a/moviepy/tools.py +++ b/moviepy/tools.py @@ -1,4 +1,5 @@ """Misc. useful functions that can be used at many places in the program.""" + import os import subprocess as sp import warnings diff --git a/moviepy/video/fx/all/__init__.py b/moviepy/video/fx/all/__init__.py index 34b0627dd..0e4d6f2f0 100644 --- a/moviepy/video/fx/all/__init__.py +++ b/moviepy/video/fx/all/__init__.py @@ -4,6 +4,7 @@ Use the fx method directly from the clip instance (e.g. ``clip.resize(...)``) or import the function from moviepy.video.fx instead. """ + import warnings from moviepy.video.fx import * # noqa F401,F403 diff --git a/moviepy/video/io/ffmpeg_reader.py b/moviepy/video/io/ffmpeg_reader.py index 616deff6b..700b18604 100644 --- a/moviepy/video/io/ffmpeg_reader.py +++ b/moviepy/video/io/ffmpeg_reader.py @@ -1,4 +1,5 @@ """Implements all the functions to read a video or a picture using ffmpeg.""" + import os import re import subprocess as sp @@ -452,12 +453,12 @@ def parse(self): # for default streams, set their numbers globally, so it's # easy to get without iterating all if self._current_stream["default"]: - self.result[ - f"default_{stream_type_lower}_input_number" - ] = input_number - self.result[ - f"default_{stream_type_lower}_stream_number" - ] = stream_number + self.result[f"default_{stream_type_lower}_input_number"] = ( + input_number + ) + self.result[f"default_{stream_type_lower}_stream_number"] = ( + stream_number + ) # exit chapter if self._current_chapter: diff --git a/moviepy/video/tools/credits.py b/moviepy/video/tools/credits.py index f5b04025d..a7bf9fb5c 100644 --- a/moviepy/video/tools/credits.py +++ b/moviepy/video/tools/credits.py @@ -1,6 +1,7 @@ """Contains different functions to make end and opening credits, even though it is difficult to fill everyone needs in this matter. """ + from moviepy.decorators import convert_path_to_string from moviepy.video.compositing.CompositeVideoClip import CompositeVideoClip from moviepy.video.fx.resize import resize diff --git a/moviepy/video/tools/cuts.py b/moviepy/video/tools/cuts.py index 40ff5fca3..bb6efdfef 100644 --- a/moviepy/video/tools/cuts.py +++ b/moviepy/video/tools/cuts.py @@ -253,7 +253,7 @@ def distance(t1, t2): matching_frames = [] # the final result. - for (t, frame) in clip.iter_frames(with_times=True, logger=logger): + for t, frame in clip.iter_frames(with_times=True, logger=logger): flat_frame = 1.0 * frame.flatten() F_norm_sq = dot_product(flat_frame, flat_frame) @@ -359,7 +359,7 @@ def select_scenes( nomatch_threshold = match_threshold dict_starts = defaultdict(lambda: []) - for (start, end, min_distance, max_distance) in self: + for start, end, min_distance, max_distance in self: dict_starts[start].append([end, min_distance, max_distance]) starts_ends = sorted(dict_starts.items(), key=lambda k: k[0]) @@ -445,7 +445,7 @@ def write_gifs(self, clip, gifs_dir, **kwargs): MoviePy - Building file foo/00000128_00000372.gif with imageio. MoviePy - Building file foo/00000140_00000360.gif with imageio. """ - for (start, end, _, _) in self: + for start, end, _, _ in self: name = "%s/%08d_%08d.gif" % (gifs_dir, 100 * start, 100 * end) clip.subclip(start, end).write_gif(name, **kwargs) From 456ebe983f9c251d021ebd7210eda3bc81588d4a Mon Sep 17 00:00:00 2001 From: osaajani <> Date: Fri, 10 Jan 2025 19:26:00 +0100 Subject: [PATCH 3/5] linting --- examples/soundtrack.py | 1 + moviepy/Clip.py | 1 + tests/test_VideoFileClip.py | 1 + 3 files changed, 3 insertions(+) diff --git a/examples/soundtrack.py b/examples/soundtrack.py index 48adbb998..c2efd8c05 100644 --- a/examples/soundtrack.py +++ b/examples/soundtrack.py @@ -1,4 +1,5 @@ """A simple test script on how to put a soundtrack to a movie.""" + from moviepy import * diff --git a/moviepy/Clip.py b/moviepy/Clip.py index 5c2d88b2d..63857296f 100644 --- a/moviepy/Clip.py +++ b/moviepy/Clip.py @@ -1,6 +1,7 @@ """Implements the central object of MoviePy, the Clip, and all the methods that are common to the two subclasses of Clip, VideoClip and AudioClip. """ + import copy as _copy from functools import reduce from numbers import Real diff --git a/tests/test_VideoFileClip.py b/tests/test_VideoFileClip.py index e92f78e04..bd8f996e1 100644 --- a/tests/test_VideoFileClip.py +++ b/tests/test_VideoFileClip.py @@ -1,4 +1,5 @@ """Video file clip tests meant to be run with pytest.""" + import copy import os From 618d066e1eff850eb71a31e2abdf1f210cf00db8 Mon Sep 17 00:00:00 2001 From: osaajani <> Date: Fri, 10 Jan 2025 19:31:18 +0100 Subject: [PATCH 4/5] linting --- moviepy/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/moviepy/__init__.py b/moviepy/__init__.py index 2b9baa8d7..2d4d60c74 100644 --- a/moviepy/__init__.py +++ b/moviepy/__init__.py @@ -1,6 +1,7 @@ """Imports everything that you need from the MoviePy submodules so that every thing can be directly imported with ``from moviepy import *``. """ + from moviepy.audio import fx as afx from moviepy.audio.AudioClip import ( AudioArrayClip, From 685137dcf9cc7be00c7d36253427dc9a123374c1 Mon Sep 17 00:00:00 2001 From: osaajani <> Date: Fri, 10 Jan 2025 19:53:34 +0100 Subject: [PATCH 5/5] linting --- moviepy/decorators.py | 1 - 1 file changed, 1 deletion(-) diff --git a/moviepy/decorators.py b/moviepy/decorators.py index 812803b70..3bdd13db3 100644 --- a/moviepy/decorators.py +++ b/moviepy/decorators.py @@ -126,7 +126,6 @@ def add_mask_if_none(func, clip, *args, **kwargs): def use_clip_fps_by_default(func): """Will use ``clip.fps`` if no ``fps=...`` is provided in **kwargs**.""" - argnames = inspect.getfullargspec(func).args[1:] def find_fps(clip, fps):