Skip to content

Commit

Permalink
Renaming methods, parameters and variables for increased usability, c…
Browse files Browse the repository at this point in the history
…onsistency and readability (#1170)

See PR description for details: #1170
  • Loading branch information
tburrows13 committed Oct 8, 2020
1 parent 21fff15 commit 4356fcd
Show file tree
Hide file tree
Showing 96 changed files with 1,335 additions and 1,285 deletions.
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ In this example we open a video file, select the subclip between t=50s and t=60s
# Make the text. Many more options are available.
txt_clip = ( TextClip("My Holidays 2013",fontsize=70,color='white')
.set_position('center')
.set_duration(10) )
.with_position('center')
.with_duration(10) )
result = CompositeVideoClip([video, txt_clip]) # Overlay text on video
result.write_videofile("myHolidays_edited.webm",fps=25) # Many options...
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/quick_recipes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Blurring all frames of a video
return gaussian_filter(image.astype(float), sigma=2)
clip = VideoFileClip("my_video.mp4")
clip_blurred = clip.fl_image( blur )
clip_blurred = clip.image_transform( blur )
clip_blurred.write_videofile("blurred_video.mp4")


Expand Down
2 changes: 1 addition & 1 deletion docs/getting_started/audioclips.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ Exporting and previewing audio clips

You can also export assign an audio clip as the soundtrack of a video clip with ::

videoclip2 = videoclip.set_audio(my_audioclip)
videoclip2 = videoclip.with_audio(my_audioclip)
30 changes: 15 additions & 15 deletions docs/getting_started/compositing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,46 +65,46 @@ Starting and stopping times

In a CompositionClip, all the clips start to play at a time that is specified by the ``clip.start`` attribute. You can set this starting time as follows: ::

clip1 = clip1.set_start(5) # start after 5 seconds
clip1 = clip1.with_start(5) # start after 5 seconds

So for instance your composition will look like ::

video = CompositeVideoClip([clip1, # starts at t=0
clip2.set_start(5), # start at t=5s
clip3.set_start(9)]) # start at t=9s
clip2.with_start(5), # start at t=5s
clip3.with_start(9)]) # start at t=9s

In the example above, maybe ``clip2`` will start before ``clip1`` is over. In this case you can make ``clip2`` appear with a *fade-in* effect of one second: ::

video = CompositeVideoClip([clip1, # starts at t=0
clip2.set_start(5).crossfadein(1),
clip3.set_start(9).crossfadein(1.5)])
clip2.with_start(5).crossfadein(1),
clip3.with_start(9).crossfadein(1.5)])

Positioning clips
""""""""""""""""""

If ``clip2`` and ``clip3`` are smaller than ``clip1``, you can decide where they will appear in the composition by setting their position. Here we indicate the coordinates of the top-left pixel of the clips: ::

video = CompositeVideoClip([clip1,
clip2.set_position((45,150)),
clip3.set_position((90,100))])
clip2.with_position((45,150)),
clip3.with_position((90,100))])

There are many ways to specify the position: ::

clip2.set_position((45,150)) # x=45, y=150 , in pixels
clip2.with_position((45,150)) # x=45, y=150 , in pixels

clip2.set_position("center") # automatically centered
clip2.with_position("center") # automatically centered

# clip2 is horizontally centered, and at the top of the picture
clip2.set_position(("center","top"))
clip2.with_position(("center","top"))

# clip2 is vertically centered, at the left of the picture
clip2.set_position(("left","center"))
clip2.with_position(("left","center"))

# clip2 is at 40% of the width, 70% of the height of the screen:
clip2.set_position((0.4,0.7), relative=True)
clip2.with_position((0.4,0.7), relative=True)

# clip2's position is horizontally centered, and moving down!
clip2.set_position(lambda t: ('center', 50+t) )
clip2.with_position(lambda t: ('center', 50+t) )

When indicating the position keep in mind that the ``y`` coordinate has its zero at the top of the picture:

Expand All @@ -129,6 +129,6 @@ If you want to make a custom audiotrack from several audio sources: audioc clips
# ... make some audio clips aclip1, aclip2, aclip3
concat = concatenate_audioclips([aclip1, aclip2, aclip3])
compo = CompositeAudioClip([aclip1.volumex(1.2),
aclip2.set_start(5), # start at t=5s
aclip3.set_start(9)])
aclip2.with_start(5), # start at t=5s
aclip3.with_start(9)])

26 changes: 13 additions & 13 deletions docs/getting_started/effects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ Clips transformations and effects

There are several categories of clip modifications in MoviePy:

- The very common methods to change the attributes of a clip: ``clip.set_duration``, ``clip.set_audio``, ``clip.set_mask``, ``clip.set_start`` etc.
- The very common methods to change the attributes of a clip: ``clip.with_duration``, ``clip.with_audio``, ``clip.with_mask``, ``clip.with_start`` etc.
- The already-implemented effects. Core effects like ``clip.subclip(t1, t2)`` (keep only the cut between t1 and t2), which are very important, are implemented as class methods. More advanced and less common effects like ``loop`` (makes the clip play in a loop) or ``time_mirror`` (makes the clip play backwards) are placed in the special modules ``moviepy.video.fx`` and ``moviepy.audio.fx`` and are applied with the ``clip.fx`` method, for instance ``clip.fx(time_mirror)`` (makes the clip play backwards), ``clip.fx(black_white)`` (turns the clip black and white), etc.
- The effects that you can create yourself. using

All these effects have in common that they are **not inplace**: they do NOT modify the original clip, instead they create a new clip that is a version of the former with the changes applied. For instance: ::

my_clip = VideoFileClip("some_file.mp4")
my_clip.set_start(t=5) # does nothing, changes are lost
my_new_clip = my_clip.set_start(t=5) # good!
my_clip.with_start(t=5) # does nothing, changes are lost
my_new_clip = my_clip.with_start(t=5) # good!

Also, when you write ``clip.resize(width=640)``, it does not immediately apply the effect to all the frames of the clip, but only to the first frame: all the other frames will be resized only when required (that is, when you will write the whole clip to a file of when you will preview it). Said otherwise, creating a new clip is neither time nor memory hungry, all the computations happen during the final rendering.

Expand Down Expand Up @@ -61,27 +61,27 @@ For convenience, when you use ``moviepy.editor``, frequently used methods such a
Methods to create custom effects
----------------------------------

clip.fl
clip.transform
""""""""


You can modify a clip as you want using custom *filters* with ``clip.fl_time``, ``clip.fl_image``, and more generally with ``clip.fl``.
You can modify a clip as you want using custom *filters* with ``clip.time_transform``, ``clip.image_transform``, and more generally with ``clip.transform``.

You can change the timeline of the clip with ``clip.fl_time`` like this: ::
You can change the timeline of the clip with ``clip.time_transform`` like this: ::
modifiedClip1 = my_clip.fl_time(lambda t: 3*t)
modifiedClip2 = my_clip.fl_time(lambda t: 1+sin(t))
modifiedClip1 = my_clip.time_transform(lambda t: 3*t)
modifiedClip2 = my_clip.time_transform(lambda t: 1+sin(t))
Now the clip ``modifiedClip1`` plays the same as ``my_clip``, only three times faster, while ``modifiedClip2`` will play ``my_clip`` by oscillating between the times t=0s and t=2s. Note that in the last case you have created a clip of infinite duration (which is not a problem for the moment).

You can also modify the display of a clip with ``clip.fl_image``. The following takes a clip and inverts the green and blue channels of the frames: ::
You can also modify the display of a clip with ``clip.image_transform``. The following takes a clip and inverts the green and blue channels of the frames: ::
def invert_green_blue(image):
return image[:,:,[0,2,1]]
modifiedClip = my_clip.fl_image( invert_green_blue )
modifiedClip = my_clip.image_transform( invert_green_blue )
Finally, you may want to process the clip by taking into account both the time and the frame picture. This is possible with the method ``clip.fl(filter)``. The filter must be a function which takes two arguments and returns a picture. the fist argument is a ``get_frame`` method (i.e. a function ``g(t)`` which given a time returns the clip's frame at that time), and the second argument is the time. ::
Finally, you may want to process the clip by taking into account both the time and the frame picture. This is possible with the method ``clip.transform(filter)``. The filter must be a function which takes two arguments and returns a picture. The first argument is a ``get_frame`` method (i.e. a function ``gf(t)`` which given a time returns the clip's frame at that time), and the second argument is the time. ::
def scroll(get_frame, t):
"""
Expand All @@ -92,10 +92,10 @@ Finally, you may want to process the clip by taking into account both the time a
frame_region = frame[int(t):int(t)+360,:]
return frame_region
modifiedClip = my_clip.fl( scroll )
modifiedClip = my_clip.transform( scroll )

This will scroll down the clip, with a constant height of 360 pixels.

When programming a new effect, whenever it is possible, prefer using ``fl_time`` and ``fl_image`` instead of ``fl`` if possible when implementing new effects. The reason is that, when these effects are applied to
When programming a new effect, whenever it is possible, prefer using ``time_transform`` and ``image_transform`` instead of ``transform`` when implementing new effects. The reason is that, when these effects are applied to
ImageClips, MoviePy will recognize that these methods do not need to be applied to each frame, which will
result in faster renderings.
2 changes: 1 addition & 1 deletion docs/getting_started/efficient_moviepy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ So, the rules of thumb are:
* Call ``close()`` on any clip that you **construct** once you have finished using it and have also finished using any clip that was derived from it.
* Also close any clips you create through ``AudioFileClip.coreader()``.
* Even if you close a ``CompositeVideoClip`` instance, you still need to close the clips it was created from.
* Otherwise, if you have a clip that was created by deriving it from from another clip (e.g. by calling ``set_mask()``), then generally you shouldn't close it. Closing the original clip will also close the copy.
* Otherwise, if you have a clip that was created by deriving it from from another clip (e.g. by calling ``with_mask()``), then generally you shouldn't close it. Closing the original clip will also close the copy.

Clips act as `context managers <https://docs.python.org/3/reference/datamodel.html#context-managers>`_. This means you
can use them with a ``with`` statement, and they will automatically be closed at the end of the block, even if there is
Expand Down
2 changes: 1 addition & 1 deletion docs/getting_started/quick_presentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ In a typical MoviePy script, you load video or audio files, modify them, put the
txt_clip = TextClip("My Holidays 2013",fontsize=70,color='white')

# Say that you want it to appear 10s at the center of the screen
txt_clip = txt_clip.set_position('center').set_duration(10)
txt_clip = txt_clip.with_position('center').with_duration(10)

# Overlay the text clip on the first video clip
video = CompositeVideoClip([clip, txt_clip])
Expand Down
14 changes: 7 additions & 7 deletions docs/getting_started/videoclips.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,13 @@ The fundamental difference between masks and standard clips is that standard cli

When you create or load a clip that you will use as a mask you need to declare it: ::

maskclip = VideoClip(makeframe, duration=4, ismask=True)
maskclip = ImageClip("my_mask.jpeg", ismask=True)
maskclip = VideoFileClip("myvideo.mp4", ismask=True)
maskclip = VideoClip(makeframe, duration=4, is_mask=True)
maskclip = ImageClip("my_mask.jpeg", is_mask=True)
maskclip = VideoFileClip("myvideo.mp4", is_mask=True)

In the case of video and image files, if these are not already black and white they will be converted automatically.

Then you attach this mask to a clip (which must have the same dimensions) with ``myclip.set_mask(maskclip)``.
Then you attach this mask to a clip (which must have the same dimensions) with ``myclip.with_mask(maskclip)``.

Some image formats like PNG support transparency with an *alpha layer*, which MoviePy will use as a mask: ::

Expand Down Expand Up @@ -166,12 +166,12 @@ To write a clip as a video file, use ::
MoviePy has default codec names for the most common file extensions. If you want to use exotic formats or if you are not happy with the defaults you can provide the codec with ``codec='mpeg4'`` for instance. There are many many options when you are writing a video (bitrate, parameters of the audio writing, file size optimization, number of processors to use, etc.). Please refer to :py:meth:`~moviepy.video.VideoClip.VideoClip.write_videofile` for more.


Sometimes it is impossible for MoviePy to guess the ``duration`` attribute of the clip (keep in mind that some clips, like ImageClips displaying a picture, have *a priori* an infinite duration). Then, the ``duration`` must be set manually with ``clip.set_duration``: ::
Sometimes it is impossible for MoviePy to guess the ``duration`` attribute of the clip (keep in mind that some clips, like ImageClips displaying a picture, have *args priori* an infinite duration). Then, the ``duration`` must be set manually with ``clip.with_duration``: ::

# Make a video showing a flower for 5 seconds
my_clip = ImageClip("flower.jpeg") # has infinite duration
my_clip.write_videofile("flower.mp4") # Will fail! NO DURATION!
my_clip.set_duration(5).write_videofile("flower.mp4") # works!
my_clip.with_duration(5).write_videofile("flower.mp4") # works!


Animated GIFs
Expand All @@ -197,4 +197,4 @@ You can write a frame to an image file with ::
myclip.save_frame("frame.png") # by default the first frame is extracted
myclip.save_frame("frame.jpeg", t='01:00:00') # frame at time t=1h

If the clip has a mask it will be exported as the alpha layer of the image unless you specify ``withmask=False``.
If the clip has a mask it will be exported as the alpha layer of the image unless you specify ``with_mask=False``.
2 changes: 1 addition & 1 deletion docs/ref/code_origanization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ At the root of the project you have everything required for the packaging and in

The folder ``moviepy/`` the classes and modules relative to the video and the audio are clearly separated into two subfolders ``video/`` and ``audio/``. In ``moviepy/`` you will find all the classes, functions and decorations which are useful to both submodules ``audio`` and ``video``:

- ``Clip.py`` defines the base object for ``AudioClip`` and ``VideoClip`` and the simple methods that can be used by both, like ``clip.subclip``, ``clip.set_duration``, etc.
- ``Clip.py`` defines the base object for ``AudioClip`` and ``VideoClip`` and the simple methods that can be used by both, like ``clip.subclip``, ``clip.with_duration``, etc.
- Files ``config.py`` and ``config_defaults.py`` store the default paths to the external programs FFMPEG and ImageMagick.
- ``decorators.py`` provides very useful decorators that automatize some tasks, like the fact that some effects, when applied to a clip, should also be applied to it's mask, or to its audio track.
- ``tools.py`` provides misc. functions that are useful everywhere in the library, like a standardized call to subprocess, a time converter, a standardized way to print messages in the console, etc.
Expand Down
8 changes: 4 additions & 4 deletions examples/compo_from_image.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from moviepy.editor import *
from moviepy.video.tools.segmenting import findObjects
from moviepy.video.tools.segmenting import find_objects

# Load the image specifying the regions.
im = ImageClip("../../ultracompositing/motif.png")

# Loacate the regions, return a list of ImageClips
regions = findObjects(im)
regions = find_objects(im)


# Load 7 clips from the US National Parks. Public Domain :D
Expand All @@ -24,8 +24,8 @@

# fit each clip into its region
comp_clips = [
c.resize(r.size).set_mask(r.mask).set_pos(r.screenpos)
for c, r in zip(clips, regions)
clip.resize(r.size).with_mask(r.mask).set_pos(r.screenpos)
for clip, r in zip(clips, regions)
]

cc = CompositeVideoClip(comp_clips, im.size)
Expand Down
12 changes: 6 additions & 6 deletions examples/dancing_knights.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
clips_array([[edited_left, edited_right]])
.fadein(1)
.fadeout(1)
.set_audio(audio)
.with_audio(audio)
.subclip(0.3)
)

Expand All @@ -88,18 +88,18 @@
txt_title = (
TextClip(
"15th century dancing\n(hypothetical)",
fontsize=70,
font_size=70,
font="Century-Schoolbook-Roman",
color="white",
)
.margin(top=15, opacity=0)
.set_position(("center", "top"))
.with_position(("center", "top"))
)

title = (
CompositeVideoClip([dancing_knights.to_ImageClip(), txt_title])
.fadein(0.5)
.set_duration(3.5)
.with_duration(3.5)
)


Expand Down Expand Up @@ -127,13 +127,13 @@
txt_credits,
color="white",
font="Century-Schoolbook-Roman",
fontsize=35,
font_size=35,
kerning=-2,
interline=-1,
bg_color="black",
size=title.size,
)
.set_duration(2.5)
.with_duration(2.5)
.fadein(0.5)
.fadeout(0.5)
)
Expand Down
17 changes: 11 additions & 6 deletions examples/example_with_sound.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,37 @@
# MAKE THE LEFT CLIP : cut, crop, add a mask

mask = color_split(
(2 * W / 3, H), p1=(W / 3, H), p2=(2 * W / 3, 0), col1=1, col2=0, grad_width=2
(2 * W / 3, H),
p1=(W / 3, H),
p2=(2 * W / 3, 0),
color_1=1,
color_2=0,
gradient_width=2,
)

mask_clip = ImageClip(mask, ismask=True)
mask_clip = ImageClip(mask, is_mask=True)

clip_left = (
main_clip.coreader()
.subclip(0, duration)
.crop(x1=60, x2=60 + 2 * W / 3)
.set_mask(mask_clip)
.with_mask(mask_clip)
)


# MAKE THE RIGHT CLIP : cut, crop, add a mask

mask = color_split(
(2 * W / 3, H), p1=(2, H), p2=(W / 3 + 2, 0), col1=0, col2=1, grad_width=2
(2 * W / 3, H), p1=(2, H), p2=(W / 3 + 2, 0), color_1=0, color_2=1, gradient_width=2
)

mask_clip = ImageClip(mask, ismask=True)
mask_clip = ImageClip(mask, is_mask=True)

clip_right = (
main_clip.coreader()
.subclip(21, 21 + duration)
.crop(x1=70, x2=70 + 2 * W / 3)
.set_mask(mask_clip)
.with_mask(mask_clip)
)


Expand Down
8 changes: 4 additions & 4 deletions examples/headblur.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
# IF THE MANUAL TRACKING HAS BEEN PREVIOUSLY DONE,
# LOAD THE TRACKING DATA AND CONVERT IT TO FUNCTIONS x(t),fy(t)

with open("../../chaplin_txy.dat", "r") as f:
fx, fy = to_fxfy(pickle.load(f))
with open("../../chaplin_txy.dat", "r") as file:
fx, fy = to_fxfy(pickle.load(file))


# BLUR CHAPLIN'S HEAD IN THE CLIP
Expand All @@ -39,13 +39,13 @@
size=clip.size,
bg_color="grey20",
font="Century-Schoolbook-Italic",
fontsize=40,
font_size=40,
)


# Concatenate the Chaplin clip with the text clip, add audio

final = concatenate_videoclips([clip_blurred, txt.set_duration(3)]).set_audio(
final = concatenate_videoclips([clip_blurred, txt.with_duration(3)]).with_audio(
clip.audio
)

Expand Down
4 changes: 2 additions & 2 deletions examples/logo.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ def f(t, size, a=np.pi / 3, thickness=20):
return biGradientScreen(size, center, v, 0.6, 0.0)


logo = ImageClip("../../videos/logo_descr.png").resize(width=w / 2).set_mask(mask)
logo = ImageClip("../../videos/logo_descr.png").resize(width=w / 2).with_mask(mask)

screen = logo.on_color(moviesize, color=(0, 0, 0), pos="center")

shade = ColorClip(moviesize, color=(0, 0, 0))
mask_frame = lambda t: f(t, moviesize, duration)
shade.mask = VideoClip(ismask=True, get_frame=mask_frame)
shade.mask = VideoClip(is_mask=True, get_frame=mask_frame)

cc = CompositeVideoClip([im.set_pos(2 * ["center"]), shade], size=moviesize)

Expand Down
Loading

0 comments on commit 4356fcd

Please sign in to comment.