The magic tool ffmpeg -- editing video with extreme comfort

post thumb
Python
by Admin/ on 28 Oct 2021

The magic tool ffmpeg -- editing video with extreme comfort


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 cropped
  • ss is the start time of the crop
  • t is the end time or length of the crop
  • c 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’s Popen, where the argument shell=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:


Tags:
comments powered by Disqus