Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix linting errors and refactor code #2243

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 29 additions & 27 deletions moviepy/Clip.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,17 @@
from numbers import Real
from operator import add

import numpy as np
import proglog
try:
import numpy as np
except ImportError as exc:
raise ImportError("MoviePy requires numpy. Please install it with pip install numpy") from exc
Comment on lines +10 to +13
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the benefit of doing this? numpy, and other dependencies are clearly stated in the pyproject.toml file so I think adding this is overkill.

Maybe I am missing some other benefit?


try:
import proglog
except ImportError as exc:
raise ImportError(
"MoviePy requires proglog. Please install it with pip install proglog"
) from exc

from moviepy.decorators import (
apply_to_audio,
Expand All @@ -20,6 +29,7 @@
)


# pylint: disable=too-many-instance-attributes
class Clip:
"""Base class of all clips (VideoClips and AudioClips).

Expand Down Expand Up @@ -73,14 +83,12 @@ def get_frame(self, t):
if self.memoize:
if t == self.memoized_t:
return self.memoized_frame
else:
frame = self.make_frame(t)
self.memoized_t = t
self.memoized_frame = frame
return frame
else:
# print(t)
return self.make_frame(t)
frame = self.make_frame(t)
self.memoized_t = t
self.memoized_frame = frame
return frame
# print(t)
return self.make_frame(t)

def transform(self, func, apply_to=None, keep_duration=True):
"""General processing of a clip.
Expand Down Expand Up @@ -376,8 +384,7 @@ def is_playing(self, t):
result *= t <= self.end
return result

else:
return (t >= self.start) and ((self.end is None) or (t < self.end))
return (t >= self.start) and ((self.end is None) or (t < self.end))

@convert_parameter_to_seconds(["start_time", "end_time"])
@apply_to_mask
Expand Down Expand Up @@ -420,9 +427,9 @@ def subclip(self, start_time=0, end_time=None):

if (self.duration is not None) and (start_time >= self.duration):
raise ValueError(
"start_time (%.02f) " % start_time
+ "should be smaller than the clip's "
+ "duration (%.02f)." % self.duration
f"start_time ({start_time:.02f}) "
f"should be smaller than the clip's "
f"duration ({self.duration:.02f})."
)

new_clip = self.time_transform(lambda t: t + start_time, apply_to=[])
Expand All @@ -433,15 +440,11 @@ def subclip(self, start_time=0, end_time=None):
elif (end_time is not None) and (end_time < 0):
if self.duration is None:
raise ValueError(
(
"Subclip with negative times (here %s)"
" can only be extracted from clips with a ``duration``"
)
% (str((start_time, end_time)))
f"Subclip with negative times (here {(start_time, end_time)})"
f" can only be extracted from clips with a ``duration``"
)

else:
end_time = self.duration + end_time
end_time = self.duration + end_time

if end_time is not None:
new_clip.duration = end_time - start_time
Expand Down Expand Up @@ -480,8 +483,8 @@ def cutout(self, start_time, end_time):

if self.duration is not None:
return new_clip.with_duration(self.duration - (end_time - start_time))
else: # pragma: no cover
return new_clip

return new_clip # pragma: no cover

@requires_duration
@use_clip_fps_by_default
Expand Down Expand Up @@ -629,11 +632,10 @@ def __getitem__(self, key):
apply_to=apply_to,
)
return clip
elif isinstance(key, tuple):
if isinstance(key, tuple):
# get a concatenation of subclips
return reduce(add, (self[k] for k in key))
else:
return self.get_frame(key)
return self.get_frame(key)

def __del__(self):
# WARNING: as stated in close() above, if we call close, it closes clips
Expand Down
15 changes: 13 additions & 2 deletions moviepy/audio/fx/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# import every video fx function
"""Audio FX functions for use with moviepy's audio clips.

This module provides a collection of audio effects that can be applied to audio clips
in moviepy. These effects include fading, volume adjustment, delay, normalization,
and looping.

Each function can be applied either by importing it directly from this module
or by using the fx method on an audio clip instance.
"""

from typing import Tuple # Add type imports first

# Audio effects imports sorted alphabetically
from moviepy.audio.fx.audio_delay import audio_delay
from moviepy.audio.fx.audio_fadein import audio_fadein
from moviepy.audio.fx.audio_fadeout import audio_fadeout
Expand All @@ -9,7 +20,7 @@
from moviepy.audio.fx.multiply_volume import multiply_volume


__all__ = (
__all__: Tuple[str, ...] = (
"audio_delay",
"audio_fadein",
"audio_fadeout",
Expand Down
17 changes: 14 additions & 3 deletions moviepy/audio/fx/audio_delay.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
import numpy as np
"""Audio delay effect for use with moviepy's audio clips.

This module provides a function to create an echo/delay effect by repeating
an audio clip multiple times with decreasing volume. The delay effect can be
customized by adjusting the time offset between repeats, number of repeats,
and volume decay factor.
"""

try:
import numpy as np
except ImportError as exc:
raise ImportError("MoviePy requires numpy. Please install it with pip install numpy") from exc

from moviepy.audio.AudioClip import CompositeAudioClip
from moviepy.audio.fx.multiply_volume import multiply_volume
Expand Down Expand Up @@ -42,13 +53,13 @@ def audio_delay(clip, offset=0.2, n_repeats=8, decay=1):
... clip = AudioClip(make_frame=make_frame, duration=0.1, fps=44100)
... clip = audio_delay(clip, offset=.2, n_repeats=11, decay=0)
"""
decayments = np.linspace(1, max(0, decay), n_repeats + 1)
decay_factors = np.linspace(1, max(0, decay), n_repeats + 1)
return CompositeAudioClip(
[
clip.copy(),
*[
multiply_volume(
clip.with_start((rep + 1) * offset), decayments[rep + 1]
clip.with_start((rep + 1) * offset), decay_factors[rep + 1]
)
for rep in range(n_repeats)
],
Expand Down
43 changes: 38 additions & 5 deletions moviepy/audio/fx/audio_fadein.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,46 @@
import numpy as np
"""Audio fade-in effect for use with moviepy's audio clips.

This module provides a function to create a fade-in effect where audio gradually
increases from silence to full volume over a specified duration. The effect can
be applied to both mono and stereo audio clips, and supports time specifications
in various formats through the convert_parameter_to_seconds decorator.
"""

from typing import Callable, Union

try:
import numpy as np
from numpy.typing import NDArray
except ImportError as exc:
raise ImportError("MoviePy requires numpy. Please install it with pip install numpy") from exc

from moviepy.decorators import audio_video_fx, convert_parameter_to_seconds


def _mono_factor_getter():
def _create_mono_fade_factor() -> Callable[[float, float], float]:
"""Create a fade factor function for mono audio.

Returns
-------
Callable[[float, float], float]
A function that takes time and duration and returns a fade factor.
"""
return lambda t, duration: np.minimum(t / duration, 1)


def _stereo_factor_getter(nchannels):
def _create_stereo_fade_factor(nchannels: int) -> Callable[[float, float], NDArray]:
"""Create a fade factor function for stereo/multi-channel audio.

Parameters
----------
nchannels : int
Number of audio channels.

Returns
-------
Callable[[float, float], NDArray]
A function that takes time and duration and returns an array of fade factors.
"""
def getter(t, duration):
factor = np.minimum(t / duration, 1)
return np.array([factor for _ in range(nchannels)]).T
Expand All @@ -34,9 +67,9 @@ def audio_fadein(clip, duration):
>>> clip.fx(audio_fadein, "00:00:06")
"""
get_factor = (
_mono_factor_getter()
_create_mono_fade_factor()
if clip.nchannels == 1
else _stereo_factor_getter(clip.nchannels)
else _create_mono_fade_factor(clip.nchannels)
)

return clip.transform(
Expand Down
13 changes: 12 additions & 1 deletion moviepy/audio/fx/audio_fadeout.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
import numpy as np
"""Audio fade-out effect for use with moviepy's audio clips.
This module provides a function to create a fade-out effect where audio gradually
decreases from full volume to silence over a specified duration at the end of a clip.
The effect can be applied to both mono and stereo audio clips, and supports time
specifications in various formats through the convert_parameter_to_seconds decorator.
"""

try:
import numpy as np
except ImportError as exc:
raise ImportError("MoviePy requires numpy. Please install it with pip install numpy") from exc

from moviepy.decorators import (
audio_video_fx,
Expand Down
7 changes: 7 additions & 0 deletions moviepy/audio/fx/audio_loop.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
"""Audio loop effect for use with moviepy's audio clips.

This module provides a function to create a loop effect by repeating an audio clip
multiple times or for a specified duration. The loop can be customized by setting
the number of loops or specifying the duration.
"""

from moviepy.audio.AudioClip import concatenate_audioclips
from moviepy.decorators import audio_video_fx

Expand Down
11 changes: 9 additions & 2 deletions moviepy/audio/fx/audio_normalize.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
"""Audio normalization effect for use with moviepy's audio clips.

This module provides a function to normalize the volume of an audio clip so that
the maximum volume is at 0db, the maximum achievable volume. The normalization
ensures that the loudest parts of the audio are not distorted when played at
full volume.
"""

from moviepy.audio.fx.multiply_volume import multiply_volume
from moviepy.decorators import audio_video_fx

Expand All @@ -21,5 +29,4 @@ def audio_normalize(clip):
# Nothing to normalize.
# Avoids a divide by zero error.
return clip.copy()
else:
return multiply_volume(clip, 1 / max_volume)
return multiply_volume(clip, 1 / max_volume)
8 changes: 8 additions & 0 deletions moviepy/audio/fx/multiply_stereo_volume.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
"""Audio stereo volume multiplication effect for use with moviepy's audio clips.

This module provides a function to adjust the volume of the left and right channels
independently in a stereo audio clip. The function allows for separate volume control
for each channel, which is useful for creating effects like stereo panning or
adjusting the balance between the left and right channels.
"""

from moviepy.decorators import audio_video_fx


Expand Down
12 changes: 11 additions & 1 deletion moviepy/audio/fx/multiply_volume.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
import numpy as np
"""Audio volume multiplication effect for use with moviepy's audio clips.

This module provides a function to adjust the volume of an audio clip by multiplying
the volume by a specified factor. The volume can be multiplied for a specific time
range or for the entire duration of the clip.
"""

try:
import numpy as np
except ImportError as exc:
raise ImportError("MoviePy requires numpy. Please install it with pip install numpy") from exc

from moviepy.decorators import audio_video_fx, convert_parameter_to_seconds

Expand Down
5 changes: 4 additions & 1 deletion moviepy/audio/tools/cuts.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""Cutting utilities working with audio."""

import numpy as np
try:
import numpy as np
except ImportError as exc:
raise ImportError("MoviePy requires numpy. Please install it with pip install numpy") from exc


def find_audio_period(clip, min_time=0.1, max_time=2, time_resolution=0.01):
Expand Down