Skip to content
Advertisement

MoviePy: How to move an image across a video with multiple steps?

I want to move an image in multiple steps, where the background is a video. Currently this is my code:

waterClip = ImageClip("watermark.png").set_position(lambda t: (np.exp(10*t - 10*titleTime) * -1, 75)).

Its a watermark that displays at the top left of the video, which quickly slides away to the left in a smooth fashion.

However, I want it to “pop” out towards the right, before sliding all the way to the left. So I think I would need 2 steps, the first one moving the image towards the right, and the second moving it all the way to the left (which the code above does)

How would I do this?

Thanks!

EDIT:

Here is all my code:

import numpy as np
from moviepy.editor import *
from moviepy.video.fx.all import crop
import random

finalList = []
cum = 10
first = 4
backName = random.choice(os.listdir("backgroundVid/"))
backTemp = VideoFileClip("backgroundVid/" + backName).without_audio() 
# chooses a random video from a folder, all 59s long and 1280x720 60fps

if backTemp.duration >= cum:
    backTemp = backTemp.subclip(0, cum)
elif backTemp.duration < cum:
    backTemp = backTemp.loop(duration = cum)

(w, h) = backTemp.size
if (w == 720) & (h == 1280):
    back = backTemp
else:
    backCropped = crop(backTemp, width= h/(w/h), height=h, x_center=w/2, y_center=h/2)
    back = backCropped.resize((720,1280))
# resizes video to 720x1280 

finalList.append(back)


image = ImageClip('watermark.png', duration=10)
image = image.set_position(lambda t: (np.exp(10*t - 10*first) * -1, 75))
image.fps = 60
finalList.append(image)

videoTemp = CompositeVideoClip(finalList)
videoTemp.write_videofile("TEST_FinalVideoTT" + ".mp4")

And here is what it currently looks like:

Advertisement

Answer

I am not sure that I got it exactly as you indented…

The main concept is dividing the movement to two stages:

  • Moving to the left:

     ((np.exp(10*(t - first))*(-1)
    
  • Moving to the right (most_left_col = -image.size[0]):

     most_left_col - np.exp(10*(t-end_t))*(-1))
    

The lambda may be as follows:

image = image.set_position(lambda t: ((np.exp(10*(t - first))*(-1) if t < end_t else most_left_col - np.exp(10*(t-end_t))*(-1)), 100))

end_t is computed in such way that np.exp(10*(end_t - first))*(-1) = most_left_col.

The result is that end_t = np.log(-most_left_col)/10 + first

That way when the entire watermark is out of the image, it starts moving to the other direction.


Cone sample:

import numpy as np
from moviepy.editor import *

#ffmpeg -y -f lavfi -i color=black:size=720x1280:rate=10:duration=10 -vcodec libx264 original_video.mp4
#ffmpeg -y -f lavfi -i testsrc=size=720x1280:rate=1:duration=1 -frames 1 -update 1 watermark.png

finalList = []
first = 4

backTemp = VideoFileClip("original_video.mp4").without_audio()
(w, h) = backTemp.size

back = backTemp  # The example assumes that backTemp resolution is 720x1280, and duration is 10 seconds
finalList.append(back)

image = ImageClip('watermark.png', duration=10)
most_left_col = -image.size[0]
end_t = np.log(-most_left_col)/10 + first

image = image.set_position(lambda t: ((np.exp(10*(t - first))*(-1) if t < end_t else most_left_col - np.exp(10*(t-end_t))*(-1)), 100))
image.fps = 10  # Set to 10 fps for testing
finalList.append(image)

videoTemp = CompositeVideoClip(finalList)
videoTemp.write_videofile("TEST_FinalVideoTT" + ".mp4")

For testing we may create original_video.mp4 and watermark.png using FFmpeg CLI:

ffmpeg -y -f lavfi -i color=black:size=720x1280:rate=10:duration=10 -vcodec libx264 original_video.mp4
ffmpeg -y -f lavfi -i testsrc=size=720x1280:rate=1:duration=1 -frames 1 -update 1 watermark.png

Sample output:
enter image description here

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement