"""
all decorators used in moviepy go there
"""
import decorator
from moviepy.tools import cvsecs
[docs]@decorator.decorator
def outplace(f, clip, *a, **k):
""" Applies f(clip.copy(), *a, **k) and returns clip.copy()"""
newclip = clip.copy()
f(newclip, *a, **k)
return newclip
[docs]@decorator.decorator
def convert_masks_to_RGB(f, clip, *a, **k):
""" If the clip is a mask, convert it to RGB before running the function """
if clip.ismask:
clip = clip.to_RGB()
return f(clip, *a, **k)
[docs]@decorator.decorator
def apply_to_mask(f, clip, *a, **k):
""" This decorator will apply the same function f to the mask of
the clip created with f """
newclip = f(clip, *a, **k)
if getattr(newclip, 'mask', None):
newclip.mask = f(newclip.mask, *a, **k)
return newclip
[docs]@decorator.decorator
def apply_to_audio(f, clip, *a, **k):
""" This decorator will apply the function f to the audio of
the clip created with f """
newclip = f(clip, *a, **k)
if getattr(newclip, 'audio', None):
newclip.audio = f(newclip.audio, *a, **k)
return newclip
[docs]@decorator.decorator
def requires_duration(f, clip, *a, **k):
""" Raise an error if the clip has no duration."""
if clip.duration is None:
raise ValueError("Attribute 'duration' not set")
else:
return f(clip, *a, **k)
[docs]@decorator.decorator
def audio_video_fx(f, clip, *a, **k):
""" Use an audio function on a video/audio clip
This decorator tells that the function f (audioclip -> audioclip)
can be also used on a video clip, at which case it returns a
videoclip with unmodified video and modified audio.
"""
if hasattr(clip, "audio"):
newclip = clip.copy()
if clip.audio is not None:
newclip.audio = f(clip.audio, *a, **k)
return newclip
else:
return f(clip, *a, **k)
[docs]def preprocess_args(fun,varnames):
""" Applies fun to variables in varnames before launching the function """
def wrapper(f, *a, **kw):
if hasattr(f, "func_code"):
func_code = f.func_code # Python 2
else:
func_code = f.__code__ # Python 3
names = func_code.co_varnames
new_a = [fun(arg) if (name in varnames) else arg
for (arg, name) in zip(a, names)]
new_kw = {k: fun(v) if k in varnames else v
for (k,v) in kw.items()}
return f(*new_a, **new_kw)
return decorator.decorator(wrapper)
[docs]def convert_to_seconds(varnames):
"Converts the specified variables to seconds"
return preprocess_args(cvsecs, varnames)
[docs]@decorator.decorator
def add_mask_if_none(f, clip, *a, **k):
""" Add a mask to the clip if there is none. """
if clip.mask is None:
clip = clip.add_mask()
return f(clip, *a, **k)
[docs]@decorator.decorator
def use_clip_fps_by_default(f, clip, *a, **k):
""" Will use clip.fps if no fps=... is provided in **k """
def fun(fps):
if fps is not None:
return fps
elif getattr(clip, 'fps', None):
return clip.fps
raise AttributeError("No 'fps' (frames per second) attribute specified"
" for function %s and the clip has no 'fps' attribute. Either"
" provide e.g. fps=24 in the arguments of the function, or define"
" the clip's fps with `clip.fps=24`" % f.__name__)
if hasattr(f, "func_code"):
func_code = f.func_code # Python 2
else:
func_code = f.__code__ # Python 3
names = func_code.co_varnames[1:]
new_a = [fun(arg) if (name=='fps') else arg
for (arg, name) in zip(a, names)]
new_kw = {k: fun(v) if k=='fps' else v
for (k,v) in k.items()}
return f(clip, *new_a, **new_kw)