I recently got a new task: I need to split a video of an event into smaller segments of two minutes or less for posting on a short video platform.
I thought it would be a one-time job, but it turned out to be too big and too short to handle manually, so Python came to my rescue once again.
So what are you waiting for, let’s do it!
The most important thing
No matter what you do, you have to analyze what’s the most important thing, then focus on attacking it, and then move on to the most important thing.
For our task, it is not a big project, but then, we still need to find the most important thing to start, step by step, and eventually the whole problem will be solved.
As a whole, we need to read video files from a directory, then, crop each video file, and finally save the processed files.
What is the most important thing in this process? I think, it’s video cropping. If you can’t crop the video easily, all the other work is in vain, right?
Crop video
Nowadays, short videos are very popular, and there are many video editing software with rich features, and all we need is the cropping function, and we need to call it programmatically, so there is nothing better than ffmpeg.
ffmpeg is a command line tool that is powerful and can be called programmatically.
Download the version for your operating system from the ffmpeg website.
After downloading, unzip it into a directory and configure the bin in the directory to the environment variables. Then open a command line and type.
> ffmpeg -version
ffmpeg version 2021-10-07-git-b6aeee2d8b-full_build- ...
Test it out and it shows the version information, which means it’s configured.
Now read the documentation and find that the command to split the video file is
ffmpeg -i [filename] -ss [starttime] -t [length] -c copy [newfilename]
i
is the file to be croppedss
is the start time of the cropt
is the end time or length of the cropc
is the storage of the cropped file
Okay, write a function in Python:
import subprocess as sp
def cut_video(filename, outfile, start, length=90):
cmd = "ffmpeg -i %s -ss %d -t %d -c copy %s" % (filename, start, length, outfile)
p = sp.Popen(cmd, shell=True)
p.wait()
return
- Defines a function that passes in the information needed by
ffmpeg
via parameters - Write the crop command as a string template and replace the arguments into it
- Execute the command with
subprocess
’sPopen
, where the argumentshell=True
means execute the command as a whole p.wait()
is important, because cropping takes a while and is executed in a separate process, so you need to wait for the execution to finish before doing subsequent work, otherwise you may not find the cropped file
So the video cropping is done, and then we’ll see what’s most important.
Calculating segments
When video cropping, you need some parameters, especially the start time, how to determine it? If this thing is not done properly, the cropping work will be very troublesome.
So take a look at how to calculate the crop segments.
I need to crop the video into small segments of one and a half minutes, then will need to know the duration of the target video file.
Get the video length
How to get the length? ffmpeg provides another command – ffprobe
.
After looking around, one can synthesize a command to get.
> ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 -i a.flv
920.667
The command is rather complicated, you can ignore the other parameters first, just pass in the video file to be analyzed. The result of the command is to display the length of a line of video files.
So you can write a function.
import subprocess as sp
def get_video_duration(filename):
cmd = "ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 -i %s" % filename
p = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE)
p.wait()
strout, strerr = p.communicate() # remove the last carriage return
ret = strout.decode("utf-8").split("\n")[0]
return ret
- The function has only one parameter, the video file path
- Synthesize the command statement and replace the video file path with it
- use
subprocess
to execute, note that here you need to set the output of the command execution - use
wait
to wait for the command execution to finish - Extract the output result by
communicate
- Extracts the length of the video file from the result and returns
Segmentation
After getting the length of the video, determine the length of each segment, and then calculate how many segments are needed.
The code is simple.
import math
duration = math.floor(float(get_video_duration(filename)))
part = math.ceil(duration / length)
Note that when calculating the segment, you need to do an upward rounding, i.e., use ceil
, to include the last bit of the tail.
Once you have the number of segments you need, use a loop to calculate the start time of each segment.
Getting the files
Because there are many files to process, it is necessary to automatically fetch the files that need to be processed.
The method is simple and commonly used. You can generally use os.walk
to get the files recursively, or you can write your own, depending on the actual situation.
for fname in os.listdir(dir):
fname = os.path.join(dir, os.path.join(dir, fname))
basenames = os.path.basename(fname).split('.')
mainname = basenames[0].split("_")[0]
...
Provide the directory where the video file is located, get the files in the directory via os.listdir
, and then, synthesize the absolute path of the file, because it is easier to call the crop command when you need the absolute path.
Get the file name, in order to name the cropped file later.
Code integration
Now that each part is written, the code can be integrated as follows
def main(dir):
outdir = os.path.join(dir, "output")
if not os.path.exists(outdir):
os.mkdir(outdir)
for fname in os.listdir(dir):
fname = os.path.join(dir, os.path.join(dir, fname))
if os.path.isfile(fname):
split_video(fname, outdir)
- The
main
method is a post-integration method - First create a culled storage directory and put it in the output directory of the video file directory
- After getting the files by
listdir
, each file is processed, which determines whether it is a file or not - Call the
split_video
method to start cropping a video file
Summary
Overall, this is a very simple application, the core function is to call a ffmpeg
command.
What is more important than the technology is how to analyze and break down a project and where to start.
The way to start here is to keep looking for the most important things, and to use the most important things as clues to keep moving forward and eventually solve the whole problem in a bottom-up way.
I hope this article has inspired you.
Source: