---
title: '30 Days of Python - Day 15 -  Automated Video Processing with Moviepy -   Python TUTORIAL'
source: 'https://youtube.com/watch?v=m6chqKlhpPo'
video_id: 'm6chqKlhpPo'
date: 2026-06-15
duration_sec: 0
---

# 30 Days of Python - Day 15 -  Automated Video Processing with Moviepy -   Python TUTORIAL

> Source: [30 Days of Python - Day 15 -  Automated Video Processing with Moviepy -   Python TUTORIAL](https://youtube.com/watch?v=m6chqKlhpPo)

## Summary

This tutorial covers automated video processing using the MoviePy library in Python. It demonstrates how to create thumbnails, generate videos from images, create GIFs, mix audio, and overlay text on videos.

### Key Points

- **Setup Requirements** [00:42] — MoviePy requires FFmpeg and ImageMagick. Installation instructions for Mac (Homebrew) and Windows are provided.
- **Creating Thumbnails from Video** [12:12] — Use VideoFileClip to load a video, then iterate over frames using clip.iter_frames() or get_frame() to extract images. Save frames as JPEG using Pillow.
- **Creating Video from Images** [35:48] — Use ImageSequenceClip to create a video from a folder of images. Sort file paths correctly using os.walk and dictionary sorting to maintain order.
- **Creating GIFs** [51:47] — Use subclip to extract a portion of a video, resize if needed, then write_gif(). Specify fps and program (ffmpeg recommended for smaller file size).
- **Mixing Audio** [64:25] — Extract original audio from video clip, load background music as AudioFileClip, adjust volume, combine using CompositeAudioClip, then set audio on video clip.
- **Overlaying Text** [78:40] — Create TextClip with desired text, font size, color, and size. Set duration and fps. Use CompositeVideoClip to overlay text on video. Order matters: base video first, then text.

### Conclusion

MoviePy provides a powerful Python interface for automating video editing tasks. With the basics covered, you can create custom video processing pipelines for thumbnails, GIFs, audio mixing, and text overlays.

## Transcript

Hey there. Welcome to day 15. In this
one, we're going to be processing video,
audio, and images using Python in a
package called Movie Pie.
[Music]
Now, we're going to start off by
creating thumbnails from any given
image, which is actually really useful
because you can automate the process of
creating thumbnails for all of your
videos, which is also really awesome if
you work on, let's say, for instance,
YouTube and you want to, you know, use
one of the screenshots from a video and
you don't want to have to scrub through
the the video itself and do a
screenshot. That's one of many examples
of why you'd want to use Movie Pie. So
before we actually get started, what
we're going to do is we have to set up
our system a little bit more. And the
reason for that is because Movie Pi is
really supercharged with two other
packages. One is called Image Magic and
the other one is called FFmpeg. So to
actually follow along with our guide on
getting this going, you can go to our
GitHub, which of course is
github.com/coding forrepreneurs. go to
the 30 days of Python repo and into day
15 and setup.mmd.
This will show you some of the things
that we're doing and then the
installation requirements ffmpeg and
image magic. Now, if you're on Windows,
you can go to this timestamp right here.
That's going to actually show you how to
do all of it. Install ffmpeg and image
magic. And then we'll actually all come
back and work together. If you're on
Linux, well, you know that Linux has a
lot of different distributions, so we
can't cover installing on every Linux
distribution. So, just check out the
links that we have there. Really, it's
just ffmpeg.org or imagemagic.org. You
can go to both of those places and just
download the process that you need.
Okay, so for us Mac users, we're going
to be using Homebrew. Now, if you don't
have Homebrew installed, go to brew.sh
sh and then copy and paste this command
into your terminal so that you can do
something like this brew. Now, if you
see this, that's a good sign. And what
you're just going to want to do is
upgrade brew. So, just go ahead and do
brew update and maybe even brew upgrade.
So, after that, we're just going to run
brew install ffmpeg
and
image magic with a K at the end. We hit
enter. And of course, this installation
process might take a while depending on
your system. But after you do it, we can
just type out ffmpeg. And now your
entire system can use ffmpeg. We're
going to talk about this more in just a
moment. Uh but now that we have that,
it's really simple. Our movie pie is now
ready to actually use it because once
it's on your system, movie pie can
actually run with it. And now we can
finish the rest of the setup process.
So, if you're skipping the Windows part,
which you probably are if you're on Mac,
go ahead and jump to this timestamp.
To get the most out of Movie Pie on
Windows or really any system, we're
going to want to use FFmpeg and Image
Magic. Now, in this one, I'm going to
show you how to install FFmpeg directly
from that or you can use image magic.
Just go ahead and download its
installation and make sure FFmpeg is
checked. I'll show you to do both
things, but I want to start with
ffmpeg.org
and then going into download, clicking
on the Windows icon and Windows builds.
Notice this is provided by another
service, but it is a reliable one as
ffmpeg.org references it. So, we're
going to go ahead and download this zip
file. Once it downloads, you'll see
something like this in your downloads
folder. I'm going to go ahead and
actually rename this to just ffmpeg.
And I'm going to go ahead and bring this
over into my C drive. So into my C drive
and I'll go ahead and hit continue.
Now that it's in my C drive, I'm going
to go ahead and extract it here. So with
sevenzip, I'm going to hit extract here.
And the reason for this is this is now
where my location for ffmpeg will be. Uh
as you see that this directory has now
been created. And so I can actually
reference this in my environment
variables. So all I need to do is add
this to my systems path for the bin. So
I can actually call the application of
ffmpeg. I could certainly move that
binary right there anywhere I want to on
my system and be able to run it, but
it's probably best to just leave it
inside of this ffmpeg folder. Um, so I'm
actually going to delete this other one
that I have in here. If yours was
renamed this way, like if you still have
this naming convention al together, just
rename it to ffmpeg. It's going to save
us some time in just a moment. So now
what I'm going to do is add this to my
path. I'll hit the start menu and type
out environment
variables. And you're going to want to
edit the system environment variables.
And then we're going to go ahead and
click on environment variables. This
should pop up right here. Click on that
link. And then with that, we will see
this window icon and we're just going to
want to edit our system environment
variables for path right there and then
click on edit.
Okay, so in here you just want to make
sure that you add this right here. So c
ffmpeg/ben
and with that you will be able to
actually use ffmpeg in command prompt
and powershell. Uh so let's go ahead and
verify that by just opening up
powershell and ffmpeg. I should get
something like this. Now the reason of
course I renamed it was so that my
environment variables was really easy to
work with. Right? If I didn't rename it
then I would have to have a longer item
here for the path. once I added it into
those environment variables. Now, that's
the manual way of adding FFmpeg. A
automated way is using image magic. And
of course, we want Image Magic anyway.
So, I'm going to go ahead and go to
imagemagic.org.
Click on download. And then I'm going to
scroll down to the Windows binary
release. And I want to grab the first
one that it has here with the DLL.exe.
You can try some of the other ones, but
this one I found is the easiest one to
work with. So, I hit download on the
HTTP.
And of course, in my case, I actually
already downloaded it. Uh, it's right
here. So, I'll go ahead and double click
and open that. And we're going to run
this. So, uh, naturally, we're going to
accept to the agreement. Hit next. We
can install it in the default location.
That's fine. You can leave it as the
default name or you can change it. It's
up to you. Notice that in here, this is
the option to install FFmpeg. So, we
could have saved like two minutes or
three um installing ffmpeg by just using
image magic. But I wanted to show you
that there is the manual way of doing it
and that is a valid way. So, as it's
installing, I'm actually going to open
up my program files. So, back into my C
drive into program files and I'm going
to look for image magic. I'm assuming
it's already done. It looks like it is.
And I'm not going to view the
index.html.
So going into image magic here, if I
scroll down a little bit, I will see
that binary of FFmpeg. I believe it's
the same size as the one we just
downloaded. So let's go ahead and just
check that out by opening up a file
explorer, going into there into our bin,
and we've got FFmpeg right here.
So there the one that we downloaded
directly from ffmpeg is just a little
bit smaller than the one that's inside
of image magic. Perhaps they add some
additional things to it. Uh but now we
have ffmpeg installed two times. So we
can definitely use ffmpeg on our command
line which also means that movie pi will
be able to use it as well.
Now that we have FFmpeg installed, we
can open up terminal or PowerShell and
actually type out the command and see
all of these different options. Now
FFmpeg is powerful in of itself. You
don't actually need a whole lot of
things beyond it. But customizing it and
actually using it, I would argue is not
that friendly for a new developer, let
alone a Python developer. So we use
Movie Pi to do all sorts of things that
FFmpeg can do out of the box. One of
those things being like changing from an
AVI file to an MP4 file. So video format
changing. That's not that big of a deal
with it. Just FFmpeg or extracting audio
from a video. Also not that big of a
deal. But we're not going to actually
spend a whole lot of time on this. I
just wanted to mention it because it is
a really cool program and if you want to
learn more about it, I recommend that
you do. Okay. So with that out of the
way, let's go ahead and start our
project. I'm going to create a directory
called day 15. Now, in my case, I
actually have already created this
because there's a number of things I
want to do prior to actually getting
here. So, I made a folder called day 15
and I made a pipv, which we'll do in
just a moment as well, but I also
downloaded a couple files here. I
downloaded an audio sample as well as
sample.mpp4.
So, if you want to actually do exactly
what I did, you're going to go back into
that repo and you can scroll towards the
bottom and look at the base project
start. Right? So, we're going to make
these directories here. These are where
we're going to store some of those
files. And then we're going to create
conf.py, which I'll do in a moment. And
then you can download these audio and
video samples. These are things that you
can use if you want. They're not that
big of a deal. It's just more of um we
need an MP3 file and an MP4 file. also a
video file and an audio file that we can
actually work with. In my case, my video
file also has audio. So, we will be
doing that as well. So, now let's go
ahead and actually create our project.
So, again, I already have day 15 as a
folder created. So, I'll cd into day15
and then I'll go ahead and do pipv
install and we'll do python 3.8 and
movie pi. We'll hit enter. And of
course, mine's already installed. I
already have all of that thing, all
those things set up. Uh, but yours might
not. Next, what we want to do is
actually make all of these directories
here, right? So, inside of this project
that I'm working on, I want these
directories so I have somewhere to store
my outputs. That's the main thing. But
then also a uniform way of where our
inputs are coming from. So, if you're
following along with me, I recommend
that you do it in this way. That way you
won't have any issues with the code as
it relates to where things are stored.
Okay, so let's go ahead and go into pipv
shell and the first thing I need to do
is make dur data. I already have it.
Next one is make dur samples. Again I
already have it and then inputs and
outputs.
Okay, next what I want to do is actually
make a file called conf.py. Pi. Now, all
of my other actual modules will be
importing and using at least the sample
inputs and the sample outputs. Uh, so we
want to just go ahead and grab that and
make sure that we have it in our project
as well. So, on day 15, I'm of course
now in VS Code. I'm going to go ahead
and do conf.py
and just paste these things in there.
Now, if you're confused at all on how
these are working, uh, just a quick
recap. First of all, this gives us the
path directly to where conf.py is.
Baster gives us the directory that it
lives in, right? In my case, it's day
15. And then we have paths to the
directories we just created, the data
one, the samples one, and all that.
Then, of course, the audio and sample.
You want to put that into the inputs
directory itself so that you have your
video and audio actually there and ready
to go.
Now, let's actually get to some of the
more interesting parts, and that's
actually coding it. So, in day 15, I'm
going to make a new file here, and I'm
going just going to call this one and
thumbs.py,
as in one thumbnails. And let's make
sure that this is inside of day 15. And
I'm going to go ahead and do from conf
import. Well, the things that I want to
import are sample inputs and sample
outputs. So, sample inputs and sample
outputs.
Now, of course, I want these things
installed so that I have something to
work from, right? So, I want to actually
grab my source file or in my case, I'll
call it source path. And I'll do
ospath.join
and it's going to be sample inputs and
then sample.mpp4.
Now in my case that is how I named the
video file. So of course that is how I
need to reference it right. Okay cool.
So that should give me the video file.
The next thing I need to do is actually
import from movie pie. I'm going to go
ahead and do from movie pie
editor
import
all. So this will import everything. Uh,
this isn't always standard practice, but
I'm actually going off of what they have
in their documentation to make this easy
for us. Now, if you want to be more
explicit, you could say video file clip.
This is actually the class that we'll
end up using, but again, I'm going to go
ahead and use all. Now, what I'm going
to do is initialize a clip. So, the clip
instance or this object that I'm
creating will come from a video file.
Um, so as far as I know, Movie Pie
doesn't work well with webcam. So you
can't actually do what I'm about to do
from webcam footage. It has to be a
stored and saved file. Although I think
there's a lot of different file types
that are that are actually supported. So
MP4 is not just the only one. So we'll
go ahead and say video file
clip. And then we're going to reference
the source that we had, which of course
is our source path. So I can do some
cool stuff with this. And I can actually
print out the clip reader. FPS. FPS
means frames per second.
So what this will give me is the amount
of frames that are shown every single
second. And I can also print out clip
reader
number of frames. So in frames and that
will actually give me the number of
frames that this entire clip has. Of
course, if you divided these numbers
together, you would actually get what
that clip's duration is, but you can
also do clip.duration,
and that should actually give us the
file duration of how long that is.
Anyway, so let's go ahead and open up
the terminal inside of our project here
inside of VS Code. I'm going to close
down the explorer for a moment, and
let's list things out. Let's go ahead
and change into day 15 and pipv shell.
Okay. and then python- i one thumbs.py.
Okay, so what we should see is three
print statements. The first one is the
frames per second. The second one is the
actual number of frames and then finally
the duration of the clip. And that's in
seconds, right? So this is seconds.
So what we want to do is actually turn
each frame into its own image, right?
And there's several different ways on
how we could go about doing this. One
way is to take what the duration of the
clip is and go every second. Like let's
actually do that. So I'll go ahead and
say duration equals to clip.duration.
Another way to call this is also clip
reader.duration.
And we can say for I in range well we
would do zero and then duration + 1. Now
that's to include that last second. And
what I is is this is going to be the
frame at
i seconds.
So whatever frame that is at i seconds,
you would actually be able to see that.
Okay. So let's go ahead and make sure
that that's string substitution is
correct there. So what I can do is I can
say frame equals to clip.get
frame and then the seconds being
whatever i is. Now if you remember back
to when I did the print statement of the
duration you actually need to use an
integer value. So this is 30.17
seconds. So you actually need to use a
30 seconds or 10 seconds, 9 seconds and
so on for this get frame call. So I'm
just going to call int of I. And with
this I can actually save this somewhere.
But before I do that, I'm just going to
go ahead and print out this frame so we
can talk about it. So I'm going to go
ahead and exit out of the the
interactive shell and I'll run that
again. Uh and and it's giving me a float
cannot be interpreted as an integer. So
this is my range here. So let's actually
turn my range and I'll go ahead and say
max duration
because of course ranges or this call
right here has to be a number. And going
back 30.17
is not a number but rather a float. So
we'll just do int of duration + one. So
max duration is going to be whatever
that is. Okay. So um let's actually try
it again without integer of i. So we'll
see if that still gives me an integer or
not. And actually it should it should
actually give me an integer because of
what I just did with max duration
because range will loop through each
iteration. It will be iteration one or
actually iteration zero 1 2 and so on.
Um so let's go ahead and run that again.
So we see something very strange. We see
the frame at a certain number of
seconds, right? So that's that print
statement. Uh but then we see all of
these numbers here. And what this is is
actually what's called a numpy array.
And this is actually giving us the color
values for each individual pixel. And as
you know, an image can have thousands of
pixels. So it's actually giving us all
of that data. Now, this is not
necessarily that useful yet because you
may or may not know machine learning or
computer vision, but if you understand
or study any of those things, they
actually learn from the pixel value of
any given image. Right? So, this is
actually really cool because we can see
sort of the underlying basis for what
will be much more advanced usage of
grabbing images. So in other words, if
you were using machine learning, you
could run what's called inference right
here on this numpy array, which is
sweet. But what we can also do is use a
package called pillow to actually turn
each frame into its own image. So what I
need to do is actually install one more
thing. So, let's go ahead and close out
of that
interactive shell and I'll do pip envo.
This is the Python image library. What
pillow allows me to do really easily is
to take a numpy array and turn it into
an actual image. In other words, take
all of these values that are in this big
array, like think of it as thousands of
numbers and turn that into an actual
image in a very easy way and something
you'll see a lot once you get into
computer vision if you ever do. So,
we're going to do from pill import image
the actual image class. And this we are
going to go ahead and say new img equals
to image
from array.
Okay. So from array we're going to pass
in that frame there. So each frame is a
numpy array useful for inference or to
create new images. So we can just do new
image new img.save and then some sort of
output path. Right? So uh we did create
a directory called sample outputs. So
now what I'm going to do is I'm going to
create another one and I'm going to call
this the thumbnail
dur and we'll say ospath.join.
It's going to be the sample outputs and
thumbnails.
And then we'll do os.makedurs
and this thumbnail dur exist.
Um okay equals to true.
Okay. So now I have a directory as to
where I can store these things. So all I
need to do is say new img
file path equals to ospath jojoin that
new directory that we just created and
then some sort of file name. In my case,
I'm going to keep it as the name of the
number of seconds it is. So in other
words, the actual iteration that it is.
So f and then i. So I need to turn it
into a string of JPEG and then we will
save it to this path in just a moment.
Now the reason I recommend that you do
this as well has to do with sorting
later when we want to actually reuse
these images in the future to actually
sort them and turn them into a logical
video in the correct order. Uh which
we'll talk about that in just a little
bit. So let's go ahead and save this.
And this time I'm not going to print out
the frame itself. when you print it out,
usually print statements actually take
up some some memory and some bandwidth.
So, it actually slows things down quite
a bit. So, with that running, I'll go
ahead and run Python 1 thumbs.py. No
interactive shell this time. And I'll
just go ahead and run it. It's going to
do every single frame at those
individual seconds. Uh perhaps I want to
actually do frame at those seconds and
then also print out the file path as
well. So, I'll just go ahead and add
that in there.
saved at
that file path. So that's going to be
our new print statement. Uh which we
could run it again if we wanted to
actually see what that's going to be. Of
course, in my case, that's that's not a
big surprise as to where it is. But if I
look at my outputs, I can see each image
that's actually coming through, right?
So I've now actually created every
thumbnail per second, right? So every
second I can actually create a new
thumbnail. And now that's cool. So, we
can do it based off of the duration, but
what if I wanted to do it, let's say,
for instance, based off of the actual
number of frames or the frames
themselves, not this range here. So,
what I can do is let's just copy this
exactly and I'm going to paste right
underneath it. I can actually iterate
through all of the frames. So, let's
change the
variable inside of the iterable to
frame. And then this time, I'm just
going to say clip.
frames.
What this allows me to do is actually
circumvent using the get frame here. And
this will actually create for every
single frame. Now remember when we
actually printed out the number of
frames, I got something like 900. But
what I want is well, do I actually want
900 of these frames? Potentially. And I
also want to actually make sure that I
know what frame number I'm on, right?
The iteration of this frame. Now, of
course, I could say something like I
equals to zero and then at the end of
this doing I plus equals to zero or one,
right? So, that actually counts each
time I'm looping through this. Or what I
could do is something even easier called
enumerate. So if I wrap this in
enumerate
a built-in Python function that actually
turns it into
enumerated like iterations right so now
I is that actual same number of
iteration much like we did with this
range here where it's a number this time
it's a number and then whatever the
iterable item is in this case it's a
frame so so this is doing it now every
single frame and it's going to actually
create a brand new image for me. So,
it's no longer based off of se uh
sections or seconds, but rather the
actual number of frames themselves. So,
I'm going to make another directory.
This time, I'm not going to call it
thumbnails dur. I'm just going to call
it thumbnails
dash frame or per frame.
So, thumbnail per frame dur.
and just leave it in as that. So, I'm
going to I'm going to get rid of my
print statements here, uh, just so I can
make it run just a little bit faster.
And I'll run that once again. And now,
if we look inside of that directory, I
might actually need to create the
directory. I think I skipped that part
of make dur. And yes, I did. So, let's
close this out. Let's make that
directory
as well. Let's run it again. And now I
should get both of those directories. It
might take a moment to actually run
through of it. And especially depending
on how long your clip is, uh, it might
take even longer. So this will do every
single frame, right? And I get
it.
Oops, I did enter frames. It should be
iter frames.
Well, little mistake there. Like iterate
the frames, right? iterate iter frames.
Okay. Um, so again, this is going to go
through every single frame. Now, if I
actually wanted this based off of
seconds and frames per second, let's
think about this for a moment. So, if I
grabbed the number of frames and the
number of frames per second, I can say
FPS equals to clip.reader.fps
and then the number of frames. So in
frames equals to that same thing up
here.
Now I can actually say seconds equals to
the number of frames divided by frames
per second. I might want to times it by
1.0 to make sure that it's not rounding
on me. Python 3 doesn't actually do that
very often, but in case you need to,
just make sure you just run something
like that. Therefore, you don't have any
rounding errors. Um, so what I get here
is the number of seconds inside of this
clip. Of course, this is the
mathematical way to find it, even though
you can grab it directly from the clip.
So if I actually wanted to do this it
frames thing for those seconds, I need
to think about, well, what iteration do
I actually want to run this? Well, it's
on every second. So if I want to run it
every second, I need to do it based off
of some value of frames per second,
right? So if it's 10 frames per second,
I need to save a new image every single
10 frames. So to think of this, I can
actually go off of the current
iteration, which is actually like this
is going to be you could call it in or
in frame or frame index, right? There's
all sorts of things you can think of
that as I'm going to leave it in as I.
So what I is going to say is this is
frame zero, this is frame one, this is
frame two and so on. So for me to know
that it's one of those seconds, it's
actually a very similar formula of this
up here. I would say that if I divided
by frames per second
um basically has a leftover a remainder
equals to zero, that means that it's
divisible by frames per second. And that
means that we could make the argument or
the case that it's actually a second
because again frames per second will
count the number of frames that it
happens every second. So another way to
actually write this of course is using
modulo. So if I said I modulo fps
equals equals to zero then I can
actually run this call and this would
actually happen at the current time. So
I could say current seconds now is equal
to the I / FPS,
right? So this will give me whatever
those current seconds are. And if I want
to actually change it into milliseconds,
which might be a good idea, we just
times this by a th00and.
So this is now going to be in here as
current seconds. And again, it's going
to be current milliseconds
or current
ms.
Okay, so this gives me a much different
look at this. Instead of having, you
know, 900 frames or however many frames,
this is actually going to do it on the
in number of frames that I want, right?
Which is pretty cool. So that also means
that if I wanted to change this to let's
say for instance every half second then
this call here is just going to be
slightly different. So let's go ahead
and grab this and paste underneath here.
And up here I'm going to go ahead and
make one more thing. One more directory
frames per
half half second
per half
second dur.
And let's go ahead and make sure we're
making that one. So os make dur and
exist. Okay.
Equals to true
and close this down. Okay. So going back
down to the very bottom one. This is
going to be every half second. Right. So
this this part is going to be a little
bit different. Um I can still enumerate
through the actual number of frames,
right? So either way I want to enumerate
through the number of frames and I can
say frames per I'll call it frames per
half second or FPHs.
Pretty sure that's not an actual acronym
anyone uses. But this is just going to
be the integer of frames per second
divided by 2.0. Right? So we want to
round it up to the nearest integer. So
this means then if I change that to FPS,
this should actually give me the every
frames per second or every half frame
per second. So if it's 30 frames per
second, this is going to be every 15
frames I will be divisible by 15 with
zero remainder, which again was what
that's saying. This can still take the
current time, right? So I divided by FPS
is still giving us whatever that current
time is because again it's iterating
through all of them. But this time now
it's actually every half second. So
that's giving me now every half second
of when this is going to happen. So we
can run this
and again the reason that it's every
half second is we take frames per second
and we divide it by two. That means the
seconds have been cut in half and we now
have 15 frames per half second or if you
know if it's 30 frames per second then
it's 15 per frames per half second and
then we can actually run that iteration
here. Now you could do that every fourth
or or you could do it every other frame.
I mean, there's a lot of different ways
on how you could go about doing this,
but the idea is that now we have a
little bit better understanding,
hopefully a little bit better
understanding of how to do the math on
all of these different things, which I
don't think it's that complicated to do.
So, one of the things that I actually
ran into just now is I have one of my
directories with all of the items. So,
what I'm going to do is I'm actually
going to delete the entire outputs
directory.
Okay. And one one other thing I noticed
really quickly was my current
milliseconds turns into being um a float
number. So I just want to turn it into
an integer by using so that the file
name doesn't have any other periods
other than the JPEG there. And that will
that will solve that problem for me
there. And I also want to do that up
here as well. Okay. So when we actually
delete directories, this make durus will
make the parent directory as well,
right? So it doesn't just make the
directory at the end of it, but all of
them. So I'll go ahead and run this
again
and
we look in our outputs.
We get all of our thumbnails. Um, you
know, it's going to take a moment for
all of them to finish. Uh but once they
do, we now will have all of the
thumbnails or various ways on how to
create thumbnails from this im these
videos. Um and of course this works for
any video. Now uh the speed as to which
it's going to actually create the
thumbnails all depends on a number of
factors. One and the main one is how big
your machine is, how much memory is
being used, how big the video is. Like
those numbers obviously are going to
make a big difference on actually
creating any given thumbnail. So the
next thing is um the least efficient
method that I've done was this one right
here where it's getting the frame each
time. It's actually much better to just
iterate through the frames. This will be
a lot more effective. But that's a
little bit more complicated than just
saying oh through some duration.
Obviously it's going to iterate through
each second because the duration itself
is in seconds. Um so that makes th that
whole process a lot easier. But iter
frames or iter frames will absolutely be
more efficient and thus much faster um
getting all of our data. But now if we
see in our thumbnails per half second um
we've got 0 500 1,000. Again if it's in
milliseconds that gives me these half
seconds. So 500 milliseconds is half of
a second. And that's the reason I
actually made it into milliseconds is to
make sure that we're not putting 0.5
point JPEG, but rather 500 milliseconds.
And the reason I did it in per frame as
well is just to kind of get in the habit
of like, yeah, I want to make sure that
this is done in milliseconds. This is a
a very much or it's a much more robust
way to actually grab what any given time
stamp is because it's a really simple
calculation to then grab what the actual
seconds are. Just knock three zeros off
of it and you get the number of seconds
that are in there or the number of half
seconds. Um, cool. So, that's actually
creating thumbnails. Um, now of course
this is just one piece of the very many
things that Movie Pie can do for us. Um,
but this is a very practical one. Um, so
hopefully this part makes a lot of sense
for you. But stay with us cuz we're
going to do a lot more with Movie Pie.
Now, we're going to go ahead and create
a video from a folder of images. And in
that last one, I created the Python
module one thumbs. I'm actually going to
change it to being the number one
instead of OE.
This just gives me a little bit better
order of how my files are going to come
out. That's it. So, inside of day 15, of
course, I'm going to go ahead and make a
new file in here. And we're going to
call this two. And this is dur to vid as
in directory to video or folder to
video. So, back in one thumbs, I'm going
to go ahead and just copy the first
eight lines into here. Now, the reason I
have these first eight lines, well,
first of all, I probably don't need that
source path anymore,
but I do want these different
directories. And the reason for that is
because I'm probably going to make a
video off of each one, or at least have
the option to do that in the future. So,
let's go ahead and just grab a path or
set a path for our output video. And
this is going to be sample outputs
just like we did here. And then this one
is going to just be the thumbs.mpp4.
Okay. So the nice thing about movie pie
is it will actually infer a lot of
things from the extension that you use
as in the codeex necessary to actually
make that. Um we're not going to worry
about that too much. So just like what
we saw before we had the image or rather
the video file clip.
We can also do another one called image
sequence clip. So, I'm going to go ahead
and say clip equals to image sequence
clip.
And this is also imported from the Movie
Pi editor. So, if you in the last one
didn't use the all import, you would
want to make sure you import that. And
this is now a directory or file paths of
the images that we want. Right? So, if I
actually put in this
thumbnail dur, it might work, but I
actually want to make sure that this
thumbnail directory actually has the
files I need. So, I'll go ahead and just
say this dur equals to whatever that
thumbnail directory is. But really, uh,
we're going to go ahead and say
ospath.list
dur as in list directory. So, all of the
items in there are there. So, I'm going
to go ahead and say the file paths
equals to well, we're going to do an
iteration here. I'll just go ahead and
first off say path for path in this dur.
Uh, but what that actually is going to
give me is not a path, but rather a file
name. But I just wanted to put that just
to make sure that I can add this if
statement if path.sith
JPEG. I just want to make sure that all
of my JPEG images are coming through
here. Because in the case of this
thumbnail directory, there might be
other files in there. And of course, I
want to ignore what those other files
are. And this is actually not a path.
This is a file name. So I'm going to
just change it to fname as in file name
like that. So these are actually file
names. Now to turn it into a path, we
would just do ospath.join
that original thumbnail dur. So
thumbnail dur
and that file name.
Now this is an inline iteration. Another
way to write this I will just show you
is file path equals to this for fname in
this dur then we'll say if fnames
with jpeg
then we'll go ahead and say path equals
to ospath.join join thumbnail dur fname
and then file paths.append
path
uh that is the exact same thing but this
one is just all in one line. Cool. I'm
going to leave that commented out.
That is a little bit of a review but
hopefully it makes sense. But now that
we've got these file paths I can go
ahead and grab this clip just like that.
And I can run something called
clip.right
video
file. Okay, so image sequence clip. No
surprise here. It actually is a sequence
of images and we're just bringing them
all together. And then we're going to
write this file. But I also need to
declare the frames per second here. So
in this case, I'm going to do four
frames per second because again I'm
using only a handful of images. So if I
want this to be a little bit longer,
I'll have the images last a little bit
longer. So each image as a frame will
last a little bit longer. Um, so that
turns it into a frames per second of
being four. And then the writing to the
file will be our output video.
Okay. So now that in our project, I'll
go ahead and run python 2_dur
to vid.py
and hit enter.
And I'm getting we don't have list der.
Oops. That should not be os path but
rather os.lististerlistister.
There we go. And we run it again. And
this time it does a little bit more
processing. And now it's actually
showing us the movie pi thing. And if we
look at our outputs, we should see a
video here.
And if I reveal it in the finder window
or the file explorer, depending on where
you are, uh you should actually see it.
it kind of running in a way that that I
expected. Okay. So, um that is using
every second, right? And and it's every
second as a frames per second. So, if I
wanted to change it to where it was
literally every second, I would just
change frames per second to being one.
And what this would do is actually turn
this into a 30- secondond video. It
doesn't actually have all of the frames,
but it is the same duration of a video
as the original one. So, it it's really
it's going to be a lot more choppy than
the original one. So, that's kind of
cool. But, we actually have a problem
with how this is. And that's our file
paths. So, I'm not going to actually
write this clip just yet. I'll go ahead
and print out the file paths themselves.
And I will also run the interactive
shell here with dash I. Hit enter. Close
this down a little bit. Open this up.
And what I see is some sort of strange
ordering going on here. Right. The very
first item is 8.jpeg. The next one is
nine. And actually upon further
inspection, you might see some issues
with the video itself, like the ordering
of the video, like this is out of order,
uh, which you could verify by actually
looking at the video. Um, so yeah, this
is nice. This is super convenient of a
method to actually be able to just, you
know, get a list of file paths and then
output them to a video. Uh, so that's
definitely the easy way, but this is
incorrect. This is not actually how we
want to go about doing this. So I'll
leave this method in here in case you
want to create a video from these file
paths in this way. But what I want to do
is actually take a little bit of a
harder step and that is actually better
understanding how to go through an
entire directory using a method called
walk. Um so the first thing I want to do
is create a dictionary and I'm going to
call this dictionary directory as in the
directory itself. So directory and it's
equal to an empty dictionary. And then
we're going to do for root dur files n
os or rather not files in files but
rather files n os.walk
and then the directory that I want to go
through. In this case I'm going to do
thumbnails per frame.
Okay. So this will actually walk through
that directory, every file that's in
there, including child files. So if you
have other directories in there, it's
going to definitely go through all of
those. So to get the file path, we need
to actually go through each file. It's
really simple. We just do for the I'll
say underscore file in files. The reason
I'm using underscore file or well, let's
just use fname in files. The file path
is ospath.join. join and there's going
to be root and fname.
Okay, so this will give us the file path
that I'm looking for for every single
file. We could print all that out to see
exactly what it is that I mean by that.
Um, but what I want to do is actually
grab and create key value pairs for
every single file. So that means that
I'm going to go ahead and come in here
and say try key equals to the float of
name.replace
and it's going to replace JPEG because I
know it's a JPEG image with an empty
string. And then it's going to try and
grab from the fname. It's going to try
and look for a float item in there.
Otherwise, it'll run an error. Like if
there isn't an actual float in there,
it'll run an exception. And that in that
case, we'll just say key equals to none.
And then we'll do if key is not equal to
none, then I'll go into my dictionary
value that I set up here for the key.
And we'll set that equal to the file
path or the actual value that we're
going to be using. So this now gives me
a directory full of key value pairs that
are coming from the name of the file
itself. So the name of the file will
have a number or um you know a big
number. It doesn't really matter. It's
going to turn that into a float and then
that's going to be my new key value pair
for this d uh directory this directory
dictionary that is. Okay. Um, so now
that I've got that, what I can do is I
can say for K in sorted
directory
keys
and then I can actually print out what K
is. Okay, so let's go ahead and try
this. I'm going to open up the terminal
here. Let's clear out what we've got. So
I'll exit out of this and run the
interactive shell again. And what I see
is all of these numbers, right? So I've
got 0.0 zero and so on all the way down
to 3,00. So, they're actually in order.
And that's actually why I did this is to
to add the name of the file to the
directory and turn it into the file
path. Now, you actually don't have to
convert it into a float. That's not 100%
necessary. You could just remove the
file extension and use that as the key
and then sort it as well. So this will
also sort ABC or or like character
values as well if if you need to. Uh but
with this what I'm going to do is I'm
basically going to grab whatever the
file path is at this key value pair and
say new paths equals to this empty
like list here. And so I'll go ahead and
grab the directory at whatever that key
value is.
And then that's going to be my new file
path. So I'll say file path equals to
that. So new paths.append
file path.
And I don't need to print out that print
statement anymore. And I can scroll back
up to my clip or that original clip and
actually output this based off of my new
paths now.
Okay. So, that's another image sequence
clip. It's now in a different order. Uh,
so if I exit this out, uh, I'm still
doing frames per second. Let's just
change that to, I don't know, 10. Going
to be a much shorter video. Um, so this
should now be in an order that makes
sense based off of how I named those
files. Uh, and then let's go ahead and
open up the finder
for this one. And this looks a lot
closer to the order that I actually had
in that video. It should be actually
pretty accurate to that order. Uh but
there's actually one more thing that I
can do is I can actually turn each
individual file path into a frame
itself. So I want to use something
called image clip. Not just image
sequence clip, but image clip. Uh it's
another class that's imported by the
editor by default. So now what I can do
is say
after I have these new paths I can say
my clips equals to just an empty list
here. And now I can say for path in the
list of
these new paths
which it is a list but I'm going to
change that in just a moment. Um, now
I'm going to go ahead and say clip or
rather frame equals to image clip of
that path. And let's go ahead and just
print out what that frame is and what it
looks like. So we'll exit out of here
and run that again. And we're getting an
object here. It's an image clip object.
Uh, if you printed out the
dur. So doing the dur gives you all of
the methods available on there. uh sub
clip is one of them that's really useful
for images which we'll cover in a little
while. Uh but what we want to find is
the img. So we actually want to append
my clips.append
frame img.
And after we do that we will then make
our image sequence clip. Actually, let's
make sure we keep this in as a backup or
for reference that is. We'll put my
clips in here now. And our frames per
second, I'll just do 22. We'll exit out
of here. And then we'll run that again.
And of course, if you wanted to actually
see what the frame img looked like,
I'm going to guess that you might have
some intuition as to what that will look
like. And if you didn't, that's okay.
but it's a it's a numpy array just like
what we talked about before. So that's
actually how you would get the numpy
array from a specific image itself. So
if you wanted to open up any given image
and turn it into a numpy array, that's
one way to do it with actual movie pie.
Uh but now that we've done this, I'm
going to go ahead and take a look at my
new outputed clip.
And this one's going to go really fast
cuz it's only it's 22 frames per second
and there's not that many frames. Um, so
that's the the more challenging way to
do it. Um, now of course you could use
your new paths this order and just stop
here. Just like reorder them in some
sort of way. There are more advanced
methods of reordering this stuff. So
like based off of the date and time that
is created and and stuff like that.
Those things I'm just not going to get
into here. But the purpose of this was
to see that there's multiple ways to
take a directory and turn it into a
video. So now that we understand how to
go from video to images and images back
to video, now let's go ahead and take a
look at how to turn a video into a
subclip and then a GIF.
All right. So, let's go ahead and create
a new file in our project here. And
we'll call this three create gif.py.
And we're going to do a lot of the same
imports we did already.
We might not need pill, but I'll leave
it in there just in case. And I'm also
going to do another import that we'll
come up with in a moment, which is from
movie pie.fx.all
import crop. Now, the actual location of
this might change, but the idea is that
we want to crop our video clip at some
point as well. And I want to go back to
the first one to grab the source video
itself.
So, coming back into three.
Okay. So, we've got our source file
here. And as you remember, just creating
a clip is as simple as doing clip equals
to video file clip and the path that we
have it. In our case, it's the source
path.
And it's really simple. We can set our
frames per second. And I'll just set the
frames per second to the exact clips
frames per second. So clip reader.fps.
And then we can get a subclip of this.
Now a subclip is just a portion of the
clip. Now, I would check the MoviePie
docs if you want more details on this.
But the general idea is that I can say
clip equals to clip subclip
and then the time that I want. So, if I
wanted between, you know, 10 and 20
seconds, so this is a 10-second long
clip, you would just write that. But
yes, there are more advanced options for
this. Now, when you actually call
subclip, it returns back another clip.
So I'm just going to call this sub clip.
And then that itself is a video file
clip itself from the original one. And
so I can just call subclip.right
GIF. And then we want to actually have a
output path. So let's go ahead and copy
our source path and call this output
path
one. And I'll call this sample.gif. GIF
sample one.gif and we'll put this in
our sample outputs. And we might as well
actually make a gif dur. So I'll say gif
dur equals to ospath jojoin sample
outputs and gif and os.maked
gifter and exist.
Okay.
Okay. So now I'll actually put it into
my GIFs directory. Let's call it GIFs
instead of just GIF. Okay. So my first
output is like this. Now notice I only
took a small clip of it. I didn't
actually change the size of it. So I
will change the size of it to speed up
the time it takes to actually make this
GIF. So we can say subclip equals to and
this is going to now be subclip.resize.
and it's going to take a dynamic width.
So, we'll just say width equals to 320.
So, this will automatically resize it
without breaking the
scale of the actual clip itself, which
we'll see in just a moment. And you
could designate something like height
equals to 320 as well, um, which we'll
also take a look at as in just a second.
But the idea here is whenever you run a
method like this or like this, it
actually returns back the original
instance. So running subclip like this
will actually allow me to resize it. But
if you forget and you run something like
this and you're wondering, hey, why
isn't it being resized? Well, that's
because you need the result from this.
So by setting sub clip equaling to this
result, it just sort of resets this
variable. um all the way through. Okay,
cool. So, now that we've got that, let's
go ahead and try this out. Of course,
I'm inside of day 15. So, python-
i3_create_gif.py.
Hit enter. And notice it's saying it's
using image io. Now, this actually takes
a good amount of time considering that
it's just a gif image. So, you can
actually do one more thing on this.
Write gif. You can set a couple options.
One of them being frames per second. So,
I can use it based off of the original
clip, which is what its default is, or I
can set my own frames per second. You
know, if I want it more choppy, I could
set it slower. If I want it to be
faster, also, well, either way, if it's
not the same frames per second, it's
going to be choppy feeling. Uh, and then
I can also declare the program I want to
use. So, in my case, I actually want to
use ffmpeg.
Um, but it used image io as a default.
So, we can take a look at sample
one.gif. And there it is. So, it has
that width that I set, but this is
actually the GIF image. And it will loop
over and over and over again. That's
what gifs do by by default. Uh, so this
is pretty cool. So, this is a nice way
if you had a like a tutorial of some
kind for a product and you just wanted
to have gifts of them, this would be a
way to do it. Um, but let's actually use
the program ffmpeg and run this again.
So, I'll exit out of here. And this time
I won't use the interactive shell. I'll
just call it and we'll run it again. So,
now it's using ffmpeg. Um, it's going to
be a little bit faster, but it also
might make a much smaller GIF file.
FFmpeg seems to be a little bit more
efficient at creating GIF files
themselves. Um, but you get sometimes
you'll get this like weird blurriness to
it. So gifts aren't a perfect, you know,
a perfect thing that happen. They don't
always work great. Um, but you can also
instead of resizing it, you can just
leave it as the original size. Um, so
that's another thing to consider. Now,
if you're getting a lot of very
pixelated items, uh, one of the options
would be to resize a clip, save it as a
video, and then reload it as a new clip
from that video and that new size. and
then run this as well. So, that is
another option that I've had some pretty
good results with, too. Okay, so this
one crashed. It actually crashed that
window, which is pretty funny. Uh, but
the reason it crashed it is probably
because of the size of the GIF itself.
So, if I look inside of the directory
here, I see the GIF is 175 megabytes at
the original size of the video. Um, so
when I run it now, it's not nearly as
pixelated as it was. Um, but it's still
a ginormous file. Uh, so that is
something to think about, too. Okay, so
back into 30 days. I'll go back to
create GIF. And there we go. So I do
want to use that resized version. And
perhaps you'll use it maybe not that
quite that small. uh you can use 500 as
a width, but it's really up to you on
how you go about doing that. Okay, so
the next thing is actually creating a
cropped clip. Okay, so I'm going to be
going off of this original clip still.
So it's still that same clip. And I'm
going to go ahead and grab the width and
the height of this by doing clip. size.
And then I already have the frames per
second declared, which is this right
here. And now I'm going to go ahead and
grab a clip of it. A new clip or let's
call it a subclip
2. That's clip.ub.
And again, I'll do the between 10 and 20
seconds. And now I'm actually going to
go ahead and crop this clip using that
function that I brought in. So to crop
this, it's really simple. We'll just
call it cropped
clip. That's going to be equal to
calling that function itself and then
calling subclip on it and then the
width. So this is going to crop it on
how we want. So I'm going to go ahead
and say 320 and the height being 320 and
then the x center being the width
divided by two and then the y center
being the height divided by two.
So this is basically saying, hey, how do
we center this image out itself? So this
is going to take the exact center of the
original clip. It's going to go right in
the middle of that, which is what this
divided by two is. The Y center is going
to take right in the middle of of that
one as well. So even if it's widescreen
or it's not already a square, this will
actually turn it into a square. So you
can think of this as a square clip
or square cropped clip, right? And now
we can do square cropped clip right GIF.
And this time I'm going to go ahead and
give a new output path. And we'll give
this two sample two.
So right GIF and
output path frames per second. This time
I'm going to go ahead and use the
original frames per second. And then the
program again being ffmpeg.
We save that. The other one, the other
GIF that I create, I'm going to go ahead
and just comment that one out. Let's
open the terminal back up. And I
probably need to reactivate
my virtual environment. So, pipv shell.
And then I'll go ahead and run python
3 create.py.
We hit enter. And it's just hanging. So,
C to cancel it out. Uh, if I scroll
down, I actually did a spelling error on
ffmpeg. That must have been the issue
before as well. So, let's go ahead and
run this. Now, it's actually running.
Okay, cool. Um, so let's go ahead and
take a look at our results. So, in the
finder window, sample 2.gif,
um, it is a square image now, and it's
off of the time that I designated
before, which of course we could compare
that to that other sample. uh to to just
see what that is. And that sample is
still way too large. So I'm going to go
ahead and use the resized version.
And I'm also going to use the other
frames per second.
Try that again with sample one.
And this one, of course, still takes a
while because I made it still fairly
large image. Um so let's see what's
going on with this one.
There we go. Um, so it should be 500
pixels wide,
which we can verify inside of the
Finder. It shows me that it's 500 pixels
wide. And this is giving me, you know,
exactly the same thing that's going on
here. It's just it's cropped in a
different way. Okay, so that's how you
make gifts. Now, how useful is this in
particular? It's hard to say. I think
that if you have a crop size that you're
actually looking for, um, it's probably
going to be a lot easier of actually
cropping a part of a video and then
saving that in particular. All right, so
I don't know how often you're going to
be making gifts necessarily, but the
nice thing to know is that Movie Pie has
the ability to write gifts on any clip.
So you just have to write underscore gif
just like that on any given video clip
and it will create a GIF for you. And I
would recommend that you use ffmpeg
because the size of the gif is going to
be a lot smaller. Um so that's pretty
cool. And then the other part of this is
that if you remember creating a video
file is just write underscore video file
on any given video clip as well or an
image sequence clip. In fact, you can
try out write GIF on a whole variety of
different places if you need to. Uh, so
I'm going to leave these write
statements out and I'll let you use it
uh how you see fit. Uh, but that's
writing gifts.
So now what we're going to do is add a
background soundtrack to our video that
just has spoken narration basically. So,
what we want to do is verify that our
inputs have audio and sample. Now, if
your video doesn't actually have audio
yet, a lot of the methods here will
still work. You just skip a step, which
I'll show you in just a moment. But,
let's go ahead and start off by creating
a new file inside of day 15. And this is
going to be four. And I'll call it mix
audio.py.
And I'm going to go ahead and go to
thumbs.py Pi and just grab some of the
defaults there. Going to grab the sample
related items here. And then I'm also
going to grab the output dur or at least
some of the base of it. And this one I'm
going to call this mix audio dur. And
I'll call this mixed
audio and ospath dot or rather os.maked
and mix audio dur exists.
Okay, being true. Okay, cool.
So, like we've seen before, we're going
to go ahead and grab our original clip.
So, the clip itself, of course, is video
file clip, and it's going to be the
source path. I want to go ahead and grab
the original audio here. So, original
audio,
and that's going to be clip.audio.
And this original audio I'm going to go
ahead and write an audio file.
And this of course I need to actually
set to a a path of its own. Uh and that
path is going to be similar to this mix
audio dur but it's actually going to use
that one. So I'll go ahead and say og
audio path equals ospath.join
and this mixed audio directory with
og.mpp3. MP3.
Okay. Uh, and this I'm going to just go
ahead and write that audio file out. So,
I'm going to go ahead and run this. Now,
let's just make sure that I can actually
run it and I can get the correct audio
coming out. So, mix audio.py
and I hit enter. It's makes og.mpp3.
So, in outputs, we got mix audio here.
Ogmpp3. Let's go ahead and reveal this
in our Finder or of course if you're on
Windows, it would be in your file f
explorer. And in this case, I actually
have it working. I don't know if you
could hear it or not, but um I have that
audio working. I definitely just
verified that that is the original audio
clip. Now, the reason I did it this way
has to do with just the finicky nature
of Movie Pie. um and what we're trying
to do here, which is mixing two
different audio clips into one and then
bringing it right back to that original
video clip. Um so that was that was
something that we have to consider with
that. Okay, so we have our source video
path. Now I'm going to add my source
audio path which I believe I just called
and here we called it audio.mpp3.
So this is going to be audio.mpp3.
Okay. And you could open that up and
hear what it sounds like. And it's
essentially just some free music that we
can use. Um, so what I want to do then
is grab that as a clip itself. So we're
going to go ahead and say background
audio
clip equals to audio
file clip and then our audio source
path.
So audio file clip is automatically
imported with this as well. So I can
actually use that one which is nice. And
now what I actually want to have is a
subclip of this. Right? So I want it to
be the same length that this video is.
So I'm going to go ahead and just call
this BG music equals to this background
audio clip. And we'll say subclip.
And I'm going to go zero and
clip.duration.
See, I've been using clip a lot here.
So, why don't I call this the actual
video clip so I don't actually get too
confused as to what's going on here with
the various clips and sub clips and all
that. So, now I've got my original video
clip. It creates an audio path for me.
And then I have a new audio file, the
sample, and then we just get a clip of
that or a sub clip of that. Now, it's I
think it's safe to assume that the video
file clip, our source video file, its
audio clip is going to be the same
length as our original video clip. So, I
don't actually have to subclip that one
either. But, of course, you could if you
wanted to clip out pieces of it. Um, so
now that we've got this, what I want to
do is actually change the volume of this
background music. Now you can inspect it
on your own, but the idea is that that
actual audio is kind of loud. Now maybe
you hear this or not, but it is kind of
loud in comparison to the source audio
or the original audio uh that is coming
through. So I want to change that
volume. Now there's a few different ways
on how to go about doing this. One of
them is just doing it directly here. So
I'll say bgusic equals to bgmusic.
volume
x and then whatever I want to times the
original volume or whatever the actual
volume of that source is times whatever
this value is. So if it's at 100 then
this would be 10% of that. Right? So
this is 10% of that original volume. And
that actually might be still kind of
loud. It really just depends on on the
volume itself. So, one method to inspect
this is you can actually write this as
an audio file, too. I'm not going to do
that. I'm not going to verify it here.
Uh, but you totally could and
potentially should to verify that the
volume is actually changing. Of course,
there's another method we can use to
actually change the volume. So, the
method that we would use is from movie
pi.audio.fx.all
all going to import the
volume
x method and then instead of calling it
like this we can use another method
which is FX and then passing volume in
here or volume X rather in here and that
will do the exact same thing or at least
it should do the same thing. So try
either one of those methods to see how
the volume is. Now, keep in mind if you
have both of these going, it's going to
change the volume here and then it's
going to change it again right there,
which, you know, may or may not be what
you want. Okay, so now we have two
different audio clips and then our
original video clip. So, what I want to
do is actually combine those two audio
clips into being my final audio. And
this is called a composite
audio clip. Now, it's a composite audio
clip because it's actually stacking them
on top of each other. There's another
one called a concatenated audio or
concatenated video where it brings them
together like from end to end. Composite
layers them on top of one another in the
order that you specify. So, if I list
put a pass a list through here, I'm
going to pass the original audio and
then the BG music, right? So again, that
original audio is from this file here.
So we may or may not want to reload the
original audio in here. Or we may or may
want to use like the original audio
file, actually grab that audio file and
reload it in as a clip itself to do this
actual final audio clip. That is a
method that you might consider trying
because again, this movie pie is really
good, but there's some little bugs that
sometimes just don't work. And I found
that audio is one of those things that
has that potential issue. So with this,
I'm going to go ahead and actually
create a final audio output. So the OG
audio path, I'm going to put the final
audio path. And I'll call this final-
audio.mpp3.
This final audio I will write out. So
final audio
write audio file just like that. And yet
another thing that we could verify here
that the original audio and the
background music are now combined prior
to ever even adding it it to a video. Um
so now that we've got that, all we need
to do is actually set the new audio to
our video. Okay. Okay, so we can take
the original video clip from up here and
we can set audio or change the audio
based off of this final audio. So it's
real simple. We say final
clip equals to and this is going to be
video clip set audio
and in this case I did the final audio
itself and then we're going to go ahead
and say final clip.right
write
video file. And now we need an output
video file. So I'm going to right next
to the final audio path, I'm going to
call this the final video path
and final video
mp4.
Going down to final video. And there we
go.
Okay. So now I'm going to go ahead and
leave it like this. and we're going to
run it. I think that there might be an
error, but let's go ahead and try it
out. We'll do Python 4_mix_audio.py.
We hit enter. Okay, so it's going to
output a number of files. Oh, and I get
a my first error. Composite audio clip
has no attribute frames per second. So
the frames per second in this case is
going to be related to the original
audio. So this write audio file um or or
rather the actual time that we export
it. We want to do FPS equals to well we
want to get the original audio. Whatever
that speed is, that's what we're going
to want to use. So original audio.fps.
Not the same as frame per second for a
video. Uh but that's what we need to
pass. Just like that. Let's try that
again.
Okay, it seems to be out outputting all
of my audio. Now, let's go into my
outputs, mixed audio. So, I should see
final audio here.
And I actually can tell that the
background music that I created is now
working with that new background music.
Uh, so the original files here, just the
audio, which is kind of cool to see,
too. We can parse out the audio from
original file just like that. Uh, and it
looks like my video is ready. So, let's
go ahead and try it.
And
I don't have any audio.
Okay. So, this actually didn't write the
file correctly. So, I could potentially
have the correct audio, but I think it's
because of my encoding. Actually, I know
that. So, I'll go ahead and say codec
equals to libx264.
Now, this should be something that
FFmpeg has for you. Uh, if it doesn't,
you might have to install these
additionally. And of course, let me know
if that is your case because again using
audio and video is not all does not
always play that well together. Then the
audio codec is going to be AAC.
So this should actually solve the MP4
video file. It might not, but let's go
ahead and try it out. Of course, it's
going to make all of those files all
over again. Um, which you didn't
necessarily have to do here. But if you
run into any errors with these codecs,
then obviously this part would have
stopped and stopped you in the tracks.
And please let me know in the comments
because I definitely want to help you
solve this problem. And hopefully other
people can chime in as well if you know
the answer to that. Uh because these
codec things, it's just it's just
another nightmare to worry about. Okay,
so now that I changed the codecs on the
output,
it's all working. So the audio and video
in my case is definitely working. Um, so
a couple things to try if you do run
into errors. One of them being that we
take this final audio
and do a new audio set. So I'll say new
audio equals to the audio
file clip and then actually grabbing in
what that final audio path is. And then
your final clip instead of being based
off of the instance that we created
there, but rather being based off of a
newly loaded in audio. That is one thing
that you could try for this. Of course,
there's different codecs if you need.
Um, but more than likely, if this
worked, then this should as well with
the correct codec. And it's all going to
be dependent on what video file you end
up using. So MP4 needs these two codecs.
So, we should be good for you for you to
be able to do this on your machine as
well as long as you have FFmpeg
installed. So, that's mixing audio. Um,
I realize that it's
probably just a lot of like writing
things and not fully understanding
exactly what's going on, but just keep
in mind that the composite audio clip,
that's the thing that brought it
together. Everything else was stuff that
we pretty much already covered to some
degree, except instead of using video,
now we're using audio.
Now, what we're going to do is overlay
text on our video. We're even going to
make a little text intro with some music
and then add it to our original input
file and see what the result is. Now,
you could use a lot of these methods to
also put an image somewhere in there
where it's overlaid of an image, but uh
we're just going to cover the text
portion of this. If you need the image
part, just check the docs for that cuz I
think once you know how to do the text,
it's really easy to do the image. Okay,
so let's go ahead and make a new file
here. And I'm going to call this five
overlay
text
pie.
So, in mix audio, I'm actually going to
copy a lot of these original things all
the way down to the background audio
clip.
Okay.
So, let's close this down. So, the
background audio clip, um, I actually am
not going to leave it that duration. Any
like the BG music is not actually going
to be that duration anymore. I'll change
it to something different. And then this
final video will be the overlay.
video and perhaps the overlay audio. I'm
not actually poss sure if we'll have the
entire final audio video clip in there
if we need. All right, first things
first. Let's go ahead and actually
create a text video and that's it.
Nothing else, just a text video. And I'm
going to go ahead and say duration or
rather intro
duration and we'll say 5 seconds. So go
intro text and this is going to be equal
to a text clip. Now the text clip itself
is going to be imported from movie pie
editor. Make sure you import that if you
need it. So text clip and I'll just go
ahead and say hello world exclamation
mark. We'll add a font size. That's one
word. We'll say go ahead and say 70.
We'll add a color of white.
And then the actual size of it. I'll go
ahead and say clip size. Now, this is
not the size of the text itself, but
rather like the box that the text lives
in. Okay? So, just keep that in mind.
So, what this is going to do is going to
make it right in the center. Now, for
some reason, if you wanted to change the
size of the clip, you totally could.
Just remember that the height and width
of the original clip is just clip
size.
And I'm using clip. I meant to say video
clip size. Okay. So, this is like as if
we were drawing a box. The size the same
size of this video clip. And now we're
just going to have just a little bit of
text in it and it's only going to show
the text. It's not going to show
anything else. Well, by default, the
background will be black. So, we don't
have to really change anything other
than the color of the text to make sure
that it can be seen. Okay. So now that
we've got that, let's go ahead and set
this duration. So we'll do intro_ext
set duration. In this case, I can just
say the intro duration here. I can set
the duration like the number of seconds
that I actually want to use. And like
any other method in movie pie, it
actually returns back the instance that
we need. So we grab that. And then we
can also set the frames per second. It's
actually a good idea to set the frames
per second to the frames per second we
want to use on our final video, which in
this case is just going to be our video
clip. So, I'll go ahead and set that
right here. Okay.
So, set frames per second. And then
finally, we're going to go ahead and set
the position for it. And this is going
to be the position not for the text
exactly, but rather for the entire frame
that's being put on top of the video
itself. And we want to say this is in
the center. Uh we'll see what I mean by
this when we actually make a little
watermark in the right hand corner or
like a text watermark in the right hand
corner a little bit later. Okay. So now
that we've got that, let's go ahead and
do intro text.
Video file. and it's going to go out to
our we'll just use it our final video
path so we can see what this looks like.
Okay, so open up the terminal here and
Python 5 overlay_ext.py
and creating a video or it actually
created the original audio which we
probably don't need to outport or output
any longer uh at this point. We could
probably use the one that's already
outputed, but in case you changed your
video or something like that, just just
get in the habit of output outputting it
when you need to. Okay, so now let's go
ahead and take a look at this this video
itself. I'm going to open up my finder.
Here's my overlay video.
And if I open it up, there it is. So
cool. And uh it's only 5 seconds long,
like I said, with that duration. It does
the frames per second, like I said. Uh
so that's uh that's nice. We have text
now. Um, so what I want to do is
actually combine this with my original
video file. And there's a method that we
imported by default with this call right
here called concatenate video clips. So
what we want to say is our final clip is
equal to concatenate
video clips and then the items that I
want to concatenate. I first want to
start with the intro text and then I
want to start with the video clip, the
original one. So, this is going to add
them to each other. First, the intro
text and then the video clip. So, the
order that you put the list of items in
there, it just extends the video that
much longer essentially. So, I could put
these back and and forth, back to each
other, back and forth, back and forth.
uh that is a way to concatenate them
versus the actual composite video clip
which we still will do where it stacks
them. This won't stack them. Okay, so
now we've got this final video clip.
Let's actually go ahead and create it
and we're going to write it out and
we'll just take a look at what the
result is. Um so again, I'll run the
Python overlay text
and we'll take a look in the finder.
might take a moment for that to finish.
So, I actually anticipate that this is
going to have the same issue that we had
with the audio mixing the audio. So,
whenever you want to export your video,
just make sure you're using the right
encoding or codeex for both the video
and the audio. Uh, so in this case, I
I'm going to reset it. I mean, I might
still have that audio, but I'm going to
have to do some stuff to it in a moment.
Uh, and so now what we have I do not
have audio. It's not showing up, but I
do have a much longer clip. It's longer
by 5 seconds. That's because I have that
intro. So, concatenate video clips
works. And so, now I'm going to have
that go. And I'll run it again.
But what I want to do is actually add
some audio to this intro text, right?
And that audio I want to use is that
background music, that sub clip there.
So, I'm actually going to come down here
and underneath this intro text, I'm
going to call this intro music now. And
it's going to still take that background
audio clip. This time, it's going to go
to the duration of the intro duration.
So, I can make sure I put that there.
And so, I want to actually set the
actual intro
as this music, right? So to do this, I'm
going to go ahead and say intro text
equals to intro text set audio. And now
I've got my intro text music. Okay, so
let's save it. I'm going to verify that
the audio came through this time.
And sure enough, it did. So I'm going to
run it again. Now I'll have audio on my
intro. While that's exporting, we want
to think about the next portion of this,
which is adding text over my video clip
video. Video clip video. Yes. Um, okay.
So, this now is going to be, let's call
it our watermark
text. And this is going to be again a
text clip. In this case, I'll just go
ahead and write CF. The font size, I'll
go ahead and just say 30. color being
white again just as my overlay. This
time I'm gonna say something like align
equals to east and the size well now the
size is going to be w as in the width of
the original video
and then the height that I designate.
I'm going to give it the same height as
my font size. Okay. So now I have the
watermark text that I want. There's
still a few more things I need to set.
So watermark text set frames per second
being the original clip. So video clip
or I think I already designated the FPS
right here.
Okay. And then the duration. So the
duration being set duration. And this
duration should probably be the same as
the video clip.
You could also use videoclipip.duration.
Both of those should work just fine. And
then now what I want to do is actually
set the position somewhere different. So
I'm going to go ahead and say watermark
text equals to watermark text set
position. And this time I'm gonna pass
in a tpple for bottom.
Okay.
So this means that it's going to go to
the bottom of the page. Top and center
are other options. Um but right now I've
got this aligned to the east versus the
west. I don't know why it's not left and
right, but it's east and west. So we're
going to align it to the east, which
should be on the right hand side. And
then we're setting it equal to this
size. So, it's going to be the full
width of the entire, you know, clip, the
video clip itself, the original video
clip, but then the height is not going
to be nearly as high. And hopefully what
this does is bring it right down to the
bottom. Okay. So, now that we've got
this text, let's actually just verify
the output of our last part, which
should give us audio to the beginning.
And sure enough, it does. And it's only
for 5 seconds, hopefully. And there it
is. Okay, great. So, that part's
working. So, back in here, we're going
to go ahead and now make a composite
video clip. So, the composite video clip
stacks the the videos in the way that I
want them to. Right? So, I want the
intro text on top of the actual video
itself. Right? So, I'm going to make a
composite video clip from the original
and the watermark text. Okay? So, let's
go ahead and do this. And I'll say
CVC as in composite video clip equals to
composite video clip. And we're going to
pass in the watermark text. And then our
video clip.
And I'm going to set the size on here to
our video clip size. The original size
for this one. The duration is going to
be the same as the video clip as we
might expect. Set duration. So video uh
video clip duration
video clip reader dot duration
and CVC
equals to CVC set frames per second
being yes. Okay. So now I've got my new
clip here. The problem with this clip is
it doesn't actually have audio. Right?
So, this is where you also might run
into another issue. So, what I'm going
to say here is I'll say CVC equals to
CVC's set audio being none.
Okay. So, now I've got no audio here.
But let's go ahead and use this instead
of our final video clip. I'll use this
composite video clip. And let's take a
look at what happens here.
Back in the terminal, I'll press up and
run it.
And I used the wrong variable somewhere
in here. I used CVS right there or CSV
rather. So used to writing CSV. Okay. So
now with it running, I'll just give that
a minute to finish.
Okay, with that finished, I hear music
here.
And then I don't hear music and I
actually don't see my composite video.
Okay, so obviously I set audio to being
none. So that makes sense. The problem
here is that my watermark text didn't
actually hold up. So this is one of
those challenges that comes up from time
to time. So, we're going to go ahead and
get rid of my original video clip and
create a composite video clip from this
text and add another one. And we'll call
this the overlay clip. And we're going
to make another composite video clip.
And this time, I'm going to take my
original video. And then I'm going to
add in my composite video clip. And
again, size being equal to my video clip
size. And then my overlay clip, I will
add in a lot of these same things. So,
let's go ahead and just copy them.
Okay. And change all of the CBC's to
overlay clip.
And then after that, what I want is to
actually change the audio again. And
I'll say set audio.
This time I'm going to use the audio
file clip. And I want to grab the
original music that I had or the
original audio that I had, which was the
OG source path or the OG audio path. So
we bring that down here. Let's go ahead
and make this a little bit wider so we
can see it.
Okay. So, I can just OG audio
like that. So, now we've got our overlay
clip here
and
let's bring that in. Okay. So, we save
it and let's run it again.
So, it's not quite done yet, but one of
the things that is important here is
actually the ordering of the composite
video clip. If you put your top level
thing first, as in my text, if I put
that before the main video, it's
actually going to be gone. Like, we're
not going to see it. So, the ordering of
this actually matters. The watermark
text should be last because it's putting
the first thing inside of this composite
clip at the bottom. Um, and then it's
stacking each every everything after
that, which kind of makes sense. I mean,
if you think about concatenate, it
starts with the intro and then adds to
it after that. So, this is the base.
This is like the foundation. This is
level one, level two, and so on. So, our
composite video clip in this case is
correct or it should be. So, if we check
in our overlay video and just click over
to where our item is, what I actually
see here, um, I'm going to go ahead and
just pause this. I see that there's my
text off in the corner there. Um, so of
course I can make it bigger and change
how that fits and all that. So I
actually don't need those dual composite
video clips there. I just needed to
change the ordering. Um, so that's a
fairly simple thing, but it's important
to see that yeah, you can combine
composite video clips for sure. No big
deal there. That's one thing. And number
two, to see the actual ramifications of
not having these in the correct order.
Um, so now that we've got that, we
actually have completed everything that
I wanted to do here, which was adding a
watermark to that video. And of course,
if you wanted to change the size, let's
go ahead and do that. I'll go ahead and
just say watermark
size. And we'll use let's try 60 this
time.
And I'll put that instead.
And then I want to align it on the west
side or the other side of the video.
I'll go ahead and run it again. And this
time, now we only have one composite
video clip with our primary video clip
at the base and then all of our text. So
text by default has an opacity to it. So
it actually you can see through the text
to what's underneath it. Uh which is
really nice because of text. Um
sometimes you want to overlay text, you
don't want to have like a black bar
around it or something like that. So
that's where coming in with this is
pretty useful.
So now with it done, I have my like
little text over here with CF and it's
now on the left hand side. Um you can
also add something called margin around
any one of these clips. So margin just
gives it a little bit of extra padding.
So we could say this margin
and you could do left or right or left
equals to two, right equals to two,
bottom equals to two, top, you know,
opacity equals to zero. That's another
thing that you can add in there as well.
Or you could do even bigger numbers if
you'd like. So that's pretty cool that
we have that ability now. Um so as far
as the overlays are concerned um they
are definitely useful but just remember
that the main video that you want to be
overlaid on needs to be at the bottom of
this composite video clip. Okay, so that
actually does it for us with Movie Pie
and Day 15. Now I actually think this is
a good time for you to go and check out
some of their example scripts. They have
all sorts of really cool things that
they can do that are a lot more advanced
than what we've done here. But now that
you have a basis of it, you can actually
go in and use some of these scripts and
have a better understanding of even
doing it. Now, personally, I think just
creating thumbnails is enough uh for
what the purpose of using Movie Pie,
just thumbnails itself or even doing
machine learning analysis. Um, and but
those things kind of go hand in hand. So
the idea here is that we now have a way
to generate videos, images, and text all
through Python. So it's up to you now to
make this as creative as possible,
right? So like how do you actually go
one step further and make just some
really cool videos automatically without
really writing all of this code? Like
can you make that? I think you can. Um,
so I'm really interested in seeing what
you guys come up with. Please upload
them to YouTube and send a link in the
comments below. I would definitely love
to check out any cool Python program
generated videos that you might come up
with. Thanks so much for watching and
we'll see you in the next day.
